2 * expression evaluator: performs a standard recursive
3 * descent parse to evaluate any expression permissible
4 * within the following grammar:
8 * | lor "?" query ":" query
9 * lor : land { "||" land }
10 * land : bor { "&&" bor }
11 * bor : bxor { "|" bxor }
12 * bxor : band { "^" band }
13 * band : eql { "&" eql }
14 * eql : relat { eqrel relat }
15 * relat : shift { rel shift }
16 * shift : primary { shop primary }
17 * primary : term { addop term }
18 * term : unary { mulop unary }
45 * This expression evaluator is lifted from a public-domain
46 * C Pre-Processor included with the DECUS C Compiler distribution.
47 * It is hacked somewhat to be suitable for m4.
49 * Originally by: Mike Lutz
65 static char *nxtch
; /* Parser scan pointer */
71 static jmp_buf expjump
;
76 * ungetch - Put back the last character examined.
77 * getch - return the next character from expr string.
79 #define ungetch() nxtch--
80 #define getch() *nxtch++
88 if (setjmp(expjump
) != 0)
93 experr("Ill-formed expression");
99 * query : lor | lor '?' query ':' query
104 register int bool, true_val
, false_val
;
107 if (skipws() != '?') {
117 return(bool ? true_val
: false_val
);
121 * lor : land { '||' land }
126 register int c
, vl
, vr
;
129 while ((c
= skipws()) == '|' && getch() == '|') {
141 * land : bor { '&&' bor }
146 register int c
, vl
, vr
;
149 while ((c
= skipws()) == '&' && getch() == '&') {
161 * bor : bxor { '|' bxor }
166 register int vl
, vr
, c
;
169 while ((c
= skipws()) == '|' && getch() != '|') {
182 * bxor : band { '^' band }
190 while (skipws() == '^') {
200 * band : eql { '&' eql }
205 register int vl
, vr
, c
;
208 while ((c
= skipws()) == '&' && getch() != '&') {
221 * eql : relat { eqrel relat }
226 register int vl
, vr
, rel
;
229 while ((rel
= geteql()) != -1) {
246 * relat : shift { rel shift }
251 register int vl
, vr
, rel
;
254 while ((rel
= getrel()) != -1) {
277 * shift : primary { shop primary }
282 register int vl
, vr
, c
;
285 while (((c
= skipws()) == '<' || c
== '>') && c
== getch()) {
294 if (c
== '<' || c
== '>')
301 * primary : term { addop term }
306 register int c
, vl
, vr
;
309 while ((c
= skipws()) == '+' || c
== '-') {
322 * <term> := <unary> { <mulop> <unary> }
327 register int c
, vl
, vr
;
330 while ((c
= skipws()) == '*' || c
== '/' || c
== '%') {
350 * unary : factor | unop unary
357 if ((c
= skipws()) == '!' || c
== '~' || c
== '-') {
375 * factor : constant | '(' query ')'
382 if (skipws() == '(') {
385 experr("Bad factor");
394 * constant: num | 'char'
400 * Note: constant() handles multi-byte constants
408 if (skipws() != '\'') {
412 for (i
= 0; i
< sizeof(int); i
++) {
413 if ((c
= getch()) == '\'') {
418 switch (c
= getch()) {
449 if (i
== 0 || getch() != '\'')
450 experr("Illegal character constant");
451 for (value
= 0; --i
>= 0;) {
459 * num : digit | num digit
464 register int rval
, c
, base
;
468 if ((c
= skipws()) == '0') {
470 if (c
== 'x' || c
== 'X') {
482 if (isdigit(c
)) c
-= '0';
483 else if (isupper (c
)) c
-= ('A' - 10);
484 else if (islower (c
)) c
-= ('a' - 10);
486 if (c
< 0 || c
>= base
)
497 experr("Bad constant");
503 * eqlrel : '=' | '==' | '!='
535 * rel : '<' | '>' | '<=' | '>='
567 * Skip over any white space and return terminating char.
573 while ((c
= getch()) <= ' ' && c
> EOS
)
579 * Error handler - resets environment to eval(), prints an error,
585 printf("mp: %s\n",msg
);
586 longjmp(expjump
, -1); /* Force eval() to return FALSE */