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