2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Ozan Yigit at York University.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 static char sccsid[] = "@(#)expr.c 8.1 (Berkeley) 6/6/93";
41 #include <sys/cdefs.h>
45 * expression evaluator: performs a standard recursive
46 * descent parse to evaluate any expression permissible
47 * within the following grammar:
51 * | lor "?" query ":" query
52 * lor : land { "||" land }
53 * land : not { "&&" not }
56 * eqrel : shift { eqrelop shift }
57 * shift : primary { shop primary }
58 * primary : term { addop term }
59 * term : exp { mulop exp }
60 * exp : unary { expop unary }
80 * This expression evaluator is lifted from a public-domain
81 * C Pre-Processor included with the DECUS C Compiler distribution.
82 * It is hacked somewhat to be suitable for m4.
84 * Originally by: Mike Lutz
100 static char *nxtch; /* Parser scan pointer */
102 static int query __P((void));
103 static int lor __P((void));
104 static int land __P((void));
105 static int not __P((void));
106 static int eqrel __P((void));
107 static int shift __P((void));
108 static int primary __P((void));
109 static int term __P((void));
110 static int exp __P((void));
111 static int unary __P((void));
112 static int factor __P((void));
113 static int constant __P((void));
114 static int num __P((void));
115 static int geteqrel __P((void));
116 static int skipws __P((void));
117 static void experr __P((char *));
123 static jmp_buf expjump;
127 * ungetch - Put back the last character examined.
128 * getch - return the next character from expr string.
130 #define ungetch() nxtch--
131 #define getch() *nxtch++
140 if (setjmp(expjump) != 0)
147 printf("m4: ill-formed expression.\n");
152 * query : lor | lor '?' query ':' query
157 register int bool, true_val, false_val;
160 if (skipws() != '?') {
170 return bool ? true_val : false_val;
174 * lor : land { '||' land }
179 register int c, vl, vr;
182 while ((c = skipws()) == '|') {
194 * land : not { '&&' not }
199 register int c, vl, vr;
202 while ((c = skipws()) == '&') {
214 * not : eqrel | '!' not
221 if ((c = skipws()) == '!' && getch() != '=') {
234 * eqrel : shift { eqrelop shift }
239 register int vl, vr, eqrel;
242 while ((eqrel = geteqrel()) != -1) {
272 * shift : primary { shop primary }
277 register int vl, vr, c;
280 while (((c = skipws()) == '<' || c == '>') && getch() == c) {
289 if (c == '<' || c == '>')
296 * primary : term { addop term }
301 register int c, vl, vr;
304 while ((c = skipws()) == '+' || c == '-') {
318 * <term> := <exp> { <mulop> <exp> }
323 register int c, vl, vr;
326 while ((c = skipws()) == '*' || c == '/' || c == '%') {
346 * <term> := <unary> { <expop> <unary> }
351 register c, vl, vr, n;
354 switch (c = skipws()) {
357 if (getch() != '*') {
375 * unary : factor | unop unary
382 if ((c = skipws()) == '+' || c == '-' || c == '~') {
400 * factor : constant | '(' query ')'
407 if (skipws() == '(') {
410 experr("bad factor");
419 * constant: num | 'char'
420 * Note: constant() handles multi-byte constants
430 if (skipws() != '\'') {
434 for (i = 0; i < sizeof(int); i++) {
435 if ((c = getch()) == '\'') {
440 switch (c = getch()) {
471 if (i == 0 || getch() != '\'')
472 experr("illegal character constant");
473 for (value = 0; --i >= 0;) {
481 * num : digit | num digit
486 register int rval, c, base;
489 base = ((c = skipws()) == '0') ? OCTAL : DECIMAL;
492 while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) {
501 experr("bad constant");
508 * eqrel : '=' | '==' | '!=' | '<' | '>' | '<=' | '>='
552 * Skip over any white space and return terminating char.
559 while ((c = getch()) <= ' ' && c > EOS)
565 * resets environment to eval(), prints an error
566 * and forces eval to return FALSE.
572 printf("m4: %s in expr.\n", msg);
573 longjmp(expjump, -1);