summaryrefslogtreecommitdiff
path: root/gas/expr.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2009-04-20 06:26:23 +0000
committerJan Beulich <jbeulich@novell.com>2009-04-20 06:26:23 +0000
commit8abc84de9c16c650b76a8cb3950224bc8f2b3775 (patch)
tree11680dc1cdb9e30bafd6cb90a4c323c64f084c11 /gas/expr.c
parent0001c65e41a5ef24db17a9abdbab0850e3a9d60b (diff)
downloadbinutils-redhat-8abc84de9c16c650b76a8cb3950224bc8f2b3775.tar.gz
gas/
2009-04-20 Jan Beulich <jbeulich@novell.com> * expr.c (operand): Call md_need_index_operator() and md_operator() if defined. Add unary label. (operator): Call md_operator() if defined. (expr): Adjust assertions on range and rank of op_left and op_right. Don't abort on unhandled operators when reducing expressions with both operands being constant. (expr_set_rank): New. * expr.h (expr_set_rank): Declare.
Diffstat (limited to 'gas/expr.c')
-rw-r--r--gas/expr.c111
1 files changed, 104 insertions, 7 deletions
diff --git a/gas/expr.c b/gas/expr.c
index 39f21ef797..a75be2c1ea 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -950,10 +950,15 @@ operand (expressionS *expressionP, enum expr_mode mode)
break;
- case '(':
#ifndef NEED_INDEX_OPERATOR
case '[':
+# ifdef md_need_index_operator
+ if (md_need_index_operator())
+ goto de_fault;
+# endif
+ /* FALLTHROUGH */
#endif
+ case '(':
/* Didn't begin with digit & not a name. */
if (mode != expr_defer)
segment = expression (expressionP);
@@ -1011,6 +1016,9 @@ operand (expressionS *expressionP, enum expr_mode mode)
case '-':
case '+':
{
+#ifdef md_operator
+ unary:
+#endif
operand (expressionP, mode);
if (expressionP->X_op == O_constant)
{
@@ -1207,7 +1215,7 @@ operand (expressionS *expressionP, enum expr_mode mode)
#endif
default:
-#ifdef TC_M68K
+#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. */
@@ -1218,6 +1226,43 @@ operand (expressionS *expressionP, enum expr_mode mode)
name = --input_line_pointer;
c = get_symbol_end ();
+#ifdef md_operator
+ {
+ operatorT operator = md_operator (name, 1, &c);
+
+ switch (operator)
+ {
+ case O_uminus:
+ *input_line_pointer = c;
+ c = '-';
+ goto unary;
+ case O_bit_not:
+ *input_line_pointer = c;
+ c = '~';
+ goto unary;
+ case O_logical_not:
+ *input_line_pointer = c;
+ c = '!';
+ goto unary;
+ case O_illegal:
+ as_bad (_("invalid use of operator \"%s\""), name);
+ break;
+ default:
+ break;
+ }
+ if (operator != O_absent && operator != O_illegal)
+ {
+ *input_line_pointer = c;
+ expr (9, expressionP, mode);
+ expressionP->X_add_symbol = make_expr_symbol (expressionP);
+ expressionP->X_op_symbol = NULL;
+ expressionP->X_add_number = 0;
+ expressionP->X_op = operator;
+ break;
+ }
+ }
+#endif
+
#ifdef md_parse_name
/* This is a hook for the backend to parse certain names
specially in certain contexts. If a name always has a
@@ -1516,6 +1561,13 @@ expr_set_precedence (void)
}
}
+void
+expr_set_rank (operatorT operator, operator_rankT rank)
+{
+ assert (operator >= O_md1 && operator < ARRAY_SIZE (op_rank));
+ op_rank[operator] = rank;
+}
+
/* Initialize the expression parser. */
void
@@ -1547,10 +1599,50 @@ operator (int *num_chars)
if (is_end_of_line[c])
return O_illegal;
+#ifdef md_operator
+ if (is_name_beginner (c))
+ {
+ char *name = input_line_pointer;
+ char c = get_symbol_end ();
+
+ ret = md_operator (name, 2, &c);
+ switch (ret)
+ {
+ case O_absent:
+ *input_line_pointer = c;
+ input_line_pointer = name;
+ break;
+ case O_uminus:
+ case O_bit_not:
+ case O_logical_not:
+ as_bad (_("invalid use of operator \"%s\""), name);
+ ret = O_illegal;
+ /* FALLTHROUGH */
+ default:
+ *input_line_pointer = c;
+ *num_chars = input_line_pointer - name;
+ input_line_pointer = name;
+ return ret;
+ }
+ }
+#endif
+
switch (c)
{
default:
- return op_encoding[c];
+ ret = op_encoding[c];
+#ifdef md_operator
+ if (ret == O_illegal)
+ {
+ char *start = input_line_pointer;
+
+ ret = md_operator (NULL, 2, NULL);
+ if (ret != O_illegal)
+ *num_chars = input_line_pointer - start;
+ input_line_pointer = start;
+ }
+#endif
+ return ret;
case '+':
case '-':
@@ -1689,10 +1781,14 @@ expr (int rankarg, /* Larger # is higher rank. */
op_right = operator (&op_chars);
- know (op_right == O_illegal
+ know (op_right == O_illegal || op_left == O_index
|| op_rank[(int) op_right] <= op_rank[(int) op_left]);
- know ((int) op_left >= (int) O_multiply
- && (int) op_left <= (int) O_index);
+ know ((int) op_left >= (int) O_multiply);
+#ifndef md_operator
+ know ((int) op_left <= (int) O_index);
+#else
+ know ((int) op_left < (int) O_max);
+#endif
/* input_line_pointer->after right-hand quantity. */
/* left-hand quantity in resultP. */
@@ -1796,7 +1892,7 @@ expr (int rankarg, /* Larger # is higher rank. */
}
switch (op_left)
{
- default: abort ();
+ default: goto general;
case O_multiply: resultP->X_add_number *= v; break;
case O_divide: resultP->X_add_number /= v; break;
case O_modulus: resultP->X_add_number %= v; break;
@@ -1871,6 +1967,7 @@ expr (int rankarg, /* Larger # is higher rank. */
}
else
{
+ general:
/* The general case. */
resultP->X_add_symbol = make_expr_symbol (resultP);
resultP->X_op_symbol = make_expr_symbol (&right);