|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Ozan Yigit.
7: *
8: * Redistribution and use in source and binary forms are permitted
9: * provided that: (1) source distributions retain this entire copyright
10: * notice and comment, and (2) distributions including binaries display
11: * the following acknowledgement: ``This product includes software
12: * developed by the University of California, Berkeley and its contributors''
13: * in the documentation or other materials provided with the distribution
14: * and in all advertising materials mentioning features or use of this
15: * software. Neither the name of the University nor the names of its
16: * contributors may be used to endorse or promote products derived
17: * from this software without specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: static char sccsid[] = "@(#)expr.c 5.2 (Berkeley) 6/1/90";
25: #endif /* not lint */
26:
27: /*
28: * expression evaluator: performs a standard recursive
29: * descent parse to evaluate any expression permissible
30: * within the following grammar:
31: *
32: * expr : query EOS
33: * query : lor
34: * | lor "?" query ":" query
35: * lor : land { "||" land }
36: * land : bor { "&&" bor }
37: * bor : bxor { "|" bxor }
38: * bxor : band { "^" band }
39: * band : eql { "&" eql }
40: * eql : relat { eqrel relat }
41: * relat : shift { rel shift }
42: * shift : primary { shop primary }
43: * primary : term { addop term }
44: * term : unary { mulop unary }
45: * unary : factor
46: * | unop unary
47: * factor : constant
48: * | "(" query ")"
49: * constant: num
50: * | "'" CHAR "'"
51: * num : DIGIT
52: * | DIGIT num
53: * shop : "<<"
54: * | ">>"
55: * eqlrel : "="
56: * | "=="
57: * | "!="
58: * rel : "<"
59: * | ">"
60: * | "<="
61: * | ">="
62: *
63: *
64: * This expression evaluator is lifted from a public-domain
65: * C Pre-Processor included with the DECUS C Compiler distribution.
66: * It is hacked somewhat to be suitable for m4.
67: *
68: * Originally by: Mike Lutz
69: * Bob Harper
70: */
71:
72: #define TRUE 1
73: #define FALSE 0
74: #define EOS (char) 0
75: #define EQL 0
76: #define NEQ 1
77: #define LSS 2
78: #define LEQ 3
79: #define GTR 4
80: #define GEQ 5
81: #define OCTAL 8
82: #define DECIMAL 10
83:
84: static char *nxtch; /* Parser scan pointer */
85:
86: /*
87: * For longjmp
88: */
89: #include <setjmp.h>
90: static jmp_buf expjump;
91:
92: /*
93: * macros:
94: *
95: * ungetch - Put back the last character examined.
96: * getch - return the next character from expr string.
97: */
98: #define ungetch() nxtch--
99: #define getch() *nxtch++
100:
101: expr(expbuf)
102: char *expbuf;
103: {
104: register int rval;
105:
106: nxtch = expbuf;
107: if (setjmp(expjump) != 0)
108: return (FALSE);
109: rval = query();
110: if (skipws() == EOS)
111: return(rval);
112: experr("Ill-formed expression");
113: }
114:
115: /*
116: * query : lor | lor '?' query ':' query
117: *
118: */
119: query()
120: {
121: register int bool, true_val, false_val;
122:
123: bool = lor();
124: if (skipws() != '?') {
125: ungetch();
126: return(bool);
127: }
128:
129: true_val = query();
130: if (skipws() != ':')
131: experr("Bad query");
132:
133: false_val = query();
134: return(bool ? true_val : false_val);
135: }
136:
137: /*
138: * lor : land { '||' land }
139: *
140: */
141: lor()
142: {
143: register int c, vl, vr;
144:
145: vl = land();
146: while ((c = skipws()) == '|' && getch() == '|') {
147: vr = land();
148: vl = vl || vr;
149: }
150:
151: if (c == '|')
152: ungetch();
153: ungetch();
154: return(vl);
155: }
156:
157: /*
158: * land : bor { '&&' bor }
159: *
160: */
161: land()
162: {
163: register int c, vl, vr;
164:
165: vl = bor();
166: while ((c = skipws()) == '&' && getch() == '&') {
167: vr = bor();
168: vl = vl && vr;
169: }
170:
171: if (c == '&')
172: ungetch();
173: ungetch();
174: return(vl);
175: }
176:
177: /*
178: * bor : bxor { '|' bxor }
179: *
180: */
181: bor()
182: {
183: register int vl, vr, c;
184:
185: vl = bxor();
186: while ((c = skipws()) == '|' && getch() != '|') {
187: ungetch();
188: vr = bxor();
189: vl |= vr;
190: }
191:
192: if (c == '|')
193: ungetch();
194: ungetch();
195: return(vl);
196: }
197:
198: /*
199: * bxor : band { '^' band }
200: *
201: */
202: bxor()
203: {
204: register int vl, vr;
205:
206: vl = band();
207: while (skipws() == '^') {
208: vr = band();
209: vl ^= vr;
210: }
211:
212: ungetch();
213: return(vl);
214: }
215:
216: /*
217: * band : eql { '&' eql }
218: *
219: */
220: band()
221: {
222: register int vl, vr, c;
223:
224: vl = eql();
225: while ((c = skipws()) == '&' && getch() != '&') {
226: ungetch();
227: vr = eql();
228: vl &= vr;
229: }
230:
231: if (c == '&')
232: ungetch();
233: ungetch();
234: return(vl);
235: }
236:
237: /*
238: * eql : relat { eqrel relat }
239: *
240: */
241: eql()
242: {
243: register int vl, vr, rel;
244:
245: vl = relat();
246: while ((rel = geteql()) != -1) {
247: vr = relat();
248:
249: switch (rel) {
250:
251: case EQL:
252: vl = (vl == vr);
253: break;
254: case NEQ:
255: vl = (vl != vr);
256: break;
257: }
258: }
259: return(vl);
260: }
261:
262: /*
263: * relat : shift { rel shift }
264: *
265: */
266: relat()
267: {
268: register int vl, vr, rel;
269:
270: vl = shift();
271: while ((rel = getrel()) != -1) {
272:
273: vr = shift();
274: switch (rel) {
275:
276: case LEQ:
277: vl = (vl <= vr);
278: break;
279: case LSS:
280: vl = (vl < vr);
281: break;
282: case GTR:
283: vl = (vl > vr);
284: break;
285: case GEQ:
286: vl = (vl >= vr);
287: break;
288: }
289: }
290: return(vl);
291: }
292:
293: /*
294: * shift : primary { shop primary }
295: *
296: */
297: shift()
298: {
299: register int vl, vr, c;
300:
301: vl = primary();
302: while (((c = skipws()) == '<' || c == '>') && c == getch()) {
303: vr = primary();
304:
305: if (c == '<')
306: vl <<= vr;
307: else
308: vl >>= vr;
309: }
310:
311: if (c == '<' || c == '>')
312: ungetch();
313: ungetch();
314: return(vl);
315: }
316:
317: /*
318: * primary : term { addop term }
319: *
320: */
321: primary()
322: {
323: register int c, vl, vr;
324:
325: vl = term();
326: while ((c = skipws()) == '+' || c == '-') {
327: vr = term();
328: if (c == '+')
329: vl += vr;
330: else
331: vl -= vr;
332: }
333:
334: ungetch();
335: return(vl);
336: }
337:
338: /*
339: * <term> := <unary> { <mulop> <unary> }
340: *
341: */
342: term()
343: {
344: register int c, vl, vr;
345:
346: vl = unary();
347: while ((c = skipws()) == '*' || c == '/' || c == '%') {
348: vr = unary();
349:
350: switch (c) {
351: case '*':
352: vl *= vr;
353: break;
354: case '/':
355: vl /= vr;
356: break;
357: case '%':
358: vl %= vr;
359: break;
360: }
361: }
362: ungetch();
363: return(vl);
364: }
365:
366: /*
367: * unary : factor | unop unary
368: *
369: */
370: unary()
371: {
372: register int val, c;
373:
374: if ((c = skipws()) == '!' || c == '~' || c == '-') {
375: val = unary();
376:
377: switch (c) {
378: case '!':
379: return(! val);
380: case '~':
381: return(~ val);
382: case '-':
383: return(- val);
384: }
385: }
386:
387: ungetch();
388: return(factor());
389: }
390:
391: /*
392: * factor : constant | '(' query ')'
393: *
394: */
395: factor()
396: {
397: register int val;
398:
399: if (skipws() == '(') {
400: val = query();
401: if (skipws() != ')')
402: experr("Bad factor");
403: return(val);
404: }
405:
406: ungetch();
407: return(constant());
408: }
409:
410: /*
411: * constant: num | 'char'
412: *
413: */
414: constant()
415: {
416: /*
417: * Note: constant() handles multi-byte constants
418: */
419:
420: register int i;
421: register int value;
422: register char c;
423: int v[sizeof (int)];
424:
425: if (skipws() != '\'') {
426: ungetch();
427: return(num());
428: }
429: for (i = 0; i < sizeof(int); i++) {
430: if ((c = getch()) == '\'') {
431: ungetch();
432: break;
433: }
434: if (c == '\\') {
435: switch (c = getch()) {
436: case '0':
437: case '1':
438: case '2':
439: case '3':
440: case '4':
441: case '5':
442: case '6':
443: case '7':
444: ungetch();
445: c = num();
446: break;
447: case 'n':
448: c = 012;
449: break;
450: case 'r':
451: c = 015;
452: break;
453: case 't':
454: c = 011;
455: break;
456: case 'b':
457: c = 010;
458: break;
459: case 'f':
460: c = 014;
461: break;
462: }
463: }
464: v[i] = c;
465: }
466: if (i == 0 || getch() != '\'')
467: experr("Illegal character constant");
468: for (value = 0; --i >= 0;) {
469: value <<= 8;
470: value += v[i];
471: }
472: return(value);
473: }
474:
475: /*
476: * num : digit | num digit
477: *
478: */
479: num()
480: {
481: register int rval, c, base;
482: int ndig;
483:
484: base = ((c = skipws()) == '0') ? OCTAL : DECIMAL;
485: rval = 0;
486: ndig = 0;
487: while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) {
488: rval *= base;
489: rval += (c - '0');
490: c = getch();
491: ndig++;
492: }
493: ungetch();
494: if (ndig)
495: return(rval);
496: experr("Bad constant");
497: }
498:
499: /*
500: * eqlrel : '=' | '==' | '!='
501: *
502: */
503: geteql()
504: {
505: register int c1, c2;
506:
507: c1 = skipws();
508: c2 = getch();
509:
510: switch (c1) {
511:
512: case '=':
513: if (c2 != '=')
514: ungetch();
515: return(EQL);
516:
517: case '!':
518: if (c2 == '=')
519: return(NEQ);
520: ungetch();
521: ungetch();
522: return(-1);
523:
524: default:
525: ungetch();
526: ungetch();
527: return(-1);
528: }
529: }
530:
531: /*
532: * rel : '<' | '>' | '<=' | '>='
533: *
534: */
535: getrel()
536: {
537: register int c1, c2;
538:
539: c1 = skipws();
540: c2 = getch();
541:
542: switch (c1) {
543:
544: case '<':
545: if (c2 == '=')
546: return(LEQ);
547: ungetch();
548: return(LSS);
549:
550: case '>':
551: if (c2 == '=')
552: return(GEQ);
553: ungetch();
554: return(GTR);
555:
556: default:
557: ungetch();
558: ungetch();
559: return(-1);
560: }
561: }
562:
563: /*
564: * Skip over any white space and return terminating char.
565: */
566: skipws()
567: {
568: register char c;
569:
570: while ((c = getch()) <= ' ' && c > EOS)
571: ;
572: return(c);
573: }
574:
575: /*
576: * Error handler - resets environment to eval(), prints an error,
577: * and returns FALSE.
578: */
579: experr(msg)
580: char *msg;
581: {
582: printf("mp: %s\n",msg);
583: longjmp(expjump, -1); /* Force eval() to return FALSE */
584: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.