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