xref: /original-bsd/old/sed/sed0.c (revision 4a4a73e6)
1 /*	sed0.c	4.1	85/04/05	*/
2 
3 #include <stdio.h>
4 #include "sed.h"
5 
6 struct label	*labtab = ltab;
7 char	CGMES[]	= "command garbled: %s\n";
8 char	TMMES[]	= "Too much text: %s\n";
9 char	LTL[]	= "Label too long: %s\n";
10 char	AD0MES[]	= "No addresses allowed: %s\n";
11 char	AD1MES[]	= "Only one address allowed: %s\n";
12 char	bittab[]  = {
13 		1,
14 		2,
15 		4,
16 		8,
17 		16,
18 		32,
19 		64,
20 		128
21 	};
22 
23 main(argc, argv)
24 char	*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 }
117 fcomp()
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 
144 comploop:
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 
198 swit:
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;
342 jtcommon:
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) {
444 					rep->re1 = op;
445 				} else {
446 					op = rep->re1;
447 				}
448 
449 				if((rep->rhs = p) > reend) {
450 					fprintf(stderr, TMMES, linebuf);
451 					exit(2);
452 				}
453 
454 				if((p = compsub(rep->rhs)) == badp) {
455 					fprintf(stderr, CGMES, linebuf);
456 					exit(2);
457 				}
458 				if(*cp == 'g') {
459 					cp++;
460 					rep->gfl++;
461 				} else if(gflag)
462 					rep->gfl++;
463 
464 				if(*cp == 'p') {
465 					cp++;
466 					rep->pfl = 1;
467 				}
468 
469 				if(*cp == 'P') {
470 					cp++;
471 					rep->pfl = 2;
472 				}
473 
474 				if(*cp == 'w') {
475 					cp++;
476 					if(*cp++ !=  ' ') {
477 						fprintf(stderr, CGMES, linebuf);
478 						exit(2);
479 					}
480 					if(nfiles >= 10) {
481 						fprintf(stderr, "Too many files in w commands\n");
482 						exit(2);
483 					}
484 
485 					text(fname[nfiles]);
486 					for(i = nfiles - 1; i >= 0; i--)
487 						if(cmp(fname[nfiles],fname[i]) == 0) {
488 							rep->fcode = fcode[i];
489 							goto done;
490 						}
491 					if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) {
492 						fprintf(stderr, "cannot open %s\n", fname[nfiles]);
493 						exit(2);
494 					}
495 					fcode[nfiles++] = rep->fcode;
496 				}
497 				break;
498 
499 			case 'w':
500 				rep->command = WCOM;
501 				if(*cp++ != ' ') {
502 					fprintf(stderr, CGMES, linebuf);
503 					exit(2);
504 				}
505 				if(nfiles >= 10){
506 					fprintf(stderr, "Too many files in w commands\n");
507 					exit(2);
508 				}
509 
510 				text(fname[nfiles]);
511 				for(i = nfiles - 1; i >= 0; i--)
512 					if(cmp(fname[nfiles], fname[i]) == 0) {
513 						rep->fcode = fcode[i];
514 						goto done;
515 					}
516 
517 				if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) {
518 					fprintf(stderr, "Cannot create %s\n", fname[nfiles]);
519 					exit(2);
520 				}
521 				fcode[nfiles++] = rep->fcode;
522 				break;
523 
524 			case 'x':
525 				rep->command = XCOM;
526 				break;
527 
528 			case 'y':
529 				rep->command = YCOM;
530 				seof = *cp++;
531 				rep->re1 = p;
532 				p = ycomp(rep->re1);
533 				if(p == badp) {
534 					fprintf(stderr, CGMES, linebuf);
535 					exit(2);
536 				}
537 				if(p > reend) {
538 					fprintf(stderr, TMMES, linebuf);
539 					exit(2);
540 				}
541 				break;
542 
543 		}
544 done:
545 		if(++rep >= ptrend) {
546 			fprintf(stderr, "Too many commands, last: %s\n", linebuf);
547 			exit(2);
548 		}
549 
550 		rep->ad1 = p;
551 
552 		if(*cp++ != '\0') {
553 			if(cp[-1] == ';')
554 				goto comploop;
555 			fprintf(stderr, CGMES, linebuf);
556 			exit(2);
557 		}
558 
559 	}
560 	rep->command = 0;
561 	lastre = op;
562 }
563 char	*compsub(rhsbuf)
564 char	*rhsbuf;
565 {
566 	register char	*p, *q;
567 
568 	p = rhsbuf;
569 	q = cp;
570 	for(;;) {
571 		if((*p = *q++) == '\\') {
572 			*p = *q++;
573 			if(*p > numbra + '0' && *p <= '9')
574 				return(badp);
575 			*p++ |= 0200;
576 			continue;
577 		}
578 		if(*p == seof) {
579 			*p++ = '\0';
580 			cp = q;
581 			return(p);
582 		}
583 		if(*p++ == '\0') {
584 			return(badp);
585 		}
586 
587 	}
588 }
589 
590 char *compile(expbuf)
591 char	*expbuf;
592 {
593 	register c;
594 	register char *ep, *sp;
595 	char	neg;
596 	char *lastep, *cstart;
597 	int cclcnt;
598 	int	closed;
599 	char	bracket[NBRA], *bracketp;
600 
601 	if(*cp == seof) {
602 		cp++;
603 		return(expbuf);
604 	}
605 
606 	ep = expbuf;
607 	lastep = 0;
608 	bracketp = bracket;
609 	closed = numbra = 0;
610 	sp = cp;
611 	if (*sp == '^') {
612 		*ep++ = 1;
613 		sp++;
614 	} else {
615 		*ep++ = 0;
616 	}
617 	for (;;) {
618 		if (ep >= &expbuf[ESIZE]) {
619 			cp = sp;
620 			return(badp);
621 		}
622 		if((c = *sp++) == seof) {
623 			if(bracketp != bracket) {
624 				cp = sp;
625 				return(badp);
626 			}
627 			cp = sp;
628 			*ep++ = CEOF;
629 			return(ep);
630 		}
631 		if(c != '*')
632 			lastep = ep;
633 		switch (c) {
634 
635 		case '\\':
636 			if((c = *sp++) == '(') {
637 				if(numbra >= NBRA) {
638 					cp = sp;
639 					return(badp);
640 				}
641 				*bracketp++ = numbra;
642 				*ep++ = CBRA;
643 				*ep++ = numbra++;
644 				continue;
645 			}
646 			if(c == ')') {
647 				if(bracketp <= bracket) {
648 					cp = sp;
649 					return(badp);
650 				}
651 				*ep++ = CKET;
652 				*ep++ = *--bracketp;
653 				closed++;
654 				continue;
655 			}
656 
657 			if(c >= '1' && c <= '9') {
658 				if((c -= '1') >= closed)
659 					return(badp);
660 
661 				*ep++ = CBACK;
662 				*ep++ = c;
663 				continue;
664 			}
665 			if(c == '\n') {
666 				cp = sp;
667 				return(badp);
668 			}
669 			if(c == 'n') {
670 				c = '\n';
671 			}
672 			goto defchar;
673 
674 		case '\0':
675 			continue;
676 		case '\n':
677 			cp = sp;
678 			return(badp);
679 
680 		case '.':
681 			*ep++ = CDOT;
682 			continue;
683 
684 		case '*':
685 			if (lastep == 0)
686 				goto defchar;
687 			if(*lastep == CKET) {
688 				cp = sp;
689 				return(badp);
690 			}
691 			*lastep |= STAR;
692 			continue;
693 
694 		case '$':
695 			if (*sp != seof)
696 				goto defchar;
697 			*ep++ = CDOL;
698 			continue;
699 
700 		case '[':
701 			if(&ep[17] >= &expbuf[ESIZE]) {
702 				fprintf(stderr, "RE too long: %s\n", linebuf);
703 				exit(2);
704 			}
705 
706 			*ep++ = CCL;
707 
708 			neg = 0;
709 			if((c = *sp++) == '^') {
710 				neg = 1;
711 				c = *sp++;
712 			}
713 
714 			cstart = sp;
715 			do {
716 				if(c == '\0') {
717 					fprintf(stderr, CGMES, linebuf);
718 					exit(2);
719 				}
720 				if (c=='-' && sp>cstart && *sp!=']') {
721 					for (c = sp[-2]; c<*sp; c++)
722 						ep[c>>3] |= bittab[c&07];
723 				}
724 				if(c == '\\') {
725 					switch(c = *sp++) {
726 						case 'n':
727 							c = '\n';
728 							break;
729 					}
730 				}
731 
732 				ep[c >> 3] |= bittab[c & 07];
733 			} while((c = *sp++) != ']');
734 
735 			if(neg)
736 				for(cclcnt = 0; cclcnt < 16; cclcnt++)
737 					ep[cclcnt] ^= -1;
738 			ep[0] &= 0376;
739 
740 			ep += 16;
741 
742 			continue;
743 
744 		defchar:
745 		default:
746 			*ep++ = CCHR;
747 			*ep++ = c;
748 		}
749 	}
750 }
751 rline(lbuf)
752 char	*lbuf;
753 {
754 	register char	*p, *q;
755 	register	t;
756 	static char	*saveq;
757 
758 	p = lbuf - 1;
759 
760 	if(eflag) {
761 		if(eflag > 0) {
762 			eflag = -1;
763 			if(eargc-- <= 0)
764 				exit(2);
765 			q = *++eargv;
766 			while(*++p = *q++) {
767 				if(*p == '\\') {
768 					if((*++p = *q++) == '\0') {
769 						saveq = 0;
770 						return(-1);
771 					} else
772 						continue;
773 				}
774 				if(*p == '\n') {
775 					*p = '\0';
776 					saveq = q;
777 					return(1);
778 				}
779 			}
780 			saveq = 0;
781 			return(1);
782 		}
783 		if((q = saveq) == 0)	return(-1);
784 
785 		while(*++p = *q++) {
786 			if(*p == '\\') {
787 				if((*++p = *q++) == '0') {
788 					saveq = 0;
789 					return(-1);
790 				} else
791 					continue;
792 			}
793 			if(*p == '\n') {
794 				*p = '\0';
795 				saveq = q;
796 				return(1);
797 			}
798 		}
799 		saveq = 0;
800 		return(1);
801 	}
802 
803 	while((t = getc(fin)) != EOF) {
804 		*++p = t;
805 		if(*p == '\\') {
806 			t = getc(fin);
807 			*++p = t;
808 		}
809 		else if(*p == '\n') {
810 			*p = '\0';
811 			return(1);
812 		}
813 	}
814 	*++p = '\0';
815 	return(-1);
816 }
817 
818 char	*address(expbuf)
819 char	*expbuf;
820 {
821 	register char	*rcp;
822 	long	lno;
823 
824 	if(*cp == '$') {
825 		cp++;
826 		*expbuf++ = CEND;
827 		*expbuf++ = CEOF;
828 		return(expbuf);
829 	}
830 
831 	if(*cp == '/') {
832 		seof = '/';
833 		cp++;
834 		return(compile(expbuf));
835 	}
836 
837 	rcp = cp;
838 	lno = 0;
839 
840 	while(*rcp >= '0' && *rcp <= '9')
841 		lno = lno*10 + *rcp++ - '0';
842 
843 	if(rcp > cp) {
844 		*expbuf++ = CLNUM;
845 		*expbuf++ = nlno;
846 		tlno[nlno++] = lno;
847 		if(nlno >= NLINES) {
848 			fprintf(stderr, "Too many line numbers\n");
849 			exit(2);
850 		}
851 		*expbuf++ = CEOF;
852 		cp = rcp;
853 		return(expbuf);
854 	}
855 	return(0);
856 }
857 cmp(a, b)
858 char	*a,*b;
859 {
860 	register char	*ra, *rb;
861 
862 	ra = a - 1;
863 	rb = b - 1;
864 
865 	while(*++ra == *++rb)
866 		if(*ra == '\0')	return(0);
867 	return(1);
868 }
869 
870 char	*text(textbuf)
871 char	*textbuf;
872 {
873 	register char	*p, *q;
874 
875 	p = textbuf;
876 	q = cp;
877 	while(*q == '\t' || *q == ' ')	q++;
878 	for(;;) {
879 
880 		if((*p = *q++) == '\\')
881 			*p = *q++;
882 		if(*p == '\0') {
883 			cp = --q;
884 			return(++p);
885 		}
886 		if(*p == '\n') {
887 			while(*q == '\t' || *q == ' ')	q++;
888 		}
889 		p++;
890 	}
891 }
892 
893 
894 struct label	*search(ptr)
895 struct label	*ptr;
896 {
897 	struct label	*rp;
898 
899 	rp = labtab;
900 	while(rp < ptr) {
901 		if(cmp(rp->asc, ptr->asc) == 0)
902 			return(rp);
903 		rp++;
904 	}
905 
906 	return(0);
907 }
908 
909 
910 dechain()
911 {
912 	struct label	*lptr;
913 	union reptr	*rptr, *trptr;
914 
915 	for(lptr = labtab; lptr < lab; lptr++) {
916 
917 		if(lptr->address == 0) {
918 			fprintf(stderr, "Undefined label: %s\n", lptr->asc);
919 			exit(2);
920 		}
921 
922 		if(lptr->chain) {
923 			rptr = lptr->chain;
924 			while(trptr = rptr->lb1) {
925 				rptr->lb1 = lptr->address;
926 				rptr = trptr;
927 			}
928 			rptr->lb1 = lptr->address;
929 		}
930 	}
931 }
932 
933 char *ycomp(expbuf)
934 char	*expbuf;
935 {
936 	register char	c, *ep, *tsp;
937 	char	*sp;
938 
939 	ep = expbuf;
940 	sp = cp;
941 	for(tsp = cp; *tsp != seof; tsp++) {
942 		if(*tsp == '\\')
943 			tsp++;
944 		if(*tsp == '\n')
945 			return(badp);
946 	}
947 	tsp++;
948 
949 	while((c = *sp++ & 0177) != seof) {
950 		if(c == '\\' && *sp == 'n') {
951 			sp++;
952 			c = '\n';
953 		}
954 		if((ep[c] = *tsp++) == '\\' && *tsp == 'n') {
955 			ep[c] = '\n';
956 			tsp++;
957 		}
958 		if(ep[c] == seof || ep[c] == '\0')
959 			return(badp);
960 	}
961 	if(*tsp != seof)
962 		return(badp);
963 	cp = ++tsp;
964 
965 	for(c = 0; !(c & 0200); c++)
966 		if(ep[c] == 0)
967 			ep[c] = c;
968 
969 	return(ep + 0200);
970 }
971