1,7 → 1,5 |
/* expr.c -operands, expressions- |
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, |
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011, |
2012 Free Software Foundation, Inc. |
Copyright (C) 1987-2015 Free Software Foundation, Inc. |
|
This file is part of GAS, the GNU Assembler. |
|
29,7 → 27,6 |
|
#include "as.h" |
#include "safe-ctype.h" |
#include "obstack.h" |
|
#ifdef HAVE_LIMITS_H |
#include <limits.h> |
127,7 → 124,7 |
int |
expr_symbol_where (symbolS *sym, 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) |
{ |
288,6 → 285,12 |
#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; |
835,18 → 838,10 |
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); |
853,14 → 848,18 |
break; |
} |
/* Otherwise, parse this as a binary number. */ |
} |
/* Fall through. */ |
case 'B': |
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) |
input_line_pointer++; |
goto default_case; |
integer_constant (2, expressionP); |
break; |
|
case '0': |
case '1': |
878,48 → 877,35 |
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; |
if (!is_end_of_line[(unsigned char) input_line_pointer[1]] |
&& strchr (FLT_CHARS, 'f') != NULL) |
{ |
char *cp = input_line_pointer + 1; |
int r = atof_generic (&cp, ".", EXP_CHARS, |
|
atof_generic (&cp, ".", EXP_CHARS, |
&generic_floating_point_number); |
switch (r) |
|
/* 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) |
{ |
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. */ |
; |
} |
|
case 'd': |
case 'D': |
1024,7 → 1010,8 |
/* 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. */ |
1155,8 → 1142,7 |
|
++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) |
1171,7 → 1157,7 |
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 |
1227,13 → 1213,13 |
#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 |
{ |
1242,15 → 1228,15 |
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: |
1259,9 → 1245,10 |
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; |
1279,7 → 1266,7 |
entering it in the symbol table. */ |
if (md_parse_name (name, expressionP, mode, &c)) |
{ |
*input_line_pointer = c; |
restore_line_pointer (c); |
break; |
} |
#endif |
1299,10 → 1286,9 |
|| 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) |
1317,8 → 1303,7 |
expressionP->X_add_number = 0; |
|
*input_line_pointer = c; |
SKIP_WHITESPACE (); |
|
SKIP_WHITESPACE_AFTER_NAME (); |
break; |
} |
#endif |
1346,7 → 1331,8 |
expressionP->X_add_symbol = symbolP; |
expressionP->X_add_number = 0; |
} |
*input_line_pointer = c; |
|
restore_line_pointer (c); |
} |
else |
{ |
1602,8 → 1588,8 |
#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) |
2331,9 → 2317,11 |
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. |
There will always be a char following symbol name, because all good |
2340,10 → 2328,11 |
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') |
2354,10 → 2343,38 |
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 |
get_single_number (void) |
{ |