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