CVSROOT: /sources/m4 Module name: m4 Changes by: Eric Blake <ericb> 07/01/03 14:44:11
Index: modules/evalparse.c =================================================================== RCS file: /sources/m4/m4/modules/evalparse.c,v retrieving revision 1.14 retrieving revision 1.15 diff -u -b -r1.14 -r1.15 --- modules/evalparse.c 9 Aug 2006 21:33:24 -0000 1.14 +++ modules/evalparse.c 3 Jan 2007 14:44:11 -0000 1.15 @@ -1,5 +1,5 @@ /* GNU m4 -- A simple macro processor - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2001, 2006 + Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2001, 2006, 2007 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -40,7 +40,7 @@ typedef enum eval_token { - ERROR, + ERROR, BADOP, PLUS, MINUS, EXPONENT, TIMES, DIVIDE, MODULO, RATIO, @@ -62,6 +62,7 @@ SYNTAX_ERROR, UNKNOWN_INPUT, EXCESS_INPUT, + INVALID_OPERATOR, DIVIDE_ZERO, MODULO_ZERO } @@ -72,8 +73,7 @@ static eval_error or_term (m4 *, eval_token, number *); static eval_error xor_term (m4 *, eval_token, number *); static eval_error and_term (m4 *, eval_token, number *); -static eval_error not_term (m4 *, eval_token, number *); -static eval_error logical_not_term (m4 *, eval_token, number *); +static eval_error equality_term (m4 *, eval_token, number *); static eval_error cmp_term (m4 *, eval_token, number *); static eval_error shift_term (m4 *, eval_token, number *); static eval_error add_term (m4 *, eval_token, number *); @@ -107,7 +107,9 @@ eval_text = last_text; } -/* VAL is numerical value, if any. */ +/* VAL is numerical value, if any. Recognize C assignment operators, + even though we cannot support them, to issue better error + messages. */ static eval_token eval_lex (number *val) @@ -159,7 +161,7 @@ else base = 10; - numb_set_si(val,0); + numb_set_si (val, 0); for (; *eval_text; eval_text++) { if (isdigit (*eval_text)) @@ -176,17 +178,17 @@ { /* (*val) = (*val) * base; */ number xbase; - numb_init(xbase); - numb_set_si(&xbase,base); - numb_times(*val,xbase); - numb_fini(xbase); + numb_init (xbase); + numb_set_si (&xbase, base); + numb_times (*val, xbase); + numb_fini (xbase); } { /* (*val) = (*val) + digit; */ number xdigit; - numb_init(xdigit); - numb_set_si(&xdigit,digit); - numb_plus(*val,xdigit); - numb_fini(xdigit); + numb_init (xdigit); + numb_set_si (&xdigit, digit); + numb_plus (*val, xdigit); + numb_fini (xdigit); } } return NUMBER; @@ -195,8 +197,12 @@ switch (*eval_text++) { case '+': + if (*eval_text == '+' || *eval_text == '=') + return BADOP; return PLUS; case '-': + if (*eval_text == '-' || *eval_text == '=') + return BADOP; return MINUS; case '*': if (*eval_text == '*') @@ -204,25 +210,32 @@ eval_text++; return EXPONENT; } - else + else if (*eval_text == '=') + return BADOP; return TIMES; case '/': + if (*eval_text == '=') + return BADOP; return DIVIDE; case '%': + if (*eval_text == '=') + return BADOP; return MODULO; case ':': - return RATIO; + return RATIO; /* FIXME - this clashes with supporting ?:. */ case '=': if (*eval_text == '=') + { eval_text++; return EQ; + } + return BADOP; case '!': if (*eval_text == '=') { eval_text++; return NOTEQ; } - else return LNOT; case '>': if (*eval_text == '=') @@ -232,7 +245,8 @@ } else if (*eval_text == '>') { - eval_text++; + if (*eval_text++ == '=') + return BADOP; return RSHIFT; } else @@ -245,12 +259,15 @@ } else if (*eval_text == '<') { - eval_text++; + if (*eval_text++ == '=') + return BADOP; return LSHIFT; } else return LS; case '^': + if (*eval_text == '=') + return BADOP; return XOR; case '~': return NOT; @@ -260,7 +277,8 @@ eval_text++; return LAND; } - else + else if (*eval_text == '=') + return BADOP; return AND; case '|': if (*eval_text == '|') @@ -268,7 +286,8 @@ eval_text++; return LOR; } - else + else if (*eval_text == '=') + return BADOP; return OR; case '(': return LEFTP; @@ -289,19 +308,24 @@ if ((er = logical_and_term (context, et, v1)) != NO_ERROR) return er; - numb_init(v2); + numb_init (v2); while ((et = eval_lex (&v2)) == LOR) { et = eval_lex (&v2); if (et == ERROR) return UNKNOWN_INPUT; - if ((er = logical_and_term (context, et, &v2)) != NO_ERROR) + /* Implement short-circuiting of valid syntax. */ + er = logical_and_term (context, et, &v2); + if (er == NO_ERROR) + numb_lior (*v1, v2); + else if (! numb_zerop (*v1) + && (er == DIVIDE_ZERO || er == MODULO_ZERO)) + numb_set (*v1, numb_ONE); + else return er; - - numb_lior(*v1,v2); } - numb_fini(v2); + numb_fini (v2); if (et == ERROR) return UNKNOWN_INPUT; @@ -318,19 +342,24 @@ if ((er = or_term (context, et, v1)) != NO_ERROR) return er; - numb_init(v2); + numb_init (v2); while ((et = eval_lex (&v2)) == LAND) { et = eval_lex (&v2); if (et == ERROR) return UNKNOWN_INPUT; - if ((er = or_term (context, et, &v2)) != NO_ERROR) + /* Implement short-circuiting of valid syntax. */ + er = or_term (context, et, &v2); + if (er == NO_ERROR) + numb_land (*v1, v2); + else if (numb_zerop (*v1) + && (er == DIVIDE_ZERO || er == MODULO_ZERO)) + numb_set (*v1, numb_ZERO); + else return er; - - numb_land(*v1,v2); } - numb_fini(v2); + numb_fini (v2); if (et == ERROR) return UNKNOWN_INPUT; @@ -347,7 +376,7 @@ if ((er = xor_term (context, et, v1)) != NO_ERROR) return er; - numb_init(v2); + numb_init (v2); while ((et = eval_lex (&v2)) == OR) { et = eval_lex (&v2); @@ -357,9 +386,9 @@ if ((er = xor_term (context, et, &v2)) != NO_ERROR) return er; - numb_ior(context, v1, &v2); + numb_ior (context, v1, &v2); } - numb_fini(v2); + numb_fini (v2); if (et == ERROR) return UNKNOWN_INPUT; @@ -376,7 +405,7 @@ if ((er = and_term (context, et, v1)) != NO_ERROR) return er; - numb_init(v2); + numb_init (v2); while ((et = eval_lex (&v2)) == XOR) { et = eval_lex (&v2); @@ -386,9 +415,9 @@ if ((er = and_term (context, et, &v2)) != NO_ERROR) return er; - numb_eor(context, v1, &v2); + numb_eor (context, v1, &v2); } - numb_fini(v2); + numb_fini (v2); if (et == ERROR) return UNKNOWN_INPUT; @@ -402,22 +431,22 @@ number v2; eval_error er; - if ((er = not_term (context, et, v1)) != NO_ERROR) + if ((er = equality_term (context, et, v1)) != NO_ERROR) return er; - numb_init(v2); + numb_init (v2); while ((et = eval_lex (&v2)) == AND) { et = eval_lex (&v2); if (et == ERROR) return UNKNOWN_INPUT; - if ((er = not_term (context, et, &v2)) != NO_ERROR) + if ((er = equality_term (context, et, &v2)) != NO_ERROR) return er; - numb_and(context, v1, &v2); + numb_and (context, v1, &v2); } - numb_fini(v2); + numb_fini (v2); if (et == ERROR) return UNKNOWN_INPUT; @@ -426,46 +455,35 @@ } static eval_error -not_term (m4 *context, eval_token et, number *v1) +equality_term (m4 *context, eval_token et, number *v1) { + eval_token op; + number v2; eval_error er; - if (et == NOT) - { - et = eval_lex (v1); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = not_term (context, et, v1)) != NO_ERROR) - return er; - numb_not(context, v1); - } - else - if ((er = logical_not_term (context, et, v1)) != NO_ERROR) + if ((er = cmp_term (context, et, v1)) != NO_ERROR) return er; - return NO_ERROR; -} - -static eval_error -logical_not_term (m4 *context, eval_token et, number *v1) -{ - eval_error er; - - if (et == LNOT) + numb_init (v2); + while ((op = eval_lex (&v2)) == EQ || op == NOTEQ) { - et = eval_lex (v1); + et = eval_lex (&v2); if (et == ERROR) return UNKNOWN_INPUT; - if ((er = logical_not_term (context, et, v1)) != NO_ERROR) + if ((er = cmp_term (context, et, &v2)) != NO_ERROR) return er; - numb_lnot(*v1); - } + + if (op == EQ) + numb_eq (*v1, v2); else - if ((er = cmp_term (context, et, v1)) != NO_ERROR) - return er; + numb_ne (*v1, v2); + } + numb_fini (v2); + if (op == ERROR) + return UNKNOWN_INPUT; + eval_undo (); return NO_ERROR; } @@ -479,9 +497,8 @@ if ((er = shift_term (context, et, v1)) != NO_ERROR) return er; - numb_init(v2); - while ((op = eval_lex (&v2)) == EQ || op == NOTEQ - || op == GT || op == GTEQ + numb_init (v2); + while ((op = eval_lex (&v2)) == GT || op == GTEQ || op == LS || op == LSEQ) { @@ -494,28 +511,20 @@ switch (op) { - case EQ: - numb_eq(*v1,v2); - break; - - case NOTEQ: - numb_ne(*v1,v2); - break; - case GT: - numb_gt(*v1,v2); + numb_gt (*v1, v2); break; case GTEQ: - numb_ge(*v1,v2); + numb_ge (*v1, v2); break; case LS: - numb_lt(*v1,v2); + numb_lt (*v1, v2); break; case LSEQ: - numb_le(*v1,v2); + numb_le (*v1, v2); break; default: @@ -523,7 +532,7 @@ abort (); } } - numb_fini(v2); + numb_fini (v2); if (op == ERROR) return UNKNOWN_INPUT; @@ -541,7 +550,7 @@ if ((er = add_term (context, et, v1)) != NO_ERROR) return er; - numb_init(v2); + numb_init (v2); while ((op = eval_lex (&v2)) == LSHIFT || op == RSHIFT) { @@ -555,11 +564,11 @@ switch (op) { case LSHIFT: - numb_lshift(context, v1, &v2); + numb_lshift (context, v1, &v2); break; case RSHIFT: - numb_rshift(context, v1, &v2); + numb_rshift (context, v1, &v2); break; default: @@ -567,7 +576,7 @@ abort (); } } - numb_fini(v2); + numb_fini (v2); if (op == ERROR) return UNKNOWN_INPUT; @@ -585,7 +594,7 @@ if ((er = mult_term (context, et, v1)) != NO_ERROR) return er; - numb_init(v2); + numb_init (v2); while ((op = eval_lex (&v2)) == PLUS || op == MINUS) { et = eval_lex (&v2); @@ -595,13 +604,12 @@ if ((er = mult_term (context, et, &v2)) != NO_ERROR) return er; - if (op == PLUS) { - numb_plus(*v1,v2); - } else { - numb_minus(*v1,v2); - } + if (op == PLUS) + numb_plus (*v1, v2); + else + numb_minus (*v1, v2); } - numb_fini(v2); + numb_fini (v2); if (op == ERROR) return UNKNOWN_INPUT; @@ -619,7 +627,7 @@ if ((er = exp_term (context, et, v1)) != NO_ERROR) return er; - numb_init(v2); + numb_init (v2); while (op = eval_lex (&v2), op == TIMES || op == DIVIDE @@ -636,31 +644,28 @@ switch (op) { case TIMES: - numb_times(*v1,v2); + numb_times (*v1, v2); break; case DIVIDE: - if (numb_zerop(v2)) + if (numb_zerop (v2)) return DIVIDE_ZERO; - else { + else numb_divide(v1, &v2); - } break; case RATIO: - if (numb_zerop(v2)) + if (numb_zerop (v2)) return DIVIDE_ZERO; - else { - numb_ratio(*v1,v2); - } + else + numb_ratio (*v1, v2); break; case MODULO: - if (numb_zerop(v2)) + if (numb_zerop (v2)) return MODULO_ZERO; - else { - numb_modulo(context, v1, &v2); - } + else + numb_modulo (context, v1, &v2); break; default: @@ -668,7 +673,7 @@ abort (); } } - numb_fini(v2); + numb_fini (v2); if (op == ERROR) return UNKNOWN_INPUT; @@ -685,9 +690,9 @@ if ((er = unary_term (context, et, v1)) != NO_ERROR) return er; - memcpy(&result, v1, sizeof(number)); + memcpy (&result, v1, sizeof(number)); - numb_init(v2); + numb_init (v2); while ((et = eval_lex (&v2)) == EXPONENT) { et = eval_lex (&v2); @@ -697,9 +702,9 @@ if ((er = exp_term (context, et, &v2)) != NO_ERROR) return er; - numb_pow(v1, &v2); + numb_pow (v1, &v2); } - numb_fini(v2); + numb_fini (v2); if (et == ERROR) return UNKNOWN_INPUT; @@ -713,17 +718,21 @@ eval_token et2 = et; eval_error er; - if (et == PLUS || et == MINUS) + if (et == PLUS || et == MINUS || et == NOT || et == LNOT) { et2 = eval_lex (v1); if (et2 == ERROR) return UNKNOWN_INPUT; - if ((er = simple_term (context, et2, v1)) != NO_ERROR) + if ((er = unary_term (context, et2, v1)) != NO_ERROR) return er; if (et == MINUS) numb_negate(*v1); + else if (et == NOT) + numb_not (context, v1); + else if (et == LNOT) + numb_lnot (*v1); } else if ((er = simple_term (context, et, v1)) != NO_ERROR) @@ -760,6 +769,9 @@ case NUMBER: break; + case BADOP: + return INVALID_OPERATOR; + default: return SYNTAX_ERROR; } @@ -782,7 +794,7 @@ if (radix <= 1 || radix > 36) { m4_error (context, 0, 0, _("%s: radix out of range: %d"), - M4ARG(0), radix); + M4ARG (0), radix); return; } @@ -791,23 +803,29 @@ if (min <= 0) { - m4_error (context, 0, 0, _("%s: negative width: %d"), M4ARG(0), min); + m4_error (context, 0, 0, _("%s: negative width: %d"), M4ARG (0), min); return; } numb_initialise (); eval_init_lex (M4ARG (1)); - numb_init(val); + numb_init (val); et = eval_lex (&val); err = logical_or_term (context, et, &val); if (err == NO_ERROR && *eval_text != '\0') + { + if (eval_lex (&val) == BADOP) + err = INVALID_OPERATOR; + else err = EXCESS_INPUT; + } switch (err) { case NO_ERROR: + numb_obstack (obs, val, radix, min); break; case MISSING_RIGHT: @@ -829,6 +847,11 @@ M4ARG (1)); break; + case INVALID_OPERATOR: + m4_error (context, 0, 0, _("%s: invalid operator: %s"), M4ARG (0), + M4ARG (1)); + break; + case DIVIDE_ZERO: m4_error (context, 0, 0, _("%s: divide by zero: %s"), M4ARG (0), M4ARG (1)); @@ -844,9 +867,6 @@ abort (); } - if (err == NO_ERROR) - numb_obstack (obs, val, radix, min); - numb_fini (val); }