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