expr.y revision 468
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 : /b/source/CVS/src/bin/expr/expr.y,v 1.11 1993/08/17 16:01:23 jtc 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 17enum valtype { 18 integer, string 19} ; 20 21struct val { 22 enum valtype type; 23 union { 24 char *s; 25 int i; 26 } u; 27} ; 28 29struct val *result; 30struct val *op_or (); 31struct val *op_and (); 32struct val *op_eq (); 33struct val *op_gt (); 34struct val *op_lt (); 35struct val *op_ge (); 36struct val *op_le (); 37struct val *op_ne (); 38struct val *op_plus (); 39struct val *op_minus (); 40struct val *op_times (); 41struct val *op_div (); 42struct val *op_rem (); 43struct val *op_colon (); 44 45char **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 66start: expr { result = $$; } 67 68expr: 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 89struct val * 90make_integer (i) 91int 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 105struct val * 106make_str (s) 107char *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 121void 122free_value (vp) 123struct val *vp; 124{ 125 if (vp->type == string) 126 free (vp->u.s); 127} 128 129 130int 131to_integer (vp) 132struct 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 165void 166to_string (vp) 167struct 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 185int 186isstring (vp) 187struct val *vp; 188{ 189 return (vp->type == string); 190} 191 192 193int 194yylex () 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 219int 220is_zero_or_null (vp) 221struct 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 231void 232main (argc, argv) 233int argc; 234char **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 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 489struct val * 490op_colon (a, b) 491struct val *a, *b; 492{ 493 regex_t rp; 494 regmatch_t rm[2]; 495 char errbuf[256]; 496 int eval; 497 struct val *v; 498 char *newpat; 499 500 /* coerce to both arguments to strings */ 501 to_string(a); 502 to_string(b); 503 504 /* patterns are anchored to the beginning of the line */ 505 newpat = malloc (strlen (b->u.s) + 2); 506 strcpy (newpat, "^"); 507 strcat (newpat, b->u.s); 508 509 /* compile regular expression */ 510 if ((eval = regcomp (&rp, newpat, 0)) != 0) { 511 regerror (eval, &rp, errbuf, sizeof(errbuf)); 512 errx (2, "%s", errbuf); 513 } 514 free (newpat); 515 516 /* compare string against pattern */ 517 if (regexec(&rp, a->u.s, 2, rm, 0) == 0) { 518 if (rm[1].rm_so >= 0) { 519 *(a->u.s + rm[1].rm_eo) = '\0'; 520 v = make_str (a->u.s + rm[1].rm_so); 521 522 } else { 523 v = make_integer (rm[0].rm_eo - rm[0].rm_so); 524 } 525 } else { 526 if (rp.re_nsub == 0) { 527 v = make_integer (0); 528 } else { 529 v = make_str (""); 530 } 531 } 532 533 /* free arguments and pattern buffer */ 534 free_value (a); 535 free_value (b); 536 regfree (&rp); 537 538 return v; 539} 540