|
|
1.1 root 1: /*
2: * A stream editor.
3: * Execution.
4: */
5: #include <stdio.h>
6: #include <ctype.h>
7: #include "sed.h"
8:
9: char *match();
10:
11: /*
12: * Execute the compiled commands on each line of the input file.
13: */
14: process()
15: {
16: FILE *fp;
17: QCL **qcrpp, *qcrp, *lqp, *qp;
18: int n, subflag;
19: char com;
20: register COM *cp;
21: register char *bp1, *bp2;
22:
23: subflag = 0;
24: cp = NULL;
25: com = '\0';
26: lno = 0;
27: qcrpp = &qcrp;
28: dolflag = 0;
29: pattlen = 0;
30: holdlen = 0;
31: pattbuf[0] = '\0';
32: holdbuf[0] = '\0';
33: for (;;) {
34: while (cp == NULL) {
35: if (com != 'D') {
36: if (nflag==0 && pattlen!=0)
37: printf("%s\n", pattbuf);
38: pattlen = 0;
39: }
40: *qcrpp = NULL;
41: qp = qcrp;
42: while (qp != NULL) {
43: cp = qp->q_comp;
44: lqp = qp;
45: qp = qp->q_next;
46: free(lqp);
47: switch (cp->c_name) {
48: case 'a':
49: printf("%s\n", cp->c_p.p_buf);
50: break;
51: case 'r':
52: bp1 = cp->c_p.p_buf;
53: if ((fp=fopen(bp1, "r")) == NULL) {
54: printe("Cannot open %s", bp1);
55: continue;
56: }
57: while (fgets(linebuf, LHPSIZE, fp))
58: printf("%s", linebuf);
59: fclose(fp);
60: }
61: }
62: if (com == 'q')
63: exit(0);
64: if (com != 'D') {
65: if (readpat() == 0)
66: exit(0);
67: }
68: cp = comp;
69: qcrpp = &qcrp;
70: com = '\0';
71: }
72: if (admitr(cp) == 0) {
73: cp = cp->c_next;
74: continue;
75: }
76: switch (com=cp->c_name) {
77: case '=':
78: printf("%d\n", lno);
79: break;
80: case '{':
81: cp = cp->c_p.p_com;
82: continue;
83: case '}':
84: break;
85: case 'a':
86: *qcrpp = qp = (QCL *)salloc(sizeof (QCL));
87: qp->q_comp = cp;
88: qcrpp = &qp->q_next;
89: break;
90: case 'b':
91: cp = cp->c_p.p_lab->l_comp;
92: continue;
93: case 'c':
94: if (cp->c_iran == 0)
95: printf("%s\n", cp->c_p.p_buf);
96: case 'd':
97: pattlen = 0;
98: cp = NULL;
99: continue;
100: case 'D':
101: bp1 = bp2 = pattbuf;
102: pattlen = 0;
103: while (*bp2 != '\0') {
104: if (*bp2++ == '\n') {
105: pattlen = 1;
106: break;
107: }
108: }
109: while (*bp1++=*bp2++)
110: pattlen++;
111: if (pattlen == 0)
112: com = 'd';
113: cp = NULL;
114: continue;
115: case 'g':
116: n = pattlen = holdlen;
117: bp1 = pattbuf;
118: bp2 = holdbuf;
119: while (n--)
120: *bp1++ = *bp2++;
121: break;
122: case 'G':
123: if (pattlen+holdlen > LHPSIZE) {
124: printe("Pattern buffer overflow");
125: break;
126: }
127: bp1 = &pattbuf[pattlen];
128: bp2 = &holdbuf[0];
129: if (pattlen != 0)
130: bp1[-1] = '\n';
131: pattlen += n = holdlen;
132: while (n--)
133: *bp1++ = *bp2++;
134: break;
135: case 'h':
136: n = holdlen = pattlen;
137: bp1 = holdbuf;
138: bp2 = pattbuf;
139: while (n--)
140: *bp1++ = *bp2++;
141: break;
142: case 'H':
143: if (holdlen+pattlen > LHPSIZE) {
144: printe("Hold buffer overflow");
145: break;
146: }
147: bp1 = &holdbuf[holdlen];
148: bp2 = &pattbuf[0];
149: if (holdlen != 0)
150: bp1[-1] = '\n';
151: holdlen += n = pattlen;
152: while (n--)
153: *bp1++ = *bp2++;
154: break;
155: case 'i':
156: printf("%s\n", cp->c_p.p_buf);
157: break;
158: case 'l':
159: execlis();
160: break;
161: case 'n':
162: if (pattlen != 0)
163: printf("%s\n", pattbuf);
164: pattlen = 0;
165: case 'N':
166: if (readpat() == 0) {
167: com = 'q';
168: cp = NULL;
169: continue;
170: }
171: break;
172: case 'p':
173: if (pattlen != 0)
174: printf("%s\n", pattbuf);
175: break;
176: case 'P':
177: bp1 = pattbuf;
178: while (*bp1!='\0' && *bp1!='\n')
179: putchar(*bp1++);
180: putchar('\n');
181: break;
182: case 'q':
183: cp = NULL;
184: continue;
185: case 'r':
186: *qcrpp = qp = (QCL *)salloc(sizeof (QCL));
187: qp->q_comp = cp;
188: qcrpp = &qp->q_next;
189: break;
190: case 's':
191: subflag = execsub(cp->c_p.p_sub);
192: break;
193: case 't':
194: if (subflag) {
195: cp = cp->c_p.p_lab->l_comp;
196: continue;
197: }
198: break;
199: case 'w':
200: fprintf(cp->c_p.p_fil->f_filp, "%s\n", pattbuf);
201: break;
202: case 'x':
203: n = pattlen;
204: bp1 = linebuf;
205: bp2 = pattbuf;
206: while (n--)
207: *bp1++ = *bp2++;
208: n = holdlen;
209: bp1 = pattbuf;
210: bp2 = holdbuf;
211: while (n--)
212: *bp1++ = *bp2++;
213: n = pattlen;
214: bp1 = holdbuf;
215: bp2 = linebuf;
216: while (n--)
217: *bp1++ = *bp2++;
218: n = pattlen;
219: pattlen = holdlen;
220: holdlen = n;
221: break;
222: case 'y':
223: bp2 = cp->c_p.p_buf;
224: for (bp1=pattbuf; *bp1; bp1++)
225: *bp1 = bp2[*bp1];
226: break;
227: }
228: cp = cp->c_next;
229: }
230: }
231:
232: /*
233: * See if a the current line is within a given line range.
234: */
235: admitr(cp)
236: register COM *cp;
237: {
238: register int n;
239:
240: switch (cp->c_nadd) {
241: case 0:
242: cp->c_iran = 0;
243: n = 1;
244: break;
245: case 1:
246: cp->c_iran = 0;
247: n = admits(&cp->c_a[0]);
248: break;
249: case 2:
250: if (cp->c_iran == 0) {
251: n = cp->c_iran = admits(&cp->c_a[0]);
252: } else {
253: if (admits(&cp->c_a[1]) != 0)
254: cp->c_iran = 0;
255: n = 1;
256: }
257: }
258: return (cp->c_notf!=n);
259: }
260:
261: /*
262: * See if the current line matches the given line address.
263: */
264: admits(ap)
265: register ADD *ap;
266: {
267: if (ap->a_lno == 0)
268: return (execute(ap->a_pat));
269: if (ap->a_lno == HUGE)
270: return (dolflag);
271: return (ap->a_lno-1 == lno);
272: }
273:
274: /*
275: * Append a line into the pattern buffer. The current line number
276: * is incremented. If the line overflows, an error message is
277: * printed out.
278: */
279: readpat()
280: {
281: static int lastc = '\0';
282: register int c, n;
283: register char *cp;
284:
285: if (dolflag)
286: return (0);
287: cp = &pattbuf[pattlen];
288: if (pattlen != 0)
289: cp[-1] = '\n';
290: n = &pattbuf[LHPSIZE-1] - cp;
291: if (lastc == '\0')
292: c = getp();
293: else {
294: c = lastc;
295: lastc = '\0';
296: }
297: while (c!='\n' && c!=EOF) {
298: if (n-- <= 0) {
299: fprintf(stderr, "%d: Line too long\n", lno);
300: exit(1);
301: }
302: *cp++ = c;
303: c = getp();
304: }
305: *cp++ = '\0';
306: pattlen = cp - pattbuf;
307: lno++;
308: if (c==EOF || (c=getp())==EOF)
309: dolflag++;
310: else
311: lastc = c;
312: return (1);
313: }
314:
315: /*
316: * Get a character.
317: */
318: getp()
319: {
320: ECL *ep;
321: register int c;
322:
323: while (ifp==NULL || (c=getc(ifp))==EOF) {
324: if (ifp != NULL)
325: fclose(ifp);
326: if ((ep=eclp) == NULL)
327: return (EOF);
328: if ((ifp=fopen(ep->e_argp, "r")) == NULL) {
329: fprintf(stderr, "Cannot open %s\n", ep->e_argp);
330: exit(1);
331: }
332: eclp = ep->e_next;
333: free(ep);
334: }
335: return (c);
336: }
337:
338: /*
339: * Print out the contents of the pattern buffer in an unambigous
340: * form. All non-printing characters are escaped.
341: */
342: execlis()
343: {
344: register int n;
345: register char *cp;
346:
347: n = 0;
348: for (cp=pattbuf; *cp; cp++) {
349: if (n++ >= 72) {
350: n = 0;
351: printf("\\\n");
352: }
353: switch (*cp) {
354: case '\b':
355: printf("-\b<");
356: continue;
357: case '\t':
358: printf("-\b>");
359: continue;
360: case '\\':
361: printf("\\\\");
362: continue;
363: default:
364: if (isascii(*cp) && !iscntrl(*cp)) {
365: putchar(*cp);
366: continue;
367: }
368: printf("\\%03o", *cp);
369: n += 3;
370: }
371: }
372: putchar('\n');
373: }
374:
375: /*
376: * Execute substitute command.
377: */
378: execsub(sp)
379: SUB *sp;
380: {
381: register char *np;
382: register char *pp;
383: register int n;
384: register char *lp;
385: register char *rp;
386: register int nth;
387: register int len;
388: register int subflag;
389: register int subnths;
390:
391: subflag = 0;
392: subnths = sp->s_nth;
393: for (n=0; n<1+NBRC; n++) {
394: brcl[n].b_bp = NULL;
395: brcl[n].b_ep = NULL;
396: }
397: brcl[0].b_ep = pattbuf;
398: lp = pattbuf;
399: np = linebuf;
400: nth = 0;
401: for (;;) {
402: pp = sp->s_pat;
403: if (*pp == CSSOL) {
404: if (lp != pattbuf)
405: break;
406: pp++;
407: }
408: if ((pp=match(lp, pp)) == NULL) {
409: if (*lp++ == '\0')
410: break;
411: continue;
412: }
413: nth++;
414: if (subnths) {
415: if (nth < subnths) {
416: lp = pp;
417: continue;
418: }
419: if (nth > subnths)
420: goto done;
421: }
422: subflag = 1;
423: len = pp - lp;
424: brcl[0].b_bp = lp;
425: lp = pp;
426: pp = brcl[0].b_ep;
427: brcl[0].b_ep = lp;
428: n = brcl[0].b_bp - pp;
429: if (np+n >= &linebuf[LHPSIZE-1])
430: goto ovf;
431: while (n--)
432: *np++ = *pp++;
433: rp = sp->s_rep;
434: while (*rp) {
435: if (np >= &linebuf[LHPSIZE-4])
436: goto ovf;
437: if (*rp != '\\') {
438: *np++ = *rp++;
439: continue;
440: }
441: if (*++rp == '\\') {
442: *np++ = *rp++;
443: continue;
444: }
445: n = *rp++ - '0';
446: if ((pp=brcl[n].b_bp) == NULL)
447: continue;
448: n = brcl[n].b_ep-pp;
449: if (np+n >= &linebuf[LHPSIZE-4])
450: goto ovf;
451: while (n--)
452: *np++ = *pp++;
453: }
454: if (*lp == '\0')
455: break;
456: if (len == 0)
457: lp++;
458: if (subnths!=0 && nth==subnths)
459: break;
460: }
461: done:
462: pp = brcl[0].b_ep;
463: while (*pp) {
464: if (np >= &linebuf[LHPSIZE-1])
465: goto ovf;
466: *np++ = *pp++;
467: }
468: *np++ = '\0';
469: pattlen = n = np - linebuf;
470: pp = pattbuf;
471: np = linebuf;
472: do {
473: *pp++ = *np++;
474: } while (--n);
475: if (subflag) {
476: if (sp->s_cop)
477: printf("%s\n", pattbuf);
478: if (sp->s_fil)
479: fprintf(sp->s_fil->f_filp, "%s\n", pattbuf);
480: }
481: return (subflag);
482: ovf:
483: printc("Line buffer overflow");
484: return (0);
485: }
486:
487: /*
488: * See if the compiled pattern `pat' matches the line in pattbuf.
489: */
490: execute(pat)
491: char *pat;
492: {
493: register int i;
494: register char *lp, *ep;
495:
496: for (i=0; i<1+NBRC; i++) {
497: brcl[i].b_bp = NULL;
498: brcl[i].b_ep = NULL;
499: }
500: if (pat[0] == CSSOL)
501: ep = match(lp=pattbuf, &pat[1]);
502: else {
503: ep = NULL;
504: lp = pattbuf;
505: do {
506: if (ep=match(lp, pat))
507: break;
508: } while (*lp++);
509: }
510: if (ep) {
511: brcl[0].b_bp = lp;
512: brcl[0].b_ep = ep;
513: }
514: return (ep ? 1 : 0);
515: }
516:
517: /*
518: * Given a pointer to a compiled expression, `cp', and a pointer to
519: * a line, `lp', return 1 if the expression matches, else 0.
520: */
521: char *
522: match(lp, cp)
523: register char *lp, *cp;
524: {
525: register int n;
526: char *llp, *lcp;
527:
528: for (;;) {
529: switch (*cp++) {
530: case CSNUL:
531: return (lp);
532: case CSEOL:
533: if (*lp)
534: return (NULL);
535: return (lp);
536: case CSOPR:
537: brcl[*cp++].b_bp = lp;
538: continue;
539: case CSCPR:
540: brcl[*cp++].b_ep = lp;
541: continue;
542: case CSBRN:
543: n = *cp++;
544: lcp = cp;
545: cp = brcl[n].b_bp;
546: n = brcl[n].b_ep - cp;
547: if (n > LHPSIZE)
548: return (NULL);
549: while (n-- > 0)
550: if (*lp++ != *cp++)
551: return (NULL);
552: cp = lcp;
553: continue;
554: case CSDOT:
555: if (*lp++ == '\0')
556: return (NULL);
557: continue;
558: case CMDOT:
559: llp = lp;
560: while (*lp)
561: lp++;
562: goto star;
563: case CSCHR:
564: if (*cp++ != *lp++)
565: return (NULL);
566: continue;
567: case CMCHR:
568: llp = lp;
569: while (*cp == *lp)
570: lp++;
571: cp++;
572: goto star;
573: case CSSCC:
574: if (*cp++ == tolower(*lp++))
575: continue;
576: return (NULL);
577: case CMSCC:
578: llp = lp;
579: while (*cp == tolower(*lp++))
580: ;
581: cp++;
582: goto star;
583: case CSCCL:
584: n = *cp++;
585: while (*cp++ != *lp)
586: if (--n == 0)
587: return (NULL);
588: lp++;
589: cp += n-1;
590: continue;
591: case CMCCL:
592: llp = lp;
593: lcp = cp;
594: while (*lp) {
595: cp = lcp;
596: n = *cp++;
597: while (*cp++ != *lp)
598: if (--n == 0)
599: goto star;
600: lp++;
601: }
602: cp = lcp + *lcp + 1;
603: goto star;
604: case CSNCL:
605: if (*lp == '\0')
606: return (NULL);
607: n = *cp++;
608: while (n--)
609: if (*cp++ == *lp)
610: return (NULL);
611: lp++;
612: continue;
613: case CMNCL:
614: llp = lp;
615: lcp = cp;
616: while (*lp) {
617: cp = lcp;
618: n = *cp++;
619: while (n--) {
620: if (*cp++ == *lp) {
621: cp = lcp + *lcp + 1;
622: goto star;
623: }
624: }
625: lp++;
626: }
627: cp = lcp + *lcp + 1;
628: star:
629: do {
630: if (lcp=match(lp, cp))
631: return (lcp);
632: } while (--lp >= llp);
633: return (NULL);
634: }
635: }
636: }
637:
638:
639: /*
640: * Print out an execution error message.
641: */
642: printe(s)
643: {
644: fprintf(stderr, "%r", &s);
645: putc('\n', stderr);
646: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.