19b50d902SRodney W. Grimes /* 29b50d902SRodney W. Grimes * Copyright (c) 1989, 1993 39b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * This code is derived from software contributed to Berkeley by 69b50d902SRodney W. Grimes * Ozan Yigit at York University. 79b50d902SRodney W. Grimes * 89b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 99b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 109b50d902SRodney W. Grimes * are met: 119b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 129b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 139b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 149b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 159b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 169b50d902SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 179b50d902SRodney W. Grimes * must display the following acknowledgement: 189b50d902SRodney W. Grimes * This product includes software developed by the University of 199b50d902SRodney W. Grimes * California, Berkeley and its contributors. 209b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 219b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 229b50d902SRodney W. Grimes * without specific prior written permission. 239b50d902SRodney W. Grimes * 249b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 259b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 269b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 279b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 289b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 299b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 309b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 319b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 329b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 339b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 349b50d902SRodney W. Grimes * SUCH DAMAGE. 359b50d902SRodney W. Grimes */ 369b50d902SRodney W. Grimes 379b50d902SRodney W. Grimes #ifndef lint 389b50d902SRodney W. Grimes static char sccsid[] = "@(#)expr.c 8.1 (Berkeley) 6/6/93"; 399b50d902SRodney W. Grimes #endif /* not lint */ 409b50d902SRodney W. Grimes 419b50d902SRodney W. Grimes #include <sys/cdefs.h> 429b50d902SRodney W. Grimes #include <stdio.h> 439b50d902SRodney W. Grimes 449b50d902SRodney W. Grimes /* 459b50d902SRodney W. Grimes * expression evaluator: performs a standard recursive 469b50d902SRodney W. Grimes * descent parse to evaluate any expression permissible 479b50d902SRodney W. Grimes * within the following grammar: 489b50d902SRodney W. Grimes * 499b50d902SRodney W. Grimes * expr : query EOS 509b50d902SRodney W. Grimes * query : lor 519b50d902SRodney W. Grimes * | lor "?" query ":" query 529b50d902SRodney W. Grimes * lor : land { "||" land } 539b50d902SRodney W. Grimes * land : bor { "&&" bor } 549b50d902SRodney W. Grimes * bor : bxor { "|" bxor } 559b50d902SRodney W. Grimes * bxor : band { "^" band } 569b50d902SRodney W. Grimes * band : eql { "&" eql } 579b50d902SRodney W. Grimes * eql : relat { eqrel relat } 589b50d902SRodney W. Grimes * relat : shift { rel shift } 599b50d902SRodney W. Grimes * shift : primary { shop primary } 609b50d902SRodney W. Grimes * primary : term { addop term } 619b50d902SRodney W. Grimes * term : unary { mulop unary } 629b50d902SRodney W. Grimes * unary : factor 639b50d902SRodney W. Grimes * | unop unary 649b50d902SRodney W. Grimes * factor : constant 659b50d902SRodney W. Grimes * | "(" query ")" 669b50d902SRodney W. Grimes * constant: num 679b50d902SRodney W. Grimes * | "'" CHAR "'" 689b50d902SRodney W. Grimes * num : DIGIT 699b50d902SRodney W. Grimes * | DIGIT num 709b50d902SRodney W. Grimes * shop : "<<" 719b50d902SRodney W. Grimes * | ">>" 729b50d902SRodney W. Grimes * eqlrel : "=" 739b50d902SRodney W. Grimes * | "==" 749b50d902SRodney W. Grimes * | "!=" 759b50d902SRodney W. Grimes * rel : "<" 769b50d902SRodney W. Grimes * | ">" 779b50d902SRodney W. Grimes * | "<=" 789b50d902SRodney W. Grimes * | ">=" 799b50d902SRodney W. Grimes * 809b50d902SRodney W. Grimes * 819b50d902SRodney W. Grimes * This expression evaluator is lifted from a public-domain 829b50d902SRodney W. Grimes * C Pre-Processor included with the DECUS C Compiler distribution. 839b50d902SRodney W. Grimes * It is hacked somewhat to be suitable for m4. 849b50d902SRodney W. Grimes * 859b50d902SRodney W. Grimes * Originally by: Mike Lutz 869b50d902SRodney W. Grimes * Bob Harper 879b50d902SRodney W. Grimes */ 889b50d902SRodney W. Grimes 899b50d902SRodney W. Grimes #define TRUE 1 909b50d902SRodney W. Grimes #define FALSE 0 919b50d902SRodney W. Grimes #define EOS (char) 0 929b50d902SRodney W. Grimes #define EQL 0 939b50d902SRodney W. Grimes #define NEQ 1 949b50d902SRodney W. Grimes #define LSS 2 959b50d902SRodney W. Grimes #define LEQ 3 969b50d902SRodney W. Grimes #define GTR 4 979b50d902SRodney W. Grimes #define GEQ 5 989b50d902SRodney W. Grimes #define OCTAL 8 999b50d902SRodney W. Grimes #define DECIMAL 10 1009b50d902SRodney W. Grimes 1019b50d902SRodney W. Grimes static char *nxtch; /* Parser scan pointer */ 1029b50d902SRodney W. Grimes 1039b50d902SRodney W. Grimes static int query __P((void)); 1049b50d902SRodney W. Grimes static int lor __P((void)); 1059b50d902SRodney W. Grimes static int land __P((void)); 1069b50d902SRodney W. Grimes static int bor __P((void)); 1079b50d902SRodney W. Grimes static int bxor __P((void)); 1089b50d902SRodney W. Grimes static int band __P((void)); 1099b50d902SRodney W. Grimes static int eql __P((void)); 1109b50d902SRodney W. Grimes static int relat __P((void)); 1119b50d902SRodney W. Grimes static int shift __P((void)); 1129b50d902SRodney W. Grimes static int primary __P((void)); 1139b50d902SRodney W. Grimes static int term __P((void)); 1149b50d902SRodney W. Grimes static int unary __P((void)); 1159b50d902SRodney W. Grimes static int factor __P((void)); 1169b50d902SRodney W. Grimes static int constant __P((void)); 1179b50d902SRodney W. Grimes static int num __P((void)); 1189b50d902SRodney W. Grimes static int geteql __P((void)); 1199b50d902SRodney W. Grimes static int getrel __P((void)); 1209b50d902SRodney W. Grimes static int skipws __P((void)); 1219b50d902SRodney W. Grimes static void experr __P((char *)); 1229b50d902SRodney W. Grimes 1239b50d902SRodney W. Grimes /* 1249b50d902SRodney W. Grimes * For longjmp 1259b50d902SRodney W. Grimes */ 1269b50d902SRodney W. Grimes #include <setjmp.h> 1279b50d902SRodney W. Grimes static jmp_buf expjump; 1289b50d902SRodney W. Grimes 1299b50d902SRodney W. Grimes /* 1309b50d902SRodney W. Grimes * macros: 1319b50d902SRodney W. Grimes * ungetch - Put back the last character examined. 1329b50d902SRodney W. Grimes * getch - return the next character from expr string. 1339b50d902SRodney W. Grimes */ 1349b50d902SRodney W. Grimes #define ungetch() nxtch-- 1359b50d902SRodney W. Grimes #define getch() *nxtch++ 1369b50d902SRodney W. Grimes 1379b50d902SRodney W. Grimes int 1389b50d902SRodney W. Grimes expr(expbuf) 1399b50d902SRodney W. Grimes char *expbuf; 1409b50d902SRodney W. Grimes { 1419b50d902SRodney W. Grimes register int rval; 1429b50d902SRodney W. Grimes 1439b50d902SRodney W. Grimes nxtch = expbuf; 1449b50d902SRodney W. Grimes if (setjmp(expjump) != 0) 1459b50d902SRodney W. Grimes return FALSE; 1469b50d902SRodney W. Grimes 1479b50d902SRodney W. Grimes rval = query(); 1489b50d902SRodney W. Grimes if (skipws() == EOS) 1499b50d902SRodney W. Grimes return rval; 1509b50d902SRodney W. Grimes 1519b50d902SRodney W. Grimes printf("m4: ill-formed expression.\n"); 1529b50d902SRodney W. Grimes return FALSE; 1539b50d902SRodney W. Grimes } 1549b50d902SRodney W. Grimes 1559b50d902SRodney W. Grimes /* 1569b50d902SRodney W. Grimes * query : lor | lor '?' query ':' query 1579b50d902SRodney W. Grimes */ 1589b50d902SRodney W. Grimes static int 1599b50d902SRodney W. Grimes query() 1609b50d902SRodney W. Grimes { 1619b50d902SRodney W. Grimes register int bool, true_val, false_val; 1629b50d902SRodney W. Grimes 1639b50d902SRodney W. Grimes bool = lor(); 1649b50d902SRodney W. Grimes if (skipws() != '?') { 1659b50d902SRodney W. Grimes ungetch(); 1669b50d902SRodney W. Grimes return bool; 1679b50d902SRodney W. Grimes } 1689b50d902SRodney W. Grimes 1699b50d902SRodney W. Grimes true_val = query(); 1709b50d902SRodney W. Grimes if (skipws() != ':') 1719b50d902SRodney W. Grimes experr("bad query"); 1729b50d902SRodney W. Grimes 1739b50d902SRodney W. Grimes false_val = query(); 1749b50d902SRodney W. Grimes return bool ? true_val : false_val; 1759b50d902SRodney W. Grimes } 1769b50d902SRodney W. Grimes 1779b50d902SRodney W. Grimes /* 1789b50d902SRodney W. Grimes * lor : land { '||' land } 1799b50d902SRodney W. Grimes */ 1809b50d902SRodney W. Grimes static int 1819b50d902SRodney W. Grimes lor() 1829b50d902SRodney W. Grimes { 1839b50d902SRodney W. Grimes register int c, vl, vr; 1849b50d902SRodney W. Grimes 1859b50d902SRodney W. Grimes vl = land(); 1869b50d902SRodney W. Grimes while ((c = skipws()) == '|' && getch() == '|') { 1879b50d902SRodney W. Grimes vr = land(); 1889b50d902SRodney W. Grimes vl = vl || vr; 1899b50d902SRodney W. Grimes } 1909b50d902SRodney W. Grimes 1919b50d902SRodney W. Grimes if (c == '|') 1929b50d902SRodney W. Grimes ungetch(); 1939b50d902SRodney W. Grimes ungetch(); 1949b50d902SRodney W. Grimes return vl; 1959b50d902SRodney W. Grimes } 1969b50d902SRodney W. Grimes 1979b50d902SRodney W. Grimes /* 1989b50d902SRodney W. Grimes * land : bor { '&&' bor } 1999b50d902SRodney W. Grimes */ 2009b50d902SRodney W. Grimes static int 2019b50d902SRodney W. Grimes land() 2029b50d902SRodney W. Grimes { 2039b50d902SRodney W. Grimes register int c, vl, vr; 2049b50d902SRodney W. Grimes 2059b50d902SRodney W. Grimes vl = bor(); 2069b50d902SRodney W. Grimes while ((c = skipws()) == '&' && getch() == '&') { 2079b50d902SRodney W. Grimes vr = bor(); 2089b50d902SRodney W. Grimes vl = vl && vr; 2099b50d902SRodney W. Grimes } 2109b50d902SRodney W. Grimes 2119b50d902SRodney W. Grimes if (c == '&') 2129b50d902SRodney W. Grimes ungetch(); 2139b50d902SRodney W. Grimes ungetch(); 2149b50d902SRodney W. Grimes return vl; 2159b50d902SRodney W. Grimes } 2169b50d902SRodney W. Grimes 2179b50d902SRodney W. Grimes /* 2189b50d902SRodney W. Grimes * bor : bxor { '|' bxor } 2199b50d902SRodney W. Grimes */ 2209b50d902SRodney W. Grimes static int 2219b50d902SRodney W. Grimes bor() 2229b50d902SRodney W. Grimes { 2239b50d902SRodney W. Grimes register int vl, vr, c; 2249b50d902SRodney W. Grimes 2259b50d902SRodney W. Grimes vl = bxor(); 2269b50d902SRodney W. Grimes while ((c = skipws()) == '|' && getch() != '|') { 2279b50d902SRodney W. Grimes ungetch(); 2289b50d902SRodney W. Grimes vr = bxor(); 2299b50d902SRodney W. Grimes vl |= vr; 2309b50d902SRodney W. Grimes } 2319b50d902SRodney W. Grimes 2329b50d902SRodney W. Grimes if (c == '|') 2339b50d902SRodney W. Grimes ungetch(); 2349b50d902SRodney W. Grimes ungetch(); 2359b50d902SRodney W. Grimes return vl; 2369b50d902SRodney W. Grimes } 2379b50d902SRodney W. Grimes 2389b50d902SRodney W. Grimes /* 2399b50d902SRodney W. Grimes * bxor : band { '^' band } 2409b50d902SRodney W. Grimes */ 2419b50d902SRodney W. Grimes static int 2429b50d902SRodney W. Grimes bxor() 2439b50d902SRodney W. Grimes { 2449b50d902SRodney W. Grimes register int vl, vr; 2459b50d902SRodney W. Grimes 2469b50d902SRodney W. Grimes vl = band(); 2479b50d902SRodney W. Grimes while (skipws() == '^') { 2489b50d902SRodney W. Grimes vr = band(); 2499b50d902SRodney W. Grimes vl ^= vr; 2509b50d902SRodney W. Grimes } 2519b50d902SRodney W. Grimes 2529b50d902SRodney W. Grimes ungetch(); 2539b50d902SRodney W. Grimes return vl; 2549b50d902SRodney W. Grimes } 2559b50d902SRodney W. Grimes 2569b50d902SRodney W. Grimes /* 2579b50d902SRodney W. Grimes * band : eql { '&' eql } 2589b50d902SRodney W. Grimes */ 2599b50d902SRodney W. Grimes static int 2609b50d902SRodney W. Grimes band() 2619b50d902SRodney W. Grimes { 2629b50d902SRodney W. Grimes register int vl, vr, c; 2639b50d902SRodney W. Grimes 2649b50d902SRodney W. Grimes vl = eql(); 2659b50d902SRodney W. Grimes while ((c = skipws()) == '&' && getch() != '&') { 2669b50d902SRodney W. Grimes ungetch(); 2679b50d902SRodney W. Grimes vr = eql(); 2689b50d902SRodney W. Grimes vl &= vr; 2699b50d902SRodney W. Grimes } 2709b50d902SRodney W. Grimes 2719b50d902SRodney W. Grimes if (c == '&') 2729b50d902SRodney W. Grimes ungetch(); 2739b50d902SRodney W. Grimes ungetch(); 2749b50d902SRodney W. Grimes return vl; 2759b50d902SRodney W. Grimes } 2769b50d902SRodney W. Grimes 2779b50d902SRodney W. Grimes /* 2789b50d902SRodney W. Grimes * eql : relat { eqrel relat } 2799b50d902SRodney W. Grimes */ 2809b50d902SRodney W. Grimes static int 2819b50d902SRodney W. Grimes eql() 2829b50d902SRodney W. Grimes { 2839b50d902SRodney W. Grimes register int vl, vr, rel; 2849b50d902SRodney W. Grimes 2859b50d902SRodney W. Grimes vl = relat(); 2869b50d902SRodney W. Grimes while ((rel = geteql()) != -1) { 2879b50d902SRodney W. Grimes vr = relat(); 2889b50d902SRodney W. Grimes 2899b50d902SRodney W. Grimes switch (rel) { 2909b50d902SRodney W. Grimes 2919b50d902SRodney W. Grimes case EQL: 2929b50d902SRodney W. Grimes vl = (vl == vr); 2939b50d902SRodney W. Grimes break; 2949b50d902SRodney W. Grimes case NEQ: 2959b50d902SRodney W. Grimes vl = (vl != vr); 2969b50d902SRodney W. Grimes break; 2979b50d902SRodney W. Grimes } 2989b50d902SRodney W. Grimes } 2999b50d902SRodney W. Grimes return vl; 3009b50d902SRodney W. Grimes } 3019b50d902SRodney W. Grimes 3029b50d902SRodney W. Grimes /* 3039b50d902SRodney W. Grimes * relat : shift { rel shift } 3049b50d902SRodney W. Grimes */ 3059b50d902SRodney W. Grimes static int 3069b50d902SRodney W. Grimes relat() 3079b50d902SRodney W. Grimes { 3089b50d902SRodney W. Grimes register int vl, vr, rel; 3099b50d902SRodney W. Grimes 3109b50d902SRodney W. Grimes vl = shift(); 3119b50d902SRodney W. Grimes while ((rel = getrel()) != -1) { 3129b50d902SRodney W. Grimes 3139b50d902SRodney W. Grimes vr = shift(); 3149b50d902SRodney W. Grimes switch (rel) { 3159b50d902SRodney W. Grimes 3169b50d902SRodney W. Grimes case LEQ: 3179b50d902SRodney W. Grimes vl = (vl <= vr); 3189b50d902SRodney W. Grimes break; 3199b50d902SRodney W. Grimes case LSS: 3209b50d902SRodney W. Grimes vl = (vl < vr); 3219b50d902SRodney W. Grimes break; 3229b50d902SRodney W. Grimes case GTR: 3239b50d902SRodney W. Grimes vl = (vl > vr); 3249b50d902SRodney W. Grimes break; 3259b50d902SRodney W. Grimes case GEQ: 3269b50d902SRodney W. Grimes vl = (vl >= vr); 3279b50d902SRodney W. Grimes break; 3289b50d902SRodney W. Grimes } 3299b50d902SRodney W. Grimes } 3309b50d902SRodney W. Grimes return vl; 3319b50d902SRodney W. Grimes } 3329b50d902SRodney W. Grimes 3339b50d902SRodney W. Grimes /* 3349b50d902SRodney W. Grimes * shift : primary { shop primary } 3359b50d902SRodney W. Grimes */ 3369b50d902SRodney W. Grimes static int 3379b50d902SRodney W. Grimes shift() 3389b50d902SRodney W. Grimes { 3399b50d902SRodney W. Grimes register int vl, vr, c; 3409b50d902SRodney W. Grimes 3419b50d902SRodney W. Grimes vl = primary(); 3429b50d902SRodney W. Grimes while (((c = skipws()) == '<' || c == '>') && c == getch()) { 3439b50d902SRodney W. Grimes vr = primary(); 3449b50d902SRodney W. Grimes 3459b50d902SRodney W. Grimes if (c == '<') 3469b50d902SRodney W. Grimes vl <<= vr; 3479b50d902SRodney W. Grimes else 3489b50d902SRodney W. Grimes vl >>= vr; 3499b50d902SRodney W. Grimes } 3509b50d902SRodney W. Grimes 3519b50d902SRodney W. Grimes if (c == '<' || c == '>') 3529b50d902SRodney W. Grimes ungetch(); 3539b50d902SRodney W. Grimes ungetch(); 3549b50d902SRodney W. Grimes return vl; 3559b50d902SRodney W. Grimes } 3569b50d902SRodney W. Grimes 3579b50d902SRodney W. Grimes /* 3589b50d902SRodney W. Grimes * primary : term { addop term } 3599b50d902SRodney W. Grimes */ 3609b50d902SRodney W. Grimes static int 3619b50d902SRodney W. Grimes primary() 3629b50d902SRodney W. Grimes { 3639b50d902SRodney W. Grimes register int c, vl, vr; 3649b50d902SRodney W. Grimes 3659b50d902SRodney W. Grimes vl = term(); 3669b50d902SRodney W. Grimes while ((c = skipws()) == '+' || c == '-') { 3679b50d902SRodney W. Grimes vr = term(); 3689b50d902SRodney W. Grimes if (c == '+') 3699b50d902SRodney W. Grimes vl += vr; 3709b50d902SRodney W. Grimes else 3719b50d902SRodney W. Grimes vl -= vr; 3729b50d902SRodney W. Grimes } 3739b50d902SRodney W. Grimes 3749b50d902SRodney W. Grimes ungetch(); 3759b50d902SRodney W. Grimes return vl; 3769b50d902SRodney W. Grimes } 3779b50d902SRodney W. Grimes 3789b50d902SRodney W. Grimes /* 3799b50d902SRodney W. Grimes * <term> := <unary> { <mulop> <unary> } 3809b50d902SRodney W. Grimes */ 3819b50d902SRodney W. Grimes static int 3829b50d902SRodney W. Grimes term() 3839b50d902SRodney W. Grimes { 3849b50d902SRodney W. Grimes register int c, vl, vr; 3859b50d902SRodney W. Grimes 3869b50d902SRodney W. Grimes vl = unary(); 3879b50d902SRodney W. Grimes while ((c = skipws()) == '*' || c == '/' || c == '%') { 3889b50d902SRodney W. Grimes vr = unary(); 3899b50d902SRodney W. Grimes 3909b50d902SRodney W. Grimes switch (c) { 3919b50d902SRodney W. Grimes case '*': 3929b50d902SRodney W. Grimes vl *= vr; 3939b50d902SRodney W. Grimes break; 3949b50d902SRodney W. Grimes case '/': 3959b50d902SRodney W. Grimes vl /= vr; 3969b50d902SRodney W. Grimes break; 3979b50d902SRodney W. Grimes case '%': 3989b50d902SRodney W. Grimes vl %= vr; 3999b50d902SRodney W. Grimes break; 4009b50d902SRodney W. Grimes } 4019b50d902SRodney W. Grimes } 4029b50d902SRodney W. Grimes ungetch(); 4039b50d902SRodney W. Grimes return vl; 4049b50d902SRodney W. Grimes } 4059b50d902SRodney W. Grimes 4069b50d902SRodney W. Grimes /* 4079b50d902SRodney W. Grimes * unary : factor | unop unary 4089b50d902SRodney W. Grimes */ 4099b50d902SRodney W. Grimes static int 4109b50d902SRodney W. Grimes unary() 4119b50d902SRodney W. Grimes { 4129b50d902SRodney W. Grimes register int val, c; 4139b50d902SRodney W. Grimes 4149b50d902SRodney W. Grimes if ((c = skipws()) == '!' || c == '~' || c == '-') { 4159b50d902SRodney W. Grimes val = unary(); 4169b50d902SRodney W. Grimes 4179b50d902SRodney W. Grimes switch (c) { 4189b50d902SRodney W. Grimes case '!': 4199b50d902SRodney W. Grimes return !val; 4209b50d902SRodney W. Grimes case '~': 4219b50d902SRodney W. Grimes return ~val; 4229b50d902SRodney W. Grimes case '-': 4239b50d902SRodney W. Grimes return -val; 4249b50d902SRodney W. Grimes } 4259b50d902SRodney W. Grimes } 4269b50d902SRodney W. Grimes 4279b50d902SRodney W. Grimes ungetch(); 4289b50d902SRodney W. Grimes return factor(); 4299b50d902SRodney W. Grimes } 4309b50d902SRodney W. Grimes 4319b50d902SRodney W. Grimes /* 4329b50d902SRodney W. Grimes * factor : constant | '(' query ')' 4339b50d902SRodney W. Grimes */ 4349b50d902SRodney W. Grimes static int 4359b50d902SRodney W. Grimes factor() 4369b50d902SRodney W. Grimes { 4379b50d902SRodney W. Grimes register int val; 4389b50d902SRodney W. Grimes 4399b50d902SRodney W. Grimes if (skipws() == '(') { 4409b50d902SRodney W. Grimes val = query(); 4419b50d902SRodney W. Grimes if (skipws() != ')') 4429b50d902SRodney W. Grimes experr("bad factor"); 4439b50d902SRodney W. Grimes return val; 4449b50d902SRodney W. Grimes } 4459b50d902SRodney W. Grimes 4469b50d902SRodney W. Grimes ungetch(); 4479b50d902SRodney W. Grimes return constant(); 4489b50d902SRodney W. Grimes } 4499b50d902SRodney W. Grimes 4509b50d902SRodney W. Grimes /* 4519b50d902SRodney W. Grimes * constant: num | 'char' 4529b50d902SRodney W. Grimes * Note: constant() handles multi-byte constants 4539b50d902SRodney W. Grimes */ 4549b50d902SRodney W. Grimes static int 4559b50d902SRodney W. Grimes constant() 4569b50d902SRodney W. Grimes { 4579b50d902SRodney W. Grimes register int i; 4589b50d902SRodney W. Grimes register int value; 4599b50d902SRodney W. Grimes register char c; 4609b50d902SRodney W. Grimes int v[sizeof(int)]; 4619b50d902SRodney W. Grimes 4629b50d902SRodney W. Grimes if (skipws() != '\'') { 4639b50d902SRodney W. Grimes ungetch(); 4649b50d902SRodney W. Grimes return num(); 4659b50d902SRodney W. Grimes } 4669b50d902SRodney W. Grimes for (i = 0; i < sizeof(int); i++) { 4679b50d902SRodney W. Grimes if ((c = getch()) == '\'') { 4689b50d902SRodney W. Grimes ungetch(); 4699b50d902SRodney W. Grimes break; 4709b50d902SRodney W. Grimes } 4719b50d902SRodney W. Grimes if (c == '\\') { 4729b50d902SRodney W. Grimes switch (c = getch()) { 4739b50d902SRodney W. Grimes case '0': 4749b50d902SRodney W. Grimes case '1': 4759b50d902SRodney W. Grimes case '2': 4769b50d902SRodney W. Grimes case '3': 4779b50d902SRodney W. Grimes case '4': 4789b50d902SRodney W. Grimes case '5': 4799b50d902SRodney W. Grimes case '6': 4809b50d902SRodney W. Grimes case '7': 4819b50d902SRodney W. Grimes ungetch(); 4829b50d902SRodney W. Grimes c = num(); 4839b50d902SRodney W. Grimes break; 4849b50d902SRodney W. Grimes case 'n': 4859b50d902SRodney W. Grimes c = 012; 4869b50d902SRodney W. Grimes break; 4879b50d902SRodney W. Grimes case 'r': 4889b50d902SRodney W. Grimes c = 015; 4899b50d902SRodney W. Grimes break; 4909b50d902SRodney W. Grimes case 't': 4919b50d902SRodney W. Grimes c = 011; 4929b50d902SRodney W. Grimes break; 4939b50d902SRodney W. Grimes case 'b': 4949b50d902SRodney W. Grimes c = 010; 4959b50d902SRodney W. Grimes break; 4969b50d902SRodney W. Grimes case 'f': 4979b50d902SRodney W. Grimes c = 014; 4989b50d902SRodney W. Grimes break; 4999b50d902SRodney W. Grimes } 5009b50d902SRodney W. Grimes } 5019b50d902SRodney W. Grimes v[i] = c; 5029b50d902SRodney W. Grimes } 5039b50d902SRodney W. Grimes if (i == 0 || getch() != '\'') 5049b50d902SRodney W. Grimes experr("illegal character constant"); 5059b50d902SRodney W. Grimes for (value = 0; --i >= 0;) { 5069b50d902SRodney W. Grimes value <<= 8; 5079b50d902SRodney W. Grimes value += v[i]; 5089b50d902SRodney W. Grimes } 5099b50d902SRodney W. Grimes return value; 5109b50d902SRodney W. Grimes } 5119b50d902SRodney W. Grimes 5129b50d902SRodney W. Grimes /* 5139b50d902SRodney W. Grimes * num : digit | num digit 5149b50d902SRodney W. Grimes */ 5159b50d902SRodney W. Grimes static int 5169b50d902SRodney W. Grimes num() 5179b50d902SRodney W. Grimes { 5189b50d902SRodney W. Grimes register int rval, c, base; 5199b50d902SRodney W. Grimes int ndig; 5209b50d902SRodney W. Grimes 5219b50d902SRodney W. Grimes base = ((c = skipws()) == '0') ? OCTAL : DECIMAL; 5229b50d902SRodney W. Grimes rval = 0; 5239b50d902SRodney W. Grimes ndig = 0; 5249b50d902SRodney W. Grimes while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) { 5259b50d902SRodney W. Grimes rval *= base; 5269b50d902SRodney W. Grimes rval += (c - '0'); 5279b50d902SRodney W. Grimes c = getch(); 5289b50d902SRodney W. Grimes ndig++; 5299b50d902SRodney W. Grimes } 5309b50d902SRodney W. Grimes ungetch(); 5319b50d902SRodney W. Grimes 5329b50d902SRodney W. Grimes if (ndig == 0) 5339b50d902SRodney W. Grimes experr("bad constant"); 5349b50d902SRodney W. Grimes 5359b50d902SRodney W. Grimes return rval; 5369b50d902SRodney W. Grimes 5379b50d902SRodney W. Grimes } 5389b50d902SRodney W. Grimes 5399b50d902SRodney W. Grimes /* 5409b50d902SRodney W. Grimes * eqlrel : '=' | '==' | '!=' 5419b50d902SRodney W. Grimes */ 5429b50d902SRodney W. Grimes static int 5439b50d902SRodney W. Grimes geteql() 5449b50d902SRodney W. Grimes { 5459b50d902SRodney W. Grimes register int c1, c2; 5469b50d902SRodney W. Grimes 5479b50d902SRodney W. Grimes c1 = skipws(); 5489b50d902SRodney W. Grimes c2 = getch(); 5499b50d902SRodney W. Grimes 5509b50d902SRodney W. Grimes switch (c1) { 5519b50d902SRodney W. Grimes 5529b50d902SRodney W. Grimes case '=': 5539b50d902SRodney W. Grimes if (c2 != '=') 5549b50d902SRodney W. Grimes ungetch(); 5559b50d902SRodney W. Grimes return EQL; 5569b50d902SRodney W. Grimes 5579b50d902SRodney W. Grimes case '!': 5589b50d902SRodney W. Grimes if (c2 == '=') 5599b50d902SRodney W. Grimes return NEQ; 5609b50d902SRodney W. Grimes ungetch(); 5619b50d902SRodney W. Grimes ungetch(); 5629b50d902SRodney W. Grimes return -1; 5639b50d902SRodney W. Grimes 5649b50d902SRodney W. Grimes default: 5659b50d902SRodney W. Grimes ungetch(); 5669b50d902SRodney W. Grimes ungetch(); 5679b50d902SRodney W. Grimes return -1; 5689b50d902SRodney W. Grimes } 5699b50d902SRodney W. Grimes } 5709b50d902SRodney W. Grimes 5719b50d902SRodney W. Grimes /* 5729b50d902SRodney W. Grimes * rel : '<' | '>' | '<=' | '>=' 5739b50d902SRodney W. Grimes */ 5749b50d902SRodney W. Grimes static int 5759b50d902SRodney W. Grimes getrel() 5769b50d902SRodney W. Grimes { 5779b50d902SRodney W. Grimes register int c1, c2; 5789b50d902SRodney W. Grimes 5799b50d902SRodney W. Grimes c1 = skipws(); 5809b50d902SRodney W. Grimes c2 = getch(); 5819b50d902SRodney W. Grimes 5829b50d902SRodney W. Grimes switch (c1) { 5839b50d902SRodney W. Grimes 5849b50d902SRodney W. Grimes case '<': 5859b50d902SRodney W. Grimes if (c2 == '=') 5869b50d902SRodney W. Grimes return LEQ; 5879b50d902SRodney W. Grimes ungetch(); 5889b50d902SRodney W. Grimes return LSS; 5899b50d902SRodney W. Grimes 5909b50d902SRodney W. Grimes case '>': 5919b50d902SRodney W. Grimes if (c2 == '=') 5929b50d902SRodney W. Grimes return GEQ; 5939b50d902SRodney W. Grimes ungetch(); 5949b50d902SRodney W. Grimes return GTR; 5959b50d902SRodney W. Grimes 5969b50d902SRodney W. Grimes default: 5979b50d902SRodney W. Grimes ungetch(); 5989b50d902SRodney W. Grimes ungetch(); 5999b50d902SRodney W. Grimes return -1; 6009b50d902SRodney W. Grimes } 6019b50d902SRodney W. Grimes } 6029b50d902SRodney W. Grimes 6039b50d902SRodney W. Grimes /* 6049b50d902SRodney W. Grimes * Skip over any white space and return terminating char. 6059b50d902SRodney W. Grimes */ 6069b50d902SRodney W. Grimes static int 6079b50d902SRodney W. Grimes skipws() 6089b50d902SRodney W. Grimes { 6099b50d902SRodney W. Grimes register char c; 6109b50d902SRodney W. Grimes 6119b50d902SRodney W. Grimes while ((c = getch()) <= ' ' && c > EOS) 6129b50d902SRodney W. Grimes ; 6139b50d902SRodney W. Grimes return c; 6149b50d902SRodney W. Grimes } 6159b50d902SRodney W. Grimes 6169b50d902SRodney W. Grimes /* 6179b50d902SRodney W. Grimes * resets environment to eval(), prints an error 6189b50d902SRodney W. Grimes * and forces eval to return FALSE. 6199b50d902SRodney W. Grimes */ 6209b50d902SRodney W. Grimes static void 6219b50d902SRodney W. Grimes experr(msg) 6229b50d902SRodney W. Grimes char *msg; 6239b50d902SRodney W. Grimes { 6249b50d902SRodney W. Grimes printf("m4: %s in expr.\n", msg); 6259b50d902SRodney W. Grimes longjmp(expjump, -1); 6269b50d902SRodney W. Grimes } 627