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