expr.y revision 468
1344957Smarcel%{ 2344957Smarcel/* Written by Pace Willisson (pace@blitz.com) 3344957Smarcel * and placed in the public domain. 4344957Smarcel * 5344957Smarcel * Largely rewritten by J.T. Conklin (jtc@wimsey.com) 6344957Smarcel * 7344957Smarcel * $Id : /b/source/CVS/src/bin/expr/expr.y,v 1.11 1993/08/17 16:01:23 jtc Exp $ 8344957Smarcel */ 9344957Smarcel 10344957Smarcel#include <stdio.h> 11344957Smarcel#include <stdlib.h> 12344957Smarcel#include <string.h> 13344957Smarcel#include <locale.h> 14344957Smarcel#include <ctype.h> 15344957Smarcel#include <err.h> 16344957Smarcel 17344957Smarcelenum valtype { 18344957Smarcel integer, string 19344957Smarcel} ; 20344957Smarcel 21344957Smarcelstruct val { 22344957Smarcel enum valtype type; 23344957Smarcel union { 24344957Smarcel char *s; 25344957Smarcel int i; 26344957Smarcel } u; 27344957Smarcel} ; 28344957Smarcel 29344957Smarcelstruct val *result; 30344957Smarcelstruct val *op_or (); 31344957Smarcelstruct val *op_and (); 32344957Smarcelstruct val *op_eq (); 33344957Smarcelstruct val *op_gt (); 34344957Smarcelstruct val *op_lt (); 35344957Smarcelstruct val *op_ge (); 36344957Smarcelstruct val *op_le (); 37344957Smarcelstruct val *op_ne (); 38344957Smarcelstruct val *op_plus (); 39344957Smarcelstruct val *op_minus (); 40344957Smarcelstruct val *op_times (); 41344957Smarcelstruct val *op_div (); 42344957Smarcelstruct val *op_rem (); 43344957Smarcelstruct val *op_colon (); 44344957Smarcel 45344957Smarcelchar **av; 46344957Smarcel%} 47344957Smarcel 48344957Smarcel%union 49344957Smarcel{ 50344957Smarcel struct val *val; 51344957Smarcel} 52344957Smarcel 53344957Smarcel%left <val> '|' 54344957Smarcel%left <val> '&' 55344957Smarcel%left <val> '=' '>' '<' GE LE NE 56344957Smarcel%left <val> '+' '-' 57344957Smarcel%left <val> '*' '/' '%' 58344957Smarcel%left <val> ':' 59344957Smarcel%left UNARY 60344957Smarcel 61344957Smarcel%token <val> TOKEN 62344957Smarcel%type <val> start expr 63344957Smarcel 64344957Smarcel%% 65344957Smarcel 66344957Smarcelstart: expr { result = $$; } 67344957Smarcel 68344957Smarcelexpr: TOKEN 69344957Smarcel | '(' expr ')' { $$ = $2; } 70344957Smarcel | expr '|' expr { $$ = op_or ($1, $3); } 71344957Smarcel | expr '&' expr { $$ = op_and ($1, $3); } 72344957Smarcel | expr '=' expr { $$ = op_eq ($1, $3); } 73344957Smarcel | expr '>' expr { $$ = op_gt ($1, $3); } 74344957Smarcel | expr '<' expr { $$ = op_lt ($1, $3); } 75344957Smarcel | expr GE expr { $$ = op_ge ($1, $3); } 76344957Smarcel | expr LE expr { $$ = op_le ($1, $3); } 77344957Smarcel | expr NE expr { $$ = op_ne ($1, $3); } 78344957Smarcel | expr '+' expr { $$ = op_plus ($1, $3); } 79344957Smarcel | expr '-' expr { $$ = op_minus ($1, $3); } 80344957Smarcel | expr '*' expr { $$ = op_times ($1, $3); } 81344957Smarcel | expr '/' expr { $$ = op_div ($1, $3); } 82344957Smarcel | expr '%' expr { $$ = op_rem ($1, $3); } 83344957Smarcel | expr ':' expr { $$ = op_colon ($1, $3); } 84344957Smarcel ; 85344957Smarcel 86344957Smarcel 87344957Smarcel%% 88344957Smarcel 89344957Smarcelstruct val * 90344957Smarcelmake_integer (i) 91344957Smarcelint i; 92344957Smarcel{ 93344957Smarcel struct val *vp; 94344957Smarcel 95344957Smarcel vp = (struct val *) malloc (sizeof (*vp)); 96344957Smarcel if (vp == NULL) { 97344957Smarcel err (2, NULL); 98344957Smarcel } 99344957Smarcel 100344957Smarcel vp->type = integer; 101344957Smarcel vp->u.i = i; 102344957Smarcel return vp; 103344957Smarcel} 104344957Smarcel 105344957Smarcelstruct val * 106344957Smarcelmake_str (s) 107344957Smarcelchar *s; 108344957Smarcel{ 109344957Smarcel struct val *vp; 110344957Smarcel 111344957Smarcel vp = (struct val *) malloc (sizeof (*vp)); 112344957Smarcel if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) { 113344957Smarcel err (2, NULL); 114344957Smarcel } 115344957Smarcel 116344957Smarcel vp->type = string; 117344957Smarcel return vp; 118344957Smarcel} 119344957Smarcel 120344957Smarcel 121344957Smarcelvoid 122344957Smarcelfree_value (vp) 123344957Smarcelstruct val *vp; 124344957Smarcel{ 125344957Smarcel if (vp->type == string) 126344957Smarcel free (vp->u.s); 127344957Smarcel} 128344957Smarcel 129344957Smarcel 130344957Smarcelint 131344957Smarcelto_integer (vp) 132344957Smarcelstruct val *vp; 133344957Smarcel{ 134344957Smarcel char *s; 135344957Smarcel int neg; 136344957Smarcel int i; 137344957Smarcel 138344957Smarcel if (vp->type == integer) 139344957Smarcel return 1; 140344957Smarcel 141344957Smarcel s = vp->u.s; 142344957Smarcel i = 0; 143344957Smarcel 144344957Smarcel neg = (*s == '-'); 145344957Smarcel if (neg) 146344957Smarcel s++; 147344957Smarcel 148344957Smarcel for (;*s; s++) { 149344957Smarcel if (!isdigit (*s)) 150344957Smarcel return 0; 151344957Smarcel 152344957Smarcel i *= 10; 153344957Smarcel i += *s - '0'; 154344957Smarcel } 155344957Smarcel 156344957Smarcel free (vp->u.s); 157344957Smarcel if (neg) 158344957Smarcel i *= -1; 159344957Smarcel 160344957Smarcel vp->type = integer; 161344957Smarcel vp->u.i = i; 162344957Smarcel return 1; 163344957Smarcel} 164344957Smarcel 165344957Smarcelvoid 166344957Smarcelto_string (vp) 167344957Smarcelstruct val *vp; 168344957Smarcel{ 169344957Smarcel char *tmp; 170344957Smarcel 171344957Smarcel if (vp->type == string) 172344957Smarcel return; 173344957Smarcel 174344957Smarcel tmp = malloc (25); 175344957Smarcel if (tmp == NULL) { 176344957Smarcel err (2, NULL); 177344957Smarcel } 178344957Smarcel 179344957Smarcel sprintf (tmp, "%d", vp->u.i); 180344957Smarcel vp->type = string; 181344957Smarcel vp->u.s = tmp; 182344957Smarcel} 183344957Smarcel 184344957Smarcel 185344957Smarcelint 186344957Smarcelisstring (vp) 187344957Smarcelstruct val *vp; 188344957Smarcel{ 189344957Smarcel return (vp->type == string); 190344957Smarcel} 191344957Smarcel 192344957Smarcel 193344957Smarcelint 194344957Smarcelyylex () 195344957Smarcel{ 196344957Smarcel struct val *vp; 197344957Smarcel char *p; 198344957Smarcel 199344957Smarcel if (*av == NULL) 200344957Smarcel return (0); 201344957Smarcel 202344957Smarcel p = *av++; 203344957Smarcel 204344957Smarcel if (strlen (p) == 1) { 205344957Smarcel if (strchr ("|&=<>+-*/%:()", *p)) 206344957Smarcel return (*p); 207344957Smarcel } else if (strlen (p) == 2 && p[1] == '=') { 208344957Smarcel switch (*p) { 209344957Smarcel case '>': return (GE); 210344957Smarcel case '<': return (LE); 211344957Smarcel case '!': return (NE); 212344957Smarcel } 213344957Smarcel } 214344957Smarcel 215344957Smarcel yylval.val = make_str (p); 216344957Smarcel return (TOKEN); 217344957Smarcel} 218344957Smarcel 219344957Smarcelint 220344957Smarcelis_zero_or_null (vp) 221344957Smarcelstruct val *vp; 222344957Smarcel{ 223344957Smarcel if (vp->type == integer) { 224344957Smarcel return (vp->u.i == 0); 225344957Smarcel } else { 226344957Smarcel return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0)); 227344957Smarcel } 228344957Smarcel /* NOTREACHED */ 229344957Smarcel} 230344957Smarcel 231344957Smarcelvoid 232344957Smarcelmain (argc, argv) 233344957Smarcelint argc; 234344957Smarcelchar **argv; 235344957Smarcel{ 236344957Smarcel setlocale (LC_ALL, ""); 237344957Smarcel 238344957Smarcel av = argv + 1; 239344957Smarcel 240344957Smarcel yyparse (); 241344957Smarcel 242344957Smarcel if (result->type == integer) 243344957Smarcel printf ("%d\n", result->u.i); 244344957Smarcel else 245344957Smarcel printf ("%s\n", result->u.s); 246344957Smarcel 247344957Smarcel exit (is_zero_or_null (result)); 248344957Smarcel} 249344957Smarcel 250344957Smarcelint 251344957Smarcelyyerror (s) 252344957Smarcelchar *s; 253344957Smarcel{ 254344957Smarcel errx (2, "syntax error"); 255344957Smarcel} 256344957Smarcel 257344957Smarcel 258344957Smarcelstruct val * 259344957Smarcelop_or (a, b) 260344957Smarcelstruct val *a, *b; 261344957Smarcel{ 262344957Smarcel if (is_zero_or_null (a)) { 263344957Smarcel free_value (a); 264344957Smarcel return (b); 265344957Smarcel } else { 266344957Smarcel free_value (b); 267344957Smarcel return (a); 268344957Smarcel } 269344957Smarcel} 270344957Smarcel 271344957Smarcelstruct val * 272344957Smarcelop_and (a, b) 273344957Smarcelstruct val *a, *b; 274344957Smarcel{ 275344957Smarcel if (is_zero_or_null (a) || is_zero_or_null (b)) { 276344957Smarcel free_value (a); 277344957Smarcel free_value (b); 278344957Smarcel return (make_integer (0)); 279344957Smarcel } else { 280344957Smarcel free_value (b); 281344957Smarcel return (a); 282344957Smarcel } 283344957Smarcel} 284344957Smarcel 285344957Smarcelstruct val * 286344957Smarcelop_eq (a, b) 287344957Smarcelstruct val *a, *b; 288344957Smarcel{ 289344957Smarcel struct val *r; 290344957Smarcel 291344957Smarcel if (isstring (a) || isstring (b)) { 292344957Smarcel to_string (a); 293344957Smarcel to_string (b); 294344957Smarcel r = make_integer (strcoll (a->u.s, b->u.s) == 0); 295344957Smarcel } else { 296344957Smarcel r = make_integer (a->u.i == b->u.i); 297344957Smarcel } 298344957Smarcel 299344957Smarcel free_value (a); 300344957Smarcel free_value (b); 301344957Smarcel return r; 302344957Smarcel} 303344957Smarcel 304344957Smarcelstruct val * 305344957Smarcelop_gt (a, b) 306344957Smarcelstruct val *a, *b; 307344957Smarcel{ 308344957Smarcel struct val *r; 309344957Smarcel 310344957Smarcel if (isstring (a) || isstring (b)) { 311344957Smarcel to_string (a); 312344957Smarcel to_string (b); 313344957Smarcel r = make_integer (strcoll (a->u.s, b->u.s) > 0); 314344957Smarcel } else { 315344957Smarcel 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