1 /* Yacc productions for "expr" command: */ 2 %{ 3 typedef char *yystype; 4 #define YYSTYPE yystype 5 %} 6 7 %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ 8 %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH 9 10 /* operators listed below in increasing precedence: */ 11 %left OR 12 %left AND 13 %left EQ LT GT GEQ LEQ NEQ 14 %left ADD SUBT 15 %left MULT DIV REM 16 %left MCH 17 %left MATCH 18 %left SUBSTR 19 %left LENGTH INDEX 20 %% 21 22 /* a single `expression' is evaluated and printed: */ 23 24 expression: expr NOARG = { 25 printf("%s\n", $1); 26 exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0); 27 } 28 ; 29 30 31 expr: '(' expr ')' = { $$ = $2; } 32 | expr OR expr = { $$ = conj(OR, $1, $3); } 33 | expr AND expr = { $$ = conj(AND, $1, $3); } 34 | expr EQ expr = { $$ = rel(EQ, $1, $3); } 35 | expr GT expr = { $$ = rel(GT, $1, $3); } 36 | expr GEQ expr = { $$ = rel(GEQ, $1, $3); } 37 | expr LT expr = { $$ = rel(LT, $1, $3); } 38 | expr LEQ expr = { $$ = rel(LEQ, $1, $3); } 39 | expr NEQ expr = { $$ = rel(NEQ, $1, $3); } 40 | expr ADD expr = { $$ = arith(ADD, $1, $3); } 41 | expr SUBT expr = { $$ = arith(SUBT, $1, $3); } 42 | expr MULT expr = { $$ = arith(MULT, $1, $3); } 43 | expr DIV expr = { $$ = arith(DIV, $1, $3); } 44 | expr REM expr = { $$ = arith(REM, $1, $3); } 45 | expr MCH expr = { $$ = match($1, $3); } 46 | MATCH expr expr = { $$ = match($2, $3); } 47 | SUBSTR expr expr expr = { $$ = substr($2, $3, $4); } 48 | LENGTH expr = { $$ = length($2); } 49 | INDEX expr expr = { $$ = index($2, $3); } 50 | A_STRING 51 ; 52 %% 53 /* expression command */ 54 #include <stdio.h> 55 #define ESIZE 256 56 #define error(c) errxx(c) 57 #define EQL(x,y) !strcmp(x,y) 58 long atol(); 59 char **Av; 60 int Ac; 61 int Argi; 62 63 char Mstring[1][128]; 64 char *malloc(); 65 extern int nbra; 66 67 main(argc, argv) char **argv; { 68 Ac = argc; 69 Argi = 1; 70 Av = argv; 71 yyparse(); 72 } 73 74 char *operators[] = { "|", "&", "+", "-", "*", "/", "%", ":", 75 "=", "==", "<", "<=", ">", ">=", "!=", 76 "match", "substr", "length", "index", "\0" }; 77 int op[] = { OR, AND, ADD, SUBT, MULT, DIV, REM, MCH, 78 EQ, EQ, LT, LEQ, GT, GEQ, NEQ, 79 MATCH, SUBSTR, LENGTH, INDEX }; 80 yylex() { 81 register char *p; 82 register i; 83 84 if(Argi >= Ac) return NOARG; 85 86 p = Av[Argi++]; 87 88 if(*p == '(' || *p == ')') 89 return (int)*p; 90 for(i = 0; *operators[i]; ++i) 91 if(EQL(operators[i], p)) 92 return op[i]; 93 94 yylval = p; 95 return A_STRING; 96 } 97 98 char *rel(op, r1, r2) register char *r1, *r2; { 99 register long i; 100 101 if(ematch(r1, "-*[0-9]*$") && ematch(r2, "[0-9]*$")) 102 i = atol(r1) - atol(r2); 103 else 104 i = strcmp(r1, r2); 105 switch(op) { 106 case EQ: i = i==0; break; 107 case GT: i = i>0; break; 108 case GEQ: i = i>=0; break; 109 case LT: i = i<0; break; 110 case LEQ: i = i<=0; break; 111 case NEQ: i = i!=0; break; 112 } 113 return i? "1": "0"; 114 } 115 116 char *arith(op, r1, r2) char *r1, *r2; { 117 long i1, i2; 118 register char *rv; 119 120 if(!((ematch(r1, "[0-9]*$") || ematch(r1, "-[0-9]*$")) && 121 (ematch(r2, "[0-9]*$") || ematch(r2, "-[0-9]*$")))) 122 yyerror("non-numeric argument"); 123 i1 = atol(r1); 124 i2 = atol(r2); 125 126 switch(op) { 127 case ADD: i1 = i1 + i2; break; 128 case SUBT: i1 = i1 - i2; break; 129 case MULT: i1 = i1 * i2; break; 130 case DIV: i1 = i1 / i2; break; 131 case REM: i1 = i1 % i2; break; 132 } 133 rv = malloc(16); 134 (void)sprintf(rv, "%ld", i1); 135 return rv; 136 } 137 char *conj(op, r1, r2) char *r1, *r2; { 138 register char *rv; 139 140 switch(op) { 141 142 case OR: 143 if(EQL(r1, "0") 144 || EQL(r1, "")) 145 if(EQL(r2, "0") 146 || EQL(r2, "")) 147 rv = "0"; 148 else 149 rv = r2; 150 else 151 rv = r1; 152 break; 153 case AND: 154 if(EQL(r1, "0") 155 || EQL(r1, "")) 156 rv = "0"; 157 else if(EQL(r2, "0") 158 || EQL(r2, "")) 159 rv = "0"; 160 else 161 rv = r1; 162 break; 163 } 164 return rv; 165 } 166 167 char *substr(v, s, w) char *v, *s, *w; { 168 register si, wi; 169 register char *res; 170 171 si = atol(s); 172 wi = atol(w); 173 while(--si) if(*v) ++v; 174 175 res = v; 176 177 while(wi--) if(*v) ++v; 178 179 *v = '\0'; 180 return res; 181 } 182 183 char *length(s) register char *s; { 184 register i = 0; 185 register char *rv; 186 187 while(*s++) ++i; 188 189 rv = malloc(8); 190 (void)sprintf(rv, "%d", i); 191 return rv; 192 } 193 194 char *index(s, t) char *s, *t; { 195 register i, j; 196 register char *rv; 197 198 for(i = 0; s[i] ; ++i) 199 for(j = 0; t[j] ; ++j) 200 if(s[i]==t[j]) { 201 (void)sprintf(rv = malloc(8), "%d", ++i); 202 return rv; 203 } 204 return "0"; 205 } 206 207 char *match(s, p) 208 { 209 register char *rv; 210 211 (void)sprintf(rv = malloc(8), "%d", ematch(s, p)); 212 if(nbra) { 213 rv = malloc(strlen(Mstring[0])+1); 214 strcpy(rv, Mstring[0]); 215 } 216 return rv; 217 } 218 219 #define INIT register char *sp = instring; 220 #define GETC() (*sp++) 221 #define PEEKC() (*sp) 222 #define UNGETC(c) (--sp) 223 #define RETURN(c) return 224 #define ERROR(c) errxx(c) 225 226 227 ematch(s, p) 228 char *s; 229 register char *p; 230 { 231 static char expbuf[ESIZE]; 232 char *compile(); 233 register num; 234 extern char *braslist[], *braelist[], *loc2; 235 236 compile(p, expbuf, &expbuf[ESIZE], 0); 237 if(nbra > 1) 238 yyerror("Too many '\\('s"); 239 if(advance(s, expbuf)) { 240 if(nbra == 1) { 241 p = braslist[0]; 242 num = braelist[0] - p; 243 strncpy(Mstring[0], p, num); 244 Mstring[0][num] = '\0'; 245 } 246 return(loc2-s); 247 } 248 return(0); 249 } 250 251 errxx(c) 252 { 253 yyerror("RE error"); 254 } 255 256 #define CBRA 2 257 #define CCHR 4 258 #define CDOT 8 259 #define CCL 12 260 #define CDOL 20 261 #define CEOF 22 262 #define CKET 24 263 #define CBACK 36 264 265 #define STAR 01 266 #define RNGE 03 267 268 #define NBRA 9 269 270 #define PLACE(c) ep[c >> 3] |= bittab[c & 07] 271 #define ISTHERE(c) (ep[c >> 3] & bittab[c & 07]) 272 273 char *braslist[NBRA]; 274 char *braelist[NBRA]; 275 int nbra; 276 char *loc1, *loc2, *locs; 277 int sed; 278 279 int circf; 280 int low; 281 int size; 282 283 char bittab[] = { 284 1, 285 2, 286 4, 287 8, 288 16, 289 32, 290 64, 291 128 292 }; 293 294 char * 295 compile(instring, ep, endbuf, seof) 296 register char *ep; 297 char *instring, *endbuf; 298 { 299 INIT /* Dependent declarations and initializations */ 300 register c; 301 register eof = seof; 302 char *lastep = instring; 303 int cclcnt; 304 char bracket[NBRA], *bracketp; 305 int closed; 306 char neg; 307 int lc; 308 int i, cflg; 309 310 lastep = 0; 311 if((c = GETC()) == eof) { 312 if(*ep == 0 && !sed) 313 ERROR(41); 314 RETURN(ep); 315 } 316 bracketp = bracket; 317 circf = closed = nbra = 0; 318 if (c == '^') 319 circf++; 320 else 321 UNGETC(c); 322 for (;;) { 323 if (ep >= endbuf) 324 ERROR(50); 325 if((c = GETC()) != '*' && ((c != '\\') || (PEEKC() != '{'))) 326 lastep = ep; 327 if (c == eof) { 328 *ep++ = CEOF; 329 RETURN(ep); 330 } 331 switch (c) { 332 333 case '.': 334 *ep++ = CDOT; 335 continue; 336 337 case '\n': 338 ERROR(36); 339 case '*': 340 if (lastep==0 || *lastep==CBRA || *lastep==CKET) 341 goto defchar; 342 *lastep |= STAR; 343 continue; 344 345 case '$': 346 if(PEEKC() != eof) 347 goto defchar; 348 *ep++ = CDOL; 349 continue; 350 351 case '[': 352 if(&ep[17] >= endbuf) 353 ERROR(50); 354 355 *ep++ = CCL; 356 lc = 0; 357 for(i = 0; i < 16; i++) 358 ep[i] = 0; 359 360 neg = 0; 361 if((c = GETC()) == '^') { 362 neg = 1; 363 c = GETC(); 364 } 365 366 do { 367 if(c == '\0' || c == '\n') 368 ERROR(49); 369 if(c == '-' && lc != 0) { 370 if ((c = GETC()) == ']') { 371 PLACE('-'); 372 break; 373 } 374 while(lc < c) { 375 PLACE(lc); 376 lc++; 377 } 378 } 379 lc = c; 380 PLACE(c); 381 } while((c = GETC()) != ']'); 382 if(neg) { 383 for(cclcnt = 0; cclcnt < 16; cclcnt++) 384 ep[cclcnt] ^= -1; 385 ep[0] &= 0376; 386 } 387 388 ep += 16; 389 390 continue; 391 392 case '\\': 393 switch(c = GETC()) { 394 395 case '(': 396 if(nbra >= NBRA) 397 ERROR(43); 398 *bracketp++ = nbra; 399 *ep++ = CBRA; 400 *ep++ = nbra++; 401 continue; 402 403 case ')': 404 if(bracketp <= bracket) 405 ERROR(42); 406 *ep++ = CKET; 407 *ep++ = *--bracketp; 408 closed++; 409 continue; 410 411 case '{': 412 if(lastep == (char *) (0)) 413 goto defchar; 414 *lastep |= RNGE; 415 cflg = 0; 416 nlim: 417 c = GETC(); 418 i = 0; 419 do { 420 if ('0' <= c && c <= '9') 421 i = 10 * i + c - '0'; 422 else 423 ERROR(16); 424 } while(((c = GETC()) != '\\') && (c != ',')); 425 if (i > 255) 426 ERROR(11); 427 *ep++ = i; 428 if (c == ',') { 429 if(cflg++) 430 ERROR(44); 431 if((c = GETC()) == '\\') 432 *ep++ = 255; 433 else { 434 UNGETC(c); 435 goto nlim; /* get 2'nd number */ 436 } 437 } 438 if(GETC() != '}') 439 ERROR(45); 440 if(!cflg) /* one number */ 441 *ep++ = i; 442 else if((ep[-1] & 0377) < (ep[-2] & 0377)) 443 ERROR(46); 444 continue; 445 446 case '\n': 447 ERROR(36); 448 449 case 'n': 450 c = '\n'; 451 goto defchar; 452 453 default: 454 if(c >= '1' && c <= '9') { 455 if((c -= '1') >= closed) 456 ERROR(25); 457 *ep++ = CBACK; 458 *ep++ = c; 459 continue; 460 } 461 } 462 /* Drop through to default to use \ to turn off special chars */ 463 464 defchar: 465 default: 466 lastep = ep; 467 *ep++ = CCHR; 468 *ep++ = c; 469 } 470 } 471 } 472 473 step(p1, p2) 474 register char *p1, *p2; 475 { 476 register c; 477 478 if (circf) { 479 loc1 = p1; 480 return(advance(p1, p2)); 481 } 482 /* fast check for first character */ 483 if (*p2==CCHR) { 484 c = p2[1]; 485 do { 486 if (*p1 != c) 487 continue; 488 if (advance(p1, p2)) { 489 loc1 = p1; 490 return(1); 491 } 492 } while (*p1++); 493 return(0); 494 } 495 /* regular algorithm */ 496 do { 497 if (advance(p1, p2)) { 498 loc1 = p1; 499 return(1); 500 } 501 } while (*p1++); 502 return(0); 503 } 504 505 advance(lp, ep) 506 register char *lp, *ep; 507 { 508 register char *curlp; 509 char c; 510 char *bbeg; 511 int ct; 512 513 for (;;) switch (*ep++) { 514 515 case CCHR: 516 if (*ep++ == *lp++) 517 continue; 518 return(0); 519 520 case CDOT: 521 if (*lp++) 522 continue; 523 return(0); 524 525 case CDOL: 526 if (*lp==0) 527 continue; 528 return(0); 529 530 case CEOF: 531 loc2 = lp; 532 return(1); 533 534 case CCL: 535 c = *lp++ & 0177; 536 if(ISTHERE(c)) { 537 ep += 16; 538 continue; 539 } 540 return(0); 541 case CBRA: 542 braslist[*ep++] = lp; 543 continue; 544 545 case CKET: 546 braelist[*ep++] = lp; 547 continue; 548 549 case CCHR|RNGE: 550 c = *ep++; 551 getrnge(ep); 552 while(low--) 553 if(*lp++ != c) 554 return(0); 555 curlp = lp; 556 while(size--) 557 if(*lp++ != c) 558 break; 559 if(size < 0) 560 lp++; 561 ep += 2; 562 goto star; 563 564 case CDOT|RNGE: 565 getrnge(ep); 566 while(low--) 567 if(*lp++ == '\0') 568 return(0); 569 curlp = lp; 570 while(size--) 571 if(*lp++ == '\0') 572 break; 573 if(size < 0) 574 lp++; 575 ep += 2; 576 goto star; 577 578 case CCL|RNGE: 579 getrnge(ep + 16); 580 while(low--) { 581 c = *lp++ & 0177; 582 if(!ISTHERE(c)) 583 return(0); 584 } 585 curlp = lp; 586 while(size--) { 587 c = *lp++ & 0177; 588 if(!ISTHERE(c)) 589 break; 590 } 591 if(size < 0) 592 lp++; 593 ep += 18; /* 16 + 2 */ 594 goto star; 595 596 case CBACK: 597 bbeg = braslist[*ep]; 598 ct = braelist[*ep++] - bbeg; 599 600 if(ecmp(bbeg, lp, ct)) { 601 lp += ct; 602 continue; 603 } 604 return(0); 605 606 case CBACK|STAR: 607 bbeg = braslist[*ep]; 608 ct = braelist[*ep++] - bbeg; 609 curlp = lp; 610 while(ecmp(bbeg, lp, ct)) 611 lp += ct; 612 613 while(lp >= curlp) { 614 if(advance(lp, ep)) return(1); 615 lp -= ct; 616 } 617 return(0); 618 619 620 case CDOT|STAR: 621 curlp = lp; 622 while (*lp++); 623 goto star; 624 625 case CCHR|STAR: 626 curlp = lp; 627 while (*lp++ == *ep); 628 ep++; 629 goto star; 630 631 case CCL|STAR: 632 curlp = lp; 633 do { 634 c = *lp++ & 0177; 635 } while(ISTHERE(c)); 636 ep += 16; 637 goto star; 638 639 star: 640 do { 641 if(--lp == locs) 642 break; 643 if (advance(lp, ep)) 644 return(1); 645 } while (lp > curlp); 646 return(0); 647 648 } 649 } 650 651 getrnge(str) 652 register char *str; 653 { 654 low = *str++ & 0377; 655 size = (*str & 0377) == 255 ? 20000 : (*str & 0377) - low; 656 } 657 658 ecmp(a, b, count) 659 register char *a, *b; 660 register count; 661 { 662 if(a == b) /* should have been caught in compile() */ 663 error(51); 664 while(count--) 665 if(*a++ != *b++) return(0); 666 return(1); 667 } 668 669 static char *sccsid = "@(#)expr.y 4.8 (Berkeley) 06/24/90"; 670 yyerror(s) 671 672 { 673 fprintf(stderr, "%s\n", s); 674 exit(2); 675 } 676