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