This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: [patch] BROKEN expression evaluation
- To: Mikulas Patocka <mikulas at artax dot karlin dot mff dot cuni dot cz>
- Subject: Re: [patch] BROKEN expression evaluation
- From: Alan Modra <alan at linuxcare dot com dot au>
- Date: Tue, 13 Feb 2001 22:09:58 +1100 (EST)
- cc: binutils at sources dot redhat dot com
On Mon, 12 Feb 2001, Mikulas Patocka wrote:
> Expression evaluation in gas is broken:
>
> $ as
> movl $0x10 >> 2 << 3, %eax
>[snip]
> This patch should fix the bug, check it and commit it to CVS. I hope it
> doesn't break anything else.
Thanks. I think your patch is correct, but this code needs cleaning up
rather than patching around problems. (And in this case it's relatively
easy).
gas/ChangeLog
* expr.c (operator): Don't bump input_line_pointer for two char
operators. Instead return operator size via new param num_chars.
(expr): Use above to parse multi-char operators correctly.
Applying to mainline and branch.
Alan Modra
--
Linuxcare. Support for the Revolution.
Index: expr.c
===================================================================
RCS file: /cvs/src/src/gas/expr.c,v
retrieving revision 1.27
diff -u -p -r1.27 expr.c
--- expr.c 2000/11/28 13:33:22 1.27
+++ expr.c 2001/02/13 10:47:48
@@ -41,7 +41,7 @@ static void mri_char_constant PARAMS ((e
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[];
@@ -1552,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;
@@ -1587,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 '>':
@@ -1609,7 +1611,7 @@ operator ()
ret = O_ge;
break;
}
- ++input_line_pointer;
+ *num_chars = 2;
return ret;
case '!':
@@ -1620,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;
}
@@ -1653,6 +1655,7 @@ expr (rankarg, resultP)
expressionS right;
operatorT op_left;
operatorT op_right;
+ int op_chars;
know (rank >= 0);
@@ -1661,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)
@@ -1706,7 +1709,7 @@ expr (rankarg, resultP)
)
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]);