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