xref: /original-bsd/old/sed/sed0.c (revision 410efcb1)
1 /*-
2  * %sccs.include.proprietary.c%
3  */
4 
5 #ifndef lint
6 static char sccsid[] = "@(#)sed0.c	4.8 (Berkeley) 09/11/91";
7 #endif /* not lint */
8 
9 #include <sys/param.h>
10 #include <stdio.h>
11 #include "sed.h"
12 
13 struct label	*labtab = ltab;
14 char	CGMES[]	= "command garbled: %s\n";
15 char	TMMES[]	= "Too much text: %s\n";
16 char	LTL[]	= "Label too long: %s\n";
17 char	AD0MES[]	= "No addresses allowed: %s\n";
18 char	AD1MES[]	= "Only one address allowed: %s\n";
19 char	bittab[]  = {
20 		1,
21 		2,
22 		4,
23 		8,
24 		16,
25 		32,
26 		64,
27 		128
28 	};
29 
30 main(argc, argv)
31 char	*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;
54 	fname[0] = "";
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 }
125 fcomp()
126 {
127 
128 	register char	*p, *op, *tp;
129 	char	*address();
130 	struct reptr	*pt, *pt1;
131 	int	i;
132 	struct label	*lpt;
133 	char fbuf[MAXPATHLEN + 1], *newstr();
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 
153 comploop:
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 
207 swit:
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;
351 jtcommon:
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) {
453 					if(op)
454 					    rep->re1 = op;
455 					else {
456 					    fprintf(stderr,
457 						"First RE may not be null\n");
458 					    exit(2);
459 					}
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 					}
495 					if(nfiles > 10) {
496 						fprintf(stderr, "Too many files in w commands\n");
497 						exit(2);
498 					}
499 
500 					text(fbuf);
501 					fname[nfiles] = newstr(fbuf);
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 				}
521 				if(nfiles > 10){
522 					fprintf(stderr, "Too many files in w commands\n");
523 					exit(2);
524 				}
525 
526 				text(fbuf);
527 				fname[nfiles] = newstr(fbuf);
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 		}
561 done:
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 }
580 char	*compsub(rhsbuf)
581 char	*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 
607 char *compile(expbuf)
608 char	*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 }
768 rline(lbuf)
769 char	*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 
835 char	*address(expbuf)
836 char	*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 }
874 cmp(a, b)
875 char	*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 
887 char	*text(textbuf)
888 char	*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 
911 struct label	*search(ptr)
912 struct 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 
927 dechain()
928 {
929 	struct label	*lptr;
930 	struct reptr	*rptr, *trptr;
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 
950 char *ycomp(expbuf)
951 char	*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 }
988 
989 char *
990 newstr(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 }
1001