|
|
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.