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