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