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