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.8 1994/09/24 02:55:37 davidg 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 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 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 void 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 ("%d\n", result->u.i); 245 else 246 printf ("%s\n", result->u.s); 247 248 exit (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 (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 (strcoll (a->u.s, b->u.s) == 0); 296 } else { 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 r= make_integer (a->u.i > b->u.i); 317 } 318 319 free_value (a); 320 free_value (b); 321 return r; 322 } 323 324 struct val * 325 op_lt (a, b) 326 struct val *a, *b; 327 { 328 struct val *r; 329 330 if (isstring (a) || isstring (b)) { 331 to_string (a); 332 to_string (b); 333 r = make_integer (strcoll (a->u.s, b->u.s) < 0); 334 } else { 335 r = make_integer (a->u.i < b->u.i); 336 } 337 338 free_value (a); 339 free_value (b); 340 return r; 341 } 342 343 struct val * 344 op_ge (a, b) 345 struct val *a, *b; 346 { 347 struct val *r; 348 349 if (isstring (a) || isstring (b)) { 350 to_string (a); 351 to_string (b); 352 r = make_integer (strcoll (a->u.s, b->u.s) >= 0); 353 } else { 354 r = make_integer (a->u.i >= b->u.i); 355 } 356 357 free_value (a); 358 free_value (b); 359 return r; 360 } 361 362 struct val * 363 op_le (a, b) 364 struct val *a, *b; 365 { 366 struct val *r; 367 368 if (isstring (a) || isstring (b)) { 369 to_string (a); 370 to_string (b); 371 r = make_integer (strcoll (a->u.s, b->u.s) <= 0); 372 } else { 373 r = make_integer (a->u.i <= b->u.i); 374 } 375 376 free_value (a); 377 free_value (b); 378 return r; 379 } 380 381 struct val * 382 op_ne (a, b) 383 struct val *a, *b; 384 { 385 struct val *r; 386 387 if (isstring (a) || isstring (b)) { 388 to_string (a); 389 to_string (b); 390 r = make_integer (strcoll (a->u.s, b->u.s) != 0); 391 } else { 392 r = make_integer (a->u.i != b->u.i); 393 } 394 395 free_value (a); 396 free_value (b); 397 return r; 398 } 399 400 struct val * 401 op_plus (a, b) 402 struct val *a, *b; 403 { 404 struct val *r; 405 406 if (!to_integer (a) || !to_integer (b)) { 407 errx (2, "non-numeric argument"); 408 } 409 410 r = make_integer (a->u.i + b->u.i); 411 free_value (a); 412 free_value (b); 413 return r; 414 } 415 416 struct val * 417 op_minus (a, b) 418 struct val *a, *b; 419 { 420 struct val *r; 421 422 if (!to_integer (a) || !to_integer (b)) { 423 errx (2, "non-numeric argument"); 424 } 425 426 r = make_integer (a->u.i - b->u.i); 427 free_value (a); 428 free_value (b); 429 return r; 430 } 431 432 struct val * 433 op_times (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 (a->u.i * b->u.i); 443 free_value (a); 444 free_value (b); 445 return (r); 446 } 447 448 struct val * 449 op_div (a, b) 450 struct val *a, *b; 451 { 452 struct val *r; 453 454 if (!to_integer (a) || !to_integer (b)) { 455 errx (2, "non-numeric argument"); 456 } 457 458 if (b->u.i == 0) { 459 errx (2, "division by zero"); 460 } 461 462 r = make_integer (a->u.i / b->u.i); 463 free_value (a); 464 free_value (b); 465 return r; 466 } 467 468 struct val * 469 op_rem (a, b) 470 struct val *a, *b; 471 { 472 struct val *r; 473 474 if (!to_integer (a) || !to_integer (b)) { 475 errx (2, "non-numeric argument"); 476 } 477 478 if (b->u.i == 0) { 479 errx (2, "division by zero"); 480 } 481 482 r = make_integer (a->u.i % b->u.i); 483 free_value (a); 484 free_value (b); 485 return r; 486 } 487 488 #include <sys/types.h> 489 #include <regex.h> 490 491 struct val * 492 op_colon (a, b) 493 struct val *a, *b; 494 { 495 regex_t rp; 496 regmatch_t rm[2]; 497 char errbuf[256]; 498 int eval; 499 struct val *v; 500 501 /* coerce to both arguments to strings */ 502 to_string(a); 503 to_string(b); 504 505 /* compile regular expression */ 506 if ((eval = regcomp (&rp, b->u.s, 0)) != 0) { 507 regerror (eval, &rp, errbuf, sizeof(errbuf)); 508 errx (2, "%s", errbuf); 509 } 510 511 /* compare string against pattern */ 512 /* remember that patterns are anchored to the beginning of the line */ 513 if (regexec(&rp, a->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) { 514 if (rm[1].rm_so >= 0) { 515 *(a->u.s + rm[1].rm_eo) = '\0'; 516 v = make_str (a->u.s + rm[1].rm_so); 517 518 } else { 519 v = make_integer (rm[0].rm_eo - rm[0].rm_so); 520 } 521 } else { 522 if (rp.re_nsub == 0) { 523 v = make_integer (0); 524 } else { 525 v = make_str (""); 526 } 527 } 528 529 /* free arguments and pattern buffer */ 530 free_value (a); 531 free_value (b); 532 regfree (&rp); 533 534 return v; 535 } 536