expr.c (92921) | expr.c (95060) |
---|---|
1/* $OpenBSD: expr.c,v 1.12 2002/02/16 21:27:48 millert Exp $ */ 2/* $NetBSD: expr.c,v 1.7 1995/09/28 05:37:31 tls Exp $ */ 3 |
|
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 * Redistribution and use in source and binary forms, with or without --- 18 unchanged lines hidden (view full) --- 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. | 4/* 5 * Copyright (c) 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Ozan Yigit at York University. 10 * 11 * Redistribution and use in source and binary forms, with or without --- 18 unchanged lines hidden (view full) --- 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. |
35 * 36 * $FreeBSD: head/usr.bin/m4/expr.c 92921 2002-03-22 01:33:25Z imp $ | |
37 */ 38 | 38 */ 39 |
39#ifndef lint 40static char sccsid[] = "@(#)expr.c 8.1 (Berkeley) 6/6/93"; 41#endif /* not lint */ 42 | |
43#include <sys/cdefs.h> | 40#include <sys/cdefs.h> |
41__SCCSID("@(#)expr.c 8.2 (Berkeley) 4/29/95"); 42__RCSID_SOURCE("$OpenBSD: expr.c,v 1.12 2002/02/16 21:27:48 millert Exp $"); 43__FBSDID("$FreeBSD: head/usr.bin/m4/expr.c 95060 2002-04-19 17:26:21Z jmallett $"); 44 45#include <sys/types.h> 46#include <ctype.h> 47#include <err.h> 48#include <stddef.h> |
|
44#include <stdio.h> | 49#include <stdio.h> |
50#include "mdef.h" 51#include "extern.h" |
|
45 46/* 47 * expression evaluator: performs a standard recursive 48 * descent parse to evaluate any expression permissible 49 * within the following grammar: 50 * 51 * expr : query EOS 52 * query : lor --- 29 unchanged lines hidden (view full) --- 82 * This expression evaluator is lifted from a public-domain 83 * C Pre-Processor included with the DECUS C Compiler distribution. 84 * It is hacked somewhat to be suitable for m4. 85 * 86 * Originally by: Mike Lutz 87 * Bob Harper 88 */ 89 | 52 53/* 54 * expression evaluator: performs a standard recursive 55 * descent parse to evaluate any expression permissible 56 * within the following grammar: 57 * 58 * expr : query EOS 59 * query : lor --- 29 unchanged lines hidden (view full) --- 89 * This expression evaluator is lifted from a public-domain 90 * C Pre-Processor included with the DECUS C Compiler distribution. 91 * It is hacked somewhat to be suitable for m4. 92 * 93 * Originally by: Mike Lutz 94 * Bob Harper 95 */ 96 |
90#define TRUE 1 91#define FALSE 0 92#define EOS (char) 0 | |
93#define EQL 0 94#define NEQ 1 95#define LSS 2 96#define LEQ 3 97#define GTR 4 98#define GEQ 5 99#define OCTAL 8 100#define DECIMAL 10 | 97#define EQL 0 98#define NEQ 1 99#define LSS 2 100#define LEQ 3 101#define GTR 4 102#define GEQ 5 103#define OCTAL 8 104#define DECIMAL 10 |
105#define HEX 16 |
|
101 | 106 |
102static char *nxtch; /* Parser scan pointer */ | 107static const char *nxtch; /* Parser scan pointer */ 108static const char *where; |
103 104static int query(void); 105static int lor(void); 106static int land(void); 107static int not(void); 108static int eqrel(void); 109static int shift(void); 110static int primary(void); 111static int term(void); 112static int exp(void); 113static int unary(void); 114static int factor(void); 115static int constant(void); 116static int num(void); 117static int geteqrel(void); 118static int skipws(void); | 109 110static int query(void); 111static int lor(void); 112static int land(void); 113static int not(void); 114static int eqrel(void); 115static int shift(void); 116static int primary(void); 117static int term(void); 118static int exp(void); 119static int unary(void); 120static int factor(void); 121static int constant(void); 122static int num(void); 123static int geteqrel(void); 124static int skipws(void); |
119static void experr(char *); | 125static void experr(const char *); |
120 121/* 122 * For longjmp 123 */ 124#include <setjmp.h> 125static jmp_buf expjump; 126 127/* 128 * macros: 129 * ungetch - Put back the last character examined. 130 * getch - return the next character from expr string. 131 */ 132#define ungetch() nxtch-- 133#define getch() *nxtch++ 134 135int 136expr(expbuf) | 126 127/* 128 * For longjmp 129 */ 130#include <setjmp.h> 131static jmp_buf expjump; 132 133/* 134 * macros: 135 * ungetch - Put back the last character examined. 136 * getch - return the next character from expr string. 137 */ 138#define ungetch() nxtch-- 139#define getch() *nxtch++ 140 141int 142expr(expbuf) |
137char *expbuf; | 143 const char *expbuf; |
138{ | 144{ |
139 register int rval; | 145 int rval; |
140 141 nxtch = expbuf; | 146 147 nxtch = expbuf; |
148 where = expbuf; |
|
142 if (setjmp(expjump) != 0) 143 return FALSE; 144 145 rval = query(); 146 if (skipws() == EOS) 147 return rval; 148 149 printf("m4: ill-formed expression.\n"); 150 return FALSE; 151} 152 153/* 154 * query : lor | lor '?' query ':' query 155 */ 156static int 157query() 158{ | 149 if (setjmp(expjump) != 0) 150 return FALSE; 151 152 rval = query(); 153 if (skipws() == EOS) 154 return rval; 155 156 printf("m4: ill-formed expression.\n"); 157 return FALSE; 158} 159 160/* 161 * query : lor | lor '?' query ':' query 162 */ 163static int 164query() 165{ |
159 register int bool, true_val, false_val; | 166 int bool, true_val, false_val; |
160 161 bool = lor(); 162 if (skipws() != '?') { 163 ungetch(); 164 return bool; 165 } 166 167 true_val = query(); --- 5 unchanged lines hidden (view full) --- 173} 174 175/* 176 * lor : land { '||' land } 177 */ 178static int 179lor() 180{ | 167 168 bool = lor(); 169 if (skipws() != '?') { 170 ungetch(); 171 return bool; 172 } 173 174 true_val = query(); --- 5 unchanged lines hidden (view full) --- 180} 181 182/* 183 * lor : land { '||' land } 184 */ 185static int 186lor() 187{ |
181 register int c, vl, vr; | 188 int c, vl, vr; |
182 183 vl = land(); 184 while ((c = skipws()) == '|') { 185 if (getch() != '|') 186 ungetch(); 187 vr = land(); 188 vl = vl || vr; 189 } 190 191 ungetch(); 192 return vl; 193} 194 195/* 196 * land : not { '&&' not } 197 */ 198static int 199land() 200{ | 189 190 vl = land(); 191 while ((c = skipws()) == '|') { 192 if (getch() != '|') 193 ungetch(); 194 vr = land(); 195 vl = vl || vr; 196 } 197 198 ungetch(); 199 return vl; 200} 201 202/* 203 * land : not { '&&' not } 204 */ 205static int 206land() 207{ |
201 register int c, vl, vr; | 208 int c, vl, vr; |
202 203 vl = not(); 204 while ((c = skipws()) == '&') { 205 if (getch() != '&') 206 ungetch(); 207 vr = not(); 208 vl = vl && vr; 209 } 210 211 ungetch(); 212 return vl; 213} 214 215/* 216 * not : eqrel | '!' not 217 */ 218static int 219not() 220{ | 209 210 vl = not(); 211 while ((c = skipws()) == '&') { 212 if (getch() != '&') 213 ungetch(); 214 vr = not(); 215 vl = vl && vr; 216 } 217 218 ungetch(); 219 return vl; 220} 221 222/* 223 * not : eqrel | '!' not 224 */ 225static int 226not() 227{ |
221 register int val, c; | 228 int val, c; |
222 223 if ((c = skipws()) == '!' && getch() != '=') { 224 ungetch(); 225 val = not(); 226 return !val; 227 } 228 229 if (c == '!') 230 ungetch(); 231 ungetch(); 232 return eqrel(); 233} 234 235/* 236 * eqrel : shift { eqrelop shift } 237 */ 238static int 239eqrel() 240{ | 229 230 if ((c = skipws()) == '!' && getch() != '=') { 231 ungetch(); 232 val = not(); 233 return !val; 234 } 235 236 if (c == '!') 237 ungetch(); 238 ungetch(); 239 return eqrel(); 240} 241 242/* 243 * eqrel : shift { eqrelop shift } 244 */ 245static int 246eqrel() 247{ |
241 register int vl, vr, eqrel; | 248 int vl, vr, eqrel; |
242 243 vl = shift(); 244 while ((eqrel = geteqrel()) != -1) { 245 vr = shift(); 246 247 switch (eqrel) { 248 249 case EQL: --- 21 unchanged lines hidden (view full) --- 271} 272 273/* 274 * shift : primary { shop primary } 275 */ 276static int 277shift() 278{ | 249 250 vl = shift(); 251 while ((eqrel = geteqrel()) != -1) { 252 vr = shift(); 253 254 switch (eqrel) { 255 256 case EQL: --- 21 unchanged lines hidden (view full) --- 278} 279 280/* 281 * shift : primary { shop primary } 282 */ 283static int 284shift() 285{ |
279 register int vl, vr, c; | 286 int vl, vr, c; |
280 281 vl = primary(); 282 while (((c = skipws()) == '<' || c == '>') && getch() == c) { 283 vr = primary(); 284 285 if (c == '<') 286 vl <<= vr; 287 else --- 7 unchanged lines hidden (view full) --- 295} 296 297/* 298 * primary : term { addop term } 299 */ 300static int 301primary() 302{ | 287 288 vl = primary(); 289 while (((c = skipws()) == '<' || c == '>') && getch() == c) { 290 vr = primary(); 291 292 if (c == '<') 293 vl <<= vr; 294 else --- 7 unchanged lines hidden (view full) --- 302} 303 304/* 305 * primary : term { addop term } 306 */ 307static int 308primary() 309{ |
303 register int c, vl, vr; | 310 int c, vl, vr; |
304 305 vl = term(); 306 while ((c = skipws()) == '+' || c == '-') { 307 vr = term(); 308 309 if (c == '+') 310 vl += vr; 311 else --- 5 unchanged lines hidden (view full) --- 317} 318 319/* 320 * <term> := <exp> { <mulop> <exp> } 321 */ 322static int 323term() 324{ | 311 312 vl = term(); 313 while ((c = skipws()) == '+' || c == '-') { 314 vr = term(); 315 316 if (c == '+') 317 vl += vr; 318 else --- 5 unchanged lines hidden (view full) --- 324} 325 326/* 327 * <term> := <exp> { <mulop> <exp> } 328 */ 329static int 330term() 331{ |
325 register int c, vl, vr; | 332 int c, vl, vr; |
326 327 vl = exp(); 328 while ((c = skipws()) == '*' || c == '/' || c == '%') { 329 vr = exp(); 330 331 switch (c) { 332 case '*': 333 vl *= vr; 334 break; 335 case '/': | 333 334 vl = exp(); 335 while ((c = skipws()) == '*' || c == '/' || c == '%') { 336 vr = exp(); 337 338 switch (c) { 339 case '*': 340 vl *= vr; 341 break; 342 case '/': |
336 vl /= vr; | 343 if (vr == 0) 344 errx(1, "division by zero in eval."); 345 else 346 vl /= vr; |
337 break; 338 case '%': | 347 break; 348 case '%': |
339 vl %= vr; | 349 if (vr == 0) 350 errx(1, "modulo zero in eval."); 351 else 352 vl %= vr; |
340 break; 341 } 342 } 343 ungetch(); 344 return vl; 345} 346 347/* 348 * <term> := <unary> { <expop> <unary> } 349 */ 350static int 351exp() 352{ | 353 break; 354 } 355 } 356 ungetch(); 357 return vl; 358} 359 360/* 361 * <term> := <unary> { <expop> <unary> } 362 */ 363static int 364exp() 365{ |
353 register c, vl, vr, n; | 366 int c, vl, vr, n; |
354 355 vl = unary(); 356 switch (c = skipws()) { 357 358 case '*': 359 if (getch() != '*') { 360 ungetch(); 361 break; --- 12 unchanged lines hidden (view full) --- 374} 375 376/* 377 * unary : factor | unop unary 378 */ 379static int 380unary() 381{ | 367 368 vl = unary(); 369 switch (c = skipws()) { 370 371 case '*': 372 if (getch() != '*') { 373 ungetch(); 374 break; --- 12 unchanged lines hidden (view full) --- 387} 388 389/* 390 * unary : factor | unop unary 391 */ 392static int 393unary() 394{ |
382 register int val, c; | 395 int val, c; |
383 384 if ((c = skipws()) == '+' || c == '-' || c == '~') { 385 val = unary(); 386 387 switch (c) { 388 case '+': 389 return val; 390 case '-': --- 8 unchanged lines hidden (view full) --- 399} 400 401/* 402 * factor : constant | '(' query ')' 403 */ 404static int 405factor() 406{ | 396 397 if ((c = skipws()) == '+' || c == '-' || c == '~') { 398 val = unary(); 399 400 switch (c) { 401 case '+': 402 return val; 403 case '-': --- 8 unchanged lines hidden (view full) --- 412} 413 414/* 415 * factor : constant | '(' query ')' 416 */ 417static int 418factor() 419{ |
407 register int val; | 420 int val; |
408 409 if (skipws() == '(') { 410 val = query(); 411 if (skipws() != ')') 412 experr("bad factor"); 413 return val; 414 } 415 416 ungetch(); 417 return constant(); 418} 419 420/* 421 * constant: num | 'char' 422 * Note: constant() handles multi-byte constants 423 */ 424static int 425constant() 426{ | 421 422 if (skipws() == '(') { 423 val = query(); 424 if (skipws() != ')') 425 experr("bad factor"); 426 return val; 427 } 428 429 ungetch(); 430 return constant(); 431} 432 433/* 434 * constant: num | 'char' 435 * Note: constant() handles multi-byte constants 436 */ 437static int 438constant() 439{ |
427 register int i; 428 register int value; 429 register char c; | 440 int i; 441 int value; 442 int c; |
430 int v[sizeof(int)]; 431 432 if (skipws() != '\'') { 433 ungetch(); 434 return num(); 435 } 436 for (i = 0; i < sizeof(int); i++) { 437 if ((c = getch()) == '\'') { --- 42 unchanged lines hidden (view full) --- 480} 481 482/* 483 * num : digit | num digit 484 */ 485static int 486num() 487{ | 443 int v[sizeof(int)]; 444 445 if (skipws() != '\'') { 446 ungetch(); 447 return num(); 448 } 449 for (i = 0; i < sizeof(int); i++) { 450 if ((c = getch()) == '\'') { --- 42 unchanged lines hidden (view full) --- 493} 494 495/* 496 * num : digit | num digit 497 */ 498static int 499num() 500{ |
488 register int rval, c, base; | 501 int rval, c, base; |
489 int ndig; 490 | 502 int ndig; 503 |
491 base = ((c = skipws()) == '0') ? OCTAL : DECIMAL; | |
492 rval = 0; 493 ndig = 0; | 504 rval = 0; 505 ndig = 0; |
494 while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) { 495 rval *= base; 496 rval += (c - '0'); | 506 c = skipws(); 507 if (c == '0') { 508 c = skipws(); 509 if (c == 'x' || c == 'X') { 510 base = HEX; 511 c = skipws(); 512 } else { 513 base = OCTAL; 514 ndig++; 515 } 516 } else 517 base = DECIMAL; 518 for(;;) { 519 switch(c) { 520 case '8': case '9': 521 if (base == OCTAL) 522 goto bad_digit; 523 /*FALLTHRU*/ 524 case '0': case '1': case '2': case '3': 525 case '4': case '5': case '6': case '7': 526 rval *= base; 527 rval += c - '0'; 528 break; 529 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 530 c = tolower(c); 531 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 532 if (base == HEX) { 533 rval *= base; 534 rval += c - 'a' + 10; 535 break; 536 } 537 /*FALLTHRU*/ 538 default: 539 goto bad_digit; 540 } |
497 c = getch(); 498 ndig++; 499 } | 541 c = getch(); 542 ndig++; 543 } |
544bad_digit: |
|
500 ungetch(); | 545 ungetch(); |
501 | 546 |
502 if (ndig == 0) 503 experr("bad constant"); | 547 if (ndig == 0) 548 experr("bad constant"); |
504 | 549 |
505 return rval; | 550 return rval; |
506 | |
507} 508 509/* 510 * eqrel : '=' | '==' | '!=' | '<' | '>' | '<=' | '>=' 511 */ 512static int 513geteqrel() 514{ | 551} 552 553/* 554 * eqrel : '=' | '==' | '!=' | '<' | '>' | '<=' | '>=' 555 */ 556static int 557geteqrel() 558{ |
515 register int c1, c2; | 559 int c1, c2; |
516 517 c1 = skipws(); 518 c2 = getch(); 519 520 switch (c1) { 521 522 case '=': 523 if (c2 != '=') --- 27 unchanged lines hidden (view full) --- 551} 552 553/* 554 * Skip over any white space and return terminating char. 555 */ 556static int 557skipws() 558{ | 560 561 c1 = skipws(); 562 c2 = getch(); 563 564 switch (c1) { 565 566 case '=': 567 if (c2 != '=') --- 27 unchanged lines hidden (view full) --- 595} 596 597/* 598 * Skip over any white space and return terminating char. 599 */ 600static int 601skipws() 602{ |
559 register char c; | 603 int c; |
560 561 while ((c = getch()) <= ' ' && c > EOS) 562 ; 563 return c; 564} 565 566/* | 604 605 while ((c = getch()) <= ' ' && c > EOS) 606 ; 607 return c; 608} 609 610/* |
567 * resets environment to eval(), prints an error | 611 * resets environment to eval(), prints an error |
568 * and forces eval to return FALSE. 569 */ 570static void 571experr(msg) | 612 * and forces eval to return FALSE. 613 */ 614static void 615experr(msg) |
572char *msg; | 616 const char *msg; |
573{ | 617{ |
574 printf("m4: %s in expr.\n", msg); | 618 printf("m4: %s in expr %s.\n", msg, where); |
575 longjmp(expjump, -1); 576} | 619 longjmp(expjump, -1); 620} |