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