X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fexpr.c;h=b1cdb38bab58add5550d1affbbbfcd363b298279;hb=6610dc6daa661b7cd042bc6313a29859b87263d9;hp=eb7255fe5cf01309aaf113307db103eda2fba3c1;hpb=e57e6ddc2e768323732a7eed6a5d25d3ee350638;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/expr.c b/gas/expr.c index eb7255fe5c..b1cdb38bab 100644 --- a/gas/expr.c +++ b/gas/expr.c @@ -1,5 +1,5 @@ /* expr.c -operands, expressions- - Copyright (C) 1987-2014 Free Software Foundation, Inc. + Copyright (C) 1987-2016 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -46,15 +46,13 @@ static void clean_up_expression (expressionS * expressionP); static segT operand (expressionS *, enum expr_mode); static operatorT operatorf (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 *next; symbolS *sym; - char *file; + const char *file; unsigned int line; }; @@ -108,9 +106,9 @@ make_expr_symbol (expressionS *expressionP) if (expressionP->X_op == O_constant) resolve_symbol_value (symbolP); - n = (struct expr_symbol_line *) xmalloc (sizeof *n); + n = XNEW (struct expr_symbol_line); n->sym = symbolP; - as_where (&n->file, &n->line); + n->file = as_where (&n->line); n->next = expr_symbol_lines; expr_symbol_lines = n; @@ -122,9 +120,9 @@ make_expr_symbol (expressionS *expressionP) the symbol. */ int -expr_symbol_where (symbolS *sym, char **pfile, unsigned int *pline) +expr_symbol_where (symbolS *sym, const char **pfile, unsigned int *pline) { - register struct expr_symbol_line *l; + struct expr_symbol_line *l; for (l = expr_symbol_lines; l != NULL; l = l->next) { @@ -285,6 +283,12 @@ integer_constant (int radix, expressionS *expressionP) #define valuesize 32 #endif + if (is_end_of_line[(unsigned char) *input_line_pointer]) + { + expressionP->X_op = O_absent; + return; + } + if ((NUMBERS_WITH_SUFFIX || flag_m68k_mri) && radix == 0) { int flt = 0; @@ -504,6 +508,13 @@ integer_constant (int radix, expressionS *expressionP) && input_line_pointer - 1 == suffix) c = *input_line_pointer++; +#ifndef tc_allow_U_suffix +#define tc_allow_U_suffix 1 +#endif + /* PR 19910: Look for, and ignore, a U suffix to the number. */ + if (tc_allow_U_suffix && (c == 'U' || c == 'u')) + c = * input_line_pointer++; + if (small) { /* Here with number, in correct radix. c is the next char. @@ -832,32 +843,28 @@ operand (expressionS *expressionP, enum expr_mode mode) break; case 'b': - if (LOCAL_LABELS_FB && ! (flag_m68k_mri || NUMBERS_WITH_SUFFIX)) + if (LOCAL_LABELS_FB && !flag_m68k_mri + && input_line_pointer[1] != '0' + && input_line_pointer[1] != '1') { - /* This code used to check for '+' and '-' here, and, in - some conditions, fall through to call - integer_constant. However, that didn't make sense, - as integer_constant only accepts digits. */ - /* Some of our code elsewhere does permit digits greater - than the expected base; for consistency, do the same - here. */ - if (input_line_pointer[1] < '0' - || input_line_pointer[1] > '9') - { - /* Parse this as a back reference to label 0. */ - input_line_pointer--; - integer_constant (10, expressionP); - break; - } - /* Otherwise, parse this as a binary number. */ + /* Parse this as a back reference to label 0. */ + input_line_pointer--; + integer_constant (10, expressionP); + break; } + /* Otherwise, parse this as a binary number. */ /* Fall through. */ case 'B': - input_line_pointer++; + if (input_line_pointer[1] == '0' + || input_line_pointer[1] == '1') + { + input_line_pointer++; + integer_constant (2, expressionP); + break; + } if (flag_m68k_mri || NUMBERS_WITH_SUFFIX) - goto default_case; - integer_constant (2, expressionP); - break; + input_line_pointer++; + goto default_case; case '0': case '1': @@ -875,48 +882,35 @@ operand (expressionS *expressionP, enum expr_mode mode) case 'f': if (LOCAL_LABELS_FB) { + int is_label = 1; + /* If it says "0f" and it could possibly be a floating point number, make it one. Otherwise, make it a local label, and try to deal with parsing the rest later. */ - if (!input_line_pointer[1] - || (is_end_of_line[0xff & input_line_pointer[1]]) - || strchr (FLT_CHARS, 'f') == NULL) - goto is_0f_label; - { - char *cp = input_line_pointer + 1; - int r = atof_generic (&cp, ".", EXP_CHARS, - &generic_floating_point_number); - switch (r) - { - case 0: - case ERROR_EXPONENT_OVERFLOW: - if (*cp == 'f' || *cp == 'b') - /* Looks like a difference expression. */ - goto is_0f_label; - else if (cp == input_line_pointer + 1) - /* No characters has been accepted -- looks like - end of operand. */ - goto is_0f_label; - else - goto is_0f_float; - default: - as_fatal (_("expr.c(operand): bad atof_generic return val %d"), - r); - } - } - - /* Okay, now we've sorted it out. We resume at one of these - two labels, depending on what we've decided we're probably - looking at. */ - is_0f_label: - input_line_pointer--; - integer_constant (10, expressionP); - break; - - is_0f_float: - /* Fall through. */ - ; + if (!is_end_of_line[(unsigned char) input_line_pointer[1]] + && strchr (FLT_CHARS, 'f') != NULL) + { + char *cp = input_line_pointer + 1; + + atof_generic (&cp, ".", EXP_CHARS, + &generic_floating_point_number); + + /* Was nothing parsed, or does it look like an + expression? */ + is_label = (cp == input_line_pointer + 1 + || (cp == input_line_pointer + 2 + && (cp[-1] == '-' || cp[-1] == '+')) + || *cp == 'f' + || *cp == 'b'); + } + if (is_label) + { + input_line_pointer--; + integer_constant (10, expressionP); + break; + } } + /* Fall through. */ case 'd': case 'D': @@ -963,7 +957,13 @@ operand (expressionS *expressionP, enum expr_mode mode) /* expression () will pass trailing whitespace. */ if ((c == '(' && *input_line_pointer != ')') || (c == '[' && *input_line_pointer != ']')) - as_bad (_("missing '%c'"), c == '(' ? ')' : ']'); + { + if (* input_line_pointer) + as_bad (_("found '%c', expected: '%c'"), + * input_line_pointer, c == '(' ? ')' : ']'); + else + as_bad (_("missing '%c'"), c == '(' ? ')' : ']'); + } else input_line_pointer++; SKIP_WHITESPACE (); @@ -1021,7 +1021,8 @@ operand (expressionS *expressionP, enum expr_mode mode) /* input_line_pointer -> char after operand. */ if (c == '-') { - expressionP->X_add_number = - expressionP->X_add_number; + expressionP->X_add_number + = - (addressT) expressionP->X_add_number; /* Notice: '-' may overflow: no warning is given. This is compatible with other people's assemblers. Sigh. */ @@ -1152,14 +1153,10 @@ operand (expressionS *expressionP, enum expr_mode mode) ++input_line_pointer; SKIP_WHITESPACE (); - name = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (& name); - buf = (char *) xmalloc (strlen (name) + 10); - if (start) - sprintf (buf, ".startof.%s", name); - else - sprintf (buf, ".sizeof.%s", name); + buf = concat (start ? ".startof." : ".sizeof.", name, + (char *) NULL); symbolP = symbol_make (buf); free (buf); @@ -1168,7 +1165,7 @@ operand (expressionS *expressionP, enum expr_mode mode) expressionP->X_add_number = 0; *input_line_pointer = c; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); if (*input_line_pointer != ')') as_bad (_("syntax error in .startof. or .sizeof.")); else @@ -1224,13 +1221,13 @@ operand (expressionS *expressionP, enum expr_mode mode) #if defined(md_need_index_operator) || defined(TC_M68K) de_fault: #endif - if (is_name_beginner (c)) /* Here if did not begin with a digit. */ + if (is_name_beginner (c) || c == '"') /* Here if did not begin with a digit. */ { /* Identifier begins here. This is kludged for speed, so code is repeated. */ isname: - name = --input_line_pointer; - c = get_symbol_end (); + -- input_line_pointer; + c = get_symbol_name (&name); #ifdef md_operator { @@ -1239,15 +1236,15 @@ operand (expressionS *expressionP, enum expr_mode mode) switch (op) { case O_uminus: - *input_line_pointer = c; + restore_line_pointer (c); c = '-'; goto unary; case O_bit_not: - *input_line_pointer = c; + restore_line_pointer (c); c = '~'; goto unary; case O_logical_not: - *input_line_pointer = c; + restore_line_pointer (c); c = '!'; goto unary; case O_illegal: @@ -1256,9 +1253,10 @@ operand (expressionS *expressionP, enum expr_mode mode) default: break; } + if (op != O_absent && op != O_illegal) { - *input_line_pointer = c; + restore_line_pointer (c); expr (9, expressionP, mode); expressionP->X_add_symbol = make_expr_symbol (expressionP); expressionP->X_op_symbol = NULL; @@ -1276,7 +1274,7 @@ operand (expressionS *expressionP, enum expr_mode mode) entering it in the symbol table. */ if (md_parse_name (name, expressionP, mode, &c)) { - *input_line_pointer = c; + restore_line_pointer (c); break; } #endif @@ -1296,16 +1294,12 @@ operand (expressionS *expressionP, enum expr_mode mode) || name[1] == 'T'); *input_line_pointer = c; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); - name = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (& name); - buf = (char *) xmalloc (strlen (name) + 10); - if (start) - sprintf (buf, ".startof.%s", name); - else - sprintf (buf, ".sizeof.%s", name); + buf = concat (start ? ".startof." : ".sizeof.", name, + (char *) NULL); symbolP = symbol_make (buf); free (buf); @@ -1314,8 +1308,7 @@ operand (expressionS *expressionP, enum expr_mode mode) expressionP->X_add_number = 0; *input_line_pointer = c; - SKIP_WHITESPACE (); - + SKIP_WHITESPACE_AFTER_NAME (); break; } #endif @@ -1343,7 +1336,8 @@ operand (expressionS *expressionP, enum expr_mode mode) expressionP->X_add_symbol = symbolP; expressionP->X_add_number = 0; } - *input_line_pointer = c; + + restore_line_pointer (c); } else { @@ -1599,8 +1593,8 @@ operatorf (int *num_chars) #ifdef md_operator if (is_name_beginner (c)) { - char *name = input_line_pointer; - char ec = get_symbol_end (); + char *name; + char ec = get_symbol_name (& name); ret = md_operator (name, 2, &ec); switch (ret) @@ -2328,19 +2322,22 @@ resolve_expression (expressionS *expressionP) expr.c is just a branch office read.c anyway, and putting it here lessens the crowd at read.c. - Assume input_line_pointer is at start of symbol name. + Assume input_line_pointer is at start of symbol name, or the + start of a double quote enclosed symbol name. Advance input_line_pointer past symbol name. - Turn that character into a '\0', returning its former value. + Turn that character into a '\0', returning its former value, + which may be the closing double quote. This allows a string compare (RMS wants symbol names to be strings) - of the symbol name. + of the symbol name. There will always be a char following symbol name, because all good lines end in end-of-line. */ char -get_symbol_end (void) +get_symbol_name (char ** ilp_return) { char c; + * ilp_return = input_line_pointer; /* We accept \001 in a name in case this is being called with a constructed string. */ if (is_name_beginner (c = *input_line_pointer++) || c == '\001') @@ -2351,8 +2348,36 @@ get_symbol_end (void) if (is_name_ender (c)) c = *input_line_pointer++; } + else if (c == '"') + { + bfd_boolean backslash_seen; + + * ilp_return = input_line_pointer; + do + { + backslash_seen = c == '\\'; + c = * input_line_pointer ++; + } + while (c != 0 && (c != '"' || backslash_seen)); + + if (c == 0) + as_warn (_("missing closing '\"'")); + } *--input_line_pointer = 0; - return (c); + return c; +} + +/* Replace the NUL character pointed to by input_line_pointer + with C. If C is \" then advance past it. Return the character + now pointed to by input_line_pointer. */ + +char +restore_line_pointer (char c) +{ + * input_line_pointer = c; + if (c == '"') + c = * ++ input_line_pointer; + return c; } unsigned int