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