expr.y revision 295
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 * $Header: /b/source/CVS/src/bin/expr/expr.y,v 1.11 1993/08/17 16:01:23 jtc Exp $ 8 */ 9#include <stdio.h> 10#include <stdlib.h> 11#include <string.h> 12#include <ctype.h> 13#include <err.h> 14 15enum valtype { 16 integer, string 17} ; 18 19struct val { 20 enum valtype type; 21 union { 22 char *s; 23 int i; 24 } u; 25} ; 26 27struct val *result; 28struct val *op_or (); 29struct val *op_and (); 30struct val *op_eq (); 31struct val *op_gt (); 32struct val *op_lt (); 33struct val *op_ge (); 34struct val *op_le (); 35struct val *op_ne (); 36struct val *op_plus (); 37struct val *op_minus (); 38struct val *op_times (); 39struct val *op_div (); 40struct val *op_rem (); 41struct val *op_colon (); 42 43char **av; 44%} 45 46%union 47{ 48 struct val *val; 49} 50 51%left <val> '|' 52%left <val> '&' 53%left <val> '=' '>' '<' GE LE NE 54%left <val> '+' '-' 55%left <val> '*' '/' '%' 56%left <val> ':' 57%left UNARY 58 59%token <val> TOKEN 60%type <val> start expr 61 62%% 63 64start: expr { result = $$; } 65 66expr: TOKEN 67 | '(' expr ')' { $$ = $2; } 68 | expr '|' expr { $$ = op_or ($1, $3); } 69 | expr '&' expr { $$ = op_and ($1, $3); } 70 | expr '=' expr { $$ = op_eq ($1, $3); } 71 | expr '>' expr { $$ = op_gt ($1, $3); } 72 | expr '<' expr { $$ = op_lt ($1, $3); } 73 | expr GE expr { $$ = op_ge ($1, $3); } 74 | expr LE expr { $$ = op_le ($1, $3); } 75 | expr NE expr { $$ = op_ne ($1, $3); } 76 | expr '+' expr { $$ = op_plus ($1, $3); } 77 | expr '-' expr { $$ = op_minus ($1, $3); } 78 | expr '*' expr { $$ = op_times ($1, $3); } 79 | expr '/' expr { $$ = op_div ($1, $3); } 80 | expr '%' expr { $$ = op_rem ($1, $3); } 81 | expr ':' expr { $$ = op_colon ($1, $3); } 82 | '-' expr %prec UNARY { $$ = op_minus (NULL, $2); } 83 ; 84 85 86%% 87 88struct val * 89make_integer (i) 90int i; 91{ 92 struct val *vp; 93 94 vp = (struct val *) malloc (sizeof (*vp)); 95 if (vp == NULL) { 96 err (2, NULL); 97 } 98 99 vp->type = integer; 100 vp->u.i = i; 101 return vp; 102} 103 104struct val * 105make_str (s) 106char *s; 107{ 108 struct val *vp; 109 110 vp = (struct val *) malloc (sizeof (*vp)); 111 if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) { 112 err (2, NULL); 113 } 114 115 vp->type = string; 116 return vp; 117} 118 119 120void 121free_value (vp) 122struct val *vp; 123{ 124 if (vp->type == string) 125 free (vp->u.s); 126} 127 128 129int 130to_integer (vp) 131struct val *vp; 132{ 133 char *s; 134 int neg; 135 int i; 136 137 if (vp->type == integer) 138 return 1; 139 140 s = vp->u.s; 141 i = 0; 142 143 neg = (*s == '-'); 144 if (neg) 145 s++; 146 147 for (;*s; s++) { 148 if (!isdigit (*s)) 149 return 0; 150 151 i *= 10; 152 i += *s - '0'; 153 } 154 155 free (vp->u.s); 156 if (neg) 157 i *= -1; 158 159 vp->type = integer; 160 vp->u.i = i; 161 return 1; 162} 163 164void 165to_string (vp) 166struct val *vp; 167{ 168 char *tmp; 169 170 if (vp->type == string) 171 return; 172 173 tmp = malloc (25); 174 if (tmp == NULL) { 175 err (2, NULL); 176 } 177 178 sprintf (tmp, "%d", vp->u.i); 179 vp->type = string; 180 vp->u.s = tmp; 181} 182 183 184int 185isstring (vp) 186struct val *vp; 187{ 188 return (vp->type == string); 189} 190 191 192int 193yylex () 194{ 195 struct val *vp; 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 218int 219is_zero_or_null (vp) 220struct 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 230void 231main (argc, argv) 232int argc; 233char **argv; 234{ 235 av = argv + 1; 236 237 yyparse (); 238 239 if (result->type == integer) 240 printf ("%d\n", result->u.i); 241 else 242 printf ("%s\n", result->u.s); 243 244 if (is_zero_or_null (result)) 245 exit (1); 246 else 247 exit (0); 248} 249 250int 251yyerror (s) 252char *s; 253{ 254 errx (2, "syntax error"); 255} 256 257 258struct val * 259op_or (a, b) 260struct 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 271struct val * 272op_and (a, b) 273struct 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 285struct val * 286op_eq (a, b) 287struct 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 304struct val * 305op_gt (a, b) 306struct 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 323struct val * 324op_lt (a, b) 325struct 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 342struct val * 343op_ge (a, b) 344struct 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 361struct val * 362op_le (a, b) 363struct 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 380struct val * 381op_ne (a, b) 382struct 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 399struct val * 400op_plus (a, b) 401struct 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 415struct val * 416op_minus (a, b) 417struct 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 431struct val * 432op_times (a, b) 433struct 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 447struct val * 448op_div (a, b) 449struct 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 467struct val * 468op_rem (a, b) 469struct 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 <regex.h> 488#define SE_MAX 30 489 490struct val * 491op_colon (a, b) 492struct val *a, *b; 493{ 494 regex_t rp; 495 regmatch_t rm[SE_MAX]; 496 char errbuf[256]; 497 int eval; 498 struct val *v; 499 char *newpat; 500 501 /* coerce to both arguments to strings */ 502 to_string(a); 503 to_string(b); 504 505 /* patterns are anchored to the beginning of the line */ 506 newpat = malloc (strlen (b->u.s) + 2); 507 strcpy (newpat, "^"); 508 strcat (newpat, b->u.s); 509 510 /* compile regular expression */ 511 if ((eval = regcomp (&rp, newpat, 0)) != 0) { 512 regerror (eval, &rp, errbuf, sizeof(errbuf)); 513 errx (2, "%s", errbuf); 514 } 515 free (newpat); 516 517 /* compare string against pattern */ 518 if (regexec(&rp, a->u.s, SE_MAX, rm, 0) == 0) { 519 if (rm[1].rm_so >= 0) { 520 *(a->u.s + rm[1].rm_eo) = '\0'; 521 v = make_str (a->u.s + rm[1].rm_so); 522 523 } else { 524 v = make_integer (rm[0].rm_eo - rm[0].rm_so); 525 } 526 } else { 527 if (rp.re_nsub == 0) { 528 v = make_integer (0); 529 } else { 530 v = make_str (""); 531 } 532 } 533 534 /* free arguments and pattern buffer */ 535 free_value (a); 536 free_value (b); 537 regfree (&rp); 538 539 return v; 540} 541