|
|
1.1 ! root 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) 4/24/88"; ! 666: yyerror(s) ! 667: ! 668: { ! 669: fprintf(stderr, "%s\n", s); ! 670: exit(2); ! 671: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.