|
|
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.