diff options
author | rgrimes <rgrimes@FreeBSD.org> | 1994-05-27 12:33:43 +0000 |
---|---|---|
committer | rgrimes <rgrimes@FreeBSD.org> | 1994-05-27 12:33:43 +0000 |
commit | 34f25f0a2a416c910d4bbd058e510c46816355fe (patch) | |
tree | 617ba061dcc614170f39c0c4bdbd6efee6f9c3d0 /usr.bin/m4/expr.c | |
parent | 366dfaba192d02d567e9a39508305b9c547c3586 (diff) | |
download | FreeBSD-src-34f25f0a2a416c910d4bbd058e510c46816355fe.zip FreeBSD-src-34f25f0a2a416c910d4bbd058e510c46816355fe.tar.gz |
BSD 4.4 Lite Usr.bin Sources
Diffstat (limited to 'usr.bin/m4/expr.c')
-rw-r--r-- | usr.bin/m4/expr.c | 626 |
1 files changed, 626 insertions, 0 deletions
diff --git a/usr.bin/m4/expr.c b/usr.bin/m4/expr.c new file mode 100644 index 0000000..8503733 --- /dev/null +++ b/usr.bin/m4/expr.c @@ -0,0 +1,626 @@ +/* + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 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. + * + * 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 +static char sccsid[] = "@(#)expr.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <sys/cdefs.h> +#include <stdio.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 : bxor { "|" bxor } + * bxor : band { "^" band } + * band : eql { "&" eql } + * eql : relat { eqrel relat } + * relat : shift { rel shift } + * shift : primary { shop primary } + * primary : term { addop term } + * term : unary { mulop unary } + * unary : factor + * | unop unary + * factor : constant + * | "(" query ")" + * constant: num + * | "'" CHAR "'" + * num : DIGIT + * | DIGIT num + * shop : "<<" + * | ">>" + * eqlrel : "=" + * | "==" + * | "!=" + * rel : "<" + * | ">" + * | "<=" + * | ">=" + * + * + * 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 TRUE 1 +#define FALSE 0 +#define EOS (char) 0 +#define EQL 0 +#define NEQ 1 +#define LSS 2 +#define LEQ 3 +#define GTR 4 +#define GEQ 5 +#define OCTAL 8 +#define DECIMAL 10 + +static char *nxtch; /* Parser scan pointer */ + +static int query __P((void)); +static int lor __P((void)); +static int land __P((void)); +static int bor __P((void)); +static int bxor __P((void)); +static int band __P((void)); +static int eql __P((void)); +static int relat __P((void)); +static int shift __P((void)); +static int primary __P((void)); +static int term __P((void)); +static int unary __P((void)); +static int factor __P((void)); +static int constant __P((void)); +static int num __P((void)); +static int geteql __P((void)); +static int getrel __P((void)); +static int skipws __P((void)); +static void experr __P((char *)); + +/* + * For longjmp + */ +#include <setjmp.h> +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(expbuf) +char *expbuf; +{ + register int rval; + + nxtch = 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() +{ + register int bool, true_val, false_val; + + bool = lor(); + if (skipws() != '?') { + ungetch(); + return bool; + } + + true_val = query(); + if (skipws() != ':') + experr("bad query"); + + false_val = query(); + return bool ? true_val : false_val; +} + +/* + * lor : land { '||' land } + */ +static int +lor() +{ + register int c, vl, vr; + + vl = land(); + while ((c = skipws()) == '|' && getch() == '|') { + vr = land(); + vl = vl || vr; + } + + if (c == '|') + ungetch(); + ungetch(); + return vl; +} + +/* + * land : bor { '&&' bor } + */ +static int +land() +{ + register int c, vl, vr; + + vl = bor(); + while ((c = skipws()) == '&' && getch() == '&') { + vr = bor(); + vl = vl && vr; + } + + if (c == '&') + ungetch(); + ungetch(); + return vl; +} + +/* + * bor : bxor { '|' bxor } + */ +static int +bor() +{ + register int vl, vr, c; + + vl = bxor(); + while ((c = skipws()) == '|' && getch() != '|') { + ungetch(); + vr = bxor(); + vl |= vr; + } + + if (c == '|') + ungetch(); + ungetch(); + return vl; +} + +/* + * bxor : band { '^' band } + */ +static int +bxor() +{ + register int vl, vr; + + vl = band(); + while (skipws() == '^') { + vr = band(); + vl ^= vr; + } + + ungetch(); + return vl; +} + +/* + * band : eql { '&' eql } + */ +static int +band() +{ + register int vl, vr, c; + + vl = eql(); + while ((c = skipws()) == '&' && getch() != '&') { + ungetch(); + vr = eql(); + vl &= vr; + } + + if (c == '&') + ungetch(); + ungetch(); + return vl; +} + +/* + * eql : relat { eqrel relat } + */ +static int +eql() +{ + register int vl, vr, rel; + + vl = relat(); + while ((rel = geteql()) != -1) { + vr = relat(); + + switch (rel) { + + case EQL: + vl = (vl == vr); + break; + case NEQ: + vl = (vl != vr); + break; + } + } + return vl; +} + +/* + * relat : shift { rel shift } + */ +static int +relat() +{ + register int vl, vr, rel; + + vl = shift(); + while ((rel = getrel()) != -1) { + + vr = shift(); + switch (rel) { + + 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() +{ + register int vl, vr, c; + + vl = primary(); + while (((c = skipws()) == '<' || c == '>') && c == getch()) { + vr = primary(); + + if (c == '<') + vl <<= vr; + else + vl >>= vr; + } + + if (c == '<' || c == '>') + ungetch(); + ungetch(); + return vl; +} + +/* + * primary : term { addop term } + */ +static int +primary() +{ + register int c, vl, vr; + + vl = term(); + while ((c = skipws()) == '+' || c == '-') { + vr = term(); + if (c == '+') + vl += vr; + else + vl -= vr; + } + + ungetch(); + return vl; +} + +/* + * <term> := <unary> { <mulop> <unary> } + */ +static int +term() +{ + register int c, vl, vr; + + vl = unary(); + while ((c = skipws()) == '*' || c == '/' || c == '%') { + vr = unary(); + + switch (c) { + case '*': + vl *= vr; + break; + case '/': + vl /= vr; + break; + case '%': + vl %= vr; + break; + } + } + ungetch(); + return vl; +} + +/* + * unary : factor | unop unary + */ +static int +unary() +{ + register 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() +{ + register 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() +{ + register int i; + register int value; + register char 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() +{ + register int rval, c, base; + int ndig; + + base = ((c = skipws()) == '0') ? OCTAL : DECIMAL; + rval = 0; + ndig = 0; + while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) { + rval *= base; + rval += (c - '0'); + c = getch(); + ndig++; + } + ungetch(); + + if (ndig == 0) + experr("bad constant"); + + return rval; + +} + +/* + * eqlrel : '=' | '==' | '!=' + */ +static int +geteql() +{ + register int c1, c2; + + c1 = skipws(); + c2 = getch(); + + switch (c1) { + + case '=': + if (c2 != '=') + ungetch(); + return EQL; + + case '!': + if (c2 == '=') + return NEQ; + ungetch(); + ungetch(); + return -1; + + default: + ungetch(); + ungetch(); + return -1; + } +} + +/* + * rel : '<' | '>' | '<=' | '>=' + */ +static int +getrel() +{ + register int c1, c2; + + c1 = skipws(); + c2 = getch(); + + switch (c1) { + + 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() +{ + register char c; + + while ((c = getch()) <= ' ' && c > EOS) + ; + return c; +} + +/* + * resets environment to eval(), prints an error + * and forces eval to return FALSE. + */ +static void +experr(msg) +char *msg; +{ + printf("m4: %s in expr.\n", msg); + longjmp(expjump, -1); +} |