X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fexpr.c;h=58db726191ebeb08ab5e987ed18ce4f07396130c;hb=f7df6a7927fca92d8839b024faa9353a0fac5c13;hp=1fa5f7e2569bda97cb9b94a0f944074e2f073c78;hpb=a8a22e336510477a9710d98a7d57ec56fc167c2e;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/expr.c b/gas/expr.c index 1fa5f7e256..58db726191 100644 --- a/gas/expr.c +++ b/gas/expr.c @@ -1,6 +1,6 @@ /* expr.c -operands, expressions- Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001 + 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -25,11 +25,11 @@ (It also gives smaller files to re-compile.) Here, "operand"s are of expressions, not instructions. */ -#include #include #define min(a, b) ((a) < (b) ? (a) : (b)) #include "as.h" +#include "safe-ctype.h" #include "obstack.h" static void floating_constant PARAMS ((expressionS * expressionP)); @@ -67,7 +67,6 @@ make_expr_symbol (expressionP) expressionS *expressionP; { expressionS zero; - const char *fake; symbolS *symbolP; struct expr_symbol_line *n; @@ -78,12 +77,12 @@ make_expr_symbol (expressionP) if (expressionP->X_op == O_big) { /* This won't work, because the actual value is stored in - generic_floating_point_number or generic_bignum, and we are - going to lose it if we haven't already. */ + generic_floating_point_number or generic_bignum, and we are + going to lose it if we haven't already. */ if (expressionP->X_add_number > 0) - as_bad (_("bignum invalid; zero assumed")); + as_bad (_("bignum invalid")); else - as_bad (_("floating point number invalid; zero assumed")); + as_bad (_("floating point number invalid")); zero.X_op = O_constant; zero.X_add_number = 0; zero.X_unsigned = 0; @@ -91,13 +90,11 @@ make_expr_symbol (expressionP) expressionP = &zero; } - fake = FAKE_LABEL_NAME; - /* Putting constant symbols in absolute_section rather than expr_section is convenient for the old a.out code, for which S_GET_SEGMENT does not always retrieve the value put in by S_SET_SEGMENT. */ - symbolP = symbol_create (fake, + symbolP = symbol_create (FAKE_LABEL_NAME, (expressionP->X_op == O_constant ? absolute_section : expr_section), @@ -105,7 +102,7 @@ make_expr_symbol (expressionP) symbol_set_value_expression (symbolP, expressionP); if (expressionP->X_op == O_constant) - resolve_symbol_value (symbolP, finalize_syms); + resolve_symbol_value (symbolP); n = (struct expr_symbol_line *) xmalloc (sizeof *n); n->sym = symbolP; @@ -243,11 +240,12 @@ floating_constant (expressionP) { if (error_code == ERROR_EXPONENT_OVERFLOW) { - as_bad (_("bad floating-point constant: exponent overflow, probably assembling junk")); + as_bad (_("bad floating-point constant: exponent overflow")); } else { - as_bad (_("bad floating-point constant: unknown error code=%d."), error_code); + as_bad (_("bad floating-point constant: unknown error code=%d"), + error_code); } } expressionP->X_op = O_big; @@ -328,11 +326,9 @@ integer_constant (radix, expressionP) int flt = 0; /* In MRI mode, the number may have a suffix indicating the - radix. For that matter, it might actually be a floating - point constant. */ - for (suffix = input_line_pointer; - isalnum ((unsigned char) *suffix); - suffix++) + radix. For that matter, it might actually be a floating + point constant. */ + for (suffix = input_line_pointer; ISALNUM (*suffix); suffix++) { if (*suffix == 'e' || *suffix == 'E') flt = 1; @@ -346,8 +342,7 @@ integer_constant (radix, expressionP) else { c = *--suffix; - if (islower ((unsigned char) c)) - c = toupper (c); + c = TOUPPER (c); if (c == 'B') radix = 2; else if (c == 'D') @@ -403,7 +398,7 @@ integer_constant (radix, expressionP) if (radix == 16 && c == '_') { /* This is literal of the form 0x333_0_12345678_1. - This example is equivalent to 0x00000333000000001234567800000001. */ + This example is equivalent to 0x00000333000000001234567800000001. */ int num_little_digits = 0; int i; @@ -427,7 +422,7 @@ integer_constant (radix, expressionP) /* Check for 8 digit per word max. */ if (ndigit > 8) - as_bad (_("A bignum with underscores may not have more than 8 hex digits in any word.")); + as_bad (_("a bignum with underscores may not have more than 8 hex digits in any word")); /* Add this chunk to the bignum. Shift things down 2 little digits. */ @@ -450,7 +445,7 @@ integer_constant (radix, expressionP) assert (num_little_digits >= 4); if (num_little_digits != 8) - as_bad (_("A bignum with underscores must have exactly 4 words.")); + as_bad (_("a bignum with underscores must have exactly 4 words")); /* We might have some leading zeros. These can be trimmed to give us a change to fit this constant into a small number. */ @@ -573,7 +568,7 @@ integer_constant (radix, expressionP) /* Either not seen or not defined. */ /* @@ Should print out the original string instead of the parsed number. */ - as_bad (_("backw. ref to unknown label \"%d:\", 0 assumed."), + as_bad (_("backward ref to unknown label \"%d:\""), (int) number); expressionP->X_op = O_constant; } @@ -683,8 +678,8 @@ mri_char_constant (expressionP) if (i < SIZE_OF_LARGE_NUMBER - 1) { /* If there is more than one littlenum, left justify the - last one to make it match the earlier ones. If there is - only one, we can just use the value directly. */ + last one to make it match the earlier ones. If there is + only one, we can just use the value directly. */ for (; j < CHARS_PER_LITTLENUM; j++) generic_bignum[i] <<= 8; } @@ -696,7 +691,7 @@ mri_char_constant (expressionP) if (i < 0) { - as_bad (_("Character constant too large")); + as_bad (_("character constant too large")); i = 0; } @@ -747,13 +742,8 @@ current_location (expressionp) } else { - symbolS *symbolp; - - symbolp = symbol_new (FAKE_LABEL_NAME, now_seg, - (valueT) frag_now_fix (), - frag_now); expressionp->X_op = O_symbol; - expressionp->X_add_symbol = symbolp; + expressionp->X_add_symbol = symbol_temp_new_now (); expressionp->X_add_number = 0; } } @@ -761,7 +751,7 @@ current_location (expressionp) /* In: Input_line_pointer points to 1st char of operand, which may be a space. - Out: A expressionS. + Out: An expressionS. The operand may have been empty: in this case X_op == O_absent. Input_line_pointer->(next non-blank) char after operand. */ @@ -805,11 +795,14 @@ operand (expressionP) integer_constant ((NUMBERS_WITH_SUFFIX || flag_m68k_mri) ? 0 : 10, - expressionP); + expressionP); break; #ifdef LITERAL_PREFIXDOLLAR_HEX case '$': + /* $L is the start of a local label, not a hex constant. */ + if (* input_line_pointer == 'L') + goto isname; integer_constant (16, expressionP); break; #endif @@ -827,10 +820,10 @@ operand (expressionP) { char *s; - /* Check for a hex constant. */ + /* Check for a hex or float constant. */ for (s = input_line_pointer; hex_p (*s); s++) ; - if (*s == 'h' || *s == 'H') + if (*s == 'h' || *s == 'H' || *input_line_pointer == '.') { --input_line_pointer; integer_constant (0, expressionP); @@ -858,8 +851,7 @@ operand (expressionP) { input_line_pointer++; floating_constant (expressionP); - expressionP->X_add_number = - - (isupper ((unsigned char) c) ? tolower (c) : c); + expressionP->X_add_number = - TOLOWER (c); } else { @@ -981,8 +973,7 @@ operand (expressionP) case 'G': input_line_pointer++; floating_constant (expressionP); - expressionP->X_add_number = - - (isupper ((unsigned char) c) ? tolower (c) : c); + expressionP->X_add_number = - TOLOWER (c); break; case '$': @@ -1010,7 +1001,7 @@ operand (expressionP) #ifdef RELAX_PAREN_GROUPING if (c != '(') #endif - as_bad (_("Missing '%c' assumed"), c == '(' ? ')' : ']'); + as_bad (_("missing '%c'"), c == '(' ? ')' : ']'); } else input_line_pointer++; @@ -1080,6 +1071,18 @@ operand (expressionP) else expressionP->X_add_number = ! expressionP->X_add_number; } + else if (expressionP->X_op == O_big + && expressionP->X_add_number <= 0 + && c == '-' + && (generic_floating_point_number.sign == '+' + || generic_floating_point_number.sign == 'P')) + { + /* Negative flonum (eg, -1.000e0). */ + if (generic_floating_point_number.sign == '+') + generic_floating_point_number.sign = '-'; + else + generic_floating_point_number.sign = 'N'; + } else if (expressionP->X_op != O_illegal && expressionP->X_op != O_absent) { @@ -1101,7 +1104,7 @@ operand (expressionP) #if defined (DOLLAR_DOT) || defined (TC_M68K) case '$': /* '$' is the program counter when in MRI mode, or when - DOLLAR_DOT is defined. */ + DOLLAR_DOT is defined. */ #ifndef DOLLAR_DOT if (! flag_m68k_mri) goto de_fault; @@ -1109,7 +1112,7 @@ operand (expressionP) if (flag_m68k_mri && hex_p (*input_line_pointer)) { /* In MRI mode, '$' is also used as the prefix for a - hexadecimal constant. */ + hexadecimal constant. */ integer_constant (16, expressionP); break; } @@ -1200,7 +1203,7 @@ operand (expressionP) goto de_fault; /* In MRI mode, this is a floating point constant represented - using hexadecimal digits. */ + using hexadecimal digits. */ ++input_line_pointer; integer_constant (16, expressionP); @@ -1228,9 +1231,9 @@ operand (expressionP) #ifdef md_parse_name /* This is a hook for the backend to parse certain names - specially in certain contexts. If a name always has a - specific value, it can often be handled by simply - entering it in the symbol table. */ + specially in certain contexts. If a name always has a + specific value, it can often be handled by simply + entering it in the symbol table. */ if (md_parse_name (name, expressionP, &c)) { *input_line_pointer = c; @@ -1312,7 +1315,7 @@ operand (expressionP) if (expressionP->X_op == O_absent) { ++input_line_pointer; - as_bad (_("Bad expression")); + as_bad (_("bad expression")); expressionP->X_op = O_constant; expressionP->X_add_number = 0; } @@ -1343,13 +1346,11 @@ operand (expressionP) /* Internal. Simplify a struct expression for use by expr (). */ -/* In: address of a expressionS. +/* In: address of an expressionS. The X_op field of the expressionS may only take certain values. Elsewise we waste time special-case testing. Sigh. Ditto SEG_ABSENT. Out: expressionS may have been modified: - 'foo-foo' symbol references cancelled to 0, which changes X_op - from O_subtract to O_constant. Unused fields zeroed to help expr (). */ static void @@ -1372,23 +1373,6 @@ clean_up_expression (expressionP) case O_bit_not: expressionP->X_op_symbol = NULL; break; - case O_subtract: - if (expressionP->X_op_symbol == expressionP->X_add_symbol - || ((symbol_get_frag (expressionP->X_op_symbol) - == symbol_get_frag (expressionP->X_add_symbol)) - && SEG_NORMAL (S_GET_SEGMENT (expressionP->X_add_symbol)) - && (S_GET_VALUE (expressionP->X_op_symbol) - == S_GET_VALUE (expressionP->X_add_symbol)))) - { - addressT diff = (S_GET_VALUE (expressionP->X_add_symbol) - - S_GET_VALUE (expressionP->X_op_symbol)); - - expressionP->X_op = O_constant; - expressionP->X_add_symbol = NULL; - expressionP->X_op_symbol = NULL; - expressionP->X_add_number += diff; - } - break; default: break; } @@ -1400,7 +1384,7 @@ clean_up_expression (expressionP) Unary operators and parenthetical expressions are treated as operands. As usual, Q==quantity==operand, O==operator, X==expression mnemonics. - We used to do a aho/ullman shift-reduce parser, but the logic got so + We used to do an aho/ullman shift-reduce parser, but the logic got so warped that I flushed it and wrote a recursive-descent parser instead. Now things are stable, would anybody like to write a fast parser? Most expressions are either register (which does not even reach here) @@ -1456,7 +1440,7 @@ static const operatorT op_encoding[256] = { 0 operand, (expression) 1 || 2 && - 3 = <> < <= >= > + 3 == <> < <= >= > 4 + - 5 used for * / % in MRI mode 6 & ^ ! | @@ -1660,6 +1644,10 @@ expr (rankarg, resultP) know (rank >= 0); + /* Save the value of dot for the fixup code. */ + if (rank == 0) + dot_value = frag_now_fix (); + retval = operand (resultP); /* operand () gobbles spaces. */ @@ -1695,21 +1683,6 @@ expr (rankarg, resultP) } } - if (retval == undefined_section) - { - if (SEG_NORMAL (rightseg)) - retval = rightseg; - } - else if (! SEG_NORMAL (retval)) - retval = rightseg; - else if (SEG_NORMAL (rightseg) - && retval != rightseg -#ifdef DIFF_EXPR_OK - && op_left != O_subtract -#endif - ) - as_bad (_("operation combines symbols in different segments")); - op_right = operator (&op_chars); know (op_right == O_illegal @@ -1765,8 +1738,8 @@ expr (rankarg, resultP) && resultP->X_op == O_symbol && (symbol_get_frag (right.X_add_symbol) == symbol_get_frag (resultP->X_add_symbol)) - && SEG_NORMAL (S_GET_SEGMENT (right.X_add_symbol))) - + && (SEG_NORMAL (rightseg) + || right.X_add_symbol == resultP->X_add_symbol)) { resultP->X_add_number -= right.X_add_number; resultP->X_add_number += (S_GET_VALUE (resultP->X_add_symbol) @@ -1806,7 +1779,7 @@ expr (rankarg, resultP) case O_left_shift: resultP->X_add_number <<= v; break; case O_right_shift: /* We always use unsigned shifts, to avoid relying on - characteristics of the compiler used to compile gas. */ + characteristics of the compiler used to compile gas. */ resultP->X_add_number = (offsetT) ((valueT) resultP->X_add_number >> (valueT) v); break; @@ -1861,7 +1834,14 @@ expr (rankarg, resultP) if (op_left == O_add) resultP->X_add_number += right.X_add_number; else if (op_left == O_subtract) - resultP->X_add_number -= right.X_add_number; + { + resultP->X_add_number -= right.X_add_number; + if (retval == rightseg && SEG_NORMAL (retval)) + { + retval = absolute_section; + rightseg = absolute_section; + } + } } else { @@ -1873,6 +1853,21 @@ expr (rankarg, resultP) resultP->X_unsigned = 1; } + if (retval != rightseg) + { + if (! SEG_NORMAL (retval)) + { + if (retval != undefined_section || SEG_NORMAL (rightseg)) + retval = rightseg; + } + else if (SEG_NORMAL (rightseg) +#ifdef DIFF_EXPR_OK + && op_left != O_subtract +#endif + ) + as_bad (_("operation combines symbols in different segments")); + } + op_left = op_right; } /* While next operator is >= this rank. */