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