diff options
Diffstat (limited to 'usr.bin/m4/expr.c')
-rw-r--r-- | usr.bin/m4/expr.c | 649 |
1 files changed, 28 insertions, 621 deletions
diff --git a/usr.bin/m4/expr.c b/usr.bin/m4/expr.c index 8f4dd9c..85bd8f1 100644 --- a/usr.bin/m4/expr.c +++ b/usr.bin/m4/expr.c @@ -1,640 +1,47 @@ -/* $OpenBSD: expr.c,v 1.14 2002/04/26 16:15:16 espie Exp $ */ -/* $NetBSD: expr.c,v 1.7 1995/09/28 05:37:31 tls Exp $ */ - +/* $OpenBSD: expr.c,v 1.18 2010/09/07 19:58:09 marco 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. + * Copyright (c) 2004 Marc Espie <espie@cvs.openbsd.org> * - * 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. - * 4. 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. + * 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. * - * 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. + * 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. */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)expr.c 8.2 (Berkeley) 4/29/95"; -#else -#if 0 -static char rcsid[] = "$OpenBSD: expr.c,v 1.14 2002/04/26 16:15:16 espie Exp $"; -#endif -#endif -#endif /* not lint */ - #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include <sys/types.h> -#include <ctype.h> -#include <err.h> -#include <stddef.h> +#include <stdint.h> #include <stdio.h> +#include <stddef.h> #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 : bor { "&&" bor } - * bor : xor { "|" xor } - * xor : band { "^" eqrel } - * band : eqrel { "&" eqrel } - * eqrel : nerel { ("==" | "!=") nerel } - * nerel : shift { ("<" | ">" | "<=" | ">=") shift } - * shift : primary { ("<<" | ">>") primary } - * primary : term { ("+" | "-") term } - * term : exponent { ("*" | "/" | "%") exponent } - * exponent: unary { "**" unary } - * unary : factor - * | ("+" | "-" | "~" | "!") unary - * factor : constant - * | "(" query ")" - * constant: num - * | "'" CHAR "'" - * num : DIGIT - * | DIGIT num - * - * - * 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(int mayeval); -static int lor(int mayeval); -static int land(int mayeval); -static int bor(int mayeval); -static int xor(int mayeval); -static int band(int mayeval); -static int eqrel(int mayeval); -static int nerel(int mayeval); -static int shift(int mayeval); -static int primary(int mayeval); -static int term(int mayeval); -static int exponent(int mayeval); -static int unary(int mayeval); -static int factor(int mayeval); -static int constant(int mayeval); -static int num(int mayeval); -static int skipws(void); -static void experr(const char *); - -/* - * For longjmp - */ -#include <setjmp.h> -static jmp_buf expjump; +int32_t end_result; +const char *copy_toeval; +int yyerror(const char *msg); -/* - * macros: - * ungetch - Put back the last character examined. - * getch - return the next character from expr string. - */ -#define ungetch() nxtch-- -#define getch() *nxtch++ +extern void yy_scan_string(const char *); +extern int yyparse(void); int -expr(const char *expbuf) -{ - int rval; - - nxtch = expbuf; - where = expbuf; - if (setjmp(expjump) != 0) - return FALSE; - - rval = query(1); - if (skipws() == EOS) - return rval; - - printf("m4: ill-formed expression.\n"); - return FALSE; -} - -/* - * query : lor | lor '?' query ':' query - */ -static int -query(int mayeval) -{ - int result, true_val, false_val; - - result = lor(mayeval); - if (skipws() != '?') { - ungetch(); - return result; - } - - true_val = query(result); - if (skipws() != ':') - experr("bad query: missing \":\""); - - false_val = query(!result); - return result ? true_val : false_val; -} - -/* - * lor : land { '||' land } - */ -static int -lor(int mayeval) +yyerror(const char *msg) { - int c, vl, vr; - - vl = land(mayeval); - while ((c = skipws()) == '|') { - if (getch() != '|') { - ungetch(); - break; - } - if (vl != 0) - mayeval = 0; - vr = land(mayeval); - vl = vl || vr; - } - - ungetch(); - return vl; -} - -/* - * land : not { '&&' not } - */ -static int -land(int mayeval) -{ - int c, vl, vr; - - vl = bor(mayeval); - while ((c = skipws()) == '&') { - if (getch() != '&') { - ungetch(); - break; - } - if (vl == 0) - mayeval = 0; - vr = bor(mayeval); - vl = vl && vr; - } - - ungetch(); - return vl; -} - -/* - * bor : xor { "|" xor } - */ -static int -bor(int mayeval) -{ - int vl, vr, c, cr; - - vl = xor(mayeval); - while ((c = skipws()) == '|') { - cr = getch(); - ungetch(); - if (cr == '|') - break; - vr = xor(mayeval); - vl |= vr; - } - ungetch(); - return (vl); -} - -/* - * xor : band { "^" band } - */ -static int -xor(int mayeval) -{ - int vl, vr, c; - - vl = band(mayeval); - while ((c = skipws()) == '^') { - vr = band(mayeval); - vl ^= vr; - } - ungetch(); - return (vl); -} - -/* - * band : eqrel { "&" eqrel } - */ -static int -band(int mayeval) -{ - int c, cr, vl, vr; - - vl = eqrel(mayeval); - while ((c = skipws()) == '&') { - cr = getch(); - ungetch(); - if (cr == '&') - break; - vr = eqrel(mayeval); - vl &= vr; - } - ungetch(); - return vl; + fprintf(stderr, "m4: %s in expr %s\n", msg, copy_toeval); + return(0); } -/* - * eqrel : nerel { ("==" | "!=" ) nerel } - */ -static int -eqrel(int mayeval) -{ - int vl, vr, c, cr; - - vl = nerel(mayeval); - while ((c = skipws()) == '!' || c == '=') { - if ((cr = getch()) != '=') { - ungetch(); - break; - } - vr = nerel(mayeval); - switch (c) { - case '=': - vl = (vl == vr); - break; - case '!': - vl = (vl != vr); - break; - } - } - ungetch(); - return vl; -} - -/* - * nerel : shift { ("<=" | ">=" | "<" | ">") shift } - */ -static int -nerel(int mayeval) -{ - int vl, vr, c, cr; - - vl = shift(mayeval); - while ((c = skipws()) == '<' || c == '>') { - if ((cr = getch()) != '=') { - ungetch(); - cr = '\0'; - } - vr = shift(mayeval); - switch (c) { - case '<': - vl = (cr == '\0') ? (vl < vr) : (vl <= vr); - break; - case '>': - vl = (cr == '\0') ? (vl > vr) : (vl >= vr); - break; - } - } - ungetch(); - return vl; -} - -/* - * shift : primary { ("<<" | ">>") primary } - */ -static int -shift(int mayeval) -{ - int vl, vr, c; - - vl = primary(mayeval); - while (((c = skipws()) == '<' || c == '>') && getch() == c) { - vr = primary(mayeval); - - if (c == '<') - vl <<= vr; - else - vl >>= vr; - } - - if (c == '<' || c == '>') - ungetch(); - ungetch(); - return vl; -} - -/* - * primary : term { ("+" | "-") term } - */ -static int -primary(int mayeval) -{ - int c, vl, vr; - - vl = term(mayeval); - while ((c = skipws()) == '+' || c == '-') { - vr = term(mayeval); - - if (c == '+') - vl += vr; - else - vl -= vr; - } - - ungetch(); - return vl; -} - -/* - * term : exponent { ("*" | "/" | "%") exponent } - */ -static int -term(int mayeval) -{ - int c, vl, vr; - - vl = exponent(mayeval); - while ((c = skipws()) == '*' || c == '/' || c == '%') { - vr = exponent(mayeval); - - switch (c) { - case '*': - vl *= vr; - break; - case '/': - if (!mayeval) - /* short-circuit */; - else if (vr == 0) - errx(1, "division by zero in eval."); - else - vl /= vr; - break; - case '%': - if (!mayeval) - /* short-circuit */; - else if (vr == 0) - errx(1, "modulo zero in eval."); - else - vl %= vr; - break; - } - } - ungetch(); - return vl; -} - -/* - * exponent : unary { "**" exponent } - */ -static int -exponent(int mayeval) -{ - int c, vl, vr, n; - - vl = unary(mayeval); - while ((c = skipws()) == '*') { - if (getch() != '*') { - ungetch(); - break; - } - vr = unary(mayeval); - n = 1; - while (vr-- > 0) - n *= vl; - return n; - } - - ungetch(); - return vl; -} - -/* - * unary : factor | ("+" | "-" | "~" | "!") unary - */ -static int -unary(int mayeval) -{ - int val, c; - - if ((c = skipws()) == '+' || c == '-' || c == '~' || c == '!') { - val = unary(mayeval); - - switch (c) { - case '+': - return val; - case '-': - return -val; - case '~': - return ~val; - case '!': - return !val; - } - } - - ungetch(); - return factor(mayeval); -} - -/* - * factor : constant | '(' query ')' - */ -static int -factor(int mayeval) -{ - int val; - - if (skipws() == '(') { - val = query(mayeval); - if (skipws() != ')') - experr("bad factor: missing \")\""); - return val; - } - - ungetch(); - return constant(mayeval); -} - -/* - * constant: num | 'char' - * Note: constant() handles multi-byte constants - */ -static int -constant(int mayeval) -{ - int i; - int value; - int c; - int v[sizeof(int)]; - - if (skipws() != '\'') { - ungetch(); - return num(mayeval); - } - for (i = 0; i < (ssize_t)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(mayeval); - 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 mayeval __unused) -{ - 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; -} - -/* - * Skip over any white space and return terminating char. - */ -static int -skipws(void) -{ - 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) +int +expr(const char *toeval) { - printf("m4: %s in expr %s.\n", msg, where); - longjmp(expjump, -1); + copy_toeval = toeval; + yy_scan_string(toeval); + yyparse(); + return end_result; } |