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