/* 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, 2002
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
(It also gives smaller files to re-compile.)
Here, "operand"s are of expressions, not instructions. */
-#include <ctype.h>
#include <string.h>
#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));
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;
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;
{
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;
/* 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;
else
{
c = *--suffix;
- if (islower ((unsigned char) c))
- c = toupper (c);
+ c = TOUPPER (c);
if (c == 'B')
radix = 2;
else if (c == 'D')
/* 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. */
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. */
/* 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;
}
if (i < 0)
{
- as_bad (_("Character constant too large"));
+ as_bad (_("character constant too large"));
i = 0;
}
/* 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. */
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
{
input_line_pointer++;
floating_constant (expressionP);
- expressionP->X_add_number =
- - (isupper ((unsigned char) c) ? tolower (c) : c);
+ expressionP->X_add_number = - TOLOWER (c);
}
else
{
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 '$':
#ifdef RELAX_PAREN_GROUPING
if (c != '(')
#endif
- as_bad (_("Missing '%c' assumed"), c == '(' ? ')' : ']');
+ as_bad (_("missing '%c'"), c == '(' ? ')' : ']');
}
else
input_line_pointer++;
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;
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;
}
\f
/* 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.
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))))
+ && SEG_NORMAL (S_GET_SEGMENT (expressionP->X_add_symbol))))
{
addressT diff = (S_GET_VALUE (expressionP->X_add_symbol)
- S_GET_VALUE (expressionP->X_op_symbol));
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)
0 operand, (expression)
1 ||
2 &&
- 3 = <> < <= >= >
+ 3 == <> < <= >= >
4 + -
5 used for * / % in MRI mode
6 & ^ ! |
}
}
- 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
&& 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)
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
{
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. */