|
|
1.1 root 1: /*
2: * An editor.
3: * Regular expressions and the substitute and global commands.
4: */
5: #include <stdio.h>
6: #include <ctype.h>
7: #include "ed.h"
8:
9: /*
10: * Global command.
11: */
12: global(a1, a2, not)
13: {
14: register int a, c;
15: register char *gp;
16:
17: if (a1>a2 || a1<1 || a2>doladd) {
18: derror("Address out of range");
19: return (0);
20: }
21: if (gcp != NULL) {
22: derror("Global inside global not allowed");
23: return (0);
24: }
25: if ((c=getx()) == '\n') {
26: ungetx(c);
27: derror("Syntax error");
28: return (0);
29: }
30: if (compile(c) == 0)
31: return;
32: gp = globbuf;
33: while ((c=getx()) != '\n') {
34: if (gp >= &globbuf[GBSIZE-3]) {
35: derror("Global buffer overflow");
36: return (0);
37: }
38: if (c == '\\')
39: if ((c=getx())!='\n' && c!='\\')
40: *gp++ = '\\';
41: *gp++ = c;
42: }
43: if (gp == globbuf)
44: goto out;
45: *gp++ = '\n';
46: *gp = '\0';
47: for (a=a1; a<=a2; a++) {
48: if (intflag)
49: goto out;
50: if (execute(a) != not)
51: line[a] |= 1;
52: }
53: a = 1;
54: while (a <= doladd) {
55: if (intflag)
56: goto out;
57: if ((line[a]&1) == 0) {
58: a++;
59: continue;
60: }
61: --line[a];
62: dotadd = a;
63: gcp = globbuf;
64: while (*gcp != '\0')
65: if (command() == 0)
66: goto out;
67: a = 1;
68: }
69: out:
70: for (a=1; a<=doladd; a++)
71: line[a] &= ~1;
72: gcp = NULL;
73: ungetx('\n');
74: return (1);
75: }
76:
77: /*
78: * Substitute part 1.
79: * Check that address range is legal and parse substitute command.
80: */
81: subs1(a1, a2)
82: {
83: register int ec, c;
84: register char *sp;
85:
86: if (a1>a2 || a1<1 || a2>doladd) {
87: derror("Address out of range");
88: return (0);
89: }
90: subnewl = 0;
91: subnths = 1;
92: if (isascii(c=getx()) && isdigit(c)) {
93: subnths = 0;
94: while (isascii(c) && isdigit(c)) {
95: subnths = subnths*10 + c-'0';
96: c = getx();
97: }
98: }
99: if ((ec=c) == '\n') {
100: ungetx(c);
101: derror("Syntax error");
102: return (0);
103: }
104: if (compile(ec) == 0)
105: return (0);
106: sp = subsbuf;
107: while ((c=getx()) != ec) {
108: if (sp >= &subsbuf[SBSIZE-4]) {
109: derror("Temporary buffer overflow");
110: return (0);
111: }
112: switch (c) {
113: case '\n':
114: ungetx(c);
115: derror("Syntax error");
116: return (0);
117: case '&':
118: *sp++ = '\\';
119: *sp++ = '0';
120: continue;
121: case '\\':
122: if ((c=getx()) == '\\') {
123: *sp++ = '\\';
124: *sp++ = '\\';
125: continue;
126: }
127: if (c >= '1' && c <= '9') {
128: *sp++ = '\\';
129: *sp++ = c;
130: continue;
131: }
132: if (c == '\n')
133: subnewl++;
134: default:
135: *sp++ = c;
136: continue;
137: }
138: }
139: *sp++ = '\0';
140: if ((c=getx()) == 'g')
141: subnths = 0;
142: else
143: ungetx(c);
144: return (1);
145: }
146:
147: /*
148: * Substitute (part 2).
149: * Execute substitute command.
150: */
151: subs2(a1, a2)
152: {
153: long seek, mark;
154: int len, nth, err, a;
155: char *mp, *sp;
156: register int n;
157: register char *lp, *rp;
158:
159: err = 1;
160: for (a=a1; a<=a2; a++) {
161: if (intflag)
162: return (1);
163: if (getline(a, tempbuf) == 0)
164: return (0);
165: for (n=0; n<1+BRSIZE; n++) {
166: brace[n].b_bp = NULL;
167: brace[n].b_ep = NULL;
168: }
169: brace[0].b_ep = tempbuf;
170: mp = tempbuf;
171: lp = linebuf;
172: nth = 0;
173: for (;;) {
174: rp = codebuf;
175: if (*rp == CSSOL) {
176: if (mp != tempbuf)
177: break;
178: rp++;
179: }
180: if ((rp=match(mp, rp)) == NULL) {
181: if (*mp++ == '\0')
182: break;
183: continue;
184: }
185: nth++;
186: if (subnths) {
187: if (nth < subnths) {
188: mp = rp;
189: continue;
190: }
191: if (nth > subnths)
192: goto done;
193: }
194: err = 0;
195: saved = 0;
196: dotadd = a;
197: brace[0].b_bp = mp;
198: mp = rp;
199: rp = brace[0].b_ep;
200: brace[0].b_ep = mp;
201: len = mp - brace[0].b_bp;
202: n = brace[0].b_bp - rp;
203: if (lp+n >= &linebuf[LBSIZE-1])
204: goto ovf;
205: while (n--)
206: *lp++ = *rp++;
207: sp = subsbuf;
208: while (*sp) {
209: if (lp >= &linebuf[LBSIZE-4])
210: goto ovf;
211: if (*sp != '\\') {
212: *lp++ = *sp++;
213: continue;
214: }
215: if (*++sp == '\\') {
216: *lp++ = *sp++;
217: continue;
218: }
219: n = *sp++ - '0';
220: if ((rp=brace[n].b_bp) == NULL)
221: continue;
222: n = brace[n].b_ep-rp;
223: if (lp+n >= &linebuf[LBSIZE-4])
224: goto ovf;
225: while (n--)
226: *lp++ = *rp++;
227: }
228: if (*mp == '\0')
229: break;
230: if (len == 0)
231: mp++;
232: if (subnths!=0 && nth==subnths)
233: break;
234: }
235: done:
236: if (dotadd != a)
237: continue;
238: rp = brace[0].b_ep;
239: while (*rp) {
240: if (lp >= &linebuf[LBSIZE-1])
241: goto ovf;
242: *lp++ = *rp++;
243: }
244: *lp++ = '\0';
245: seek = linead();
246: if (subnewl) {
247: lp = linebuf;
248: while (*lp != '\n')
249: lp++;
250: *lp++ = '\0';
251: }
252: if (putline(linebuf, lp-linebuf) == 0)
253: return (0);
254: suborig = line[a];
255: if (suborig&1)
256: --suborig;
257: subseek = seek|1;
258: line[a] = seek;
259: mark = suborig|1;
260: for (n=0; n<MKSIZE; n++)
261: if (marklin[n] == mark)
262: marklin[n] = subseek;
263: if (subnewl != 0) {
264: n = 1;
265: do {
266: mp = lp;
267: while (*lp!='\n' && *lp!='\0')
268: lp++;
269: if (*lp == '\0')
270: n = 0;
271: *lp++ = '\0';
272: seek = linead();
273: if (putline(mp, lp-mp) == 0)
274: return (0);
275: if (expand(a) == 0)
276: return (0);
277: line[++a] = seek;
278: dotadd = a;
279: a2++;
280: } while (n);
281: }
282: }
283: if (err!=0 && gcp==NULL) {
284: derror("Pattern not matched");
285: return (0);
286: }
287: return (1);
288:
289: ovf:
290: derror("Temporary buffer overflow");
291: return (0);
292: }
293:
294: /*
295: * Compile a regular expression. `ec' is the character upon which
296: * the regular expression ends. If an error is encountered, the
297: * pattern is restored and input characters are thrown away until
298: * a new line is found.
299: */
300: compile(ec)
301: {
302: int bstack[BRSIZE], bcount, blevel, n;
303: register int c;
304: register char *cp, *lcp;
305:
306: bcopy(tempbuf, codebuf);
307: bcount = 1;
308: blevel = 0;
309: cp = &codebuf[0];
310: if ((c=getx()) == ec) {
311: if (*cp == CSNUL) {
312: derror("No saved pattern");
313: goto err;
314: }
315: return (1);
316: }
317: if (c == '^') {
318: *cp++ = CSSOL;
319: c = getx();
320: }
321: while (c != ec) {
322: if (c == '\n') {
323: goto nwl;
324: }
325: if (cp > &codebuf[CBSIZE-4])
326: goto ovf;
327: switch (c) {
328: case '*':
329: goto syn;
330: case '.':
331: if ((c=getx()) != '*') {
332: *cp++ = CSDOT;
333: continue;
334: }
335: *cp++ = CMDOT;
336: c = getx();
337: continue;
338: case '$':
339: if ((c=getx()) != ec) {
340: ungetx(c);
341: c = '$';
342: goto character;
343: }
344: *cp++ = CSEOL;
345: continue;
346: case '[':
347: lcp = cp;
348: if ((c=getx()) == '^')
349: *cp++ = CSNCL;
350: else {
351: ungetx(c);
352: *cp++ = CSCCL;
353: }
354: *cp++ = 0;
355: if ((c=getx()) == ']')
356: *cp++ = c;
357: else
358: ungetx(c);
359: while ((c=getx()) != ']') {
360: if (c == '\n')
361: goto nwl;
362: if (c!='-' || cp==lcp+2) {
363: if (cp >= &codebuf[CBSIZE-4])
364: goto ovf;
365: *cp++ = c;
366: if (sflag && isascii(c) && isallet(c))
367: *cp++ = toother(c);
368: continue;
369: }
370: if ((c=getx()) == '\n')
371: goto nwl;
372: if (c == ']') {
373: *cp++ = '-';
374: ungetx(c);
375: continue;
376: }
377: if ((n=cp[-1]) > c)
378: goto syn;
379: while (++n <= c) {
380: if (cp >= &codebuf[CBSIZE-4])
381: goto ovf;
382: *cp++ = n;
383: if (sflag && isascii(c) && isallet(c))
384: *cp++ = toother(c);
385: }
386: }
387: if ((c=getx()) == '*') {
388: (*lcp)++;
389: c = getx();
390: }
391: if ((n=cp-(lcp+2)) > 255) {
392: derror("Character class too large");
393: goto err;
394: }
395: *++lcp = n;
396: continue;
397: case '\\':
398: switch (c=getx()) {
399: case '\n':
400: goto nwl;
401: case '(':
402: if (bcount > BRSIZE) {
403: derror("Too many \\(");
404: goto err;
405: }
406: *cp++ = CSOPR;
407: *cp++ = bstack[blevel++] = bcount++;
408: c = getx();
409: continue;
410: case ')':
411: if (blevel == 0)
412: goto syn;
413: *cp++ = CSCPR;
414: *cp++ = bstack[--blevel];
415: c = getx();
416: continue;
417: default:
418: if (isascii(c) && isdigit(c)) {
419: *cp++ = CSBRN;
420: *cp++ = c-'0';
421: c = getx();
422: continue;
423: }
424: }
425: default:
426: character:
427: if (sflag && isascii(c) && isallet(c)) {
428: *cp++ = CSSCC;
429: if (isupper(c))
430: c = tolower(c);
431: } else
432: *cp++ = CSCHR;
433: *cp++ = c;
434: if ((c=getx()) == '*') {
435: cp[-2]++;
436: c = getx();
437: }
438: }
439: }
440: *cp++ = CSNUL;
441: return (1);
442: ovf:
443: derror("Code buffer overflow");
444: bcopy(codebuf, tempbuf);
445: return (0);
446: nwl:
447: ungetx(c);
448: syn:
449: derror("Syntax error");
450: err:
451: bcopy(codebuf, tempbuf);
452: return (0);
453: }
454:
455: /*
456: * Copy BSIZE buffer into dest from source
457: */
458: bcopy(dest, source)
459: register char *dest;
460: register char *source;
461: {
462: register int n;
463:
464: n = CBSIZE;
465: do
466: *dest++ = *source++;
467: while (--n > 0);
468: }
469:
470: /*
471: * Return 1 if the compiled expression in `codebuf' matches the line in
472: * `linebuf', else 0.
473: */
474: execute(a)
475: {
476: register int i;
477: register char *lp, *ep;
478:
479: if (getline(a, linebuf) == 0)
480: return (0);
481: for (i=0; i<1+BRSIZE; i++) {
482: brace[i].b_bp = NULL;
483: brace[i].b_ep = NULL;
484: }
485: if (codebuf[0] == CSSOL)
486: ep = match(lp=linebuf, &codebuf[1]);
487: else {
488: ep = NULL;
489: lp = linebuf;
490: do {
491: if (ep=match(lp, codebuf))
492: break;
493: } while (*lp++);
494: }
495: if (ep) {
496: brace[0].b_bp = lp;
497: brace[0].b_ep = ep;
498: }
499: return (ep ? 1 : 0);
500: }
501:
502: /*
503: * Given a pointer to a compiled expression, `cp', and a pointer to
504: * a line, `lp', return 1 if the expression matches, else 0.
505: */
506: char *
507: match(lp, cp)
508: register char *lp, *cp;
509: {
510: register int n;
511: char *llp, *lcp;
512:
513: for (;;) {
514: switch (*cp++) {
515: case CSNUL:
516: return (lp);
517: case CSEOL:
518: if (*lp)
519: return (NULL);
520: return (lp);
521: case CSOPR:
522: brace[*cp++].b_bp = lp;
523: continue;
524: case CSCPR:
525: brace[*cp++].b_ep = lp;
526: continue;
527: case CSBRN:
528: n = *cp++;
529: lcp = cp;
530: cp = brace[n].b_bp;
531: n = brace[n].b_ep - cp;
532: if (n > LBSIZE)
533: return (NULL);
534: while (n-- > 0)
535: if (*lp++ != *cp++)
536: return (NULL);
537: cp = lcp;
538: continue;
539: case CSDOT:
540: if (*lp++ == '\0')
541: return (NULL);
542: continue;
543: case CMDOT:
544: llp = lp;
545: while (*lp)
546: lp++;
547: goto star;
548: case CSCHR:
549: if (*cp++ != *lp++)
550: return (NULL);
551: continue;
552: case CMCHR:
553: llp = lp;
554: while (*cp == *lp)
555: lp++;
556: cp++;
557: goto star;
558: case CSSCC:
559: if (*cp++ == tolower(*lp++))
560: continue;
561: return (NULL);
562: case CMSCC:
563: llp = lp;
564: while (*cp == tolower(*lp++))
565: ;
566: cp++;
567: goto star;
568: case CSCCL:
569: n = *cp++;
570: while (*cp++ != *lp)
571: if (--n == 0)
572: return (NULL);
573: lp++;
574: cp += n-1;
575: continue;
576: case CMCCL:
577: llp = lp;
578: lcp = cp;
579: while (*lp) {
580: cp = lcp;
581: n = *cp++;
582: while (*cp++ != *lp)
583: if (--n == 0)
584: goto star;
585: lp++;
586: }
587: cp = lcp + *lcp + 1;
588: goto star;
589: case CSNCL:
590: if (*lp == '\0')
591: return (NULL);
592: n = *cp++;
593: while (n--)
594: if (*cp++ == *lp)
595: return (NULL);
596: lp++;
597: continue;
598: case CMNCL:
599: llp = lp;
600: lcp = cp;
601: while (*lp) {
602: cp = lcp;
603: n = *cp++;
604: while (n--) {
605: if (*cp++ == *lp) {
606: cp = lcp + *lcp + 1;
607: goto star;
608: }
609: }
610: lp++;
611: }
612: cp = lcp + *lcp + 1;
613: star:
614: do {
615: if (lcp=match(lp, cp))
616: return (lcp);
617: } while (--lp >= llp);
618: return (NULL);
619: }
620: }
621: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.