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: expr.y,v 1.9 1995/03/19 13:28:41 joerg Exp $ 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 int i, isint; 111 112 vp = (struct val *) malloc (sizeof (*vp)); 113 if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) { 114 err (2, NULL); 115 } 116 117 for(i = 1, isint = isdigit(s[0]) || s[0] == '-'; 118 isint && i < strlen(s); 119 i++) 120 { 121 if(!isdigit(s[i])) 122 isint = 0; 123 } 124 125 vp->type = string; 126 if(isint) 127 to_integer(vp); 128 129 return vp; 130 } 131 132 133 void 134 free_value (vp) 135 struct val *vp; 136 { 137 if (vp->type == string) 138 free (vp->u.s); 139 } 140 141 142 int 143 to_integer (vp) 144 struct val *vp; 145 { 146 char *s; 147 int neg; 148 int i; 149 150 if (vp->type == integer) 151 return 1; 152 153 s = vp->u.s; 154 i = 0; 155 156 neg = (*s == '-'); 157 if (neg) 158 s++; 159 160 for (;*s; s++) { 161 if (!isdigit (*s)) 162 return 0; 163 164 i *= 10; 165 i += *s - '0'; 166 } 167 168 free (vp->u.s); 169 if (neg) 170 i *= -1; 171 172 vp->type = integer; 173 vp->u.i = i; 174 return 1; 175 } 176 177 void 178 to_string (vp) 179 struct val *vp; 180 { 181 char *tmp; 182 183 if (vp->type == string) 184 return; 185 186 tmp = malloc (25); 187 if (tmp == NULL) { 188 err (2, NULL); 189 } 190 191 sprintf (tmp, "%d", vp->u.i); 192 vp->type = string; 193 vp->u.s = tmp; 194 } 195 196 197 int 198 isstring (vp) 199 struct val *vp; 200 { 201 return (vp->type == string); 202 } 203 204 205 int 206 yylex () 207 { 208 char *p; 209 210 if (*av == NULL) 211 return (0); 212 213 p = *av++; 214 215 if (strlen (p) == 1) { 216 if (strchr ("|&=<>+-*/%:()", *p)) 217 return (*p); 218 } else if (strlen (p) == 2 && p[1] == '=') { 219 switch (*p) { 220 case '>': return (GE); 221 case '<': return (LE); 222 case '!': return (NE); 223 } 224 } 225 226 yylval.val = make_str (p); 227 return (TOKEN); 228 } 229 230 int 231 is_zero_or_null (vp) 232 struct val *vp; 233 { 234 if (vp->type == integer) { 235 return (vp->u.i == 0); 236 } else { 237 return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0)); 238 } 239 /* NOTREACHED */ 240 } 241 242 int yyparse (); 243 244 void 245 main (argc, argv) 246 int argc; 247 char **argv; 248 { 249 setlocale (LC_ALL, ""); 250 251 av = argv + 1; 252 253 yyparse (); 254 255 if (result->type == integer) 256 printf ("%d\n", result->u.i); 257 else 258 printf ("%s\n", result->u.s); 259 260 exit (is_zero_or_null (result)); 261 } 262 263 int 264 yyerror (s) 265 char *s; 266 { 267 errx (2, "syntax error"); 268 } 269 270 271 struct val * 272 op_or (a, b) 273 struct val *a, *b; 274 { 275 if (is_zero_or_null (a)) { 276 free_value (a); 277 return (b); 278 } else { 279 free_value (b); 280 return (a); 281 } 282 } 283 284 struct val * 285 op_and (a, b) 286 struct val *a, *b; 287 { 288 if (is_zero_or_null (a) || is_zero_or_null (b)) { 289 free_value (a); 290 free_value (b); 291 return (make_integer (0)); 292 } else { 293 free_value (b); 294 return (a); 295 } 296 } 297 298 struct val * 299 op_eq (a, b) 300 struct val *a, *b; 301 { 302 struct val *r; 303 304 if (isstring (a) || isstring (b)) { 305 to_string (a); 306 to_string (b); 307 r = make_integer (strcoll (a->u.s, b->u.s) == 0); 308 } else { 309 r = make_integer (a->u.i == b->u.i); 310 } 311 312 free_value (a); 313 free_value (b); 314 return r; 315 } 316 317 struct val * 318 op_gt (a, b) 319 struct val *a, *b; 320 { 321 struct val *r; 322 323 if (isstring (a) || isstring (b)) { 324 to_string (a); 325 to_string (b); 326 r = make_integer (strcoll (a->u.s, b->u.s) > 0); 327 } else { 328 r= make_integer (a->u.i > b->u.i); 329 } 330 331 free_value (a); 332 free_value (b); 333 return r; 334 } 335 336 struct val * 337 op_lt (a, b) 338 struct val *a, *b; 339 { 340 struct val *r; 341 342 if (isstring (a) || isstring (b)) { 343 to_string (a); 344 to_string (b); 345 r = make_integer (strcoll (a->u.s, b->u.s) < 0); 346 } else { 347 r = make_integer (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 (strcoll (a->u.s, b->u.s) >= 0); 365 } else { 366 r = make_integer (a->u.i >= b->u.i); 367 } 368 369 free_value (a); 370 free_value (b); 371 return r; 372 } 373 374 struct val * 375 op_le (a, b) 376 struct val *a, *b; 377 { 378 struct val *r; 379 380 if (isstring (a) || isstring (b)) { 381 to_string (a); 382 to_string (b); 383 r = make_integer (strcoll (a->u.s, b->u.s) <= 0); 384 } else { 385 r = make_integer (a->u.i <= b->u.i); 386 } 387 388 free_value (a); 389 free_value (b); 390 return r; 391 } 392 393 struct val * 394 op_ne (a, b) 395 struct val *a, *b; 396 { 397 struct val *r; 398 399 if (isstring (a) || isstring (b)) { 400 to_string (a); 401 to_string (b); 402 r = make_integer (strcoll (a->u.s, b->u.s) != 0); 403 } else { 404 r = make_integer (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 (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 (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 (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 (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 (a->u.i % b->u.i); 495 free_value (a); 496 free_value (b); 497 return r; 498 } 499 500 #include <sys/types.h> 501 #include <regex.h> 502 503 struct val * 504 op_colon (a, b) 505 struct val *a, *b; 506 { 507 regex_t rp; 508 regmatch_t rm[2]; 509 char errbuf[256]; 510 int eval; 511 struct val *v; 512 513 /* coerce to both arguments to strings */ 514 to_string(a); 515 to_string(b); 516 517 /* compile regular expression */ 518 if ((eval = regcomp (&rp, b->u.s, 0)) != 0) { 519 regerror (eval, &rp, errbuf, sizeof(errbuf)); 520 errx (2, "%s", errbuf); 521 } 522 523 /* compare string against pattern */ 524 /* remember that patterns are anchored to the beginning of the line */ 525 if (regexec(&rp, a->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) { 526 if (rm[1].rm_so >= 0) { 527 *(a->u.s + rm[1].rm_eo) = '\0'; 528 v = make_str (a->u.s + rm[1].rm_so); 529 530 } else { 531 v = make_integer (rm[0].rm_eo - rm[0].rm_so); 532 } 533 } else { 534 if (rp.re_nsub == 0) { 535 v = make_integer (0); 536 } else { 537 v = make_str (""); 538 } 539 } 540 541 /* free arguments and pattern buffer */ 542 free_value (a); 543 free_value (b); 544 regfree (&rp); 545 546 return v; 547 } 548