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