|
|
1.1 root 1: #include <stdio.h>
2: #include "sed.h"
3:
4: struct label *labtab = ltab;
5: char CGMES[] = "sed: Command garbled: %s\n";
6: char TMMES[] = "sed: Too much text: %s\n";
7: char LTL[] = "sed: Label too long: %s\n";
8: char AD0MES[] = "sed: No addresses allowed: %s\n";
9: char AD1MES[] = "sed: Only one address allowed: %s\n";
10: char bittab[] = {
11: 1,
12: 2,
13: 4,
14: 8,
15: 16,
16: 32,
17: 64,
18: 128
19: };
20:
21: main(argc, argv)
22: char *argv[];
23: {
24:
25: eargc = argc;
26: eargv = argv;
27:
28: badp = &bad;
29: aptr = abuf;
30: hspend = holdsp;
31: lab = labtab + 1; /* 0 reserved for end-pointer */
32: rep = ptrspace;
33: rep->r1.ad1 = respace;
34: lbend = &linebuf[LBSIZE];
35: hend = &holdsp[LBSIZE];
36: lcomend = &genbuf[71];
37: ptrend = &ptrspace[PTRSIZE];
38: reend = &respace[RESIZE];
39: labend = &labtab[LABSIZE];
40: lnum = 0;
41: pending = 0;
42: depth = 0;
43: spend = linebuf;
44: hspend = holdsp;
45: fcode[0] = stdout;
46: nfiles = 1;
47: lastre = NULL;
48:
49: if(eargc == 1)
50: exit(0);
51:
52:
53: while (--eargc > 0 && (++eargv)[0][0] == '-')
54: switch (eargv[0][1]) {
55:
56: case 'n':
57: nflag++;
58: continue;
59:
60: case 'f':
61: if(eargc-- <= 0) exit(2);
62:
63: if((fin = fopen(*++eargv, "r")) == NULL) {
64: fprintf(stderr, "sed: Cannot open pattern-file: %s\n", *eargv);
65: exit(2);
66: }
67:
68: fcomp();
69: fclose(fin);
70: continue;
71:
72: case 'e':
73: eflag++;
74: fcomp();
75: eflag = 0;
76: continue;
77:
78: case 'g':
79: gflag++;
80: continue;
81:
82: default:
83: fprintf(stderr, "sed: Unknown flag: %c\n", eargv[0][1]);
84: continue;
85: }
86:
87:
88: if(compfl == 0) {
89: eargv--;
90: eargc++;
91: eflag++;
92: fcomp();
93: eargv++;
94: eargc--;
95: eflag = 0;
96: }
97:
98: if(depth) {
99: fprintf(stderr, "sed: Too many {'s");
100: exit(2);
101: }
102:
103: labtab->address = rep;
104:
105: dechain();
106:
107: /* abort(); /*DEBUG*/
108:
109: if(eargc <= 0)
110: execute((char *)NULL);
111: else while(--eargc >= 0) {
112: execute(*eargv++);
113: }
114: fclose(stdout);
115: exit(0);
116: }
117: fcomp()
118: {
119:
120: register char *p, *op, *tp;
121: char *address();
122: union reptr *pt, *pt1;
123: int i;
124: struct label *lpt;
125:
126: compfl = 1;
127: op = lastre;
128:
129: if(rline(linebuf) < 0) {
130: lastre = op;
131: return;
132: }
133: if(*linebuf == '#') {
134: if(linebuf[1] == 'n')
135: nflag = 1;
136: }
137: else {
138: cp = linebuf;
139: goto comploop;
140: }
141:
142: for(;;) {
143: if(rline(linebuf) < 0) break;
144:
145: cp = linebuf;
146:
147: comploop:
148: /* fprintf(stdout, "cp: %s\n", cp); /*DEBUG*/
149: while(*cp == ' ' || *cp == '\t') cp++;
150: if(*cp == '\0' || *cp == '#') continue;
151: if(*cp == ';') {
152: cp++;
153: goto comploop;
154: }
155:
156: p = address(rep->r1.ad1);
157: if(p == badp) {
158: fprintf(stderr, CGMES, linebuf);
159: exit(2);
160: }
161:
162: if(p == 0) {
163: p = rep->r1.ad1;
164: rep->r1.ad1 = 0;
165: } else {
166: if(p == rep->r1.ad1) {
167: if(op)
168: rep->r1.ad1 = op;
169: else {
170: fprintf(stderr, "sed: First RE may not be null\n");
171: exit(2);
172: }
173: }
174: op = rep->r1.ad1;
175: if(*cp == ',' || *cp == ';') {
176: cp++;
177: if((rep->r1.ad2 = p) > reend) {
178: fprintf(stderr, TMMES, linebuf);
179: exit(2);
180: }
181: p = address(rep->r1.ad2);
182: if(p == badp || p == 0) {
183: fprintf(stderr, CGMES, linebuf);
184: exit(2);
185: }
186: if(p == rep->r1.ad2)
187: rep->r1.ad2 = op;
188: else
189: op = rep->r1.ad2;
190:
191: } else
192: rep->r1.ad2 = 0;
193: }
194:
195: if(p > reend) {
196: fprintf(stderr, "sed: Too much text: %s\n", linebuf);
197: exit(2);
198: }
199:
200: while(*cp == ' ' || *cp == '\t') cp++;
201:
202: swit:
203: switch(*cp++) {
204:
205: default:
206: /*fprintf(stderr, "cp = %d; *cp = %o\n", cp - linebuf, *cp);*/
207: fprintf(stderr, "sed: Unrecognized command: %s\n", linebuf);
208: exit(2);
209:
210: case '!':
211: rep->r1.negfl = 1;
212: goto swit;
213:
214: case '{':
215: rep->r1.command = BCOM;
216: rep->r1.negfl = !(rep->r1.negfl);
217: cmpend[depth++] = &rep->r2.lb1;
218: if(++rep >= ptrend) {
219: fprintf(stderr, "sed: Too many commands: %s\n", linebuf);
220: exit(2);
221: }
222: rep->r1.ad1 = p;
223: if(*cp == '\0') continue;
224:
225: goto comploop;
226:
227: case '}':
228: if(rep->r1.ad1) {
229: fprintf(stderr, AD0MES, linebuf);
230: exit(2);
231: }
232:
233: if(--depth < 0) {
234: fprintf(stderr, "sed: Too many }'s\n");
235: exit(2);
236: }
237: *cmpend[depth] = rep;
238:
239: rep->r1.ad1 = p;
240: continue;
241:
242: case '=':
243: rep->r1.command = EQCOM;
244: if(rep->r1.ad2) {
245: fprintf(stderr, AD1MES, linebuf);
246: exit(2);
247: }
248: break;
249:
250: case ':':
251: if(rep->r1.ad1) {
252: fprintf(stderr, AD0MES, linebuf);
253: exit(2);
254: }
255:
256: while(*cp++ == ' ');
257: cp--;
258:
259:
260: tp = lab->asc;
261: while((*tp++ = *cp++))
262: if(tp >= &(lab->asc[8])) {
263: fprintf(stderr, LTL, linebuf);
264: exit(2);
265: }
266: *--tp = '\0';
267:
268: if(lpt = search(lab)) {
269: if(lpt->address) {
270: fprintf(stderr, "sed: Duplicate labels: %s\n", linebuf);
271: exit(2);
272: }
273: } else {
274: lab->chain = 0;
275: lpt = lab;
276: if(++lab >= labend) {
277: fprintf(stderr, "sed: Too many labels: %s\n", linebuf);
278: exit(2);
279: }
280: }
281: lpt->address = rep;
282: rep->r1.ad1 = p;
283:
284: continue;
285:
286: case 'a':
287: rep->r1.command = ACOM;
288: if(rep->r1.ad2) {
289: fprintf(stderr, AD1MES, linebuf);
290: exit(2);
291: }
292: if(*cp == '\\') cp++;
293: if(*cp++ != '\n') {
294: fprintf(stderr, CGMES, linebuf);
295: exit(2);
296: }
297: rep->r1.re1 = p;
298: p = text(rep->r1.re1);
299: break;
300: case 'c':
301: rep->r1.command = CCOM;
302: if(*cp == '\\') cp++;
303: if(*cp++ != ('\n')) {
304: fprintf(stderr, CGMES, linebuf);
305: exit(2);
306: }
307: rep->r1.re1 = p;
308: p = text(rep->r1.re1);
309: break;
310: case 'i':
311: rep->r1.command = ICOM;
312: if(rep->r1.ad2) {
313: fprintf(stderr, AD1MES, linebuf);
314: exit(2);
315: }
316: if(*cp == '\\') cp++;
317: if(*cp++ != ('\n')) {
318: fprintf(stderr, CGMES, linebuf);
319: exit(2);
320: }
321: rep->r1.re1 = p;
322: p = text(rep->r1.re1);
323: break;
324:
325: case 'g':
326: rep->r1.command = GCOM;
327: break;
328:
329: case 'G':
330: rep->r1.command = CGCOM;
331: break;
332:
333: case 'h':
334: rep->r1.command = HCOM;
335: break;
336:
337: case 'H':
338: rep->r1.command = CHCOM;
339: break;
340:
341: case 't':
342: rep->r1.command = TCOM;
343: goto jtcommon;
344:
345: case 'b':
346: rep->r1.command = BCOM;
347: jtcommon:
348: while(*cp++ == ' ');
349: cp--;
350:
351: if(*cp == '\0') {
352: if(pt = labtab->chain) {
353: while(pt1 = pt->r2.lb1)
354: pt = pt1;
355: pt->r2.lb1 = rep;
356: } else
357: labtab->chain = rep;
358: break;
359: }
360: tp = lab->asc;
361: while((*tp++ = *cp++))
362: if(tp >= &(lab->asc[8])) {
363: fprintf(stderr, LTL, linebuf);
364: exit(2);
365: }
366: cp--;
367: *--tp = '\0';
368:
369: if(lpt = search(lab)) {
370: if(lpt->address) {
371: rep->r2.lb1 = lpt->address;
372: } else {
373: pt = lpt->chain;
374: while(pt1 = pt->r2.lb1)
375: pt = pt1;
376: pt->r2.lb1 = rep;
377: }
378: } else {
379: lab->chain = rep;
380: lab->address = 0;
381: if(++lab >= labend) {
382: fprintf(stderr, "sed: Too many labels: %s\n", linebuf);
383: exit(2);
384: }
385: }
386: break;
387:
388: case 'n':
389: rep->r1.command = NCOM;
390: break;
391:
392: case 'N':
393: rep->r1.command = CNCOM;
394: break;
395:
396: case 'p':
397: rep->r1.command = PCOM;
398: break;
399:
400: case 'P':
401: rep->r1.command = CPCOM;
402: break;
403:
404: case 'r':
405: rep->r1.command = RCOM;
406: if(rep->r1.ad2) {
407: fprintf(stderr, AD1MES, linebuf);
408: exit(2);
409: }
410: if(*cp++ != ' ') {
411: fprintf(stderr, CGMES, linebuf);
412: exit(2);
413: }
414: rep->r1.re1 = p;
415: p = text(rep->r1.re1);
416: break;
417:
418: case 'd':
419: rep->r1.command = DCOM;
420: break;
421:
422: case 'D':
423: rep->r1.command = CDCOM;
424: rep->r2.lb1 = ptrspace;
425: break;
426:
427: case 'q':
428: rep->r1.command = QCOM;
429: if(rep->r1.ad2) {
430: fprintf(stderr, AD1MES, linebuf);
431: exit(2);
432: }
433: break;
434:
435: case 'l':
436: rep->r1.command = LCOM;
437: break;
438:
439: case 's':
440: rep->r1.command = SCOM;
441: seof = *cp++;
442: rep->r1.re1 = p;
443: p = compile(rep->r1.re1);
444: if(p == badp) {
445: fprintf(stderr, CGMES, linebuf);
446: exit(2);
447: }
448: if(p == rep->r1.re1) {
449: if(op == NULL) {
450: fprintf(stderr, "sed: First RE may not be null.\n");
451: exit(2);
452: }
453: rep->r1.re1 = op;
454: } else {
455: op = rep->r1.re1;
456: }
457:
458: if((rep->r1.rhs = p) > reend) {
459: fprintf(stderr, TMMES, linebuf);
460: exit(2);
461: }
462:
463: if((p = compsub(rep->r1.rhs)) == badp) {
464: fprintf(stderr, CGMES, linebuf);
465: exit(2);
466: }
467: if(*cp == 'g') {
468: cp++;
469: rep->r1.gfl++;
470: } else if(gflag)
471: rep->r1.gfl++;
472:
473: if(*cp == 'p') {
474: cp++;
475: rep->r1.pfl = 1;
476: }
477:
478: if(*cp == 'P') {
479: cp++;
480: rep->r1.pfl = 2;
481: }
482:
483: if(*cp == 'w') {
484: cp++;
485: if(*cp++ != ' ') {
486: fprintf(stderr, CGMES, linebuf);
487: exit(2);
488: }
489: if(nfiles >= 20) {
490: fprintf(stderr, "sed: Too many files in w commands\n");
491: exit(2);
492: }
493:
494: text(fname[nfiles]);
495: for(i = nfiles - 1; i >= 0; i--)
496: if(cmp(fname[nfiles],fname[i]) == 0) {
497: rep->r1.fcode = fcode[i];
498: goto done;
499: }
500: if((rep->r1.fcode = fopen(fname[nfiles], "w")) == NULL) {
501: fprintf(stderr, "sed: Cannot open %s\n", fname[nfiles]);
502: exit(2);
503: }
504: fcode[nfiles++] = rep->r1.fcode;
505: }
506: break;
507:
508: case 'w':
509: rep->r1.command = WCOM;
510: if(*cp++ != ' ') {
511: fprintf(stderr, CGMES, linebuf);
512: exit(2);
513: }
514: if(nfiles >= 20){
515: fprintf(stderr, "sed: Too many files in w commands\n");
516: exit(2);
517: }
518:
519: text(fname[nfiles]);
520: for(i = nfiles - 1; i >= 0; i--)
521: if(cmp(fname[nfiles], fname[i]) == 0) {
522: rep->r1.fcode = fcode[i];
523: goto done;
524: }
525:
526: if((rep->r1.fcode = fopen(fname[nfiles], "w")) == NULL) {
527: fprintf(stderr, "sed: Cannot create %s\n", fname[nfiles]);
528: exit(2);
529: }
530: fcode[nfiles++] = rep->r1.fcode;
531: break;
532:
533: case 'x':
534: rep->r1.command = XCOM;
535: break;
536:
537: case 'y':
538: rep->r1.command = YCOM;
539: seof = *cp++;
540: rep->r1.re1 = p;
541: p = ycomp(rep->r1.re1);
542: if(p == badp) {
543: fprintf(stderr, CGMES, linebuf);
544: exit(2);
545: }
546: if(p > reend) {
547: fprintf(stderr, TMMES, linebuf);
548: exit(2);
549: }
550: break;
551:
552: }
553: done:
554: if(++rep >= ptrend) {
555: fprintf(stderr, "sed: Too many commands, last: %s\n", linebuf);
556: exit(2);
557: }
558:
559: rep->r1.ad1 = p;
560:
561: if(*cp++ != '\0') {
562: if(cp[-1] == ';')
563: goto comploop;
564: fprintf(stderr, CGMES, linebuf);
565: exit(2);
566: }
567:
568: }
569: }
570: char *
571: compsub(rhsbuf)
572: char *rhsbuf;
573: {
574: register char *p, *q;
575:
576: p = rhsbuf;
577: q = cp;
578: for(;;) {
579: if((*p = *q++) == '\\') {
580: *p = *q++;
581: if(*p > numbra + '0' && *p <= '9')
582: return(badp);
583: if(*p == 'n')
584: *p = '\n';
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 *
601: compile(expbuf)
602: char *expbuf;
603: {
604: register c;
605: register char *ep, *sp;
606: char neg;
607: char *lastep, *cstart;
608: int cclcnt;
609: int closed;
610: char bracket[NBRA], *bracketp;
611:
612: if(*cp == seof) {
613: cp++;
614: return(expbuf);
615: }
616:
617: ep = expbuf;
618: lastep = 0;
619: bracketp = bracket;
620: closed = numbra = 0;
621: sp = cp;
622: if (*sp == '^') {
623: *ep++ = 1;
624: sp++;
625: } else {
626: *ep++ = 0;
627: }
628: for (;;) {
629: if (ep >= reend) {
630: cp = sp;
631: return(badp);
632: }
633: if((c = *sp++) == seof) {
634: if(bracketp != bracket) {
635: cp = sp;
636: return(badp);
637: }
638: cp = sp;
639: *ep++ = CEOF;
640: return(ep);
641: }
642: if(c != '*')
643: lastep = ep;
644: switch (c) {
645:
646: case '\\':
647: if((c = *sp++) == '(') {
648: if(numbra >= NBRA) {
649: cp = sp;
650: return(badp);
651: }
652: *bracketp++ = numbra;
653: *ep++ = CBRA;
654: *ep++ = numbra++;
655: continue;
656: }
657: if(c == ')') {
658: if(bracketp <= bracket) {
659: cp = sp;
660: return(badp);
661: }
662: *ep++ = CKET;
663: *ep++ = *--bracketp;
664: closed++;
665: continue;
666: }
667:
668: if(c >= '1' && c <= '9') {
669: if((c -= '1') >= closed)
670: return(badp);
671:
672: *ep++ = CBACK;
673: *ep++ = c;
674: continue;
675: }
676: if(c == '\n') {
677: cp = sp;
678: return(badp);
679: }
680: if(c == 'n') {
681: c = '\n';
682: }
683: goto defchar;
684:
685: case '\0':
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] >= reend) {
712: fprintf(stderr, "sed: 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, "sed: 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: union reptr *rptr, *trptr;
924:
925: for(lptr = labtab; lptr < lab; lptr++) {
926:
927: if(lptr->address == 0) {
928: fprintf(stderr, "sed: Undefined label: %s\n", lptr->asc);
929: exit(2);
930: }
931:
932: if(lptr->chain) {
933: rptr = lptr->chain;
934: while(trptr = rptr->r2.lb1) {
935: rptr->r2.lb1 = lptr->address;
936: rptr = trptr;
937: }
938: rptr->r2.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' || *tsp == '\0')
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.