|
|
1.1 ! root 1: /* Copyright (c) 1981 Regents of the University of California */ ! 2: static char *sccsid = "@(#)ex_re.c 7.3 6/18/83"; ! 3: #include "ex.h" ! 4: #include "ex_re.h" ! 5: ! 6: /* ! 7: * Global, substitute and regular expressions. ! 8: * Very similar to ed, with some re extensions and ! 9: * confirmed substitute. ! 10: */ ! 11: global(k) ! 12: bool k; ! 13: { ! 14: register char *gp; ! 15: register int c; ! 16: register line *a1; ! 17: char globuf[GBSIZE], *Cwas; ! 18: int lines = lineDOL(); ! 19: int oinglobal = inglobal; ! 20: char *oglobp = globp; ! 21: ! 22: Cwas = Command; ! 23: /* ! 24: * States of inglobal: ! 25: * 0: ordinary - not in a global command. ! 26: * 1: text coming from some buffer, not tty. ! 27: * 2: like 1, but the source of the buffer is a global command. ! 28: * Hence you're only in a global command if inglobal==2. This ! 29: * strange sounding convention is historically derived from ! 30: * everybody simulating a global command. ! 31: */ ! 32: if (inglobal==2) ! 33: error("Global within global@not allowed"); ! 34: markDOT(); ! 35: setall(); ! 36: nonzero(); ! 37: if (skipend()) ! 38: error("Global needs re|Missing regular expression for global"); ! 39: c = getchar(); ! 40: ignore(compile(c, 1)); ! 41: savere(scanre); ! 42: gp = globuf; ! 43: while ((c = getchar()) != '\n') { ! 44: switch (c) { ! 45: ! 46: case EOF: ! 47: c = '\n'; ! 48: goto brkwh; ! 49: ! 50: case '\\': ! 51: c = getchar(); ! 52: switch (c) { ! 53: ! 54: case '\\': ! 55: ungetchar(c); ! 56: break; ! 57: ! 58: case '\n': ! 59: break; ! 60: ! 61: default: ! 62: *gp++ = '\\'; ! 63: break; ! 64: } ! 65: break; ! 66: } ! 67: *gp++ = c; ! 68: if (gp >= &globuf[GBSIZE - 2]) ! 69: error("Global command too long"); ! 70: } ! 71: brkwh: ! 72: ungetchar(c); ! 73: out: ! 74: newline(); ! 75: *gp++ = c; ! 76: *gp++ = 0; ! 77: saveall(); ! 78: inglobal = 2; ! 79: for (a1 = one; a1 <= dol; a1++) { ! 80: *a1 &= ~01; ! 81: if (a1 >= addr1 && a1 <= addr2 && execute(0, a1) == k) ! 82: *a1 |= 01; ! 83: } ! 84: #ifdef notdef ! 85: /* ! 86: * This code is commented out for now. The problem is that we don't ! 87: * fix up the undo area the way we should. Basically, I think what has ! 88: * to be done is to copy the undo area down (since we shrunk everything) ! 89: * and move the various pointers into it down too. I will do this later ! 90: * when I have time. (Mark, 10-20-80) ! 91: */ ! 92: /* ! 93: * Special case: g/.../d (avoid n^2 algorithm) ! 94: */ ! 95: if (globuf[0]=='d' && globuf[1]=='\n' && globuf[2]=='\0') { ! 96: gdelete(); ! 97: return; ! 98: } ! 99: #endif ! 100: if (inopen) ! 101: inopen = -1; ! 102: /* ! 103: * Now for each marked line, set dot there and do the commands. ! 104: * Note the n^2 behavior here for lots of lines matching. ! 105: * This is really needed: in some cases you could delete lines, ! 106: * causing a marked line to be moved before a1 and missed if ! 107: * we didn't restart at zero each time. ! 108: */ ! 109: for (a1 = one; a1 <= dol; a1++) { ! 110: if (*a1 & 01) { ! 111: *a1 &= ~01; ! 112: dot = a1; ! 113: globp = globuf; ! 114: commands(1, 1); ! 115: a1 = zero; ! 116: } ! 117: } ! 118: globp = oglobp; ! 119: inglobal = oinglobal; ! 120: endline = 1; ! 121: Command = Cwas; ! 122: netchHAD(lines); ! 123: setlastchar(EOF); ! 124: if (inopen) { ! 125: ungetchar(EOF); ! 126: inopen = 1; ! 127: } ! 128: } ! 129: ! 130: /* ! 131: * gdelete: delete inside a global command. Handles the ! 132: * special case g/r.e./d. All lines to be deleted have ! 133: * already been marked. Squeeze the remaining lines together. ! 134: * Note that other cases such as g/r.e./p, g/r.e./s/r.e.2/rhs/, ! 135: * and g/r.e./.,/r.e.2/d are not treated specially. There is no ! 136: * good reason for this except the question: where to you draw the line? ! 137: */ ! 138: gdelete() ! 139: { ! 140: register line *a1, *a2, *a3; ! 141: ! 142: a3 = dol; ! 143: /* find first marked line. can skip all before it */ ! 144: for (a1=zero; (*a1&01)==0; a1++) ! 145: if (a1>=a3) ! 146: return; ! 147: /* copy down unmarked lines, compacting as we go. */ ! 148: for (a2=a1+1; a2<=a3;) { ! 149: if (*a2&01) { ! 150: a2++; /* line is marked, skip it */ ! 151: dot = a1; /* dot left after line deletion */ ! 152: } else ! 153: *a1++ = *a2++; /* unmarked, copy it */ ! 154: } ! 155: dol = a1-1; ! 156: if (dot>dol) ! 157: dot = dol; ! 158: change(); ! 159: } ! 160: ! 161: bool cflag; ! 162: int scount, slines, stotal; ! 163: ! 164: substitute(c) ! 165: int c; ! 166: { ! 167: register line *addr; ! 168: register int n; ! 169: int gsubf, hopcount; ! 170: ! 171: gsubf = compsub(c); ! 172: if(FIXUNDO) ! 173: save12(), undkind = UNDCHANGE; ! 174: stotal = 0; ! 175: slines = 0; ! 176: for (addr = addr1; addr <= addr2; addr++) { ! 177: scount = hopcount = 0; ! 178: if (dosubcon(0, addr) == 0) ! 179: continue; ! 180: if (gsubf) { ! 181: /* ! 182: * The loop can happen from s/\</&/g ! 183: * but we don't want to break other, reasonable cases. ! 184: */ ! 185: while (*loc2) { ! 186: if (++hopcount > sizeof linebuf) ! 187: error("substitution loop"); ! 188: if (dosubcon(1, addr) == 0) ! 189: break; ! 190: } ! 191: } ! 192: if (scount) { ! 193: stotal += scount; ! 194: slines++; ! 195: putmark(addr); ! 196: n = append(getsub, addr); ! 197: addr += n; ! 198: addr2 += n; ! 199: } ! 200: } ! 201: if (stotal == 0 && !inglobal && !cflag) ! 202: error("Fail|Substitute pattern match failed"); ! 203: snote(stotal, slines); ! 204: return (stotal); ! 205: } ! 206: ! 207: compsub(ch) ! 208: { ! 209: register int seof, c, uselastre; ! 210: static int gsubf; ! 211: ! 212: if (!value(EDCOMPATIBLE)) ! 213: gsubf = cflag = 0; ! 214: uselastre = 0; ! 215: switch (ch) { ! 216: ! 217: case 's': ! 218: ignore(skipwh()); ! 219: seof = getchar(); ! 220: if (endcmd(seof) || any(seof, "gcr")) { ! 221: ungetchar(seof); ! 222: goto redo; ! 223: } ! 224: if (isalpha(seof) || isdigit(seof)) ! 225: error("Substitute needs re|Missing regular expression for substitute"); ! 226: seof = compile(seof, 1); ! 227: uselastre = 1; ! 228: comprhs(seof); ! 229: gsubf = 0; ! 230: cflag = 0; ! 231: break; ! 232: ! 233: case '~': ! 234: uselastre = 1; ! 235: /* fall into ... */ ! 236: case '&': ! 237: redo: ! 238: if (re.Expbuf[0] == 0) ! 239: error("No previous re|No previous regular expression"); ! 240: if (subre.Expbuf[0] == 0) ! 241: error("No previous substitute re|No previous substitute to repeat"); ! 242: break; ! 243: } ! 244: for (;;) { ! 245: c = getchar(); ! 246: switch (c) { ! 247: ! 248: case 'g': ! 249: gsubf = !gsubf; ! 250: continue; ! 251: ! 252: case 'c': ! 253: cflag = !cflag; ! 254: continue; ! 255: ! 256: case 'r': ! 257: uselastre = 1; ! 258: continue; ! 259: ! 260: default: ! 261: ungetchar(c); ! 262: setcount(); ! 263: newline(); ! 264: if (uselastre) ! 265: savere(subre); ! 266: else ! 267: resre(subre); ! 268: return (gsubf); ! 269: } ! 270: } ! 271: } ! 272: ! 273: comprhs(seof) ! 274: int seof; ! 275: { ! 276: register char *rp, *orp; ! 277: register int c; ! 278: char orhsbuf[RHSSIZE]; ! 279: ! 280: rp = rhsbuf; ! 281: CP(orhsbuf, rp); ! 282: for (;;) { ! 283: c = getchar(); ! 284: if (c == seof) ! 285: break; ! 286: switch (c) { ! 287: ! 288: case '\\': ! 289: c = getchar(); ! 290: if (c == EOF) { ! 291: ungetchar(c); ! 292: break; ! 293: } ! 294: if (value(MAGIC)) { ! 295: /* ! 296: * When "magic", \& turns into a plain &, ! 297: * and all other chars work fine quoted. ! 298: */ ! 299: if (c != '&') ! 300: c |= QUOTE; ! 301: break; ! 302: } ! 303: magic: ! 304: if (c == '~') { ! 305: for (orp = orhsbuf; *orp; *rp++ = *orp++) ! 306: if (rp >= &rhsbuf[RHSSIZE - 1]) ! 307: goto toobig; ! 308: continue; ! 309: } ! 310: c |= QUOTE; ! 311: break; ! 312: ! 313: case '\n': ! 314: case EOF: ! 315: if (!(globp && globp[0])) { ! 316: ungetchar(c); ! 317: goto endrhs; ! 318: } ! 319: ! 320: case '~': ! 321: case '&': ! 322: if (value(MAGIC)) ! 323: goto magic; ! 324: break; ! 325: } ! 326: if (rp >= &rhsbuf[RHSSIZE - 1]) { ! 327: toobig: ! 328: *rp = 0; ! 329: error("Replacement pattern too long@- limit 256 characters"); ! 330: } ! 331: *rp++ = c; ! 332: } ! 333: endrhs: ! 334: *rp++ = 0; ! 335: } ! 336: ! 337: getsub() ! 338: { ! 339: register char *p; ! 340: ! 341: if ((p = linebp) == 0) ! 342: return (EOF); ! 343: strcLIN(p); ! 344: linebp = 0; ! 345: return (0); ! 346: } ! 347: ! 348: dosubcon(f, a) ! 349: bool f; ! 350: line *a; ! 351: { ! 352: ! 353: if (execute(f, a) == 0) ! 354: return (0); ! 355: if (confirmed(a)) { ! 356: dosub(); ! 357: scount++; ! 358: } ! 359: return (1); ! 360: } ! 361: ! 362: confirmed(a) ! 363: line *a; ! 364: { ! 365: register int c, ch; ! 366: ! 367: if (cflag == 0) ! 368: return (1); ! 369: pofix(); ! 370: pline(lineno(a)); ! 371: if (inopen) ! 372: putchar('\n' | QUOTE); ! 373: c = column(loc1 - 1); ! 374: ugo(c - 1 + (inopen ? 1 : 0), ' '); ! 375: ugo(column(loc2 - 1) - c, '^'); ! 376: flush(); ! 377: ch = c = getkey(); ! 378: again: ! 379: if (c == '\r') ! 380: c = '\n'; ! 381: if (inopen) ! 382: putchar(c), flush(); ! 383: if (c != '\n' && c != EOF) { ! 384: c = getkey(); ! 385: goto again; ! 386: } ! 387: noteinp(); ! 388: return (ch == 'y'); ! 389: } ! 390: ! 391: getch() ! 392: { ! 393: char c; ! 394: ! 395: if (read(2, &c, 1) != 1) ! 396: return (EOF); ! 397: return (c & TRIM); ! 398: } ! 399: ! 400: ugo(cnt, with) ! 401: int with; ! 402: int cnt; ! 403: { ! 404: ! 405: if (cnt > 0) ! 406: do ! 407: putchar(with); ! 408: while (--cnt > 0); ! 409: } ! 410: ! 411: int casecnt; ! 412: bool destuc; ! 413: ! 414: dosub() ! 415: { ! 416: register char *lp, *sp, *rp; ! 417: int c; ! 418: ! 419: lp = linebuf; ! 420: sp = genbuf; ! 421: rp = rhsbuf; ! 422: while (lp < loc1) ! 423: *sp++ = *lp++; ! 424: casecnt = 0; ! 425: while (c = *rp++) { ! 426: /* ^V <return> from vi to split lines */ ! 427: if (c == '\r') ! 428: c = '\n'; ! 429: ! 430: if (c & QUOTE) ! 431: switch (c & TRIM) { ! 432: ! 433: case '&': ! 434: sp = place(sp, loc1, loc2); ! 435: if (sp == 0) ! 436: goto ovflo; ! 437: continue; ! 438: ! 439: case 'l': ! 440: casecnt = 1; ! 441: destuc = 0; ! 442: continue; ! 443: ! 444: case 'L': ! 445: casecnt = LBSIZE; ! 446: destuc = 0; ! 447: continue; ! 448: ! 449: case 'u': ! 450: casecnt = 1; ! 451: destuc = 1; ! 452: continue; ! 453: ! 454: case 'U': ! 455: casecnt = LBSIZE; ! 456: destuc = 1; ! 457: continue; ! 458: ! 459: case 'E': ! 460: case 'e': ! 461: casecnt = 0; ! 462: continue; ! 463: } ! 464: if (c < 0 && (c &= TRIM) >= '1' && c < nbra + '1') { ! 465: sp = place(sp, braslist[c - '1'], braelist[c - '1']); ! 466: if (sp == 0) ! 467: goto ovflo; ! 468: continue; ! 469: } ! 470: if (casecnt) ! 471: *sp++ = fixcase(c & TRIM); ! 472: else ! 473: *sp++ = c & TRIM; ! 474: if (sp >= &genbuf[LBSIZE]) ! 475: ovflo: ! 476: error("Line overflow@in substitute"); ! 477: } ! 478: lp = loc2; ! 479: loc2 = sp + (linebuf - genbuf); ! 480: while (*sp++ = *lp++) ! 481: if (sp >= &genbuf[LBSIZE]) ! 482: goto ovflo; ! 483: strcLIN(genbuf); ! 484: } ! 485: ! 486: fixcase(c) ! 487: register int c; ! 488: { ! 489: ! 490: if (casecnt == 0) ! 491: return (c); ! 492: casecnt--; ! 493: if (destuc) { ! 494: if (islower(c)) ! 495: c = toupper(c); ! 496: } else ! 497: if (isupper(c)) ! 498: c = tolower(c); ! 499: return (c); ! 500: } ! 501: ! 502: char * ! 503: place(sp, l1, l2) ! 504: register char *sp, *l1, *l2; ! 505: { ! 506: ! 507: while (l1 < l2) { ! 508: *sp++ = fixcase(*l1++); ! 509: if (sp >= &genbuf[LBSIZE]) ! 510: return (0); ! 511: } ! 512: return (sp); ! 513: } ! 514: ! 515: snote(total, lines) ! 516: register int total, lines; ! 517: { ! 518: ! 519: if (!notable(total)) ! 520: return; ! 521: printf(mesg("%d subs|%d substitutions"), total); ! 522: if (lines != 1 && lines != total) ! 523: printf(" on %d lines", lines); ! 524: noonl(); ! 525: flush(); ! 526: } ! 527: ! 528: compile(eof, oknl) ! 529: int eof; ! 530: int oknl; ! 531: { ! 532: register int c; ! 533: register char *ep; ! 534: char *lastep; ! 535: char bracket[NBRA], *bracketp, *rhsp; ! 536: int cclcnt; ! 537: ! 538: if (isalpha(eof) || isdigit(eof)) ! 539: error("Regular expressions cannot be delimited by letters or digits"); ! 540: ep = expbuf; ! 541: c = getchar(); ! 542: if (eof == '\\') ! 543: switch (c) { ! 544: ! 545: case '/': ! 546: case '?': ! 547: if (scanre.Expbuf[0] == 0) ! 548: error("No previous scan re|No previous scanning regular expression"); ! 549: resre(scanre); ! 550: return (c); ! 551: ! 552: case '&': ! 553: if (subre.Expbuf[0] == 0) ! 554: error("No previous substitute re|No previous substitute regular expression"); ! 555: resre(subre); ! 556: return (c); ! 557: ! 558: default: ! 559: error("Badly formed re|Regular expression \\ must be followed by / or ?"); ! 560: } ! 561: if (c == eof || c == '\n' || c == EOF) { ! 562: if (*ep == 0) ! 563: error("No previous re|No previous regular expression"); ! 564: if (c == '\n' && oknl == 0) ! 565: error("Missing closing delimiter@for regular expression"); ! 566: if (c != eof) ! 567: ungetchar(c); ! 568: return (eof); ! 569: } ! 570: bracketp = bracket; ! 571: nbra = 0; ! 572: circfl = 0; ! 573: if (c == '^') { ! 574: c = getchar(); ! 575: circfl++; ! 576: } ! 577: ungetchar(c); ! 578: for (;;) { ! 579: if (ep >= &expbuf[ESIZE - 2]) ! 580: complex: ! 581: cerror("Re too complex|Regular expression too complicated"); ! 582: c = getchar(); ! 583: if (c == eof || c == EOF) { ! 584: if (bracketp != bracket) ! 585: cerror("Unmatched \\(|More \\('s than \\)'s in regular expression"); ! 586: *ep++ = CEOFC; ! 587: if (c == EOF) ! 588: ungetchar(c); ! 589: return (eof); ! 590: } ! 591: if (value(MAGIC)) { ! 592: if (c != '*' || ep == expbuf) ! 593: lastep = ep; ! 594: } else ! 595: if (c != '\\' || peekchar() != '*' || ep == expbuf) ! 596: lastep = ep; ! 597: switch (c) { ! 598: ! 599: case '\\': ! 600: c = getchar(); ! 601: switch (c) { ! 602: ! 603: case '(': ! 604: if (nbra >= NBRA) ! 605: cerror("Awash in \\('s!|Too many \\('d subexressions in a regular expression"); ! 606: *bracketp++ = nbra; ! 607: *ep++ = CBRA; ! 608: *ep++ = nbra++; ! 609: continue; ! 610: ! 611: case ')': ! 612: if (bracketp <= bracket) ! 613: cerror("Extra \\)|More \\)'s than \\('s in regular expression"); ! 614: *ep++ = CKET; ! 615: *ep++ = *--bracketp; ! 616: continue; ! 617: ! 618: case '<': ! 619: *ep++ = CBRC; ! 620: continue; ! 621: ! 622: case '>': ! 623: *ep++ = CLET; ! 624: continue; ! 625: } ! 626: if (value(MAGIC) == 0) ! 627: magic: ! 628: switch (c) { ! 629: ! 630: case '.': ! 631: *ep++ = CDOT; ! 632: continue; ! 633: ! 634: case '~': ! 635: rhsp = rhsbuf; ! 636: while (*rhsp) { ! 637: if (*rhsp & QUOTE) { ! 638: c = *rhsp & TRIM; ! 639: if (c == '&') ! 640: error("Replacement pattern contains &@- cannot use in re"); ! 641: if (c >= '1' && c <= '9') ! 642: error("Replacement pattern contains \\d@- cannot use in re"); ! 643: } ! 644: if (ep >= &expbuf[ESIZE-2]) ! 645: goto complex; ! 646: *ep++ = CCHR; ! 647: *ep++ = *rhsp++ & TRIM; ! 648: } ! 649: continue; ! 650: ! 651: case '*': ! 652: if (ep == expbuf) ! 653: break; ! 654: if (*lastep == CBRA || *lastep == CKET) ! 655: cerror("Illegal *|Can't * a \\( ... \\) in regular expression"); ! 656: if (*lastep == CCHR && (lastep[1] & QUOTE)) ! 657: cerror("Illegal *|Can't * a \\n in regular expression"); ! 658: *lastep |= STAR; ! 659: continue; ! 660: ! 661: case '[': ! 662: *ep++ = CCL; ! 663: *ep++ = 0; ! 664: cclcnt = 1; ! 665: c = getchar(); ! 666: if (c == '^') { ! 667: c = getchar(); ! 668: ep[-2] = NCCL; ! 669: } ! 670: if (c == ']') ! 671: cerror("Bad character class|Empty character class '[]' or '[^]' cannot match"); ! 672: while (c != ']') { ! 673: if (c == '\\' && any(peekchar(), "]-^\\")) ! 674: c = getchar() | QUOTE; ! 675: if (c == '\n' || c == EOF) ! 676: cerror("Missing ]"); ! 677: *ep++ = c; ! 678: cclcnt++; ! 679: if (ep >= &expbuf[ESIZE]) ! 680: goto complex; ! 681: c = getchar(); ! 682: } ! 683: lastep[1] = cclcnt; ! 684: continue; ! 685: } ! 686: if (c == EOF) { ! 687: ungetchar(EOF); ! 688: c = '\\'; ! 689: goto defchar; ! 690: } ! 691: *ep++ = CCHR; ! 692: if (c == '\n') ! 693: cerror("No newlines in re's|Can't escape newlines into regular expressions"); ! 694: /* ! 695: if (c < '1' || c > NBRA + '1') { ! 696: */ ! 697: *ep++ = c; ! 698: continue; ! 699: /* ! 700: } ! 701: c -= '1'; ! 702: if (c >= nbra) ! 703: cerror("Bad \\n|\\n in regular expression with n greater than the number of \\('s"); ! 704: *ep++ = c | QUOTE; ! 705: continue; ! 706: */ ! 707: ! 708: case '\n': ! 709: if (oknl) { ! 710: ungetchar(c); ! 711: *ep++ = CEOFC; ! 712: return (eof); ! 713: } ! 714: cerror("Badly formed re|Missing closing delimiter for regular expression"); ! 715: ! 716: case '$': ! 717: if (peekchar() == eof || peekchar() == EOF || oknl && peekchar() == '\n') { ! 718: *ep++ = CDOL; ! 719: continue; ! 720: } ! 721: goto defchar; ! 722: ! 723: case '.': ! 724: case '~': ! 725: case '*': ! 726: case '[': ! 727: if (value(MAGIC)) ! 728: goto magic; ! 729: defchar: ! 730: default: ! 731: *ep++ = CCHR; ! 732: *ep++ = c; ! 733: continue; ! 734: } ! 735: } ! 736: } ! 737: ! 738: cerror(s) ! 739: char *s; ! 740: { ! 741: ! 742: expbuf[0] = 0; ! 743: error(s); ! 744: } ! 745: ! 746: same(a, b) ! 747: register int a, b; ! 748: { ! 749: ! 750: return (a == b || value(IGNORECASE) && ! 751: ((islower(a) && toupper(a) == b) || (islower(b) && toupper(b) == a))); ! 752: } ! 753: ! 754: char *locs; ! 755: ! 756: execute(gf, addr) ! 757: line *addr; ! 758: { ! 759: register char *p1, *p2; ! 760: register int c; ! 761: ! 762: if (gf) { ! 763: if (circfl) ! 764: return (0); ! 765: locs = p1 = loc2; ! 766: } else { ! 767: if (addr == zero) ! 768: return (0); ! 769: p1 = linebuf; ! 770: getline(*addr); ! 771: locs = 0; ! 772: } ! 773: p2 = expbuf; ! 774: if (circfl) { ! 775: loc1 = p1; ! 776: return (advance(p1, p2)); ! 777: } ! 778: /* fast check for first character */ ! 779: if (*p2 == CCHR) { ! 780: c = p2[1]; ! 781: do { ! 782: if (c != *p1 && (!value(IGNORECASE) || ! 783: !((islower(c) && toupper(c) == *p1) || ! 784: (islower(*p1) && toupper(*p1) == c)))) ! 785: continue; ! 786: if (advance(p1, p2)) { ! 787: loc1 = p1; ! 788: return (1); ! 789: } ! 790: } while (*p1++); ! 791: return (0); ! 792: } ! 793: /* regular algorithm */ ! 794: do { ! 795: if (advance(p1, p2)) { ! 796: loc1 = p1; ! 797: return (1); ! 798: } ! 799: } while (*p1++); ! 800: return (0); ! 801: } ! 802: ! 803: #define uletter(c) (isalpha(c) || c == '_') ! 804: ! 805: advance(lp, ep) ! 806: register char *lp, *ep; ! 807: { ! 808: register char *curlp; ! 809: char *sp, *sp1; ! 810: int c; ! 811: ! 812: for (;;) switch (*ep++) { ! 813: ! 814: case CCHR: ! 815: /* useless ! 816: if (*ep & QUOTE) { ! 817: c = *ep++ & TRIM; ! 818: sp = braslist[c]; ! 819: sp1 = braelist[c]; ! 820: while (sp < sp1) { ! 821: if (!same(*sp, *lp)) ! 822: return (0); ! 823: sp++, lp++; ! 824: } ! 825: continue; ! 826: } ! 827: */ ! 828: if (!same(*ep, *lp)) ! 829: return (0); ! 830: ep++, lp++; ! 831: continue; ! 832: ! 833: case CDOT: ! 834: if (*lp++) ! 835: continue; ! 836: return (0); ! 837: ! 838: case CDOL: ! 839: if (*lp == 0) ! 840: continue; ! 841: return (0); ! 842: ! 843: case CEOFC: ! 844: loc2 = lp; ! 845: return (1); ! 846: ! 847: case CCL: ! 848: if (cclass(ep, *lp++, 1)) { ! 849: ep += *ep; ! 850: continue; ! 851: } ! 852: return (0); ! 853: ! 854: case NCCL: ! 855: if (cclass(ep, *lp++, 0)) { ! 856: ep += *ep; ! 857: continue; ! 858: } ! 859: return (0); ! 860: ! 861: case CBRA: ! 862: braslist[*ep++] = lp; ! 863: continue; ! 864: ! 865: case CKET: ! 866: braelist[*ep++] = lp; ! 867: continue; ! 868: ! 869: case CDOT|STAR: ! 870: curlp = lp; ! 871: while (*lp++) ! 872: continue; ! 873: goto star; ! 874: ! 875: case CCHR|STAR: ! 876: curlp = lp; ! 877: while (same(*lp, *ep)) ! 878: lp++; ! 879: lp++; ! 880: ep++; ! 881: goto star; ! 882: ! 883: case CCL|STAR: ! 884: case NCCL|STAR: ! 885: curlp = lp; ! 886: while (cclass(ep, *lp++, ep[-1] == (CCL|STAR))) ! 887: continue; ! 888: ep += *ep; ! 889: goto star; ! 890: star: ! 891: do { ! 892: lp--; ! 893: if (lp == locs) ! 894: break; ! 895: if (advance(lp, ep)) ! 896: return (1); ! 897: } while (lp > curlp); ! 898: return (0); ! 899: ! 900: case CBRC: ! 901: if (lp == linebuf) ! 902: continue; ! 903: if ((isdigit(*lp) || uletter(*lp)) && !uletter(lp[-1]) && !isdigit(lp[-1])) ! 904: continue; ! 905: return (0); ! 906: ! 907: case CLET: ! 908: if (!uletter(*lp) && !isdigit(*lp)) ! 909: continue; ! 910: return (0); ! 911: ! 912: default: ! 913: error("Re internal error"); ! 914: } ! 915: } ! 916: ! 917: cclass(set, c, af) ! 918: register char *set; ! 919: register int c; ! 920: int af; ! 921: { ! 922: register int n; ! 923: ! 924: if (c == 0) ! 925: return (0); ! 926: if (value(IGNORECASE) && isupper(c)) ! 927: c = tolower(c); ! 928: n = *set++; ! 929: while (--n) ! 930: if (n > 2 && set[1] == '-') { ! 931: if (c >= (set[0] & TRIM) && c <= (set[2] & TRIM)) ! 932: return (af); ! 933: set += 3; ! 934: n -= 2; ! 935: } else ! 936: if ((*set++ & TRIM) == c) ! 937: return (af); ! 938: return (!af); ! 939: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.