X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fexpr.c;h=499f9a33fb438a31ea8a2f72f8749c6206b720dd;hb=3882b010780ca1aa1ed5d7b38e936cd2d6d5486b;hp=09f38b1bb7e07b75dc91c665420e4a6f3c5c3288;hpb=bc4466dcf10e23054dc420c9eee11210dce0e9d8;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/expr.c b/gas/expr.c index 09f38b1bb7..499f9a33fb 100644 --- a/gas/expr.c +++ b/gas/expr.c @@ -1,5 +1,6 @@ /* expr.c -operands, expressions- - Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 + Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -24,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)); @@ -41,15 +42,14 @@ static void mri_char_constant PARAMS ((expressionS *)); static void current_location PARAMS ((expressionS *)); static void clean_up_expression PARAMS ((expressionS * expressionP)); static segT operand PARAMS ((expressionS *)); -static operatorT operator PARAMS ((void)); +static operatorT operator PARAMS ((int *)); extern const char EXP_CHARS[], FLT_CHARS[]; /* We keep a mapping of expression symbols to file positions, so that we can provide better error messages. */ -struct expr_symbol_line -{ +struct expr_symbol_line { struct expr_symbol_line *next; symbolS *sym; char *file; @@ -81,9 +81,9 @@ make_expr_symbol (expressionP) 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; @@ -105,7 +105,7 @@ make_expr_symbol (expressionP) symbol_set_value_expression (symbolP, expressionP); if (expressionP->X_op == O_constant) - resolve_symbol_value (symbolP, 1); + resolve_symbol_value (symbolP); n = (struct expr_symbol_line *) xmalloc (sizeof *n); n->sym = symbolP; @@ -217,8 +217,8 @@ expr_build_dot () and never write into the early words, thus they'll always be zero. I hate Dean's floating-point code. Bleh. */ LITTLENUM_TYPE generic_bignum[SIZE_OF_LARGE_NUMBER + 6]; -FLONUM_TYPE generic_floating_point_number = -{ + +FLONUM_TYPE generic_floating_point_number = { &generic_bignum[6], /* low. (JF: Was 0) */ &generic_bignum[SIZE_OF_LARGE_NUMBER + 6 - 1], /* high. JF: (added +6) */ 0, /* leader. */ @@ -243,11 +243,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; @@ -330,9 +331,7 @@ integer_constant (radix, expressionP) /* 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++) + for (suffix = input_line_pointer; ISALNUM (*suffix); suffix++) { if (*suffix == 'e' || *suffix == 'E') flt = 1; @@ -346,8 +345,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') @@ -427,7 +425,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 +448,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 +571,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; } @@ -696,7 +694,7 @@ mri_char_constant (expressionP) if (i < 0) { - as_bad (_("Character constant too large")); + as_bad (_("character constant too large")); i = 0; } @@ -810,6 +808,9 @@ operand (expressionP) #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 @@ -858,8 +859,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 +981,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 +1009,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++; @@ -1069,7 +1068,7 @@ operand (expressionP) /* input_line_pointer -> char after operand. */ if (c == '-') { - expressionP->X_add_number = -expressionP->X_add_number; + expressionP->X_add_number = - expressionP->X_add_number; /* Notice: '-' may overflow: no warning is given. This is compatible with other people's assemblers. Sigh. */ @@ -1231,7 +1230,7 @@ operand (expressionP) 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)) + if (md_parse_name (name, expressionP, &c)) { *input_line_pointer = c; break; @@ -1304,7 +1303,7 @@ operand (expressionP) { /* Let the target try to parse it. Success is indicated by changing the X_op field to something other than O_absent and pointing - input_line_pointer passed the expression. If it can't parse the + input_line_pointer past the expression. If it can't parse the expression, X_op and input_line_pointer should be unchanged. */ expressionP->X_op = O_absent; --input_line_pointer; @@ -1312,7 +1311,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; } @@ -1418,9 +1417,8 @@ clean_up_expression (expressionP) #undef __ #define __ O_illegal -static const operatorT op_encoding[256] = -{ /* Maps ASCII -> operators. */ - +/* Maps ASCII -> operators. */ +static const operatorT op_encoding[256] = { __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, @@ -1457,22 +1455,21 @@ static const operatorT op_encoding[256] = 0 operand, (expression) 1 || 2 && - 3 = <> < <= >= > + 3 == <> < <= >= > 4 + - 5 used for * / % in MRI mode 6 & ^ ! | 7 * / % << >> 8 unary - unary ~ */ -static operator_rankT op_rank[] = -{ +static operator_rankT op_rank[] = { 0, /* O_illegal */ 0, /* O_absent */ 0, /* O_constant */ 0, /* O_symbol */ 0, /* O_symbol_rva */ 0, /* O_register */ - 0, /* O_bit */ + 0, /* O_big */ 9, /* O_uminus */ 9, /* O_bit_not */ 9, /* O_logical_not */ @@ -1520,8 +1517,8 @@ static operator_rankT op_rank[] = mode. Also, MRI uses a different bit_not operator, and this fixes that as well. */ -#define STANDARD_MUL_PRECEDENCE (7) -#define MRI_MUL_PRECEDENCE (5) +#define STANDARD_MUL_PRECEDENCE 8 +#define MRI_MUL_PRECEDENCE 6 void expr_set_precedence () @@ -1555,17 +1552,19 @@ expr_begin () } } -/* Return the encoding for the operator at INPUT_LINE_POINTER. - Advance INPUT_LINE_POINTER to the last character in the operator - (i.e., don't change it for a single character operator). */ +/* Return the encoding for the operator at INPUT_LINE_POINTER, and + sets NUM_CHARS to the number of characters in the operator. + Does not advance INPUT_LINE_POINTER. */ static inline operatorT -operator () +operator (num_chars) + int *num_chars; { int c; operatorT ret; c = *input_line_pointer & 0xff; + *num_chars = 1; if (is_end_of_line[c]) return O_illegal; @@ -1590,14 +1589,14 @@ operator () ret = O_le; break; } - ++input_line_pointer; + *num_chars = 2; return ret; case '=': if (input_line_pointer[1] != '=') return op_encoding[c]; - ++input_line_pointer; + *num_chars = 2; return O_eq; case '>': @@ -1612,7 +1611,7 @@ operator () ret = O_ge; break; } - ++input_line_pointer; + *num_chars = 2; return ret; case '!': @@ -1623,21 +1622,21 @@ operator () return O_bit_inclusive_or; return op_encoding[c]; } - ++input_line_pointer; + *num_chars = 2; return O_bit_exclusive_or; case '|': if (input_line_pointer[1] != '|') return op_encoding[c]; - ++input_line_pointer; + *num_chars = 2; return O_logical_or; case '&': if (input_line_pointer[1] != '&') return op_encoding[c]; - ++input_line_pointer; + *num_chars = 2; return O_logical_and; } @@ -1656,6 +1655,7 @@ expr (rankarg, resultP) expressionS right; operatorT op_left; operatorT op_right; + int op_chars; know (rank >= 0); @@ -1664,12 +1664,12 @@ expr (rankarg, resultP) /* operand () gobbles spaces. */ know (*input_line_pointer != ' '); - op_left = operator (); + op_left = operator (&op_chars); while (op_left != O_illegal && op_rank[(int) op_left] > rank) { segT rightseg; - input_line_pointer++; /* -> after 1st character of operator. */ + input_line_pointer += op_chars; /* -> after operator. */ rightseg = expr (op_rank[(int) op_left], &right); if (right.X_op == O_absent) @@ -1694,22 +1694,7 @@ 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_right = operator (&op_chars); know (op_right == O_illegal || op_rank[(int) op_right] <= op_rank[(int) op_left]); @@ -1764,8 +1749,7 @@ 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)) { resultP->X_add_number -= right.X_add_number; resultP->X_add_number += (S_GET_VALUE (resultP->X_add_symbol) @@ -1817,27 +1801,27 @@ expr (rankarg, resultP) case O_subtract: resultP->X_add_number -= v; break; case O_eq: resultP->X_add_number = - resultP->X_add_number == v ? ~(offsetT) 0 : 0; + resultP->X_add_number == v ? ~ (offsetT) 0 : 0; break; case O_ne: resultP->X_add_number = - resultP->X_add_number != v ? ~(offsetT) 0 : 0; + resultP->X_add_number != v ? ~ (offsetT) 0 : 0; break; case O_lt: resultP->X_add_number = - resultP->X_add_number < v ? ~(offsetT) 0 : 0; + resultP->X_add_number < v ? ~ (offsetT) 0 : 0; break; case O_le: resultP->X_add_number = - resultP->X_add_number <= v ? ~(offsetT) 0 : 0; + resultP->X_add_number <= v ? ~ (offsetT) 0 : 0; break; case O_ge: resultP->X_add_number = - resultP->X_add_number >= v ? ~(offsetT) 0 : 0; + resultP->X_add_number >= v ? ~ (offsetT) 0 : 0; break; case O_gt: resultP->X_add_number = - resultP->X_add_number > v ? ~(offsetT) 0 : 0; + resultP->X_add_number > v ? ~ (offsetT) 0 : 0; break; case O_logical_and: resultP->X_add_number = resultP->X_add_number && v; @@ -1860,7 +1844,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 { @@ -1872,6 +1863,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. */