aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2010-03-09 12:52:30 +0800
committermaximilian attems <max@stro.at>2010-03-22 00:29:18 +0100
commit20e96dc369ce79c3061f44440f52329d99f26536 (patch)
tree90e76608e3ddc89508adf4752e20333ca6f77edd
parent245d8240fb9a0601ec94c80c453befc0f510a0e3 (diff)
downloadklibc-20e96dc369ce79c3061f44440f52329d99f26536.tar.gz
[klibc] [ARITH] Fix binary operator parsing
Jilles Tjoelker reported that binary operator parsing doesn't respect operator precedence correctly in the case where a lower- precedence operator is followed by a higher-precedence operator, and then by a lower-precedence operator. This patch fixes this by stopping when we encounter a binary oeprator with a precedence lower than one that we have already encountered. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: maximilian attems <max@stro.at>
-rw-r--r--usr/dash/arith_yacc.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/usr/dash/arith_yacc.c b/usr/dash/arith_yacc.c
index f4857fe642a82..74b95f8062720 100644
--- a/usr/dash/arith_yacc.c
+++ b/usr/dash/arith_yacc.c
@@ -74,6 +74,8 @@ static const char prec[ARITH_BINOP_MAX - ARITH_BINOP_MIN] = {
ARITH_PRECEDENCE(ARITH_BOR, 7),
};
+#define ARITH_MAX_PREC 8
+
static void yyerror(const char *s) __attribute__ ((noreturn));
static void yyerror(const char *s)
{
@@ -81,9 +83,14 @@ static void yyerror(const char *s)
/* NOTREACHED */
}
+static inline int arith_prec(int op)
+{
+ return prec[op - ARITH_BINOP_MIN];
+}
+
static inline int higher_prec(int op1, int op2)
{
- return prec[op1 - ARITH_BINOP_MIN] < prec[op2 - ARITH_BINOP_MIN];
+ return arith_prec(op1) < arith_prec(op2);
}
static intmax_t do_binop(int op, intmax_t a, intmax_t b)
@@ -174,7 +181,7 @@ again:
}
}
-static intmax_t binop2(intmax_t a, int op, int noeval)
+static intmax_t binop2(intmax_t a, int op, int prec, int noeval)
{
for (;;) {
union yystype val;
@@ -188,15 +195,18 @@ static intmax_t binop2(intmax_t a, int op, int noeval)
b = primary(token, &val, yylex(), noeval);
op2 = last_token;
- if (op2 < ARITH_BINOP_MIN || op2 >= ARITH_BINOP_MAX)
- return noeval ? b : do_binop(op, a, b);
-
- if (higher_prec(op2, op)) {
- b = binop2(b, op2, noeval);
- return noeval ? b : do_binop(op, a, b);
+ if (op2 >= ARITH_BINOP_MIN && op2 < ARITH_BINOP_MAX &&
+ higher_prec(op2, op)) {
+ b = binop2(b, op2, arith_prec(op), noeval);
+ op2 = last_token;
}
- a = do_binop(op, a, b);
+ a = noeval ? b : do_binop(op, a, b);
+
+ if (op2 < ARITH_BINOP_MIN || op2 >= ARITH_BINOP_MAX ||
+ arith_prec(op2) >= prec)
+ return a;
+
op = op2;
}
}
@@ -209,7 +219,7 @@ static intmax_t binop(int token, union yystype *val, int op, int noeval)
if (op < ARITH_BINOP_MIN || op >= ARITH_BINOP_MAX)
return a;
- return binop2(a, op, noeval);
+ return binop2(a, op, ARITH_MAX_PREC, noeval);
}
static intmax_t and(int token, union yystype *val, int op, int noeval)