=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/m4/expr.c,v retrieving revision 1.15 retrieving revision 1.16 diff -c -r1.15 -r1.16 *** src/usr.bin/m4/expr.c 2003/06/03 02:56:10 1.15 --- src/usr.bin/m4/expr.c 2004/05/12 21:17:03 1.16 *************** *** 1,617 **** ! /* $OpenBSD: expr.c,v 1.15 2003/06/03 02:56:10 millert Exp $ */ ! /* $NetBSD: expr.c,v 1.7 1995/09/28 05:37:31 tls Exp $ */ ! /* ! * Copyright (c) 1989, 1993 ! * The Regents of the University of California. All rights reserved. * ! * This code is derived from software contributed to Berkeley by ! * Ozan Yigit at York University. * ! * Redistribution and use in source and binary forms, with or without ! * modification, are permitted provided that the following conditions ! * are met: ! * 1. Redistributions of source code must retain the above copyright ! * notice, this list of conditions and the following disclaimer. ! * 2. Redistributions in binary form must reproduce the above copyright ! * notice, this list of conditions and the following disclaimer in the ! * documentation and/or other materials provided with the distribution. ! * 3. Neither the name of the University nor the names of its contributors ! * may be used to endorse or promote products derived from this software ! * without specific prior written permission. ! * ! * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! * SUCH DAMAGE. */ ! ! #ifndef lint ! #if 0 ! static char sccsid[] = "@(#)expr.c 8.2 (Berkeley) 4/29/95"; ! #else ! static char rcsid[] = "$OpenBSD: expr.c,v 1.15 2003/06/03 02:56:10 millert Exp $"; ! #endif ! #endif /* not lint */ ! ! #include ! #include ! #include ! #include #include #include "mdef.h" #include "extern.h" ! /* ! * expression evaluator: performs a standard recursive ! * descent parse to evaluate any expression permissible ! * within the following grammar: ! * ! * expr : query EOS ! * query : lor ! * | lor "?" query ":" query ! * lor : land { "||" land } ! * land : not { "&&" not } ! * not : eqrel ! * | '!' not ! * eqrel : shift { eqrelop shift } ! * shift : primary { shop primary } ! * primary : term { addop term } ! * term : exp { mulop exp } ! * exp : unary { expop unary } ! * unary : factor ! * | unop unary ! * factor : constant ! * | "(" query ")" ! * constant: num ! * | "'" CHAR "'" ! * num : DIGIT ! * | DIGIT num ! * shop : "<<" ! * | ">>" ! * eqrel : "=" ! * | "==" ! * | "!=" ! * | "<" ! * | ">" ! * | "<=" ! * | ">=" ! * ! * ! * This expression evaluator is lifted from a public-domain ! * C Pre-Processor included with the DECUS C Compiler distribution. ! * It is hacked somewhat to be suitable for m4. ! * ! * Originally by: Mike Lutz ! * Bob Harper ! */ ! #define EQL 0 ! #define NEQ 1 ! #define LSS 2 ! #define LEQ 3 ! #define GTR 4 ! #define GEQ 5 ! #define OCTAL 8 ! #define DECIMAL 10 ! #define HEX 16 - static const char *nxtch; /* Parser scan pointer */ - static const char *where; - - static int query(void); - static int lor(void); - static int land(void); - static int not(void); - static int eqrel(void); - static int shift(void); - static int primary(void); - static int term(void); - static int exp(void); - static int unary(void); - static int factor(void); - static int constant(void); - static int num(void); - static int geteqrel(void); - static int skipws(void); - static void experr(const char *); - - /* - * For longjmp - */ - #include - static jmp_buf expjump; - - /* - * macros: - * ungetch - Put back the last character examined. - * getch - return the next character from expr string. - */ - #define ungetch() nxtch-- - #define getch() *nxtch++ - int ! expr(const char *expbuf) { ! int rval; ! ! nxtch = expbuf; ! where = expbuf; ! if (setjmp(expjump) != 0) ! return FALSE; ! ! rval = query(); ! if (skipws() == EOS) ! return rval; ! ! printf("m4: ill-formed expression.\n"); ! return FALSE; } ! /* ! * query : lor | lor '?' query ':' query ! */ ! static int ! query() { ! int result, true_val, false_val; ! ! result = lor(); ! if (skipws() != '?') { ! ungetch(); ! return result; ! } ! ! true_val = query(); ! if (skipws() != ':') ! experr("bad query"); ! ! false_val = query(); ! return result ? true_val : false_val; ! } ! ! /* ! * lor : land { '||' land } ! */ ! static int ! lor() ! { ! int c, vl, vr; ! ! vl = land(); ! while ((c = skipws()) == '|') { ! if (getch() != '|') ! ungetch(); ! vr = land(); ! vl = vl || vr; ! } ! ! ungetch(); ! return vl; ! } ! ! /* ! * land : not { '&&' not } ! */ ! static int ! land() ! { ! int c, vl, vr; ! ! vl = not(); ! while ((c = skipws()) == '&') { ! if (getch() != '&') ! ungetch(); ! vr = not(); ! vl = vl && vr; ! } ! ! ungetch(); ! return vl; ! } ! ! /* ! * not : eqrel | '!' not ! */ ! static int ! not() ! { ! int val, c; ! ! if ((c = skipws()) == '!' && getch() != '=') { ! ungetch(); ! val = not(); ! return !val; ! } ! ! if (c == '!') ! ungetch(); ! ungetch(); ! return eqrel(); ! } ! ! /* ! * eqrel : shift { eqrelop shift } ! */ ! static int ! eqrel() ! { ! int vl, vr, eqrel; ! ! vl = shift(); ! while ((eqrel = geteqrel()) != -1) { ! vr = shift(); ! ! switch (eqrel) { ! ! case EQL: ! vl = (vl == vr); ! break; ! case NEQ: ! vl = (vl != vr); ! break; ! ! case LEQ: ! vl = (vl <= vr); ! break; ! case LSS: ! vl = (vl < vr); ! break; ! case GTR: ! vl = (vl > vr); ! break; ! case GEQ: ! vl = (vl >= vr); ! break; ! } ! } ! return vl; ! } ! ! /* ! * shift : primary { shop primary } ! */ ! static int ! shift() ! { ! int vl, vr, c; ! ! vl = primary(); ! while (((c = skipws()) == '<' || c == '>') && getch() == c) { ! vr = primary(); ! ! if (c == '<') ! vl <<= vr; ! else ! vl >>= vr; ! } ! ! if (c == '<' || c == '>') ! ungetch(); ! ungetch(); ! return vl; ! } ! ! /* ! * primary : term { addop term } ! */ ! static int ! primary() ! { ! int c, vl, vr; ! ! vl = term(); ! while ((c = skipws()) == '+' || c == '-') { ! vr = term(); ! ! if (c == '+') ! vl += vr; ! else ! vl -= vr; ! } ! ! ungetch(); ! return vl; ! } ! ! /* ! * := { } ! */ ! static int ! term() ! { ! int c, vl, vr; ! ! vl = exp(); ! while ((c = skipws()) == '*' || c == '/' || c == '%') { ! vr = exp(); ! ! switch (c) { ! case '*': ! vl *= vr; ! break; ! case '/': ! if (vr == 0) ! errx(1, "division by zero in eval."); ! else ! vl /= vr; ! break; ! case '%': ! if (vr == 0) ! errx(1, "modulo zero in eval."); ! else ! vl %= vr; ! break; ! } ! } ! ungetch(); ! return vl; ! } ! ! /* ! * := { } ! */ ! static int ! exp() ! { ! int c, vl, vr, n; ! ! vl = unary(); ! switch (c = skipws()) { ! ! case '*': ! if (getch() != '*') { ! ungetch(); ! break; ! } ! ! case '^': ! vr = exp(); ! n = 1; ! while (vr-- > 0) ! n *= vl; ! return n; ! } ! ! ungetch(); ! return vl; ! } ! ! /* ! * unary : factor | unop unary ! */ ! static int ! unary() ! { ! int val, c; ! ! if ((c = skipws()) == '+' || c == '-' || c == '~') { ! val = unary(); ! ! switch (c) { ! case '+': ! return val; ! case '-': ! return -val; ! case '~': ! return ~val; ! } ! } ! ! ungetch(); ! return factor(); ! } ! ! /* ! * factor : constant | '(' query ')' ! */ ! static int ! factor() ! { ! int val; ! ! if (skipws() == '(') { ! val = query(); ! if (skipws() != ')') ! experr("bad factor"); ! return val; ! } ! ! ungetch(); ! return constant(); ! } ! ! /* ! * constant: num | 'char' ! * Note: constant() handles multi-byte constants ! */ ! static int ! constant() ! { ! int i; ! int value; ! int c; ! int v[sizeof(int)]; ! ! if (skipws() != '\'') { ! ungetch(); ! return num(); ! } ! for (i = 0; i < sizeof(int); i++) { ! if ((c = getch()) == '\'') { ! ungetch(); ! break; ! } ! if (c == '\\') { ! switch (c = getch()) { ! case '0': ! case '1': ! case '2': ! case '3': ! case '4': ! case '5': ! case '6': ! case '7': ! ungetch(); ! c = num(); ! break; ! case 'n': ! c = 012; ! break; ! case 'r': ! c = 015; ! break; ! case 't': ! c = 011; ! break; ! case 'b': ! c = 010; ! break; ! case 'f': ! c = 014; ! break; ! } ! } ! v[i] = c; ! } ! if (i == 0 || getch() != '\'') ! experr("illegal character constant"); ! for (value = 0; --i >= 0;) { ! value <<= 8; ! value += v[i]; ! } ! return value; ! } ! ! /* ! * num : digit | num digit ! */ ! static int ! num() ! { ! int rval, c, base; ! int ndig; ! ! rval = 0; ! ndig = 0; ! c = skipws(); ! if (c == '0') { ! c = skipws(); ! if (c == 'x' || c == 'X') { ! base = HEX; ! c = skipws(); ! } else { ! base = OCTAL; ! ndig++; ! } ! } else ! base = DECIMAL; ! for(;;) { ! switch(c) { ! case '8': case '9': ! if (base == OCTAL) ! goto bad_digit; ! /*FALLTHRU*/ ! case '0': case '1': case '2': case '3': ! case '4': case '5': case '6': case '7': ! rval *= base; ! rval += c - '0'; ! break; ! case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': ! c = tolower(c); ! case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': ! if (base == HEX) { ! rval *= base; ! rval += c - 'a' + 10; ! break; ! } ! /*FALLTHRU*/ ! default: ! goto bad_digit; ! } ! c = getch(); ! ndig++; ! } ! bad_digit: ! ungetch(); ! ! if (ndig == 0) ! experr("bad constant"); ! ! return rval; ! } ! ! /* ! * eqrel : '=' | '==' | '!=' | '<' | '>' | '<=' | '>=' ! */ ! static int ! geteqrel() ! { ! int c1, c2; ! ! c1 = skipws(); ! c2 = getch(); ! ! switch (c1) { ! ! case '=': ! if (c2 != '=') ! ungetch(); ! return EQL; ! ! case '!': ! if (c2 == '=') ! return NEQ; ! ungetch(); ! ungetch(); ! return -1; ! ! case '<': ! if (c2 == '=') ! return LEQ; ! ungetch(); ! return LSS; ! ! case '>': ! if (c2 == '=') ! return GEQ; ! ungetch(); ! return GTR; ! ! default: ! ungetch(); ! ungetch(); ! return -1; ! } ! } ! ! /* ! * Skip over any white space and return terminating char. ! */ ! static int ! skipws() ! { ! int c; ! ! while ((c = getch()) <= ' ' && c > EOS) ! ; ! return c; ! } ! ! /* ! * resets environment to eval(), prints an error ! * and forces eval to return FALSE. ! */ ! static void ! experr(const char *msg) ! { ! printf("m4: %s in expr %s.\n", msg, where); ! longjmp(expjump, -1); } --- 1,43 ---- ! /* $OpenBSD: expr.c,v 1.16 2004/05/12 21:17:03 espie Exp $ */ /* ! * Copyright (c) 2004 Marc Espie * ! * Permission to use, copy, modify, and distribute this software for any ! * purpose with or without fee is hereby granted, provided that the above ! * copyright notice and this permission notice appear in all copies. * ! * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ! * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ! * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ! * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ! * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ! * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ! * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ ! #include #include + #include #include "mdef.h" #include "extern.h" ! int32_t end_result; ! const char *copy_toeval; ! extern void yy_scan_string(const char *); ! extern int yyparse(void); int ! yyerror(const char *msg) { ! fprintf(stderr, "m4: %s in expr %s\n", msg, copy_toeval); ! return(0); } ! int ! expr(const char *toeval) { ! copy_toeval = toeval; ! yy_scan_string(toeval); ! yyparse(); ! return end_result; }