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