diff options
| author | glass <glass@NetBSD.org> | 1994-06-19 03:58:22 +0000 |
|---|---|---|
| committer | glass <glass@NetBSD.org> | 1994-06-19 03:58:22 +0000 |
| commit | a7c89f0ff9463df9e8104f76f9c538fe1bfb3cbe (patch) | |
| tree | e6f67a067cb8c538cdf1b076210d28862cb06b55 /usr.bin/m4/expr.c | |
| parent | 72679b6801126ce177d4ddfd7166cdd154fe167b (diff) | |
upgrade to 4.4-lite m4. no local changes of note
Diffstat (limited to 'usr.bin/m4/expr.c')
| -rw-r--r-- | usr.bin/m4/expr.c | 1183 |
1 files changed, 596 insertions, 587 deletions
diff --git a/usr.bin/m4/expr.c b/usr.bin/m4/expr.c index fc48eb31e02..850373336fd 100644 --- a/usr.bin/m4/expr.c +++ b/usr.bin/m4/expr.c @@ -1,617 +1,626 @@ -/* File : expr.c - Authors: Mike Lutz & Bob Harper - Editors: Ozan Yigit & Richard A. O'Keefe - Updated: %G% - Purpose: arithmetic expression evaluator. - - expr() performs a standard recursive descent parse to evaluate any - expression permitted byf the following grammar: - - expr : query EOS - query : lor - | lor "?" query ":" query - lor : land { "||" land } or OR, for Pascal - land : bor { "&&" bor } or AND, for Pascal - 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 "'" or '"' CHAR '"' - num : DIGIT full ANSI C syntax - | DIGIT num - shop : "<<" - | ">>" - eqlrel : "=" - | "==" - | "!=" - rel : "<" or <>, Pascal not-equal - | ">" - | "<=" or =<, for Prolog users. - | ">=" - - This expression evaluator was lifted from a public-domain - C Pre-Processor included with the DECUS C Compiler distribution. - It has been hacked somewhat to be suitable for m4. - - 26-Mar-1993 Changed to work in any of EBCDIC, ASCII, DEC MNCS, - or ISO 8859/n. - - 26-Mar-1993 Changed to use "long int" rather than int, so that - we get the same 32-bit arithmetic on a PC as on a Sun. - It isn't fully portable, of course, but then on a 64- - bit machine we _want_ 64-bit arithmetic... - Shifting rewritten (using LONG_BIT) to give signed - shifts even when (long) >> (long) is unsigned. - - 26-Mar-1993 I finally got sick of the fact that &&, ||, and ?: - don't do conditional evaluation. What is the good - of having eval(0&&(1/0)) crash and dump core? Now - every function has a doit? argument. - - 26-Mar-1993 charcon() didn't actually accept 'abcd', which it - should have. Fixed it. - - 20-Apr-1993 eval(1/0) and eval(1%0) dumped core and crashed. - This is also true of the System V r 3.2 m4, but - it isn't good enough for ours! Changed it so that - x % 0 => x as per Concrete Mathematics - x / 0 => error and return 0 from expr(). -*/ +/* + * 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 TRUE 1 - -#include <stdio.h> +#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; /* Error exit point for expr() */ - -static unsigned char *nxtchr; /* Parser scan pointer */ - -#define deblank0 while ((unsigned)(*nxtchr-1) < ' ') nxtchr++ -#define deblank1 while ((unsigned)(*++nxtchr - 1) < ' ') -#define deblank2 nxtchr++; deblank1 - -#include "ourlims.h" -static char digval[1+UCHAR_MAX]; - -/* This file should work in any C implementation that doesn't have too - many characters to fit in one table. We use a table to convert - (unsigned) characters to numeric codes: - 0 to 9 for '0' to '9' - 10 to 35 for 'a' to 'z' - 10 to 35 for 'A' to 'Z' - 36 for '_' - Instead of asking whether tolower(c) == 'a' we ask whether - digval[c] == DIGIT_A, and so on. This essentially duplicates the - chtype[] table in main.c; we should use just one table. -*/ -#define DIGIT_A 10 -#define DIGIT_B 11 -#define DIGIT_C 12 -#define DIGIT_D 13 -#define DIGIT_E 14 -#define DIGIT_F 15 -#define DIGIT_G 16 -#define DIGIT_H 17 -#define DIGIT_I 18 -#define DIGIT_J 19 -#define DIGIT_K 20 -#define DIGIT_L 21 -#define DIGIT_M 22 -#define DIGIT_N 23 -#define DIGIT_O 24 -#define DIGIT_P 25 -#define DIGIT_Q 26 -#define DIGIT_R 27 -#define DIGIT_S 28 -#define DIGIT_T 29 -#define DIGIT_U 30 -#define DIGIT_V 31 -#define DIGIT_W 32 -#define DIGIT_X 33 -#define DIGIT_Y 34 -#define DIGIT_Z 35 - - -#ifdef __STDC__ -static long int query(int); -#else -static long int query(); -#endif - - -/* experr(msg) - prints an error message, resets environment to expr(), and - forces expr() to return FALSE. -*/ -void experr(msg) - char *msg; - { - (void) fprintf(stderr, "m4: %s\n", msg); - longjmp(expjump, -1); /* Force expr() to return FALSE */ - } - - -/* <numcon> ::= '0x' <hex> | '0X' <hex> | '0' <oct> | <dec> - For ANSI C, an integer may be followed by u, l, ul, or lu, - in any mix of cases. We accept and ignore those letters; - all the numbers are treated as long. -*/ -static long int numcon(doit) - int doit; - { - register long int v; /* current value */ - register int b; /* base (radix) */ - register int c; /* character or digit value */ - - if (!doit) { - do nxtchr++; while (digval[*nxtchr] <= 36); - deblank0; - return 0; +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; } - v = digval[*nxtchr++]; /* We already know it's a digit */ - if (v != 0) { - b = 10; /* decimal number */ - } else - if (digval[*nxtchr] == DIGIT_X) { - nxtchr++; - b = 16; /* hexadecimal number */ - } else { - b = 8; /* octal number */ + 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; } - do { - while (digval[c = *nxtchr++] < b) v = v*b + digval[c]; - } while (c == '_'); - while (digval[c] == DIGIT_L || digval[c] == DIGIT_U) c = *nxtchr++; - nxtchr--; /* unread c */ - if ((unsigned)(c-1) < ' ') { deblank1; } - return v; - } - - -/* <charcon> ::= <qt> { <char> } <qt> - Note: multibyte constants are accepted. - Note: BEL (\a) and ESC (\e) have the same values in EBCDIC and ASCII. -*/ -static long int charcon(doit) - int doit; - { - register int i; - long int value; - register int c; - int q; - int v[sizeof value]; - - q = *nxtchr++; /* the quote character */ - for (i = 0; ; i++) { - c = *nxtchr++; - if (c == q) { /* end of literal, or doubled quote */ - if (*nxtchr != c) break; - nxtchr++; /* doubled quote stands for one quote */ - } - if (i == sizeof value) experr("Unterminated character constant"); - if (c == '\\') { - switch (c = *nxtchr++) { - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - c -= '0'; - if ((unsigned)(*nxtchr - '0') < 8) - c = (c << 3) | (*nxtchr++ - '0'); - if ((unsigned)(*nxtchr - '0') < 8) - c = (c << 3) | (*nxtchr++ - '0'); + + 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; - case 'n': case 'N': c = '\n'; break; - case 'r': case 'R': c = '\r'; break; - case 't': case 'T': c = '\t'; break; - case 'b': case 'B': c = '\b'; break; - case 'f': case 'F': c = '\f'; break; - case 'a': case 'A': c = 007; break; - case 'e': case 'E': c = 033; break; -#if ' ' == 64 - case 'd': case 'D': c = 045; break; /*EBCDIC DEL */ -#else - case 'd': case 'D': c = 127; break; /* ASCII DEL */ -#endif - default : break; } - } - v[i] = c; - } - deblank0; - if (!doit) return 0; - for (value = 0; --i >= 0; ) value = (value << CHAR_BIT) | v[i]; - return value; - } - - -/* <unary> ::= <unop> <unary> | <factor> - <unop> ::= '!' || '~' | '-' - <factor> ::= '(' <query> ')' | <'> <char> <'> | <"> <char> <"> | <num> -*/ -static long int unary(doit) - int doit; - { - long int v; - - switch (nxtchr[0]) { - case 'n': case 'N': - if (digval[nxtchr[1]] != DIGIT_O - || digval[nxtchr[2]] != DIGIT_T) - experr("Bad 'not'"); - nxtchr += 2; - case '!': deblank1; return !unary(doit); - case '~': deblank1; return ~unary(doit); - case '-': deblank1; return -unary(doit); - case '+': deblank1; return unary(doit); - case '(': deblank1; v = query(doit); - if (nxtchr[0] != ')') experr("Bad factor"); - deblank1; return v; - case '\'': - case '\"': return charcon(doit); - case '0': case '1': case '2': - case '3': case '4': case '5': - case '6': case '7': case '8': - case '9': return numcon(doit); - default : experr("Bad constant"); } - return 0; /*NOTREACHED*/ - } + return vl; +} +/* + * relat : shift { rel shift } + */ +static int +relat() +{ + register int vl, vr, rel; -/* <term> ::= <unary> { <mulop> <unary> } - <mulop> ::= '*' | '/' || '%' -*/ -static long int term(doit) - int doit; - { - register long int vl, vr; + vl = shift(); + while ((rel = getrel()) != -1) { - vl = unary(doit); - for (;;) - switch (nxtchr[0]) { - case '*': - deblank1; - vr = unary(doit); - if (doit) vl *= vr; - break; - case 'd': case 'D': - if (digval[nxtchr[1]] != DIGIT_I - || digval[nxtchr[2]] != DIGIT_V) - experr("Bad 'div'"); - nxtchr += 2; - /*FALLTHROUGH*/ - case '/': - deblank1; - vr = unary(doit); - if (doit) { - if (vr == 0) experr("Division by 0"); - vl /= vr; - } - break; - case 'm': case 'M': - if (digval[nxtchr[1]] != DIGIT_O - || digval[nxtchr[2]] != DIGIT_D) - experr("Bad 'mod'"); - nxtchr += 2; - /*FALLTHROUGH*/ - case '%': - deblank1; - vr = unary(doit); - if (doit) { - if (vr != 0) vl %= vr; - } - break; - default: - return vl; - } - /*NOTREACHED*/ - } - -/* <primary> ::= <term> { <addop> <term> } - <addop> ::= '+' | '-' -*/ -static long int primary(doit) - int doit; - { - register long int vl; - - vl = term(doit); - for (;;) - if (nxtchr[0] == '+') { - deblank1; - if (doit) vl += term(doit); else (void)term(doit); - } else - if (nxtchr[0] == '-') { - deblank1; - if (doit) vl -= term(doit); else (void)term(doit); - } else - return vl; - /*NOTREACHED*/ - } - - -/* <shift> ::= <primary> { <shop> <primary> } - <shop> ::= '<<' | '>>' -*/ -static long int shift(doit) - int doit; - { - register long int vl, vr; - - vl = primary(doit); - for (;;) { - if (nxtchr[0] == '<' && nxtchr[1] == '<') { - deblank2; - vr = primary(doit); - } else - if (nxtchr[0] == '>' && nxtchr[1] == '>') { - deblank2; - vr = -primary(doit); - } else { - return vl; - } - /* The following code implements shifts portably */ - /* Shifts are signed shifts, and the shift count */ - /* acts like repeated one-bit shifts, not modulo anything */ - if (doit) { - if (vr >= LONG_BIT) { - vl = 0; - } else - if (vr <= -LONG_BIT) { - vl = -(vl < 0); - } else - if (vr > 0) { - vl <<= vr; - } else - if (vr < 0) { - vl = (vl >> -vr) | (-(vl < 0) << (LONG_BIT + vr)); + 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; } - } } - /*NOTREACHED*/ - } - - -/* <relat> ::= <shift> { <rel> <shift> } - <rel> ::= '<=' | '>=' | '=<' | '=>' | '<' | '>' - Here I rely on the fact that '<<' and '>>' are swallowed by <shift> -*/ -static long int relat(doit) - int doit; - { - register long int vl; - - vl = shift(doit); - for (;;) - switch (nxtchr[0]) { - case '=': - switch (nxtchr[1]) { - case '<': /* =<, take as <= */ - deblank2; - vl = vl <= shift(doit); - break; - case '>': /* =>, take as >= */ - deblank2; - vl = vl >= shift(doit); - break; - default: /* == or =; OOPS */ - return vl; - } - break; - case '<': - if (nxtchr[1] == '=') { /* <= */ - deblank2; - vl = vl <= shift(doit); - } else - if (nxtchr[1] == '>') { /* <> (Pascal) */ - deblank2; - vl = vl != shift(doit); - } else { /* < */ - deblank1; - vl = vl < shift(doit); - } - break; - case '>': - if (nxtchr[1] == '=') { /* >= */ - deblank2; - vl = vl >= shift(doit); - } else { /* > */ - deblank1; - vl = vl > shift(doit); - } - break; - default: - return vl; + 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; } - /*NOTREACHED*/ - } - - -/* <eql> ::= <relat> { <eqrel> <relat> } - <eqlrel> ::= '!=' | '==' | '=' -*/ -static long int eql(doit) - int doit; - { - register long int vl; - - vl = relat(doit); - for (;;) - if (nxtchr[0] == '!' && nxtchr[1] == '=') { - deblank2; - vl = vl != relat(doit); - } else - if (nxtchr[0] == '=' && nxtchr[1] == '=') { - deblank2; - vl = vl == relat(doit); - } else - if (nxtchr[0] == '=') { - deblank1; - vl = vl == relat(doit); - } else - return vl; - /*NOTREACHED*/ - } - - -/* <band> ::= <eql> { '&' <eql> } -*/ -static long int band(doit) - int doit; - { - register long int vl; - - vl = eql(doit); - while (nxtchr[0] == '&' && nxtchr[1] != '&') { - deblank1; - if (doit) vl &= eql(doit); else (void)eql(doit); + + 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; -/* <bxor> ::= <band> { '^' <band> } -*/ -static long int bxor(doit) - int doit; - { - register long int vl; + vl = unary(); + while ((c = skipws()) == '*' || c == '/' || c == '%') { + vr = unary(); - vl = band(doit); - while (nxtchr[0] == '^') { - deblank1; - if (doit) vl ^= band(doit); else (void)band(doit); + 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; + } -/* <bor> ::= <bxor> { '|' <bxor> } -*/ -static long int bor(doit) - int doit; - { - register long int vl; + 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)]; - vl = bxor(doit); - while (nxtchr[0] == '|' && nxtchr[1] != '|') { - deblank1; - if (doit) vl |= bxor(doit); else (void)bxor(doit); + if (skipws() != '\'') { + ungetch(); + return num(); } - return vl; - } - - -/* <land> ::= <bor> { '&&' <bor> } -*/ -static long int land(doit) - int doit; - { - register long int vl; - - vl = bor(doit); - for (;;) { - if (nxtchr[0] == '&') { - if (nxtchr[1] != '&') break; - deblank2; - } else - if (digval[nxtchr[0]] == DIGIT_A) { - if (digval[nxtchr[1]] != DIGIT_N) break; - if (digval[nxtchr[2]] != DIGIT_D) break; - nxtchr += 2; deblank1; - } else { - /* neither && nor and */ - break; - } - vl = bor(doit && vl) != 0; + 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; } - return vl; - } - - -/* <lor> ::= <land> { '||' <land> } -*/ -static long int lor(doit) - int doit; - { - register long int vl; - - vl = land(doit); - for (;;) { - if (nxtchr[0] == '|') { - if (nxtchr[1] != '|') break; - } else - if (digval[nxtchr[0]] == DIGIT_O) { - if (digval[nxtchr[1]] != DIGIT_R) break; - } else { - /* neither || nor or */ - break; - } - deblank2; - vl = land(doit && !vl) != 0; + if (i == 0 || getch() != '\'') + experr("illegal character constant"); + for (value = 0; --i >= 0;) { + value <<= 8; + value += v[i]; } - return vl; - } - - -/* <query> ::= <lor> [ '?' <query> ':' <query> ] -*/ -static long int query(doit) - int doit; - { - register long int bool, true_val, false_val; - - bool = lor(doit); - if (*nxtchr != '?') return bool; - deblank1; - true_val = query(doit && bool); - if (*nxtchr != ':') experr("Bad query"); - deblank1; - false_val = query(doit && !bool); - return bool ? true_val : false_val; - } - - -static void initialise_digval() - { - register unsigned char *s; - register int c; - - for (c = 0; c <= UCHAR_MAX; c++) digval[c] = 99; - for (c = 0, s = (unsigned char *)"0123456789"; - /*while*/ *s; - /*doing*/ digval[*s++] = c++) /* skip */; - for (c = 10, s = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - /*while*/ *s; - /*doing*/ digval[*s++] = c++) /* skip */; - for (c = 10, s = (unsigned char *)"abcdefghijklmnopqrstuvwxyz"; - /*while*/ *s; - /*doing*/ digval[*s++] = c++) /* skip */; - digval['_'] = 36; - } - - -long int expr(expbuf) - char *expbuf; - { - register int rval; - - if (digval['1'] == 0) initialise_digval(); - nxtchr = (unsigned char *)expbuf; - deblank0; - if (setjmp(expjump) != 0) return FALSE; - rval = query(TRUE); - if (*nxtchr) experr("Ill-formed expression"); + 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); +} |
