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