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 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 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 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. 38 */ 39 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 $");
| 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 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 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 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. 38 */ 39 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 $");
| 43__FBSDID("$FreeBSD: head/usr.bin/m4/expr.c 95095 2002-04-20 01:49:10Z jmallett $");
|
44 45#include <sys/types.h> 46#include <ctype.h> 47#include <err.h> 48#include <stddef.h> 49#include <stdio.h> 50#include "mdef.h" 51#include "extern.h" 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 60 * | lor "?" query ":" query 61 * lor : land { "||" land } 62 * land : not { "&&" not } 63 * not : eqrel 64 * | '!' not 65 * eqrel : shift { eqrelop shift } 66 * shift : primary { shop primary } 67 * primary : term { addop term } 68 * term : exp { mulop exp } 69 * exp : unary { expop unary } 70 * unary : factor 71 * | unop unary 72 * factor : constant 73 * | "(" query ")" 74 * constant: num 75 * | "'" CHAR "'" 76 * num : DIGIT 77 * | DIGIT num 78 * shop : "<<" 79 * | ">>" 80 * eqrel : "=" 81 * | "==" 82 * | "!=" 83 * | "<" 84 * | ">" 85 * | "<=" 86 * | ">=" 87 * 88 * 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 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 106 107static const char *nxtch; /* Parser scan pointer */ 108static const char *where; 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); 125static void experr(const char *); 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) 143 const char *expbuf; 144{ 145 int rval; 146 147 nxtch = expbuf; 148 where = expbuf; 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{ 166 int bool, true_val, false_val; 167 168 bool = lor(); 169 if (skipws() != '?') { 170 ungetch(); 171 return bool; 172 } 173 174 true_val = query(); 175 if (skipws() != ':') 176 experr("bad query"); 177 178 false_val = query(); 179 return bool ? true_val : false_val; 180} 181 182/* 183 * lor : land { '||' land } 184 */ 185static int 186lor() 187{ 188 int c, vl, vr; 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{ 208 int c, vl, vr; 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{ 228 int val, c; 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{
| 44 45#include <sys/types.h> 46#include <ctype.h> 47#include <err.h> 48#include <stddef.h> 49#include <stdio.h> 50#include "mdef.h" 51#include "extern.h" 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 60 * | lor "?" query ":" query 61 * lor : land { "||" land } 62 * land : not { "&&" not } 63 * not : eqrel 64 * | '!' not 65 * eqrel : shift { eqrelop shift } 66 * shift : primary { shop primary } 67 * primary : term { addop term } 68 * term : exp { mulop exp } 69 * exp : unary { expop unary } 70 * unary : factor 71 * | unop unary 72 * factor : constant 73 * | "(" query ")" 74 * constant: num 75 * | "'" CHAR "'" 76 * num : DIGIT 77 * | DIGIT num 78 * shop : "<<" 79 * | ">>" 80 * eqrel : "=" 81 * | "==" 82 * | "!=" 83 * | "<" 84 * | ">" 85 * | "<=" 86 * | ">=" 87 * 88 * 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 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 106 107static const char *nxtch; /* Parser scan pointer */ 108static const char *where; 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); 125static void experr(const char *); 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) 143 const char *expbuf; 144{ 145 int rval; 146 147 nxtch = expbuf; 148 where = expbuf; 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{ 166 int bool, true_val, false_val; 167 168 bool = lor(); 169 if (skipws() != '?') { 170 ungetch(); 171 return bool; 172 } 173 174 true_val = query(); 175 if (skipws() != ':') 176 experr("bad query"); 177 178 false_val = query(); 179 return bool ? true_val : false_val; 180} 181 182/* 183 * lor : land { '||' land } 184 */ 185static int 186lor() 187{ 188 int c, vl, vr; 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{ 208 int c, vl, vr; 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{ 228 int val, c; 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{
|
248 int vl, vr, eqrel;
| 248 int vl, vr, eqrelval;
|
249 250 vl = shift();
| 249 250 vl = shift();
|
251 while ((eqrel = geteqrel()) != -1) {
| 251 while ((eqrelval = geteqrel()) != -1) {
|
252 vr = shift(); 253
| 252 vr = shift(); 253
|
254 switch (eqrel) { 255
| 254 switch (eqrelval) {
|
256 case EQL: 257 vl = (vl == vr); 258 break; 259 case NEQ: 260 vl = (vl != vr); 261 break;
| 255 case EQL: 256 vl = (vl == vr); 257 break; 258 case NEQ: 259 vl = (vl != vr); 260 break;
|
262
| |
263 case LEQ: 264 vl = (vl <= vr); 265 break; 266 case LSS: 267 vl = (vl < vr); 268 break; 269 case GTR: 270 vl = (vl > vr); 271 break; 272 case GEQ: 273 vl = (vl >= vr); 274 break; 275 } 276 } 277 return vl; 278} 279 280/* 281 * shift : primary { shop primary } 282 */ 283static int 284shift() 285{ 286 int vl, vr, c; 287 288 vl = primary(); 289 while (((c = skipws()) == '<' || c == '>') && getch() == c) { 290 vr = primary(); 291 292 if (c == '<') 293 vl <<= vr; 294 else 295 vl >>= vr; 296 } 297 298 if (c == '<' || c == '>') 299 ungetch(); 300 ungetch(); 301 return vl; 302} 303 304/* 305 * primary : term { addop term } 306 */ 307static int 308primary() 309{ 310 int c, vl, vr; 311 312 vl = term(); 313 while ((c = skipws()) == '+' || c == '-') { 314 vr = term(); 315 316 if (c == '+') 317 vl += vr; 318 else 319 vl -= vr; 320 } 321 322 ungetch(); 323 return vl; 324} 325 326/* 327 * <term> := <exp> { <mulop> <exp> } 328 */ 329static int 330term() 331{ 332 int c, vl, vr; 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 '/': 343 if (vr == 0) 344 errx(1, "division by zero in eval."); 345 else 346 vl /= vr; 347 break; 348 case '%': 349 if (vr == 0) 350 errx(1, "modulo zero in eval."); 351 else 352 vl %= vr; 353 break; 354 } 355 } 356 ungetch(); 357 return vl; 358} 359 360/* 361 * <term> := <unary> { <expop> <unary> } 362 */ 363static int 364exp() 365{ 366 int c, vl, vr, n; 367 368 vl = unary(); 369 switch (c = skipws()) { 370 371 case '*': 372 if (getch() != '*') { 373 ungetch(); 374 break; 375 } 376 377 case '^': 378 vr = exp(); 379 n = 1; 380 while (vr-- > 0) 381 n *= vl; 382 return n; 383 } 384 385 ungetch(); 386 return vl; 387} 388 389/* 390 * unary : factor | unop unary 391 */ 392static int 393unary() 394{ 395 int val, c; 396 397 if ((c = skipws()) == '+' || c == '-' || c == '~') { 398 val = unary(); 399 400 switch (c) { 401 case '+': 402 return val; 403 case '-': 404 return -val; 405 case '~': 406 return ~val; 407 } 408 } 409 410 ungetch(); 411 return factor(); 412} 413 414/* 415 * factor : constant | '(' query ')' 416 */ 417static int 418factor() 419{ 420 int val; 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{ 440 int i; 441 int value; 442 int c; 443 int v[sizeof(int)]; 444 445 if (skipws() != '\'') { 446 ungetch(); 447 return num(); 448 }
| 261 case LEQ: 262 vl = (vl <= vr); 263 break; 264 case LSS: 265 vl = (vl < vr); 266 break; 267 case GTR: 268 vl = (vl > vr); 269 break; 270 case GEQ: 271 vl = (vl >= vr); 272 break; 273 } 274 } 275 return vl; 276} 277 278/* 279 * shift : primary { shop primary } 280 */ 281static int 282shift() 283{ 284 int vl, vr, c; 285 286 vl = primary(); 287 while (((c = skipws()) == '<' || c == '>') && getch() == c) { 288 vr = primary(); 289 290 if (c == '<') 291 vl <<= vr; 292 else 293 vl >>= vr; 294 } 295 296 if (c == '<' || c == '>') 297 ungetch(); 298 ungetch(); 299 return vl; 300} 301 302/* 303 * primary : term { addop term } 304 */ 305static int 306primary() 307{ 308 int c, vl, vr; 309 310 vl = term(); 311 while ((c = skipws()) == '+' || c == '-') { 312 vr = term(); 313 314 if (c == '+') 315 vl += vr; 316 else 317 vl -= vr; 318 } 319 320 ungetch(); 321 return vl; 322} 323 324/* 325 * <term> := <exp> { <mulop> <exp> } 326 */ 327static int 328term() 329{ 330 int c, vl, vr; 331 332 vl = exp(); 333 while ((c = skipws()) == '*' || c == '/' || c == '%') { 334 vr = exp(); 335 336 switch (c) { 337 case '*': 338 vl *= vr; 339 break; 340 case '/': 341 if (vr == 0) 342 errx(1, "division by zero in eval."); 343 else 344 vl /= vr; 345 break; 346 case '%': 347 if (vr == 0) 348 errx(1, "modulo zero in eval."); 349 else 350 vl %= vr; 351 break; 352 } 353 } 354 ungetch(); 355 return vl; 356} 357 358/* 359 * <term> := <unary> { <expop> <unary> } 360 */ 361static int 362exp() 363{ 364 int c, vl, vr, n; 365 366 vl = unary(); 367 switch (c = skipws()) { 368 369 case '*': 370 if (getch() != '*') { 371 ungetch(); 372 break; 373 } 374 375 case '^': 376 vr = exp(); 377 n = 1; 378 while (vr-- > 0) 379 n *= vl; 380 return n; 381 } 382 383 ungetch(); 384 return vl; 385} 386 387/* 388 * unary : factor | unop unary 389 */ 390static int 391unary() 392{ 393 int val, c; 394 395 if ((c = skipws()) == '+' || c == '-' || c == '~') { 396 val = unary(); 397 398 switch (c) { 399 case '+': 400 return val; 401 case '-': 402 return -val; 403 case '~': 404 return ~val; 405 } 406 } 407 408 ungetch(); 409 return factor(); 410} 411 412/* 413 * factor : constant | '(' query ')' 414 */ 415static int 416factor() 417{ 418 int val; 419 420 if (skipws() == '(') { 421 val = query(); 422 if (skipws() != ')') 423 experr("bad factor"); 424 return val; 425 } 426 427 ungetch(); 428 return constant(); 429} 430 431/* 432 * constant: num | 'char' 433 * Note: constant() handles multi-byte constants 434 */ 435static int 436constant() 437{ 438 int i; 439 int value; 440 int c; 441 int v[sizeof(int)]; 442 443 if (skipws() != '\'') { 444 ungetch(); 445 return num(); 446 }
|
449 for (i = 0; i < sizeof(int); i++) {
| 447 for (i = 0; i < (int)sizeof(int); i++) {
|
450 if ((c = getch()) == '\'') { 451 ungetch(); 452 break; 453 } 454 if (c == '\\') { 455 switch (c = getch()) { 456 case '0': 457 case '1': 458 case '2': 459 case '3': 460 case '4': 461 case '5': 462 case '6': 463 case '7': 464 ungetch(); 465 c = num(); 466 break; 467 case 'n': 468 c = 012; 469 break; 470 case 'r': 471 c = 015; 472 break; 473 case 't': 474 c = 011; 475 break; 476 case 'b': 477 c = 010; 478 break; 479 case 'f': 480 c = 014; 481 break; 482 } 483 } 484 v[i] = c; 485 } 486 if (i == 0 || getch() != '\'') 487 experr("illegal character constant"); 488 for (value = 0; --i >= 0;) { 489 value <<= 8; 490 value += v[i]; 491 } 492 return value; 493} 494 495/* 496 * num : digit | num digit 497 */ 498static int 499num() 500{ 501 int rval, c, base; 502 int ndig; 503 504 rval = 0; 505 ndig = 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 } 541 c = getch(); 542 ndig++; 543 } 544bad_digit: 545 ungetch(); 546 547 if (ndig == 0) 548 experr("bad constant"); 549 550 return rval; 551} 552 553/* 554 * eqrel : '=' | '==' | '!=' | '<' | '>' | '<=' | '>=' 555 */ 556static int 557geteqrel() 558{ 559 int c1, c2; 560 561 c1 = skipws(); 562 c2 = getch(); 563 564 switch (c1) { 565 566 case '=': 567 if (c2 != '=') 568 ungetch(); 569 return EQL; 570 571 case '!': 572 if (c2 == '=') 573 return NEQ; 574 ungetch(); 575 ungetch(); 576 return -1; 577 578 case '<': 579 if (c2 == '=') 580 return LEQ; 581 ungetch(); 582 return LSS; 583 584 case '>': 585 if (c2 == '=') 586 return GEQ; 587 ungetch(); 588 return GTR; 589 590 default: 591 ungetch(); 592 ungetch(); 593 return -1; 594 } 595} 596 597/* 598 * Skip over any white space and return terminating char. 599 */ 600static int 601skipws() 602{ 603 int c; 604 605 while ((c = getch()) <= ' ' && c > EOS) 606 ; 607 return c; 608} 609 610/* 611 * resets environment to eval(), prints an error 612 * and forces eval to return FALSE. 613 */ 614static void 615experr(msg) 616 const char *msg; 617{ 618 printf("m4: %s in expr %s.\n", msg, where); 619 longjmp(expjump, -1); 620}
| 448 if ((c = getch()) == '\'') { 449 ungetch(); 450 break; 451 } 452 if (c == '\\') { 453 switch (c = getch()) { 454 case '0': 455 case '1': 456 case '2': 457 case '3': 458 case '4': 459 case '5': 460 case '6': 461 case '7': 462 ungetch(); 463 c = num(); 464 break; 465 case 'n': 466 c = 012; 467 break; 468 case 'r': 469 c = 015; 470 break; 471 case 't': 472 c = 011; 473 break; 474 case 'b': 475 c = 010; 476 break; 477 case 'f': 478 c = 014; 479 break; 480 } 481 } 482 v[i] = c; 483 } 484 if (i == 0 || getch() != '\'') 485 experr("illegal character constant"); 486 for (value = 0; --i >= 0;) { 487 value <<= 8; 488 value += v[i]; 489 } 490 return value; 491} 492 493/* 494 * num : digit | num digit 495 */ 496static int 497num() 498{ 499 int rval, c, base; 500 int ndig; 501 502 rval = 0; 503 ndig = 0; 504 c = skipws(); 505 if (c == '0') { 506 c = skipws(); 507 if (c == 'x' || c == 'X') { 508 base = HEX; 509 c = skipws(); 510 } else { 511 base = OCTAL; 512 ndig++; 513 } 514 } else 515 base = DECIMAL; 516 for(;;) { 517 switch(c) { 518 case '8': case '9': 519 if (base == OCTAL) 520 goto bad_digit; 521 /*FALLTHRU*/ 522 case '0': case '1': case '2': case '3': 523 case '4': case '5': case '6': case '7': 524 rval *= base; 525 rval += c - '0'; 526 break; 527 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 528 c = tolower(c); 529 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 530 if (base == HEX) { 531 rval *= base; 532 rval += c - 'a' + 10; 533 break; 534 } 535 /*FALLTHRU*/ 536 default: 537 goto bad_digit; 538 } 539 c = getch(); 540 ndig++; 541 } 542bad_digit: 543 ungetch(); 544 545 if (ndig == 0) 546 experr("bad constant"); 547 548 return rval; 549} 550 551/* 552 * eqrel : '=' | '==' | '!=' | '<' | '>' | '<=' | '>=' 553 */ 554static int 555geteqrel() 556{ 557 int c1, c2; 558 559 c1 = skipws(); 560 c2 = getch(); 561 562 switch (c1) { 563 564 case '=': 565 if (c2 != '=') 566 ungetch(); 567 return EQL; 568 569 case '!': 570 if (c2 == '=') 571 return NEQ; 572 ungetch(); 573 ungetch(); 574 return -1; 575 576 case '<': 577 if (c2 == '=') 578 return LEQ; 579 ungetch(); 580 return LSS; 581 582 case '>': 583 if (c2 == '=') 584 return GEQ; 585 ungetch(); 586 return GTR; 587 588 default: 589 ungetch(); 590 ungetch(); 591 return -1; 592 } 593} 594 595/* 596 * Skip over any white space and return terminating char. 597 */ 598static int 599skipws() 600{ 601 int c; 602 603 while ((c = getch()) <= ' ' && c > EOS) 604 ; 605 return c; 606} 607 608/* 609 * resets environment to eval(), prints an error 610 * and forces eval to return FALSE. 611 */ 612static void 613experr(msg) 614 const char *msg; 615{ 616 printf("m4: %s in expr %s.\n", msg, where); 617 longjmp(expjump, -1); 618}
|