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