|
|
1.1 root 1: /* sed0.c 4.5 87/12/21 */
2:
3: #include <sys/param.h>
4: #include <stdio.h>
5: #include "sed.h"
6:
7: struct label *labtab = ltab;
8: char CGMES[] = "command garbled: %s\n";
9: char TMMES[] = "Too much text: %s\n";
10: char LTL[] = "Label too long: %s\n";
11: char AD0MES[] = "No addresses allowed: %s\n";
12: char AD1MES[] = "Only one address allowed: %s\n";
13: char bittab[] = {
14: 1,
15: 2,
16: 4,
17: 8,
18: 16,
19: 32,
20: 64,
21: 128
22: };
23:
24: main(argc, argv)
25: char *argv[];
26: {
27:
28: eargc = argc;
29: eargv = argv;
30:
31: badp = &bad;
32: aptr = abuf;
33: lab = labtab + 1; /* 0 reserved for end-pointer */
34: rep = ptrspace;
35: rep->ad1 = respace;
36: lbend = &linebuf[LBSIZE];
37: hend = &holdsp[LBSIZE];
38: lcomend = &genbuf[71];
39: ptrend = &ptrspace[PTRSIZE];
40: reend = &respace[RESIZE];
41: labend = &labtab[LABSIZE];
42: lnum = 0;
43: pending = 0;
44: depth = 0;
45: spend = linebuf;
46: hspend = holdsp;
47: fcode[0] = stdout;
48: nfiles = 1;
49:
50: if(eargc == 1)
51: exit(0);
52:
53:
54: while (--eargc > 0 && (++eargv)[0][0] == '-')
55: switch (eargv[0][1]) {
56:
57: case 'n':
58: nflag++;
59: continue;
60:
61: case 'f':
62: if(eargc-- <= 0) exit(2);
63:
64: if((fin = fopen(*++eargv, "r")) == NULL) {
65: fprintf(stderr, "Cannot open pattern-file: %s\n", *eargv);
66: exit(2);
67: }
68:
69: fcomp();
70: fclose(fin);
71: continue;
72:
73: case 'e':
74: eflag++;
75: fcomp();
76: eflag = 0;
77: continue;
78:
79: case 'g':
80: gflag++;
81: continue;
82:
83: default:
84: fprintf(stdout, "Unknown flag: %c\n", eargv[0][1]);
85: continue;
86: }
87:
88:
89: if(compfl == 0) {
90: eargv--;
91: eargc++;
92: eflag++;
93: fcomp();
94: eargv++;
95: eargc--;
96: eflag = 0;
97: }
98:
99: if(depth) {
100: fprintf(stderr, "Too many {'s");
101: exit(2);
102: }
103:
104: labtab->address = rep;
105:
106: dechain();
107:
108: /* abort(); /*DEBUG*/
109:
110: if(eargc <= 0)
111: execute((char *)NULL);
112: else while(--eargc >= 0) {
113: execute(*eargv++);
114: }
115: fclose(stdout);
116: exit(0);
117: }
118: fcomp()
119: {
120:
121: register char *p, *op, *tp;
122: char *address();
123: struct reptr *pt, *pt1;
124: int i;
125: struct label *lpt;
126: char fbuf[MAXPATHLEN + 1], *newstr();
127:
128: compfl = 1;
129: op = lastre;
130:
131: if(rline(linebuf) < 0) return;
132: if(*linebuf == '#') {
133: if(linebuf[1] == 'n')
134: nflag = 1;
135: }
136: else {
137: cp = linebuf;
138: goto comploop;
139: }
140:
141: for(;;) {
142: if(rline(linebuf) < 0) break;
143:
144: cp = linebuf;
145:
146: comploop:
147: /* fprintf(stdout, "cp: %s\n", cp); /*DEBUG*/
148: while(*cp == ' ' || *cp == '\t') cp++;
149: if(*cp == '\0' || *cp == '#') continue;
150: if(*cp == ';') {
151: cp++;
152: goto comploop;
153: }
154:
155: p = address(rep->ad1);
156: if(p == badp) {
157: fprintf(stderr, CGMES, linebuf);
158: exit(2);
159: }
160:
161: if(p == rep->ad1) {
162: if(op)
163: rep->ad1 = op;
164: else {
165: fprintf(stderr, "First RE may not be null\n");
166: exit(2);
167: }
168: } else if(p == 0) {
169: p = rep->ad1;
170: rep->ad1 = 0;
171: } else {
172: op = rep->ad1;
173: if(*cp == ',' || *cp == ';') {
174: cp++;
175: if((rep->ad2 = p) > reend) {
176: fprintf(stderr, TMMES, linebuf);
177: exit(2);
178: }
179: p = address(rep->ad2);
180: if(p == badp || p == 0) {
181: fprintf(stderr, CGMES, linebuf);
182: exit(2);
183: }
184: if(p == rep->ad2)
185: rep->ad2 = op;
186: else
187: op = rep->ad2;
188:
189: } else
190: rep->ad2 = 0;
191: }
192:
193: if(p > reend) {
194: fprintf(stderr, "Too much text: %s\n", linebuf);
195: exit(2);
196: }
197:
198: while(*cp == ' ' || *cp == '\t') cp++;
199:
200: swit:
201: switch(*cp++) {
202:
203: default:
204: fprintf(stderr, "Unrecognized command: %s\n", linebuf);
205: exit(2);
206:
207: case '!':
208: rep->negfl = 1;
209: goto swit;
210:
211: case '{':
212: rep->command = BCOM;
213: rep->negfl = !(rep->negfl);
214: cmpend[depth++] = &rep->lb1;
215: if(++rep >= ptrend) {
216: fprintf(stderr, "Too many commands: %s\n", linebuf);
217: exit(2);
218: }
219: rep->ad1 = p;
220: if(*cp == '\0') continue;
221:
222: goto comploop;
223:
224: case '}':
225: if(rep->ad1) {
226: fprintf(stderr, AD0MES, linebuf);
227: exit(2);
228: }
229:
230: if(--depth < 0) {
231: fprintf(stderr, "Too many }'s\n");
232: exit(2);
233: }
234: *cmpend[depth] = rep;
235:
236: rep->ad1 = p;
237: continue;
238:
239: case '=':
240: rep->command = EQCOM;
241: if(rep->ad2) {
242: fprintf(stderr, AD1MES, linebuf);
243: exit(2);
244: }
245: break;
246:
247: case ':':
248: if(rep->ad1) {
249: fprintf(stderr, AD0MES, linebuf);
250: exit(2);
251: }
252:
253: while(*cp++ == ' ');
254: cp--;
255:
256:
257: tp = lab->asc;
258: while((*tp++ = *cp++))
259: if(tp >= &(lab->asc[8])) {
260: fprintf(stderr, LTL, linebuf);
261: exit(2);
262: }
263: *--tp = '\0';
264:
265: if(lpt = search(lab)) {
266: if(lpt->address) {
267: fprintf(stderr, "Duplicate labels: %s\n", linebuf);
268: exit(2);
269: }
270: } else {
271: lab->chain = 0;
272: lpt = lab;
273: if(++lab >= labend) {
274: fprintf(stderr, "Too many labels: %s\n", linebuf);
275: exit(2);
276: }
277: }
278: lpt->address = rep;
279: rep->ad1 = p;
280:
281: continue;
282:
283: case 'a':
284: rep->command = ACOM;
285: if(rep->ad2) {
286: fprintf(stderr, AD1MES, linebuf);
287: exit(2);
288: }
289: if(*cp == '\\') cp++;
290: if(*cp++ != '\n') {
291: fprintf(stderr, CGMES, linebuf);
292: exit(2);
293: }
294: rep->re1 = p;
295: p = text(rep->re1);
296: break;
297: case 'c':
298: rep->command = CCOM;
299: if(*cp == '\\') cp++;
300: if(*cp++ != ('\n')) {
301: fprintf(stderr, CGMES, linebuf);
302: exit(2);
303: }
304: rep->re1 = p;
305: p = text(rep->re1);
306: break;
307: case 'i':
308: rep->command = ICOM;
309: if(rep->ad2) {
310: fprintf(stderr, AD1MES, linebuf);
311: exit(2);
312: }
313: if(*cp == '\\') cp++;
314: if(*cp++ != ('\n')) {
315: fprintf(stderr, CGMES, linebuf);
316: exit(2);
317: }
318: rep->re1 = p;
319: p = text(rep->re1);
320: break;
321:
322: case 'g':
323: rep->command = GCOM;
324: break;
325:
326: case 'G':
327: rep->command = CGCOM;
328: break;
329:
330: case 'h':
331: rep->command = HCOM;
332: break;
333:
334: case 'H':
335: rep->command = CHCOM;
336: break;
337:
338: case 't':
339: rep->command = TCOM;
340: goto jtcommon;
341:
342: case 'b':
343: rep->command = BCOM;
344: jtcommon:
345: while(*cp++ == ' ');
346: cp--;
347:
348: if(*cp == '\0') {
349: if(pt = labtab->chain) {
350: while(pt1 = pt->lb1)
351: pt = pt1;
352: pt->lb1 = rep;
353: } else
354: labtab->chain = rep;
355: break;
356: }
357: tp = lab->asc;
358: while((*tp++ = *cp++))
359: if(tp >= &(lab->asc[8])) {
360: fprintf(stderr, LTL, linebuf);
361: exit(2);
362: }
363: cp--;
364: *--tp = '\0';
365:
366: if(lpt = search(lab)) {
367: if(lpt->address) {
368: rep->lb1 = lpt->address;
369: } else {
370: pt = lpt->chain;
371: while(pt1 = pt->lb1)
372: pt = pt1;
373: pt->lb1 = rep;
374: }
375: } else {
376: lab->chain = rep;
377: lab->address = 0;
378: if(++lab >= labend) {
379: fprintf(stderr, "Too many labels: %s\n", linebuf);
380: exit(2);
381: }
382: }
383: break;
384:
385: case 'n':
386: rep->command = NCOM;
387: break;
388:
389: case 'N':
390: rep->command = CNCOM;
391: break;
392:
393: case 'p':
394: rep->command = PCOM;
395: break;
396:
397: case 'P':
398: rep->command = CPCOM;
399: break;
400:
401: case 'r':
402: rep->command = RCOM;
403: if(rep->ad2) {
404: fprintf(stderr, AD1MES, linebuf);
405: exit(2);
406: }
407: if(*cp++ != ' ') {
408: fprintf(stderr, CGMES, linebuf);
409: exit(2);
410: }
411: rep->re1 = p;
412: p = text(rep->re1);
413: break;
414:
415: case 'd':
416: rep->command = DCOM;
417: break;
418:
419: case 'D':
420: rep->command = CDCOM;
421: rep->lb1 = ptrspace;
422: break;
423:
424: case 'q':
425: rep->command = QCOM;
426: if(rep->ad2) {
427: fprintf(stderr, AD1MES, linebuf);
428: exit(2);
429: }
430: break;
431:
432: case 'l':
433: rep->command = LCOM;
434: break;
435:
436: case 's':
437: rep->command = SCOM;
438: seof = *cp++;
439: rep->re1 = p;
440: p = compile(rep->re1);
441: if(p == badp) {
442: fprintf(stderr, CGMES, linebuf);
443: exit(2);
444: }
445: if(p == rep->re1) {
446: if(op)
447: rep->re1 = op;
448: else {
449: fprintf(stderr,
450: "First RE may not be null\n");
451: exit(2);
452: }
453: } else {
454: op = rep->re1;
455: }
456:
457: if((rep->rhs = p) > reend) {
458: fprintf(stderr, TMMES, linebuf);
459: exit(2);
460: }
461:
462: if((p = compsub(rep->rhs)) == badp) {
463: fprintf(stderr, CGMES, linebuf);
464: exit(2);
465: }
466: if(*cp == 'g') {
467: cp++;
468: rep->gfl++;
469: } else if(gflag)
470: rep->gfl++;
471:
472: if(*cp == 'p') {
473: cp++;
474: rep->pfl = 1;
475: }
476:
477: if(*cp == 'P') {
478: cp++;
479: rep->pfl = 2;
480: }
481:
482: if(*cp == 'w') {
483: cp++;
484: if(*cp++ != ' ') {
485: fprintf(stderr, CGMES, linebuf);
486: exit(2);
487: }
488: if(nfiles > 10) {
489: fprintf(stderr, "Too many files in w commands\n");
490: exit(2);
491: }
492:
493: text(fbuf);
494: fname[nfiles] = newstr(fbuf);
495: for(i = nfiles - 1; i >= 0; i--)
496: if(cmp(fname[nfiles],fname[i]) == 0) {
497: rep->fcode = fcode[i];
498: goto done;
499: }
500: if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) {
501: fprintf(stderr, "cannot open %s\n", fname[nfiles]);
502: exit(2);
503: }
504: fcode[nfiles++] = rep->fcode;
505: }
506: break;
507:
508: case 'w':
509: rep->command = WCOM;
510: if(*cp++ != ' ') {
511: fprintf(stderr, CGMES, linebuf);
512: exit(2);
513: }
514: if(nfiles > 10){
515: fprintf(stderr, "Too many files in w commands\n");
516: exit(2);
517: }
518:
519: text(fbuf);
520: fname[nfiles] = newstr(fbuf);
521: for(i = nfiles - 1; i >= 0; i--)
522: if(cmp(fname[nfiles], fname[i]) == 0) {
523: rep->fcode = fcode[i];
524: goto done;
525: }
526:
527: if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) {
528: fprintf(stderr, "Cannot create %s\n", fname[nfiles]);
529: exit(2);
530: }
531: fcode[nfiles++] = rep->fcode;
532: break;
533:
534: case 'x':
535: rep->command = XCOM;
536: break;
537:
538: case 'y':
539: rep->command = YCOM;
540: seof = *cp++;
541: rep->re1 = p;
542: p = ycomp(rep->re1);
543: if(p == badp) {
544: fprintf(stderr, CGMES, linebuf);
545: exit(2);
546: }
547: if(p > reend) {
548: fprintf(stderr, TMMES, linebuf);
549: exit(2);
550: }
551: break;
552:
553: }
554: done:
555: if(++rep >= ptrend) {
556: fprintf(stderr, "Too many commands, last: %s\n", linebuf);
557: exit(2);
558: }
559:
560: rep->ad1 = p;
561:
562: if(*cp++ != '\0') {
563: if(cp[-1] == ';')
564: goto comploop;
565: fprintf(stderr, CGMES, linebuf);
566: exit(2);
567: }
568:
569: }
570: rep->command = 0;
571: lastre = op;
572: }
573: char *compsub(rhsbuf)
574: char *rhsbuf;
575: {
576: register char *p, *q;
577:
578: p = rhsbuf;
579: q = cp;
580: for(;;) {
581: if((*p = *q++) == '\\') {
582: *p = *q++;
583: if(*p > numbra + '0' && *p <= '9')
584: return(badp);
585: *p++ |= 0200;
586: continue;
587: }
588: if(*p == seof) {
589: *p++ = '\0';
590: cp = q;
591: return(p);
592: }
593: if(*p++ == '\0') {
594: return(badp);
595: }
596:
597: }
598: }
599:
600: char *compile(expbuf)
601: char *expbuf;
602: {
603: register c;
604: register char *ep, *sp;
605: char neg;
606: char *lastep, *cstart;
607: int cclcnt;
608: int closed;
609: char bracket[NBRA], *bracketp;
610:
611: if(*cp == seof) {
612: cp++;
613: return(expbuf);
614: }
615:
616: ep = expbuf;
617: lastep = 0;
618: bracketp = bracket;
619: closed = numbra = 0;
620: sp = cp;
621: if (*sp == '^') {
622: *ep++ = 1;
623: sp++;
624: } else {
625: *ep++ = 0;
626: }
627: for (;;) {
628: if (ep >= &expbuf[ESIZE]) {
629: cp = sp;
630: return(badp);
631: }
632: if((c = *sp++) == seof) {
633: if(bracketp != bracket) {
634: cp = sp;
635: return(badp);
636: }
637: cp = sp;
638: *ep++ = CEOF;
639: return(ep);
640: }
641: if(c != '*')
642: lastep = ep;
643: switch (c) {
644:
645: case '\\':
646: if((c = *sp++) == '(') {
647: if(numbra >= NBRA) {
648: cp = sp;
649: return(badp);
650: }
651: *bracketp++ = numbra;
652: *ep++ = CBRA;
653: *ep++ = numbra++;
654: continue;
655: }
656: if(c == ')') {
657: if(bracketp <= bracket) {
658: cp = sp;
659: return(badp);
660: }
661: *ep++ = CKET;
662: *ep++ = *--bracketp;
663: closed++;
664: continue;
665: }
666:
667: if(c >= '1' && c <= '9') {
668: if((c -= '1') >= closed)
669: return(badp);
670:
671: *ep++ = CBACK;
672: *ep++ = c;
673: continue;
674: }
675: if(c == '\n') {
676: cp = sp;
677: return(badp);
678: }
679: if(c == 'n') {
680: c = '\n';
681: }
682: goto defchar;
683:
684: case '\0':
685: continue;
686: case '\n':
687: cp = sp;
688: return(badp);
689:
690: case '.':
691: *ep++ = CDOT;
692: continue;
693:
694: case '*':
695: if (lastep == 0)
696: goto defchar;
697: if(*lastep == CKET) {
698: cp = sp;
699: return(badp);
700: }
701: *lastep |= STAR;
702: continue;
703:
704: case '$':
705: if (*sp != seof)
706: goto defchar;
707: *ep++ = CDOL;
708: continue;
709:
710: case '[':
711: if(&ep[17] >= &expbuf[ESIZE]) {
712: fprintf(stderr, "RE too long: %s\n", linebuf);
713: exit(2);
714: }
715:
716: *ep++ = CCL;
717:
718: neg = 0;
719: if((c = *sp++) == '^') {
720: neg = 1;
721: c = *sp++;
722: }
723:
724: cstart = sp;
725: do {
726: if(c == '\0') {
727: fprintf(stderr, CGMES, linebuf);
728: exit(2);
729: }
730: if (c=='-' && sp>cstart && *sp!=']') {
731: for (c = sp[-2]; c<*sp; c++)
732: ep[c>>3] |= bittab[c&07];
733: }
734: if(c == '\\') {
735: switch(c = *sp++) {
736: case 'n':
737: c = '\n';
738: break;
739: }
740: }
741:
742: ep[c >> 3] |= bittab[c & 07];
743: } while((c = *sp++) != ']');
744:
745: if(neg)
746: for(cclcnt = 0; cclcnt < 16; cclcnt++)
747: ep[cclcnt] ^= -1;
748: ep[0] &= 0376;
749:
750: ep += 16;
751:
752: continue;
753:
754: defchar:
755: default:
756: *ep++ = CCHR;
757: *ep++ = c;
758: }
759: }
760: }
761: rline(lbuf)
762: char *lbuf;
763: {
764: register char *p, *q;
765: register t;
766: static char *saveq;
767:
768: p = lbuf - 1;
769:
770: if(eflag) {
771: if(eflag > 0) {
772: eflag = -1;
773: if(eargc-- <= 0)
774: exit(2);
775: q = *++eargv;
776: while(*++p = *q++) {
777: if(*p == '\\') {
778: if((*++p = *q++) == '\0') {
779: saveq = 0;
780: return(-1);
781: } else
782: continue;
783: }
784: if(*p == '\n') {
785: *p = '\0';
786: saveq = q;
787: return(1);
788: }
789: }
790: saveq = 0;
791: return(1);
792: }
793: if((q = saveq) == 0) return(-1);
794:
795: while(*++p = *q++) {
796: if(*p == '\\') {
797: if((*++p = *q++) == '0') {
798: saveq = 0;
799: return(-1);
800: } else
801: continue;
802: }
803: if(*p == '\n') {
804: *p = '\0';
805: saveq = q;
806: return(1);
807: }
808: }
809: saveq = 0;
810: return(1);
811: }
812:
813: while((t = getc(fin)) != EOF) {
814: *++p = t;
815: if(*p == '\\') {
816: t = getc(fin);
817: *++p = t;
818: }
819: else if(*p == '\n') {
820: *p = '\0';
821: return(1);
822: }
823: }
824: *++p = '\0';
825: return(-1);
826: }
827:
828: char *address(expbuf)
829: char *expbuf;
830: {
831: register char *rcp;
832: long lno;
833:
834: if(*cp == '$') {
835: cp++;
836: *expbuf++ = CEND;
837: *expbuf++ = CEOF;
838: return(expbuf);
839: }
840:
841: if(*cp == '/') {
842: seof = '/';
843: cp++;
844: return(compile(expbuf));
845: }
846:
847: rcp = cp;
848: lno = 0;
849:
850: while(*rcp >= '0' && *rcp <= '9')
851: lno = lno*10 + *rcp++ - '0';
852:
853: if(rcp > cp) {
854: *expbuf++ = CLNUM;
855: *expbuf++ = nlno;
856: tlno[nlno++] = lno;
857: if(nlno >= NLINES) {
858: fprintf(stderr, "Too many line numbers\n");
859: exit(2);
860: }
861: *expbuf++ = CEOF;
862: cp = rcp;
863: return(expbuf);
864: }
865: return(0);
866: }
867: cmp(a, b)
868: char *a,*b;
869: {
870: register char *ra, *rb;
871:
872: ra = a - 1;
873: rb = b - 1;
874:
875: while(*++ra == *++rb)
876: if(*ra == '\0') return(0);
877: return(1);
878: }
879:
880: char *text(textbuf)
881: char *textbuf;
882: {
883: register char *p, *q;
884:
885: p = textbuf;
886: q = cp;
887: while(*q == '\t' || *q == ' ') q++;
888: for(;;) {
889:
890: if((*p = *q++) == '\\')
891: *p = *q++;
892: if(*p == '\0') {
893: cp = --q;
894: return(++p);
895: }
896: if(*p == '\n') {
897: while(*q == '\t' || *q == ' ') q++;
898: }
899: p++;
900: }
901: }
902:
903:
904: struct label *search(ptr)
905: struct label *ptr;
906: {
907: struct label *rp;
908:
909: rp = labtab;
910: while(rp < ptr) {
911: if(cmp(rp->asc, ptr->asc) == 0)
912: return(rp);
913: rp++;
914: }
915:
916: return(0);
917: }
918:
919:
920: dechain()
921: {
922: struct label *lptr;
923: struct reptr *rptr, *trptr;
924:
925: for(lptr = labtab; lptr < lab; lptr++) {
926:
927: if(lptr->address == 0) {
928: fprintf(stderr, "Undefined label: %s\n", lptr->asc);
929: exit(2);
930: }
931:
932: if(lptr->chain) {
933: rptr = lptr->chain;
934: while(trptr = rptr->lb1) {
935: rptr->lb1 = lptr->address;
936: rptr = trptr;
937: }
938: rptr->lb1 = lptr->address;
939: }
940: }
941: }
942:
943: char *ycomp(expbuf)
944: char *expbuf;
945: {
946: register char c, *ep, *tsp;
947: char *sp;
948:
949: ep = expbuf;
950: sp = cp;
951: for(tsp = cp; *tsp != seof; tsp++) {
952: if(*tsp == '\\')
953: tsp++;
954: if(*tsp == '\n')
955: return(badp);
956: }
957: tsp++;
958:
959: while((c = *sp++ & 0177) != seof) {
960: if(c == '\\' && *sp == 'n') {
961: sp++;
962: c = '\n';
963: }
964: if((ep[c] = *tsp++) == '\\' && *tsp == 'n') {
965: ep[c] = '\n';
966: tsp++;
967: }
968: if(ep[c] == seof || ep[c] == '\0')
969: return(badp);
970: }
971: if(*tsp != seof)
972: return(badp);
973: cp = ++tsp;
974:
975: for(c = 0; !(c & 0200); c++)
976: if(ep[c] == 0)
977: ep[c] = c;
978:
979: return(ep + 0200);
980: }
981:
982: static char *
983: newstr(buf)
984: char *buf;
985: {
986: char *new, *malloc(), *strcpy();
987:
988: if (!(new = malloc((u_int)(strlen(buf) + 1)))) {
989: fputs("sed: out of memory.\n", stderr);
990: exit(2);
991: }
992: return(strcpy(new, buf));
993: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.