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