diff --git a/gas/cond.c b/gas/cond.c index 9753369e18..19a1ea08ac 100644 --- a/gas/cond.c +++ b/gas/cond.c @@ -580,3 +580,195 @@ cond_exit_macro (int nest) obstack_free (&cond_obstack, hold); } } + +static int is_float(const char* str) { + if (!str || !*str || !strchr(str, '.')) + return 0; + if (*str == '$') + ++str; + if (*str == '-') + ++str; + if (!*str || !(*str >= '0' || *str <= '9')) + return 0; + char* p; + strtold(str, &p); + return !*p; +} + +static int is_dec(const char* str) { + if (!str || !*str) + return 0; + if (*str == '$') + ++str; + if (*str == '-') + ++str; + if (!*str || !(*str >= '0' || *str <= '9')) + return 0; + char* p; + strtoll(str, &p, 10); + return !*p; +} + +static int is_bin(const char* str) { + if (!str || !*str) + return 0; + if (*str == '$') + ++str; + if (*str == '-') + ++str; + if (!*str || !(*str == '0' || *str == '1')) + return 0; + char* p; + strtoll(str, &p, 2); + return (!*p || *p == 'b' || *p == 'B'); +} + +static int is_hex(const char* str) { + if (!str || !*str) + return 0; + if (*str == '$') + ++str; + if (*str == '-') + ++str; + if (*str == '0') + ++str; + if (*str == 'x' || *str == 'X') + ++str; + if (!*str || !((*str >= '0' && *str <= '9') + || (*str >= 'A' && *str <= 'F') + || (*str >= 'a' && *str <= 'f'))) + return 0; + char* p; + strtoll(str, &p, 16); + return (!*p || *p == 'h' || *p == 'H'); +} + +static int is_number(const char* str) { + return (is_dec(str) || is_hex(str) || is_bin(str) || is_float(str)); +} + +/* Checks for digit in any format: float, hex, dec, bin */ + +void +s_ifnumber (int arg) +{ + (void)arg; + struct conditional_frame cframe; + + initialize_cframe (&cframe); + + if (cframe.dead_tree) + cframe.ignoring = 1; + else + { + int do_skip; + char *label; + + do_skip = 1; + + SKIP_WHITESPACE (); + + get_symbol_name(&label); + + switch (arg) { + case 0: { do_skip = !is_number(label); break; } + case 2: { do_skip = !is_bin(label); break; } + case 10: { do_skip = !is_dec(label); break; } + case 16: { do_skip = !is_hex(label); break; } + case 128: { do_skip = !is_float(label); break; } + default : { do_skip = 1; break; } + } + + cframe.ignoring = do_skip; + } + + current_cframe = + (struct conditional_frame *) obstack_alloc (&cond_obstack, sizeof cframe); + memcpy (current_cframe, &cframe, sizeof cframe); + + ignore_rest_of_line (); +} + +/* Checks for string quoted by \". */ + +void +s_ifquoted (int arg) +{ + (void)arg; + struct conditional_frame cframe; + + initialize_cframe (&cframe); + + if (cframe.dead_tree) + cframe.ignoring = 1; + else + { + int do_skip; + char *label; + char c; + + do_skip = 1; + + SKIP_WHITESPACE (); + + c = get_symbol_name(&label); + // printf("label: %s; c: %c\n",(label),(c)); + + if (*label == '$') + ++label; + + if (c == '"' && !symbol_find (label) && !is_number(label)) + do_skip = 0; + + cframe.ignoring = do_skip; + } + + current_cframe = + (struct conditional_frame *) obstack_alloc (&cond_obstack, sizeof cframe); + memcpy (current_cframe, &cframe, sizeof cframe); + + ignore_rest_of_line (); +} + +/* Checks for constant (or abs value) */ + +void +s_ifconst (int arg) +{ + (void)arg; + struct conditional_frame cframe; + + initialize_cframe (&cframe); + + if (cframe.dead_tree) + cframe.ignoring = 1; + else + { + int do_skip; + char *label; + + do_skip = 1; + + SKIP_WHITESPACE (); + + get_symbol_name(&label); + + if (!symbol_find (label) && *label != '$' && is_number(label)) + do_skip = 0; + else + { + expressionS operand; + expression_and_evaluate (&operand); + if (operand.X_op == O_constant) + do_skip = 0; + } + + cframe.ignoring = do_skip; + } + + current_cframe = + (struct conditional_frame *) obstack_alloc (&cond_obstack, sizeof cframe); + memcpy (current_cframe, &cframe, sizeof cframe); + + ignore_rest_of_line (); +} diff --git a/gas/read.c b/gas/read.c index bf594f12a2..7754290606 100644 --- a/gas/read.c +++ b/gas/read.c @@ -379,12 +379,17 @@ static const pseudo_typeS potable[] = { {"hword", cons, 2}, {"if", s_if, (int) O_ne}, {"ifb", s_ifb, 1}, + {"ifbin", s_ifnumber, 2}, {"ifc", s_ifc, 0}, + {"ifconst", s_ifconst, 0}, {"ifdef", s_ifdef, 0}, + {"ifdec", s_ifnumber, 10}, {"ifeq", s_if, (int) O_eq}, {"ifeqs", s_ifeqs, 0}, + {"iffloat", s_ifnumber, 128}, {"ifge", s_if, (int) O_ge}, {"ifgt", s_if, (int) O_gt}, + {"ifhex", s_ifnumber, 16}, {"ifle", s_if, (int) O_le}, {"iflt", s_if, (int) O_lt}, {"ifnb", s_ifb, 0}, @@ -393,6 +398,8 @@ static const pseudo_typeS potable[] = { {"ifne", s_if, (int) O_ne}, {"ifnes", s_ifeqs, 1}, {"ifnotdef", s_ifdef, 1}, + {"ifnumber", s_ifnumber, 0}, + {"ifquoted", s_ifquoted, 0}, {"incbin", s_incbin, 0}, {"include", s_include, 0}, {"int", cons, 4}, diff --git a/gas/read.h b/gas/read.h index 502f3b6f2d..e1b4e79bac 100644 --- a/gas/read.h +++ b/gas/read.h @@ -186,8 +186,11 @@ extern void s_globl (int arg); extern void s_if (int arg); extern void s_ifb (int arg); extern void s_ifc (int arg); +extern void s_ifconst (int); extern void s_ifdef (int arg); extern void s_ifeqs (int arg); +extern void s_ifnumber (int); +extern void s_ifquoted (int); extern void s_ignore (int arg); extern void s_include (int arg); extern void s_irp (int arg);