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