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