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