1 %{ 2 /* Written by Pace Willisson (pace@blitz.com) 3 * and placed in the public domain. 4 * 5 * Largely rewritten by J.T. Conklin (jtc@wimsey.com) 6 * 7 * $FreeBSD$ 8 */ 9 10 #include <sys/types.h> 11 12 #include <ctype.h> 13 #include <err.h> 14 #include <errno.h> 15 #include <inttypes.h> 16 #include <limits.h> 17 #include <locale.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <regex.h> 22 #include <unistd.h> 23 24 /* 25 * POSIX specifies a specific error code for syntax errors. We exit 26 * with this code for all errors. 27 */ 28 #define ERR_EXIT 2 29 30 enum valtype { 31 integer, numeric_string, string 32 } ; 33 34 struct val { 35 enum valtype type; 36 union { 37 char *s; 38 intmax_t i; 39 } u; 40 } ; 41 42 struct val *result; 43 44 int chk_div(intmax_t, intmax_t); 45 int chk_minus(intmax_t, intmax_t, intmax_t); 46 int chk_plus(intmax_t, intmax_t, intmax_t); 47 int chk_times(intmax_t, intmax_t, intmax_t); 48 void free_value(struct val *); 49 int is_zero_or_null(struct val *); 50 int isstring(struct val *); 51 struct val *make_integer(intmax_t); 52 struct val *make_str(const char *); 53 struct val *op_and(struct val *, struct val *); 54 struct val *op_colon(struct val *, struct val *); 55 struct val *op_div(struct val *, struct val *); 56 struct val *op_eq(struct val *, struct val *); 57 struct val *op_ge(struct val *, struct val *); 58 struct val *op_gt(struct val *, struct val *); 59 struct val *op_le(struct val *, struct val *); 60 struct val *op_lt(struct val *, struct val *); 61 struct val *op_minus(struct val *, struct val *); 62 struct val *op_ne(struct val *, struct val *); 63 struct val *op_or(struct val *, struct val *); 64 struct val *op_plus(struct val *, struct val *); 65 struct val *op_rem(struct val *, struct val *); 66 struct val *op_times(struct val *, struct val *); 67 intmax_t to_integer(struct val *); 68 void to_string(struct val *); 69 int yyerror(const char *); 70 int yylex(void); 71 int yyparse(void); 72 73 static int eflag; 74 char **av; 75 %} 76 77 %union 78 { 79 struct val *val; 80 } 81 82 %left <val> '|' 83 %left <val> '&' 84 %left <val> '=' '>' '<' GE LE NE 85 %left <val> '+' '-' 86 %left <val> '*' '/' '%' 87 %left <val> ':' 88 89 %token <val> TOKEN 90 %type <val> start expr 91 92 %% 93 94 start: expr { result = $$; } 95 96 expr: TOKEN 97 | '(' expr ')' { $$ = $2; } 98 | expr '|' expr { $$ = op_or ($1, $3); } 99 | expr '&' expr { $$ = op_and ($1, $3); } 100 | expr '=' expr { $$ = op_eq ($1, $3); } 101 | expr '>' expr { $$ = op_gt ($1, $3); } 102 | expr '<' expr { $$ = op_lt ($1, $3); } 103 | expr GE expr { $$ = op_ge ($1, $3); } 104 | expr LE expr { $$ = op_le ($1, $3); } 105 | expr NE expr { $$ = op_ne ($1, $3); } 106 | expr '+' expr { $$ = op_plus ($1, $3); } 107 | expr '-' expr { $$ = op_minus ($1, $3); } 108 | expr '*' expr { $$ = op_times ($1, $3); } 109 | expr '/' expr { $$ = op_div ($1, $3); } 110 | expr '%' expr { $$ = op_rem ($1, $3); } 111 | expr ':' expr { $$ = op_colon ($1, $3); } 112 ; 113 114 115 %% 116 117 struct val * 118 make_integer(intmax_t i) 119 { 120 struct val *vp; 121 122 vp = (struct val *) malloc (sizeof (*vp)); 123 if (vp == NULL) { 124 errx(ERR_EXIT, "malloc() failed"); 125 } 126 127 vp->type = integer; 128 vp->u.i = i; 129 return vp; 130 } 131 132 struct val * 133 make_str(const char *s) 134 { 135 struct val *vp; 136 char *ep; 137 138 vp = (struct val *) malloc (sizeof (*vp)); 139 if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) { 140 errx(ERR_EXIT, "malloc() failed"); 141 } 142 143 /* 144 * Previously we tried to scan the string to see if it ``looked like'' 145 * an integer (erroneously, as it happened). Let strtoimax() do the 146 * dirty work. We could cache the value, except that we are using 147 * a union and need to preserve the original string form until we 148 * are certain that it is not needed. 149 * 150 * IEEE Std.1003.1-2001 says: 151 * /integer/ An argument consisting only of an (optional) unary minus 152 * followed by digits. 153 * 154 * This means that arguments which consist of digits followed by 155 * non-digits MUST NOT be considered integers. strtoimax() will 156 * figure this out for us. 157 */ 158 if (eflag) 159 (void)strtoimax(s, &ep, 10); 160 else 161 (void)strtol(s, &ep, 10); 162 163 if (*ep != '\0') 164 vp->type = string; 165 else 166 vp->type = numeric_string; 167 168 return vp; 169 } 170 171 172 void 173 free_value(struct val *vp) 174 { 175 if (vp->type == string || vp->type == numeric_string) 176 free (vp->u.s); 177 } 178 179 180 intmax_t 181 to_integer(struct val *vp) 182 { 183 intmax_t i; 184 185 if (vp->type == integer) 186 return 1; 187 188 if (vp->type == string) 189 return 0; 190 191 /* vp->type == numeric_string, make it numeric */ 192 errno = 0; 193 if (eflag) { 194 i = strtoimax(vp->u.s, (char **)NULL, 10); 195 if (errno == ERANGE) 196 err(ERR_EXIT, NULL); 197 } else { 198 i = strtol(vp->u.s, (char **)NULL, 10); 199 } 200 201 free (vp->u.s); 202 vp->u.i = i; 203 vp->type = integer; 204 return 1; 205 } 206 207 void 208 to_string(struct val *vp) 209 { 210 char *tmp; 211 212 if (vp->type == string || vp->type == numeric_string) 213 return; 214 215 /* 216 * log_10(x) ~= 0.3 * log_2(x). Rounding up gives the number 217 * of digits; add one each for the sign and terminating null 218 * character, respectively. 219 */ 220 #define NDIGITS(x) (3 * (sizeof(x) * CHAR_BIT) / 10 + 1 + 1 + 1) 221 tmp = malloc(NDIGITS(vp->u.i)); 222 if (tmp == NULL) 223 errx(ERR_EXIT, "malloc() failed"); 224 225 sprintf(tmp, "%jd", vp->u.i); 226 vp->type = string; 227 vp->u.s = tmp; 228 } 229 230 231 int 232 isstring(struct val *vp) 233 { 234 /* only TRUE if this string is not a valid integer */ 235 return (vp->type == string); 236 } 237 238 239 int 240 yylex(void) 241 { 242 char *p; 243 244 if (*av == NULL) 245 return (0); 246 247 p = *av++; 248 249 if (strlen (p) == 1) { 250 if (strchr ("|&=<>+-*/%:()", *p)) 251 return (*p); 252 } else if (strlen (p) == 2 && p[1] == '=') { 253 switch (*p) { 254 case '>': return (GE); 255 case '<': return (LE); 256 case '!': return (NE); 257 } 258 } 259 260 yylval.val = make_str (p); 261 return (TOKEN); 262 } 263 264 int 265 is_zero_or_null(struct val *vp) 266 { 267 if (vp->type == integer) { 268 return (vp->u.i == 0); 269 } else { 270 return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0)); 271 } 272 /* NOTREACHED */ 273 } 274 275 int 276 main(int argc, char *argv[]) 277 { 278 int c; 279 280 setlocale (LC_ALL, ""); 281 if (getenv("EXPR_COMPAT") != NULL) { 282 av = argv + 1; 283 eflag = 1; 284 } else { 285 while ((c = getopt(argc, argv, "e")) != -1) 286 switch (c) { 287 case 'e': 288 eflag = 1; 289 break; 290 291 default: 292 fprintf(stderr, 293 "usage: expr [-e] expression\n"); 294 exit(ERR_EXIT); 295 } 296 av = argv + optind; 297 } 298 299 yyparse(); 300 301 if (result->type == integer) 302 printf("%jd\n", result->u.i); 303 else 304 printf("%s\n", result->u.s); 305 306 return (is_zero_or_null(result)); 307 } 308 309 int 310 yyerror(const char *s __unused) 311 { 312 errx(ERR_EXIT, "syntax error"); 313 } 314 315 316 struct val * 317 op_or(struct val *a, struct val *b) 318 { 319 if (is_zero_or_null (a)) { 320 free_value (a); 321 return (b); 322 } else { 323 free_value (b); 324 return (a); 325 } 326 } 327 328 struct val * 329 op_and(struct val *a, struct val *b) 330 { 331 if (is_zero_or_null (a) || is_zero_or_null (b)) { 332 free_value (a); 333 free_value (b); 334 return (make_integer ((intmax_t)0)); 335 } else { 336 free_value (b); 337 return (a); 338 } 339 } 340 341 struct val * 342 op_eq(struct val *a, struct val *b) 343 { 344 struct val *r; 345 346 if (isstring (a) || isstring (b)) { 347 to_string (a); 348 to_string (b); 349 r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) == 0)); 350 } else { 351 (void)to_integer(a); 352 (void)to_integer(b); 353 r = make_integer ((intmax_t)(a->u.i == b->u.i)); 354 } 355 356 free_value (a); 357 free_value (b); 358 return r; 359 } 360 361 struct val * 362 op_gt(struct val *a, struct val *b) 363 { 364 struct val *r; 365 366 if (isstring (a) || isstring (b)) { 367 to_string (a); 368 to_string (b); 369 r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) > 0)); 370 } else { 371 (void)to_integer(a); 372 (void)to_integer(b); 373 r = make_integer ((intmax_t)(a->u.i > b->u.i)); 374 } 375 376 free_value (a); 377 free_value (b); 378 return r; 379 } 380 381 struct val * 382 op_lt(struct val *a, struct val *b) 383 { 384 struct val *r; 385 386 if (isstring (a) || isstring (b)) { 387 to_string (a); 388 to_string (b); 389 r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) < 0)); 390 } else { 391 (void)to_integer(a); 392 (void)to_integer(b); 393 r = make_integer ((intmax_t)(a->u.i < b->u.i)); 394 } 395 396 free_value (a); 397 free_value (b); 398 return r; 399 } 400 401 struct val * 402 op_ge(struct val *a, struct val *b) 403 { 404 struct val *r; 405 406 if (isstring (a) || isstring (b)) { 407 to_string (a); 408 to_string (b); 409 r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) >= 0)); 410 } else { 411 (void)to_integer(a); 412 (void)to_integer(b); 413 r = make_integer ((intmax_t)(a->u.i >= b->u.i)); 414 } 415 416 free_value (a); 417 free_value (b); 418 return r; 419 } 420 421 struct val * 422 op_le(struct val *a, struct val *b) 423 { 424 struct val *r; 425 426 if (isstring (a) || isstring (b)) { 427 to_string (a); 428 to_string (b); 429 r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) <= 0)); 430 } else { 431 (void)to_integer(a); 432 (void)to_integer(b); 433 r = make_integer ((intmax_t)(a->u.i <= b->u.i)); 434 } 435 436 free_value (a); 437 free_value (b); 438 return r; 439 } 440 441 struct val * 442 op_ne(struct val *a, struct val *b) 443 { 444 struct val *r; 445 446 if (isstring (a) || isstring (b)) { 447 to_string (a); 448 to_string (b); 449 r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) != 0)); 450 } else { 451 (void)to_integer(a); 452 (void)to_integer(b); 453 r = make_integer ((intmax_t)(a->u.i != b->u.i)); 454 } 455 456 free_value (a); 457 free_value (b); 458 return r; 459 } 460 461 int 462 chk_plus(intmax_t a, intmax_t b, intmax_t r) 463 { 464 465 /* sum of two positive numbers must be positive */ 466 if (a > 0 && b > 0 && r <= 0) 467 return 1; 468 /* sum of two negative numbers must be negative */ 469 if (a < 0 && b < 0 && r >= 0) 470 return 1; 471 /* all other cases are OK */ 472 return 0; 473 } 474 475 struct val * 476 op_plus(struct val *a, struct val *b) 477 { 478 struct val *r; 479 480 if (!to_integer(a) || !to_integer(b)) { 481 errx(ERR_EXIT, "non-numeric argument"); 482 } 483 484 if (eflag) { 485 r = make_integer(a->u.i + b->u.i); 486 if (chk_plus(a->u.i, b->u.i, r->u.i)) { 487 errx(ERR_EXIT, "overflow"); 488 } 489 } else 490 r = make_integer((long)a->u.i + (long)b->u.i); 491 492 free_value (a); 493 free_value (b); 494 return r; 495 } 496 497 int 498 chk_minus(intmax_t a, intmax_t b, intmax_t r) 499 { 500 501 /* special case subtraction of INTMAX_MIN */ 502 if (b == INTMAX_MIN) { 503 if (a >= 0) 504 return 1; 505 else 506 return 0; 507 } 508 /* this is allowed for b != INTMAX_MIN */ 509 return chk_plus (a, -b, r); 510 } 511 512 struct val * 513 op_minus(struct val *a, struct val *b) 514 { 515 struct val *r; 516 517 if (!to_integer(a) || !to_integer(b)) { 518 errx(ERR_EXIT, "non-numeric argument"); 519 } 520 521 if (eflag) { 522 r = make_integer(a->u.i - b->u.i); 523 if (chk_minus(a->u.i, b->u.i, r->u.i)) { 524 errx(ERR_EXIT, "overflow"); 525 } 526 } else 527 r = make_integer((long)a->u.i - (long)b->u.i); 528 529 free_value (a); 530 free_value (b); 531 return r; 532 } 533 534 int 535 chk_times(intmax_t a, intmax_t b, intmax_t r) 536 { 537 /* special case: first operand is 0, no overflow possible */ 538 if (a == 0) 539 return 0; 540 /* cerify that result of division matches second operand */ 541 if (r / a != b) 542 return 1; 543 return 0; 544 } 545 546 struct val * 547 op_times(struct val *a, struct val *b) 548 { 549 struct val *r; 550 551 if (!to_integer(a) || !to_integer(b)) { 552 errx(ERR_EXIT, "non-numeric argument"); 553 } 554 555 if (eflag) { 556 r = make_integer(a->u.i * b->u.i); 557 if (chk_times(a->u.i, b->u.i, r->u.i)) { 558 errx(ERR_EXIT, "overflow"); 559 } 560 } else 561 r = make_integer((long)a->u.i * (long)b->u.i); 562 563 free_value (a); 564 free_value (b); 565 return (r); 566 } 567 568 int 569 chk_div(intmax_t a, intmax_t b) 570 { 571 /* div by zero has been taken care of before */ 572 /* only INTMAX_MIN / -1 causes overflow */ 573 if (a == INTMAX_MIN && b == -1) 574 return 1; 575 /* everything else is OK */ 576 return 0; 577 } 578 579 struct val * 580 op_div(struct val *a, struct val *b) 581 { 582 struct val *r; 583 584 if (!to_integer(a) || !to_integer(b)) { 585 errx(ERR_EXIT, "non-numeric argument"); 586 } 587 588 if (b->u.i == 0) { 589 errx(ERR_EXIT, "division by zero"); 590 } 591 592 if (eflag) { 593 r = make_integer(a->u.i / b->u.i); 594 if (chk_div(a->u.i, b->u.i)) { 595 errx(ERR_EXIT, "overflow"); 596 } 597 } else 598 r = make_integer((long)a->u.i / (long)b->u.i); 599 600 free_value (a); 601 free_value (b); 602 return r; 603 } 604 605 struct val * 606 op_rem(struct val *a, struct val *b) 607 { 608 struct val *r; 609 610 if (!to_integer(a) || !to_integer(b)) { 611 errx(ERR_EXIT, "non-numeric argument"); 612 } 613 614 if (b->u.i == 0) { 615 errx(ERR_EXIT, "division by zero"); 616 } 617 618 if (eflag) 619 r = make_integer(a->u.i % b->u.i); 620 /* chk_rem necessary ??? */ 621 else 622 r = make_integer((long)a->u.i % (long)b->u.i); 623 624 free_value (a); 625 free_value (b); 626 return r; 627 } 628 629 struct val * 630 op_colon(struct val *a, struct val *b) 631 { 632 regex_t rp; 633 regmatch_t rm[2]; 634 char errbuf[256]; 635 int eval; 636 struct val *v; 637 638 /* coerce to both arguments to strings */ 639 to_string(a); 640 to_string(b); 641 642 /* compile regular expression */ 643 if ((eval = regcomp (&rp, b->u.s, 0)) != 0) { 644 regerror (eval, &rp, errbuf, sizeof(errbuf)); 645 errx(ERR_EXIT, "%s", errbuf); 646 } 647 648 /* compare string against pattern */ 649 /* remember that patterns are anchored to the beginning of the line */ 650 if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) { 651 if (rm[1].rm_so >= 0) { 652 *(a->u.s + rm[1].rm_eo) = '\0'; 653 v = make_str (a->u.s + rm[1].rm_so); 654 655 } else { 656 v = make_integer ((intmax_t)(rm[0].rm_eo - rm[0].rm_so)); 657 } 658 } else { 659 if (rp.re_nsub == 0) { 660 v = make_integer ((intmax_t)0); 661 } else { 662 v = make_str (""); 663 } 664 } 665 666 /* free arguments and pattern buffer */ 667 free_value (a); 668 free_value (b); 669 regfree (&rp); 670 671 return v; 672 } 673