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: }