|
|
1.1 ! root 1: /*************************************************************************** ! 2: * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * ! 3: * is provided to you without charge, and with no warranty. You may give * ! 4: * away copies of JOVE, including sources, provided that this notice is * ! 5: * included in all the files. * ! 6: ***************************************************************************/ ! 7: ! 8: /* search package */ ! 9: ! 10: #include "jove.h" ! 11: #include "ctype.h" ! 12: #ifdef MAC ! 13: # undef private ! 14: # define private ! 15: #endif ! 16: ! 17: #ifdef LINT_ARGS ! 18: private char * insert(char *, char *, int); ! 19: ! 20: private void ! 21: REreset(void), ! 22: search(int, int, int); ! 23: private int ! 24: backref(int, char *), ! 25: do_comp(int), ! 26: member(char *, int, int), ! 27: REgetc(void), ! 28: REmatch(char *, char *); ! 29: #else ! 30: private char * insert(); ! 31: ! 32: private void ! 33: REreset(), ! 34: search(); ! 35: private int ! 36: backref(), ! 37: do_comp(), ! 38: member(), ! 39: REgetc(), ! 40: REmatch(); ! 41: #endif /* LINT_ARGS */ ! 42: ! 43: #ifdef MAC ! 44: # undef private ! 45: # define private static ! 46: #endif ! 47: ! 48: #define NALTS 16 /* number of alternate search strings */ ! 49: ! 50: char searchstr[128], ! 51: compbuf[256], /* global default compbuf */ ! 52: rep_search[128], /* replace search string */ ! 53: rep_str[128], /* contains replacement string */ ! 54: *cur_compb, /* usually points at compbuf */ ! 55: REbuf[LBSIZE], /* points at line we're scanning */ ! 56: *alternates[NALTS]; ! 57: ! 58: int REdirection; ! 59: ! 60: int CaseIgnore = 0, ! 61: WrapScan = 0, ! 62: UseRE = 0; ! 63: ! 64: #define cind_cmp(a, b) (CaseEquiv[a] == CaseEquiv[b]) ! 65: ! 66: private int REpeekc; ! 67: private char *REptr; ! 68: ! 69: private int ! 70: REgetc() ! 71: { ! 72: int c; ! 73: ! 74: if ((c = REpeekc) != -1) ! 75: REpeekc = -1; ! 76: else if (*REptr) ! 77: c = *REptr++; ! 78: else ! 79: c = 0; ! 80: ! 81: return c; ! 82: } ! 83: ! 84: #define STAR 01 /* Match any number of last RE. */ ! 85: #define AT_BOL 2 /* ^ */ ! 86: #define AT_EOL 4 /* $ */ ! 87: #define AT_BOW 6 /* \< */ ! 88: #define AT_EOW 8 /* \> */ ! 89: #define OPENP 10 /* \( */ ! 90: #define CLOSEP 12 /* \) */ ! 91: #define CURLYB 14 /* \{ */ ! 92: ! 93: #define NOSTR 14 /* Codes <= NOSTR can't be *'d. */ ! 94: ! 95: #define ANYC NOSTR+2 /* . */ ! 96: #define NORMC ANYC+2 /* normal character */ ! 97: #define CINDC NORMC+2 /* case independent character */ ! 98: #define ONE_OF CINDC+2 /* [xxx] */ ! 99: #define NONE_OF ONE_OF+2 /* [^xxx] */ ! 100: #define BACKREF NONE_OF+2 /* \# */ ! 101: #define EOP BACKREF+2 /* end of pattern */ ! 102: ! 103: #define NPAR 10 /* [0-9] - 0th is the entire matched string, i.e. & */ ! 104: private int nparens; ! 105: private char *comp_p, ! 106: *start_p, ! 107: **alt_p, ! 108: **alt_endp; ! 109: ! 110: void ! 111: REcompile(pattern, re, into_buf, alt_bufp) ! 112: char *pattern, ! 113: *into_buf, ! 114: **alt_bufp; ! 115: { ! 116: REptr = pattern; ! 117: REpeekc = -1; ! 118: comp_p = cur_compb = start_p = into_buf; ! 119: alt_p = alt_bufp; ! 120: alt_endp = alt_p + NALTS; ! 121: *alt_p++ = comp_p; ! 122: nparens = 0; ! 123: (void) do_comp(re ? OKAY_RE : NORM); ! 124: *alt_p = 0; ! 125: } ! 126: ! 127: /* compile the pattern into an internal code */ ! 128: ! 129: private int ! 130: do_comp(kind) ! 131: { ! 132: char *last_p, ! 133: *chr_cnt = 0; ! 134: int parens[NPAR], ! 135: *parenp, ! 136: c, ! 137: ret_code; ! 138: ! 139: parenp = parens; ! 140: last_p = 0; ! 141: ret_code = 1; ! 142: ! 143: if (kind == OKAY_RE) { ! 144: *comp_p++ = OPENP; ! 145: *comp_p++ = nparens; ! 146: *parenp++ = nparens++; ! 147: start_p = comp_p; ! 148: } ! 149: ! 150: while (c = REgetc()) { ! 151: if (comp_p > &cur_compb[(sizeof compbuf) - 6]) ! 152: toolong: complain("Search string too long/complex."); ! 153: if (c != '*') ! 154: last_p = comp_p; ! 155: ! 156: if (kind == NORM && index(".[*", c) != 0) ! 157: goto defchar; ! 158: switch (c) { ! 159: case '\\': ! 160: switch (c = REgetc()) { ! 161: case 0: ! 162: complain("Premature end of pattern."); ! 163: ! 164: case '{': ! 165: { ! 166: char *wcntp; /* word count */ ! 167: ! 168: *comp_p++ = CURLYB; ! 169: wcntp = comp_p; ! 170: *comp_p++ = 0; ! 171: for (;;) { ! 172: int comp_val; ! 173: char *comp_len; ! 174: ! 175: comp_len = comp_p++; ! 176: comp_val = do_comp(IN_CB); ! 177: *comp_len = comp_p - comp_len; ! 178: (*wcntp) += 1; ! 179: if (comp_val == 0) ! 180: break; ! 181: } ! 182: break; ! 183: } ! 184: ! 185: case '}': ! 186: if (kind != IN_CB) ! 187: complain("Unexpected \}."); ! 188: ret_code = 0; ! 189: goto outahere; ! 190: ! 191: case '(': ! 192: if (nparens >= NPAR) ! 193: complain("Too many ('s; max is %d.", NPAR); ! 194: *comp_p++ = OPENP; ! 195: *comp_p++ = nparens; ! 196: *parenp++ = nparens++; ! 197: break; ! 198: ! 199: case ')': ! 200: if (parenp == parens) ! 201: complain("Too many )'s."); ! 202: *comp_p++ = CLOSEP; ! 203: *comp_p++ = *--parenp; ! 204: break; ! 205: ! 206: case '|': ! 207: if (alt_p >= alt_endp) ! 208: complain("Too many alternates; max %d.", NALTS); ! 209: *comp_p++ = CLOSEP; ! 210: *comp_p++ = *--parenp; ! 211: *comp_p++ = EOP; ! 212: *alt_p++ = comp_p; ! 213: nparens = 0; ! 214: *comp_p++ = OPENP; ! 215: *comp_p++ = nparens; ! 216: *parenp++ = nparens++; ! 217: start_p = comp_p; ! 218: break; ! 219: ! 220: case '1': ! 221: case '2': ! 222: case '3': ! 223: case '4': ! 224: case '5': ! 225: case '6': ! 226: case '7': ! 227: case '8': ! 228: case '9': ! 229: *comp_p++ = BACKREF; ! 230: *comp_p++ = c - '0'; ! 231: break; ! 232: ! 233: case '<': ! 234: *comp_p++ = AT_BOW; ! 235: break; ! 236: ! 237: case '>': ! 238: *comp_p++ = AT_EOW; ! 239: break; ! 240: ! 241: default: ! 242: goto defchar; ! 243: } ! 244: break; ! 245: ! 246: case ',': ! 247: if (kind != IN_CB) ! 248: goto defchar; ! 249: goto outahere; ! 250: ! 251: case '.': ! 252: *comp_p++ = ANYC; ! 253: break; ! 254: ! 255: case '^': ! 256: if (comp_p == start_p) { ! 257: *comp_p++ = AT_BOL; ! 258: break; ! 259: } ! 260: goto defchar; ! 261: ! 262: case '$': ! 263: if ((REpeekc = REgetc()) != 0 && REpeekc != '\\') ! 264: goto defchar; ! 265: *comp_p++ = AT_EOL; ! 266: break; ! 267: ! 268: case '[': ! 269: { ! 270: int chrcnt; ! 271: ! 272: *comp_p++ = ONE_OF; ! 273: if (comp_p + 16 >= &cur_compb[(sizeof compbuf)]) ! 274: goto toolong; ! 275: bzero(comp_p, 16); ! 276: if ((REpeekc = REgetc()) == '^') { ! 277: *last_p = NONE_OF; ! 278: /* Get it for real this time. */ ! 279: (void) REgetc(); ! 280: } ! 281: chrcnt = 1; ! 282: while ((c = REgetc()) != ']' && c != 0) { ! 283: if (c == '\\') ! 284: c = REgetc(); ! 285: else if ((REpeekc = REgetc()) == '-') { ! 286: int c2; ! 287: ! 288: (void) REgetc(); /* reread '-' */ ! 289: c2 = REgetc(); ! 290: while (c < c2) { ! 291: comp_p[c/8] |= (1 << (c%8)); ! 292: c += 1; ! 293: } ! 294: } ! 295: comp_p[c/8] |= (1 << (c%8)); ! 296: chrcnt += 1; ! 297: } ! 298: if (c == 0) ! 299: complain("Missing ]."); ! 300: if (chrcnt == 1) ! 301: complain("Empty []."); ! 302: comp_p += 16; ! 303: break; ! 304: } ! 305: ! 306: case '*': ! 307: if (last_p == 0 || *last_p <= NOSTR) ! 308: goto defchar; ! 309: ! 310: /* The * operator applies only to the previous ! 311: character. If we were building a chr_cnt at ! 312: the time we got the *, we have to remove the ! 313: last character from the chr_cnt (by decrementing ! 314: *chr_cnt) and replacing it with a new STAR entry. ! 315: ! 316: If we are decrementing the count to 0, we just ! 317: delete the chr_cnt entry altogether, replacing ! 318: it with the STAR entry. */ ! 319: ! 320: if (chr_cnt) { ! 321: char lastc = chr_cnt[*chr_cnt]; ! 322: ! 323: /* The * operator applies only to the previous ! 324: character. If we were building a chr_cnt at ! 325: the time we got the *, we have to remove the ! 326: last character from the chr_cnt (by decrementing ! 327: *chr_cnt) and replacing it with a new STAR entry. ! 328: ! 329: If we are decrementing the count to 0, we just ! 330: delete the chr_cnt entry altogether, replacing ! 331: it with the STAR entry. */ ! 332: ! 333: if (*chr_cnt == 1) { ! 334: comp_p = chr_cnt; ! 335: comp_p[-1] |= STAR; ! 336: *comp_p++ = lastc; ! 337: } else { ! 338: comp_p = chr_cnt + *chr_cnt; ! 339: (*chr_cnt) -= 1; ! 340: *comp_p++ = chr_cnt[-1] | STAR; ! 341: *comp_p++ = lastc; ! 342: } ! 343: } else ! 344: *last_p |= STAR; ! 345: break; ! 346: default: ! 347: defchar: if (chr_cnt) ! 348: (*chr_cnt) += 1; ! 349: else { ! 350: *comp_p++ = (CaseIgnore) ? CINDC : NORMC; ! 351: chr_cnt = comp_p++; ! 352: *chr_cnt = 1; /* last_p[1] = 1; */ ! 353: } ! 354: *comp_p++ = c; ! 355: continue; ! 356: } ! 357: chr_cnt = FALSE; ! 358: } ! 359: outahere: ! 360: /* End of pattern, let's do some error checking. */ ! 361: if (kind == OKAY_RE) { ! 362: *comp_p++ = CLOSEP; ! 363: *comp_p++ = *--parenp; ! 364: } ! 365: if (parenp != parens) ! 366: complain("Unmatched ()'s."); ! 367: if (kind == IN_CB && c == 0) /* End of pattern with \}. */ ! 368: complain("Missing \}."); ! 369: *comp_p++ = EOP; ! 370: ! 371: return ret_code; ! 372: } ! 373: ! 374: private char *pstrtlst[NPAR], /* index into REbuf */ ! 375: *pendlst[NPAR], ! 376: *REbolp, ! 377: *locs, ! 378: *loc1, ! 379: *loc2; ! 380: ! 381: int REbom, ! 382: REeom, /* beginning and end of match */ ! 383: REalt_num; /* if alternatives, which one matched? */ ! 384: ! 385: private int ! 386: backref(n, linep) ! 387: register char *linep; ! 388: { ! 389: register char *backsp, ! 390: *backep; ! 391: ! 392: backsp = pstrtlst[n]; ! 393: backep = pendlst[n]; ! 394: while (*backsp++ == *linep++) ! 395: if (backsp >= backep) ! 396: return 1; ! 397: return 0; ! 398: } ! 399: ! 400: private int ! 401: member(comp_p, c, af) ! 402: register char *comp_p; ! 403: register int c, ! 404: af; ! 405: { ! 406: if (c == 0) ! 407: return 0; /* try to match EOL always fails */ ! 408: if (comp_p[c/8] & (1 << (c%8))) ! 409: return af; ! 410: return !af; ! 411: } ! 412: ! 413: private int ! 414: REmatch(linep, comp_p) ! 415: register char *linep, ! 416: *comp_p; ! 417: { ! 418: char *first_p = linep; ! 419: register int n; ! 420: ! 421: for (;;) switch (*comp_p++) { ! 422: case NORMC: ! 423: n = *comp_p++; ! 424: while (--n >= 0) ! 425: if (*linep++ != *comp_p++) ! 426: return 0; ! 427: continue; ! 428: ! 429: case CINDC: /* case independent comparison */ ! 430: n = *comp_p++; ! 431: while (--n >= 0) ! 432: if (!cind_cmp(*linep++, *comp_p++)) ! 433: return 0; ! 434: continue; ! 435: ! 436: case EOP: ! 437: loc2 = linep; ! 438: REeom = (loc2 - REbolp); ! 439: return 1; /* Success! */ ! 440: ! 441: case AT_BOL: ! 442: if (linep == REbolp) ! 443: continue; ! 444: return 0; ! 445: ! 446: case AT_EOL: ! 447: if (*linep == 0) ! 448: continue; ! 449: return 0; ! 450: ! 451: case ANYC: ! 452: if (*linep++ != 0) ! 453: continue; ! 454: return 0; ! 455: ! 456: case AT_BOW: ! 457: if (ismword(*linep) && (linep == REbolp || !ismword(linep[-1]))) ! 458: continue; ! 459: return 0; ! 460: ! 461: case AT_EOW: ! 462: if ((*linep == 0 || !ismword(*linep)) && ! 463: (linep != REbolp && ismword(linep[-1]))) ! 464: continue; ! 465: return 0; ! 466: ! 467: case ONE_OF: ! 468: case NONE_OF: ! 469: if (member(comp_p, *linep++, comp_p[-1] == ONE_OF)) { ! 470: comp_p += 16; ! 471: continue; ! 472: } ! 473: return 0; ! 474: ! 475: case OPENP: ! 476: pstrtlst[*comp_p++] = linep; ! 477: continue; ! 478: ! 479: case CLOSEP: ! 480: pendlst[*comp_p++] = linep; ! 481: continue; ! 482: ! 483: case BACKREF: ! 484: if (pstrtlst[n = *comp_p++] == 0) { ! 485: s_mess("\\%d was not specified.", n + 1); ! 486: return 0; ! 487: } ! 488: if (backref(n, linep)) { ! 489: linep += pendlst[n] - pstrtlst[n]; ! 490: continue; ! 491: } ! 492: return 0; ! 493: ! 494: case CURLYB: ! 495: { ! 496: int wcnt, ! 497: any; ! 498: ! 499: wcnt = *comp_p++; ! 500: any = 0; ! 501: ! 502: while (--wcnt >= 0) { ! 503: if (any == 0) ! 504: any = REmatch(linep, comp_p + 1); ! 505: comp_p += *comp_p; ! 506: } ! 507: if (any == 0) ! 508: return 0; ! 509: linep = loc2; ! 510: continue; ! 511: } ! 512: ! 513: case ANYC | STAR: ! 514: first_p = linep; ! 515: while (*linep++) ! 516: ; ! 517: goto star; ! 518: ! 519: case NORMC | STAR: ! 520: first_p = linep; ! 521: while (*comp_p == *linep++) ! 522: ; ! 523: comp_p += 1; ! 524: goto star; ! 525: ! 526: case CINDC | STAR: ! 527: first_p = linep; ! 528: while (cind_cmp(*comp_p, *linep++)) ! 529: ; ! 530: comp_p += 1; ! 531: goto star; ! 532: ! 533: case ONE_OF | STAR: ! 534: case NONE_OF | STAR: ! 535: first_p = linep; ! 536: while (member(comp_p, *linep++, comp_p[-1] == (ONE_OF | STAR))) ! 537: ; ! 538: comp_p += 16; ! 539: goto star; ! 540: ! 541: case BACKREF | STAR: ! 542: first_p = linep; ! 543: n = *comp_p++; ! 544: while (backref(n, linep)) ! 545: linep += pendlst[n] - pstrtlst[n]; ! 546: while (linep >= first_p) { ! 547: if (REmatch(linep, comp_p)) ! 548: return 1; ! 549: linep -= pendlst[n] - pstrtlst[n]; ! 550: } ! 551: continue; ! 552: ! 553: star: do { ! 554: linep -= 1; ! 555: if (linep < locs) ! 556: break; ! 557: if (REmatch(linep, comp_p)) ! 558: return 1; ! 559: } while (linep > first_p); ! 560: return 0; ! 561: ! 562: default: ! 563: complain("RE error match (%d).", comp_p[-1]); ! 564: } ! 565: /* NOTREACHED. */ ! 566: } ! 567: ! 568: private void ! 569: REreset() ! 570: { ! 571: register int i; ! 572: ! 573: for (i = 0; i < NPAR; i++) ! 574: pstrtlst[i] = pendlst[i] = 0; ! 575: } ! 576: ! 577: /* Index LINE at OFFSET, the compiled EXPR, with alternates ALTS. If ! 578: lbuf_okay is nonzero it's okay to use linebuf if LINE is the current ! 579: line. This should save lots of time in things like paren matching in ! 580: LISP mode. Saves all that copying from linebuf to REbuf. substitute() ! 581: is the guy who calls re_lindex with lbuf_okay as 0, since the substitution ! 582: gets placed in linebuf ... doesn't work too well when the source and ! 583: destination strings are the same. I hate all these arguments! ! 584: ! 585: This code is cumbersome, repetetive for reasons of efficiency. Fast ! 586: search is a must as far as I am concerned. */ ! 587: ! 588: int ! 589: re_lindex(line, offset, expr, alts, lbuf_okay) ! 590: Line *line; ! 591: char *expr, ! 592: **alts; ! 593: { ! 594: int isquick; ! 595: register int firstc, ! 596: c; ! 597: register char *resp; ! 598: ! 599: REreset(); ! 600: if (lbuf_okay) { ! 601: REbolp = lbptr(line); ! 602: if (offset == -1) ! 603: offset = strlen(REbolp); /* arg! */ ! 604: } else { ! 605: REbolp = ltobuf(line, REbuf); ! 606: if (offset == -1) { /* Reverse search, find end of line. */ ! 607: extern int Jr_Len; ! 608: ! 609: offset = Jr_Len; /* Just Read Len. */ ! 610: } ! 611: } ! 612: resp = REbolp; ! 613: isquick = ((expr[0] == NORMC || expr[0] == CINDC) && ! 614: (alternates[1] == 0)); ! 615: if (isquick) { ! 616: firstc = expr[2]; ! 617: if (expr[0] == CINDC) ! 618: firstc = CaseEquiv[firstc]; ! 619: } ! 620: locs = REbolp + offset; ! 621: ! 622: if (REdirection == FORWARD) { ! 623: do { ! 624: char **altp = alts; ! 625: ! 626: if (isquick) { ! 627: if (expr[0] == NORMC) ! 628: while ((c = *locs++) != 0 && c != firstc) ! 629: ; ! 630: else ! 631: while (((c = *locs++) != 0) && ! 632: (CaseEquiv[c] != firstc)) ! 633: ; ! 634: if (*--locs == 0) ! 635: break; ! 636: } ! 637: REalt_num = 1; ! 638: while (*altp) { ! 639: if (REmatch(locs, *altp++)) { ! 640: loc1 = locs; ! 641: REbom = loc1 - REbolp; ! 642: return 1; ! 643: } ! 644: REalt_num += 1; ! 645: } ! 646: } while (*locs++); ! 647: } else { ! 648: do { ! 649: char **altp = alts; ! 650: ! 651: if (isquick) { ! 652: if (expr[0] == NORMC) { ! 653: while (locs >= REbolp && *locs-- != firstc) ! 654: ; ! 655: if (*++locs != firstc) ! 656: break; ! 657: } else { ! 658: while (locs >= REbolp && CaseEquiv[*locs--] != firstc) ! 659: ; ! 660: if (CaseEquiv[*++locs] != firstc) ! 661: break; ! 662: } ! 663: } ! 664: REalt_num = 1; ! 665: while (*altp) { ! 666: if (REmatch(locs, *altp++)) { ! 667: loc1 = locs; ! 668: REbom = loc1 - REbolp; ! 669: return 1; ! 670: } ! 671: REalt_num += 1; ! 672: } ! 673: } while (--locs >= resp); ! 674: } ! 675: ! 676: return 0; ! 677: } ! 678: ! 679: int okay_wrap = 0; /* Do a wrap search ... not when we're ! 680: parsing errors ... */ ! 681: ! 682: Bufpos * ! 683: dosearch(pattern, dir, re) ! 684: char *pattern; ! 685: { ! 686: Bufpos *pos; ! 687: ! 688: if (bobp() && eobp()) /* Can't match! There's no buffer. */ ! 689: return 0; ! 690: ! 691: REcompile(pattern, re, compbuf, alternates); ! 692: ! 693: pos = docompiled(dir, compbuf, alternates); ! 694: return pos; ! 695: } ! 696: ! 697: Bufpos * ! 698: docompiled(dir, expr, alts) ! 699: char *expr, ! 700: **alts; ! 701: { ! 702: static Bufpos ret; ! 703: register Line *lp; ! 704: register int offset; ! 705: int we_wrapped = NO; ! 706: ! 707: lsave(); ! 708: /* Search now lsave()'s so it doesn't make any assumptions on ! 709: whether the the contents of curline/curchar are in linebuf. ! 710: Nowhere does search write all over linebuf. However, we have to ! 711: be careful about what calls we make here, because many of them ! 712: assume (and rightly so) that curline is in linebuf. */ ! 713: ! 714: REdirection = dir; ! 715: lp = curline; ! 716: offset = curchar; ! 717: if (dir == BACKWARD) { ! 718: if (bobp()) { ! 719: if (okay_wrap && WrapScan) ! 720: goto doit; ! 721: return 0; ! 722: } ! 723: /* here we simulate BackChar() */ ! 724: if (bolp()) { ! 725: lp = lp->l_prev; ! 726: offset = strlen(lbptr(lp)); ! 727: } else ! 728: offset -= 1; ! 729: } else if ((dir == FORWARD) && ! 730: (lbptr(lp)[offset] == '\0') && ! 731: !lastp(lp)) { ! 732: lp = lp->l_next; ! 733: offset = 0; ! 734: } ! 735: ! 736: do { ! 737: if (re_lindex(lp, offset, expr, alts, YES)) ! 738: break; ! 739: doit: lp = (dir == FORWARD) ? lp->l_next : lp->l_prev; ! 740: if (lp == 0) { ! 741: if (okay_wrap && WrapScan) { ! 742: lp = (dir == FORWARD) ? ! 743: curbuf->b_first : curbuf->b_last; ! 744: we_wrapped = YES; ! 745: } else ! 746: break; ! 747: } ! 748: if (dir == FORWARD) ! 749: offset = 0; ! 750: else ! 751: offset = -1; /* signals re_lindex ... */ ! 752: } while (lp != curline); ! 753: ! 754: if (lp == curline && we_wrapped) ! 755: lp = 0; ! 756: if (lp == 0) ! 757: return 0; ! 758: ret.p_line = lp; ! 759: ret.p_char = (dir == FORWARD) ? REeom : REbom; ! 760: return &ret; ! 761: } ! 762: ! 763: private char * ! 764: insert(off, endp, which) ! 765: char *off, ! 766: *endp; ! 767: { ! 768: register char *pp; ! 769: register int n; ! 770: ! 771: n = pendlst[which] - pstrtlst[which]; ! 772: pp = pstrtlst[which]; ! 773: while (--n >= 0) { ! 774: *off++ = *pp++; ! 775: if (off >= endp) ! 776: len_error(ERROR); ! 777: } ! 778: return off; ! 779: } ! 780: ! 781: /* Perform the substitution. If DELP is nonzero the matched string is ! 782: deleted, i.e., the substitution string is not inserted. */ ! 783: ! 784: void ! 785: re_dosub(tobuf, delp) ! 786: char *tobuf; ! 787: { ! 788: register char *tp, ! 789: *rp, ! 790: *repp; ! 791: int c; ! 792: char *endp; ! 793: ! 794: tp = tobuf; ! 795: endp = tp + LBSIZE; ! 796: rp = REbuf; ! 797: repp = rep_str; ! 798: ! 799: while (rp < loc1) ! 800: *tp++ = *rp++; ! 801: ! 802: if (!delp) while (c = *repp++) { ! 803: if (c == '\\') { ! 804: c = *repp++; ! 805: if (c == '\0') { ! 806: *tp++ = '\\'; ! 807: goto endchk; ! 808: } else if (c >= '1' && c <= nparens + '1') { ! 809: tp = insert(tp, endp, c - '0'); ! 810: continue; ! 811: } ! 812: } else if (c == '&') { ! 813: tp = insert(tp, endp, 0); ! 814: continue; ! 815: } ! 816: *tp++ = c; ! 817: endchk: if (tp >= endp) ! 818: len_error(ERROR); ! 819: } ! 820: rp = loc2; ! 821: loc2 = REbuf + max(1, tp - tobuf); ! 822: REeom = loc2 - REbuf; ! 823: /* At least one character past the match, to prevent an infinite ! 824: number of replacements in the same position, e.g., ! 825: replace "^" with "". */ ! 826: while (*tp++ = *rp++) ! 827: if (tp >= endp) ! 828: len_error(ERROR); ! 829: } ! 830: ! 831: void ! 832: putmatch(which, buf, size) ! 833: char *buf; ! 834: { ! 835: *(insert(buf, buf + size, which)) = 0; ! 836: } ! 837: ! 838: void ! 839: setsearch(str) ! 840: char *str; ! 841: { ! 842: strcpy(searchstr, str); ! 843: } ! 844: ! 845: char * ! 846: getsearch() ! 847: { ! 848: return searchstr; ! 849: } ! 850: ! 851: void ! 852: RErecur() ! 853: { ! 854: char sbuf[sizeof searchstr], ! 855: cbuf[sizeof compbuf], ! 856: repbuf[sizeof rep_str], ! 857: *altbuf[NALTS]; ! 858: int npars; ! 859: Mark *m = MakeMark(curline, REbom, M_FLOATER); ! 860: ! 861: message("Type C-X C-C to continue with query replace."); ! 862: ! 863: npars = nparens; ! 864: byte_copy(compbuf, cbuf, sizeof compbuf); ! 865: byte_copy(searchstr, sbuf, sizeof searchstr); ! 866: byte_copy(rep_str, repbuf, sizeof rep_str); ! 867: byte_copy((char *) alternates, (char *) altbuf, sizeof alternates); ! 868: Recur(); ! 869: nparens = npars; ! 870: byte_copy(cbuf, compbuf, sizeof compbuf); ! 871: byte_copy(sbuf, searchstr, sizeof searchstr); ! 872: byte_copy(repbuf, rep_str, sizeof rep_str); ! 873: byte_copy((char *) altbuf, (char *) alternates, sizeof alternates); ! 874: if (!is_an_arg()) ! 875: ToMark(m); ! 876: DelMark(m); ! 877: } ! 878: ! 879: void ! 880: ForSearch() ! 881: { ! 882: search(FORWARD, UseRE, YES); ! 883: } ! 884: ! 885: void ! 886: RevSearch() ! 887: { ! 888: search(BACKWARD, UseRE, YES); ! 889: } ! 890: ! 891: void ! 892: FSrchND() ! 893: { ! 894: search(FORWARD, UseRE, NO); ! 895: } ! 896: ! 897: void ! 898: RSrchND() ! 899: { ! 900: search(BACKWARD, UseRE, NO); ! 901: } ! 902: ! 903: private void ! 904: search(dir, re, setdefault) ! 905: { ! 906: Bufpos *newdot; ! 907: char *s; ! 908: ! 909: s = ask(searchstr, ProcFmt); ! 910: if (setdefault) ! 911: setsearch(s); ! 912: okay_wrap = YES; ! 913: newdot = dosearch(s, dir, re); ! 914: okay_wrap = NO; ! 915: if (newdot == 0) { ! 916: if (WrapScan) ! 917: complain("No \"%s\" in buffer.", s); ! 918: else ! 919: complain("No \"%s\" found to %s.", s, ! 920: (dir == FORWARD) ? "bottom" : "top"); ! 921: } ! 922: PushPntp(newdot->p_line); ! 923: SetDot(newdot); ! 924: } ! 925: ! 926: /* Do we match PATTERN at OFFSET in BUF? */ ! 927: ! 928: int ! 929: LookingAt(pattern, buf, offset) ! 930: char *pattern, ! 931: *buf; ! 932: { ! 933: register char **alt = alternates; ! 934: ! 935: REcompile(pattern, 1, compbuf, alternates); ! 936: REreset(); ! 937: locs = buf + offset; ! 938: REbolp = buf; ! 939: ! 940: while (*alt) ! 941: if (REmatch(locs, *alt++)) ! 942: return 1; ! 943: return 0; ! 944: } ! 945: ! 946: int ! 947: look_at(expr) ! 948: char *expr; ! 949: { ! 950: REcompile(expr, 0, compbuf, alternates); ! 951: REreset(); ! 952: locs = linebuf + curchar; ! 953: REbolp = linebuf; ! 954: if (REmatch(locs, alternates[0])) ! 955: return 1; ! 956: return 0; ! 957: } ! 958:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.