1 /*	from Unix 7th Edition sed	*/
2 /*	Sccsid @(#)sed0.c	1.64 (gritter) 3/12/05>	*/
3 /*
4  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *   Redistributions of source code and documentation must retain the
10  *    above copyright notice, this list of conditions and the following
11  *    disclaimer.
12  *   Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *   All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed or owned by Caldera
18  *      International, Inc.
19  *   Neither the name of Caldera International, Inc. nor the names of
20  *    other contributors may be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
24  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
28  * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
34  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <locale.h>
39 #include <libgen.h>
40 #include <stdarg.h>
41 #include <wchar.h>
42 #include "sed.h"
43 
44 int	ABUFSIZE;
45 struct reptr	**abuf;
46 int	aptr;
47 char	*genbuf;
48 int	gbend;
49 int	lbend;
50 int	hend;
51 char	*linebuf;
52 char	*holdsp;
53 int	nflag;
54 long long	*tlno;
55 char	*cp;
56 
57 int	status;
58 int	multibyte;
59 int	invchar;
60 int	needdol;
61 
62 int	eargc;
63 
64 struct	reptr *ptrspace;
65 struct reptr	*pending;
66 char	*badp;
67 
68 static const char	CGMES[]	= "\1command garbled: %s";
69 static const char	TMMES[]	= "Too much text: %s";
70 static const char	LTL[]	= "Label too long: %s";
71 static const char	LINTL[]	= "line too long";
72 static const char	AD0MES[]	= "No addresses allowed: %s";
73 static const char	AD1MES[]	= "Only one address allowed: %s";
74 static FILE	**fcode;
75 static FILE	*fin;
76 static char	*lastre;
77 static wchar_t	sed_seof;
78 static int	PTRSIZE;
79 static int	eflag;
80 static int	gflag;
81 static int	nlno;
82 static char	**fname;
83 static int	nfiles;
84 static int	rep;
85 static struct label  *ltab;
86 static int	lab;
87 static size_t	LABSIZE;
88 static int	labtab = 1;
89 static int	depth;
90 static char	**eargv;
91 static int	*cmpend;
92 static size_t	DEPTH;
93 static char	bad;
94 static char	compfl;
95 static char	*progname;
96 static char	*(*ycomp)(char **);
97 static int	executing;
98 
99 static void fcomp(void);
100 static char *compsub(char **, char *);
101 static int rline(void);
102 static char *address(char **);
103 static int cmp(const char *, const char *);
104 static void text(char **);
105 static int search(struct label *);
106 static void dechain(void);
107 static char *ycomp_sb(char **);
108 static char *ycomp_mb(char **);
109 static void lab_inc(void);
110 static void rep_inc(void);
111 static void depth_check(void);
112 static void *srealloc(void *, size_t);
113 static void *scalloc(size_t, size_t);
114 static char *sed_compile(char **);
115 static void wfile(void);
116 static void morefiles(void);
117 
118 static char	*null;
119 #define	check(p, buf, sz, incr, op) \
120 	if (&p[1] >= &(buf)[sz]) { \
121 		size_t ppos = p - buf; \
122 		size_t opos = op - buf; \
123 		buf = srealloc(buf, (sz += incr) * sizeof *(buf)); \
124 		p = &(buf)[ppos]; \
125 		if (op != NULL) \
126 			op = &(buf)[opos]; \
127 	}
128 
129 int
main(int argc,char ** argv)130 main(int argc, char **argv)
131 {
132 	int c;
133 	const char optstr[] = "nf:e:g";
134 
135 	sed = 1;
136 	progname = basename(argv[0]);
137 	eargc = argc;
138 	eargv = argv;
139 
140 #ifdef	__GLIBC__
141 	putenv("POSIXLY_CORRECT=1");
142 #endif	/* __GLIBC__ */
143 #if defined (SUS) || defined (SU3) || defined (S42)
144 	setlocale(LC_COLLATE, "");
145 #endif	/* SUS || SU3 || S42 */
146 	setlocale(LC_CTYPE, "");
147 	multibyte = MB_CUR_MAX > 1;
148 	ycomp = multibyte ? ycomp_mb : ycomp_sb;
149 	badp = &bad;
150 	aptr_inc();
151 	lab_inc();
152 	lab_inc();	/* 0 reserved for end-pointer -> labtab = 1 */
153 	growsp(NULL);
154 	rep_inc();
155 	pending = 0;
156 	depth = 0;
157 	morefiles();
158 	fcode[0] = stdout;
159 	nfiles = 1;
160 	morefiles();
161 
162 	if(eargc == 1)
163 		exit(0);
164 	while ((c = getopt(eargc, eargv, optstr)) != EOF) {
165 		switch (c) {
166 		case 'n':
167 			nflag++;
168 			continue;
169 
170 		case 'f':
171 			if((fin = fopen(optarg, "r")) == NULL)
172 				fatal("Cannot open pattern-file: %s", optarg);
173 
174 			fcomp();
175 			fclose(fin);
176 			continue;
177 
178 		case 'e':
179 			eflag++;
180 			fcomp();
181 			eflag = 0;
182 			continue;
183 
184 		case 'g':
185 			gflag++;
186 			continue;
187 
188 		default:
189 			exit(2);
190 		}
191 	}
192 
193 	eargv += optind, eargc -= optind;
194 
195 
196 	if(compfl == 0 && *eargv) {
197 		optarg = *eargv++;
198 		eargc--;
199 		eflag++;
200 		fcomp();
201 		eflag = 0;
202 	}
203 
204 	if(depth)
205 		fatal("Too many {'s");
206 
207 	L(labtab)->address = rep;
208 
209 	dechain();
210 
211 /*	abort();	*/	/*DEBUG*/
212 
213 	executing++;
214 	if(eargc <= 0)
215 		execute((char *)NULL);
216 	else while(--eargc >= 0) {
217 		execute(*eargv++);
218 	}
219 	fclose(stdout);
220 	return status;
221 }
222 
223 static void
fcomp(void)224 fcomp(void)
225 {
226 
227 	register char	*op, *tp, *q;
228 	int	pt, pt1;
229 	int	lpt;
230 
231 	compfl = 1;
232 	op = lastre;
233 
234 	if(rline() < 0)	return;
235 	if(*linebuf == '#') {
236 		if(linebuf[1] == 'n')
237 			nflag = 1;
238 	}
239 	else {
240 		cp = linebuf;
241 		goto comploop;
242 	}
243 
244 	for(;;) {
245 		if(rline() < 0)	break;
246 
247 		cp = linebuf;
248 
249 comploop:
250 /*	fprintf(stdout, "cp: %s\n", cp); */	/*DEBUG*/
251 		while(*cp == ' ' || *cp == '\t')	cp++;
252 		if(*cp == '\0' || *cp == '#')		continue;
253 		if(*cp == ';') {
254 			cp++;
255 			goto comploop;
256 		}
257 
258 		q = address(&P(rep)->ad1);
259 		if(q == badp)
260 			fatal(CGMES, linebuf);
261 
262 		if(q != 0 && q == P(rep)->ad1) {
263 			if(op)
264 				P(rep)->ad1 = op;
265 			else
266 				fatal("First RE may not be null");
267 		} else if(q == 0) {
268 			P(rep)->ad1 = 0;
269 		} else {
270 			op = P(rep)->ad1;
271 			if(*cp == ',' || *cp == ';') {
272 				cp++;
273 				q = address(&P(rep)->ad2);
274 				if(q == badp || q == 0)
275 					fatal(CGMES, linebuf);
276 				if(q == P(rep)->ad2)
277 					P(rep)->ad2 = op;
278 				else
279 					op = P(rep)->ad2;
280 
281 			} else
282 				P(rep)->ad2 = 0;
283 		}
284 
285 		while(*cp == ' ' || *cp == '\t')	cp++;
286 
287 swit:
288 		switch(*cp++) {
289 
290 			default:
291 				fatal("Unrecognized command: %s", linebuf);
292 				/*NOTREACHED*/
293 
294 			case '!':
295 				P(rep)->negfl = 1;
296 				goto swit;
297 
298 			case '{':
299 				P(rep)->command = BCOM;
300 				P(rep)->negfl = !(P(rep)->negfl);
301 				depth_check();
302 				cmpend[depth++] = rep;
303 				rep_inc();
304 				if(*cp == '\0')	continue;
305 
306 				goto comploop;
307 
308 			case '}':
309 				if(P(rep)->ad1)
310 					fatal(AD0MES, linebuf);
311 
312 				if(--depth < 0)
313 					fatal("Too many }'s");
314 				P(cmpend[depth])->bptr.lb1 = rep;
315 
316 				continue;
317 
318 			case '=':
319 				P(rep)->command = EQCOM;
320 				if(P(rep)->ad2)
321 					fatal(AD1MES, linebuf);
322 				break;
323 
324 			case ':':
325 				if(P(rep)->ad1)
326 					fatal(AD0MES, linebuf);
327 
328 				while(*cp++ == ' ');
329 				cp--;
330 
331 
332 				tp = L(lab)->asc;
333 				while((*tp++ = *cp++))
334 					if(tp >= &(L(lab)->asc[sizeof
335 								L(lab)->asc]))
336 						fatal(LTL, linebuf);
337 				*--tp = '\0';
338 
339 				if(lpt = search(L(lab))) {
340 					if(L(lpt)->address)
341 						fatal("Duplicate labels: %s",
342 								linebuf);
343 				} else {
344 					L(lab)->chain = 0;
345 					lpt = lab;
346 					lab_inc();
347 				}
348 				L(lpt)->address = rep;
349 
350 				continue;
351 
352 			case 'a':
353 				P(rep)->command = ACOM;
354 				if(P(rep)->ad2)
355 					fatal(AD1MES, linebuf);
356 				if(*cp == '\\')	cp++;
357 				if(*cp++ != '\n')
358 					fatal(CGMES, linebuf);
359 				text(&P(rep)->bptr.re1);
360 				break;
361 			case 'c':
362 				P(rep)->command = CCOM;
363 				if(*cp == '\\')	cp++;
364 				if(*cp++ != ('\n'))
365 					fatal(CGMES, linebuf);
366 				text(&P(rep)->bptr.re1);
367 				needdol = 1;
368 				break;
369 			case 'i':
370 				P(rep)->command = ICOM;
371 				if(P(rep)->ad2)
372 					fatal(AD1MES, linebuf);
373 				if(*cp == '\\')	cp++;
374 				if(*cp++ != ('\n'))
375 					fatal(CGMES, linebuf);
376 				text(&P(rep)->bptr.re1);
377 				break;
378 
379 			case 'g':
380 				P(rep)->command = GCOM;
381 				break;
382 
383 			case 'G':
384 				P(rep)->command = CGCOM;
385 				break;
386 
387 			case 'h':
388 				P(rep)->command = HCOM;
389 				break;
390 
391 			case 'H':
392 				P(rep)->command = CHCOM;
393 				break;
394 
395 			case 't':
396 				P(rep)->command = TCOM;
397 				goto jtcommon;
398 
399 			case 'b':
400 				P(rep)->command = BCOM;
401 jtcommon:
402 				while(*cp++ == ' ');
403 				cp--;
404 
405 				if(*cp == '\0') {
406 					if((pt = L(labtab)->chain) != 0) {
407 						while((pt1 = P(pt)->bptr.lb1) != 0)
408 							pt = pt1;
409 						P(pt)->bptr.lb1 = rep;
410 					} else
411 						L(labtab)->chain = rep;
412 					break;
413 				}
414 				tp = L(lab)->asc;
415 				while((*tp++ = *cp++))
416 					if(tp >= &(L(lab)->asc[sizeof
417 								L(lab)->asc]))
418 						fatal(LTL, linebuf);
419 				cp--;
420 				*--tp = '\0';
421 
422 				if(lpt = search(L(lab))) {
423 					if(L(lpt)->address) {
424 						P(rep)->bptr.lb1 = L(lpt)->address;
425 					} else {
426 						pt = L(lpt)->chain;
427 						while((pt1 = P(pt)->bptr.lb1) != 0)
428 							pt = pt1;
429 						P(pt)->bptr.lb1 = rep;
430 					}
431 				} else {
432 					L(lab)->chain = rep;
433 					L(lab)->address = 0;
434 					lab_inc();
435 				}
436 				break;
437 
438 			case 'n':
439 				P(rep)->command = NCOM;
440 				break;
441 
442 			case 'N':
443 				P(rep)->command = CNCOM;
444 				break;
445 
446 			case 'p':
447 				P(rep)->command = PCOM;
448 				break;
449 
450 			case 'P':
451 				P(rep)->command = CPCOM;
452 				break;
453 
454 			case 'r':
455 				P(rep)->command = RCOM;
456 				if(P(rep)->ad2)
457 					fatal(AD1MES, linebuf);
458 #if !defined (SUS) && !defined (SU3)
459 				if(*cp++ != ' ')
460 					fatal(CGMES, linebuf);
461 #else	/* SUS, SU3 */
462 				while (*cp == ' ' || *cp == '\t')
463 					cp++;
464 #endif	/* SUS, SU3 */
465 				text(&P(rep)->bptr.re1);
466 				break;
467 
468 			case 'd':
469 				P(rep)->command = DCOM;
470 				break;
471 
472 			case 'D':
473 				P(rep)->command = CDCOM;
474 				P(rep)->bptr.lb1 = 1;
475 				break;
476 
477 			case 'q':
478 				P(rep)->command = QCOM;
479 				if(P(rep)->ad2)
480 					fatal(AD1MES, linebuf);
481 				break;
482 
483 			case 'l':
484 				P(rep)->command = LCOM;
485 				break;
486 
487 			case 's':
488 				P(rep)->command = SCOM;
489 				sed_seof = fetch(&cp);
490 				q = sed_compile(&P(rep)->bptr.re1);
491 				if(q == badp)
492 					fatal(CGMES, linebuf);
493 				if(q == P(rep)->bptr.re1) {
494 					if (op == NULL)
495 						fatal("First RE may not be null");
496 					P(rep)->bptr.re1 = op;
497 				} else {
498 					op = P(rep)->bptr.re1;
499 				}
500 
501 				if(compsub(&P(rep)->rhs, &P(rep)->nsub) == badp)
502 					fatal(CGMES, linebuf);
503 			sloop:	if(*cp == 'g') {
504 					cp++;
505 					P(rep)->gfl = -1;
506 					goto sloop;
507 				} else if(gflag)
508 					P(rep)->gfl = -1;
509 				if (*cp >= '0' && *cp <= '9') {
510 					while (*cp >= '0' && *cp <= '9') {
511 						if (P(rep)->gfl == -1)
512 							P(rep)->gfl = 0;
513 						P(rep)->gfl = P(rep)->gfl * 10
514 							+ *cp++ - '0';
515 					}
516 					goto sloop;
517 				}
518 #if !defined (SUS) && !defined (SU3)
519 				if (P(rep)->gfl > 0 && P(rep)->gfl > 512)
520 			fatal("Suffix too large - 512 max: %s", linebuf);
521 #endif
522 
523 				if(*cp == 'p') {
524 					cp++;
525 					P(rep)->pfl = 1;
526 					goto sloop;
527 				}
528 
529 				if(*cp == 'P') {
530 					cp++;
531 					P(rep)->pfl = 2;
532 					goto sloop;
533 				}
534 
535 				if(*cp == 'w') {
536 					cp++;
537 					wfile();
538 				}
539 				break;
540 
541 			case 'w':
542 				P(rep)->command = WCOM;
543 				wfile();
544 				break;
545 
546 			case 'x':
547 				P(rep)->command = XCOM;
548 				break;
549 
550 			case 'y':
551 				P(rep)->command = YCOM;
552 				sed_seof = fetch(&cp);
553 				if (ycomp(&P(rep)->bptr.re1) == badp)
554 					fatal(CGMES, linebuf);
555 				break;
556 
557 		}
558 		rep_inc();
559 
560 		if(*cp++ != '\0') {
561 			if(cp[-1] == ';')
562 				goto comploop;
563 			fatal(CGMES, linebuf);
564 		}
565 
566 	}
567 	P(rep)->command = 0;
568 	lastre = op;
569 }
570 
571 static char	*
compsub(char ** rhsbuf,char * nsubp)572 compsub(char **rhsbuf, char *nsubp)
573 {
574 	register char	*p, *op, *oq;
575 	char	*q;
576 	wint_t	c;
577 	size_t	sz = 32;
578 
579 	*rhsbuf = smalloc(sz);
580 	p = *rhsbuf;
581 	q = cp;
582 	*nsubp = 0;
583 	for(;;) {
584 		op = p;
585 		oq = q;
586 		if((c = fetch(&q)) == '\\') {
587 			check(p, *rhsbuf, sz, 32, op)
588 			*p = '\\';
589 			oq = q;
590 			c = fetch(&q);
591 			do {
592 				check(p, *rhsbuf, sz, 32, op)
593 				*++p = *oq++;
594 			} while (oq < q);
595 			if(c > nbra + '0' && c <= '9')
596 				return(badp);
597 			if (c > *nsubp + '0' && c <= '9')
598 				*nsubp = c - '0';
599 			check(p, *rhsbuf, sz, 32, op)
600 			p++;
601 			continue;
602 		} else {
603 			do {
604 				check(p, *rhsbuf, sz, 32, op)
605 				*p++ = *oq++;
606 			} while (oq < q);
607 			p--;
608 		}
609 		if(c == sed_seof) {
610 			check(p, *rhsbuf, sz, 32, op)
611 			*op++ = '\0';
612 			cp = q;
613 			return(op);
614 		}
615 		check(p, *rhsbuf, sz, 32, op)
616 		if(*p++ == '\0') {
617 			return(badp);
618 		}
619 
620 	}
621 }
622 
623 #define	rlinechk()	if (c >= lbend-2) \
624 				growsp(LINTL)
625 
626 static int
rline(void)627 rline(void)
628 {
629 	register char	*q;
630 	register int	c;
631 	register int	t;
632 	static char	*saveq;
633 
634 	c = -1;
635 
636 	if(eflag) {
637 		if(eflag > 0) {
638 			eflag = -1;
639 			q = optarg;
640 			rlinechk();
641 			while(linebuf[++c] = *q++) {
642 				rlinechk();
643 				if(linebuf[c] == '\\') {
644 					if((linebuf[++c] = *q++) == '\0') {
645 						rlinechk();
646 						saveq = 0;
647 						return(-1);
648 					} else
649 						continue;
650 				}
651 				if(linebuf[c] == '\n') {
652 					linebuf[c] = '\0';
653 					saveq = q;
654 					return(1);
655 				}
656 			}
657 			saveq = 0;
658 			return(1);
659 		}
660 		if((q = saveq) == 0)	return(-1);
661 
662 		while(linebuf[++c] = *q++) {
663 			rlinechk();
664 			if(linebuf[c] == '\\') {
665 				if((linebuf[++c] = *q++) == '0') {
666 					rlinechk();
667 					saveq = 0;
668 					return(-1);
669 				} else
670 					continue;
671 			}
672 			if(linebuf[c] == '\n') {
673 				linebuf[c] = '\0';
674 				saveq = q;
675 				return(1);
676 			}
677 		}
678 		saveq = 0;
679 		return(1);
680 	}
681 
682 	while((t = getc(fin)) != EOF) {
683 		rlinechk();
684 		linebuf[++c] = (char)t;
685 		if(linebuf[c] == '\\') {
686 			t = getc(fin);
687 			rlinechk();
688 			linebuf[++c] = (char)t;
689 		}
690 		else if(linebuf[c] == '\n') {
691 			linebuf[c] = '\0';
692 			return(1);
693 		}
694 	}
695 	linebuf[++c] = '\0';
696 	return(-1);
697 }
698 
699 static char	*
address(char ** expbuf)700 address(char **expbuf)
701 {
702 	register char	*rcp, *ep;
703 	long long	lno;
704 
705 	*expbuf = NULL;
706 	if(*cp == '$') {
707 		cp++;
708 		ep = *expbuf = smalloc(2 * sizeof *expbuf);
709 		*ep++ = CEND;
710 		*ep++ = ceof;
711 		needdol = 1;
712 		return(ep);
713 	}
714 
715 	if(*cp == '/' || *cp == '\\') {
716 		if (*cp == '\\')
717 			cp++;
718 		sed_seof = fetch(&cp);
719 		return(sed_compile(expbuf));
720 	}
721 
722 	rcp = cp;
723 	lno = 0;
724 
725 	while(*rcp >= '0' && *rcp <= '9')
726 		lno = lno*10 + *rcp++ - '0';
727 
728 	if(rcp > cp) {
729 		if (nlno > 020000000000 ||
730 		    (tlno = realloc(tlno, (nlno+1)*sizeof *tlno)) == NULL)
731 			fatal("Too many line numbers");
732 		ep = *expbuf = smalloc(6 * sizeof *expbuf);
733 		*ep++ = CLNUM;
734 		slno(ep, nlno);
735 		tlno[nlno++] = lno;
736 		*ep++ = ceof;
737 		cp = rcp;
738 		return(ep);
739 	}
740 	return(0);
741 }
742 
743 static int
cmp(const char * a,const char * b)744 cmp(const char *a, const char *b)
745 {
746 	register const char	*ra, *rb;
747 
748 	ra = a - 1;
749 	rb = b - 1;
750 
751 	while(*++ra == *++rb)
752 		if(*ra == '\0')	return(0);
753 	return(1);
754 }
755 
756 static void
text(char ** textbuf)757 text(char **textbuf)
758 {
759 	register char	*p, *oq;
760 	char *q;
761 	size_t sz = 128;
762 
763 	*textbuf = smalloc(sz);
764 	p = *textbuf;
765 	q = cp;
766 	for(;;) {
767 
768 		oq = q;
769 		if(fetch(&q) == '\\') {
770 			oq = q;
771 			fetch(&q);
772 		}
773 		while(oq < q)
774 			*p++ = *oq++;
775 		if(p[-1] == '\0') {
776 			cp = --q;
777 			return;
778 		}
779 		check(p, *textbuf, sz, 128, null)
780 	}
781 }
782 
783 static int
search(struct label * ptr)784 search(struct label *ptr)
785 {
786 	struct label	*rp;
787 
788 	rp = L(labtab);
789 	while(rp < ptr) {
790 		if(cmp(rp->asc, ptr->asc) == 0)
791 			return(rp - L(labtab) + 1);
792 		rp++;
793 	}
794 
795 	return(0);
796 }
797 
798 
799 static void
dechain(void)800 dechain(void)
801 {
802 	struct label	*lptr;
803 	int	rptr, trptr;
804 
805 	for(lptr = L(labtab); lptr < L(lab); lptr++) {
806 
807 		if(lptr->address == 0)
808 			fatal("Undefined label: %s", lptr->asc);
809 
810 		if(lptr->chain) {
811 			rptr = lptr->chain;
812 			while((trptr = P(rptr)->bptr.lb1) != 0) {
813 				P(rptr)->bptr.lb1 = lptr->address;
814 				rptr = trptr;
815 			}
816 			P(rptr)->bptr.lb1 = lptr->address;
817 		}
818 	}
819 }
820 
821 static char *
ycomp_sb(char ** expbuf)822 ycomp_sb(char **expbuf)
823 {
824 	register int	c, d;
825 	register char	*ep, *tsp;
826 	char	*sp;
827 
828 	*expbuf = smalloc(0400);
829 	ep = *expbuf;
830 	for(c = 0; !(c & 0400); c++)
831 		ep[c] = '\0';
832 	sp = cp;
833 	for(tsp = cp; *tsp != sed_seof; tsp++) {
834 		if(*tsp == '\\')
835 			tsp++;
836 		if(*tsp == '\n' || *tsp == '\0')
837 			return(badp);
838 	}
839 	tsp++;
840 
841 	while((c = *sp++ & 0377) != sed_seof) {
842 		if(c == '\\') {
843 			c = *sp == 'n' ? '\n' : *sp;
844 			sp++;
845 		}
846 		if((ep[c] = d = *tsp++ & 0377) == '\\') {
847 			ep[c] = *tsp == 'n' ? '\n' : *tsp;
848 			tsp++;
849 		}
850 		if(d != '\\' && ep[c] == sed_seof || ep[c] == '\0')
851 			return(badp);
852 	}
853 	if(*tsp != sed_seof)
854 		return(badp);
855 	cp = ++tsp;
856 
857 	for(c = 0; !(c & 0400); c++)
858 		if(ep[c] == 0)
859 			ep[c] = (char)c;
860 
861 	return(ep + 0400);
862 }
863 
864 static char *
ycomp_mb(char ** expbuf)865 ycomp_mb(char **expbuf)
866 {
867 	struct yitem	**yt, *yp;
868 	register wint_t	c, d;
869 	char	*otsp, *tsp, *sp, *mp;
870 
871 	tsp = sp = cp;
872 	while ((c = fetch(&tsp)) != sed_seof) {
873 		if (c == '\\')
874 			c = fetch(&tsp);
875 		if (c == '\n' || c == '\0')
876 			return badp;
877 	}
878 	yt = scalloc(200, sizeof *yt);
879 	while ((c = fetch(&sp)) != sed_seof) {
880 		if (c == '\\') {
881 			if ((d = fetch(&sp)) == 'n')
882 				c = '\n';
883 			else
884 				c = d;
885 		}
886 		otsp = tsp;
887 		d = fetch(&tsp);
888 		yp = ylook(c, yt, 1);
889 		yp->y_oc = c;
890 		if ((yp->y_yc = d) == '\\') {
891 			otsp = tsp;
892 			if ((c = fetch(&tsp)) == 'n')
893 				yp->y_yc = '\n';
894 			else
895 				yp->y_yc = c;
896 		}
897 		if (d != '\\' && yp->y_yc == sed_seof || yp->y_yc == '\0')
898 			return badp;
899 		mp = yp->y_mc;
900 		if (yp->y_yc != '\n')
901 			while (otsp < tsp)
902 				*mp++ = *otsp++;
903 		else
904 			*mp++ = '\n';
905 		*mp = '\0';
906 	}
907 	if (fetch(&tsp) != sed_seof)
908 		return badp;
909 	cp = tsp;
910 	*expbuf = (char *)yt;
911 	return &(*expbuf)[1];
912 }
913 
914 static void
rep_inc(void)915 rep_inc(void)
916 {
917 	register char	*p;
918 	const int	chunk = 16;
919 
920 	if (++rep >= PTRSIZE) {
921 		ptrspace = srealloc(ptrspace,
922 				(PTRSIZE += chunk) * sizeof *ptrspace);
923 		for (p = (char *)&ptrspace[PTRSIZE - chunk];
924 				p < (char *)&ptrspace[PTRSIZE]; p++)
925 			*p = '\0';
926 	}
927 }
928 
929 static void
lab_inc(void)930 lab_inc(void)
931 {
932 	register char	*p;
933 	const int	chunk = 8;
934 
935 	if (++lab >= LABSIZE) {
936 		ltab = srealloc(ltab, (LABSIZE += chunk) * sizeof *ltab);
937 		for (p = (char *)&ltab[LABSIZE - chunk];
938 				p < (char *)&ltab[LABSIZE]; p++)
939 			*p = '\0';
940 	}
941 }
942 
943 void
aptr_inc(void)944 aptr_inc(void)
945 {
946 	register char	*p;
947 	const int	chunk = 8;
948 
949 	if (++aptr > ABUFSIZE) {
950 		abuf = srealloc(abuf, (ABUFSIZE += chunk) * sizeof *abuf);
951 		for (p = (char *)&abuf[ABUFSIZE - chunk];
952 				p < (char *)&abuf[ABUFSIZE]; p++)
953 			*p = '\0';
954 	}
955 }
956 
957 static void
depth_check(void)958 depth_check(void)
959 {
960 	if (depth + 1 > DEPTH)
961 		cmpend = srealloc(cmpend, (DEPTH += 8) * sizeof *cmpend);
962 }
963 
964 void
nonfatal(const char * afmt,...)965 nonfatal(const char *afmt, ...)
966 {
967 	va_list ap;
968 	const char	*fmt;
969 
970 	if (*afmt == '\1') {
971 		fprintf(stderr, "%s: ", progname);
972 		fmt = &afmt[1];
973 	} else
974 		fmt = afmt;
975 	va_start(ap, afmt);
976 	vfprintf(stderr, fmt, ap);
977 	va_end(ap);
978 	fputc('\n', stderr);
979 	status |= 1;
980 }
981 
982 void
fatal(const char * afmt,...)983 fatal(const char *afmt, ...)
984 {
985 	va_list ap;
986 	const char	*fmt;
987 
988 	if (*afmt == '\1') {
989 		fprintf(stderr, "%s: ", progname);
990 		fmt = &afmt[1];
991 	} else
992 		fmt = afmt;
993 	va_start(ap, afmt);
994 	vfprintf(stderr, fmt, ap);
995 	va_end(ap);
996 	fputc('\n', stderr);
997 	exit(2);
998 }
999 
1000 static void *
srealloc(void * vp,size_t nbytes)1001 srealloc(void *vp, size_t nbytes)
1002 {
1003 	void *p;
1004 
1005 	if ((p = realloc(vp, nbytes)) == NULL)
1006 		fatal(TMMES, linebuf);
1007 	return p;
1008 }
1009 
1010 void *
smalloc(size_t nbytes)1011 smalloc(size_t nbytes)
1012 {
1013 	return srealloc(NULL, nbytes);
1014 }
1015 
1016 static void *
scalloc(size_t nmemb,size_t size)1017 scalloc(size_t nmemb, size_t size)
1018 {
1019 	void *p;
1020 
1021 	if ((p = calloc(nmemb, size)) == NULL)
1022 		fatal(TMMES, linebuf);
1023 	return p;
1024 }
1025 
1026 #if defined (SUS) || defined (SU3) || defined (S42)
1027 static char *
sed_compile(char ** ep)1028 sed_compile(char **ep)
1029 {
1030 	struct re_emu	*re;
1031 	static char	*pat;
1032 	static size_t	patsz;
1033 	register char	*p, *oc;
1034 	wint_t	c, d;
1035 
1036 	if (*cp != sed_seof)
1037 		nbra = 0;
1038 	if (patsz == 0)
1039 		pat = smalloc(patsz = 32);
1040 	p = pat;
1041 	do {
1042 		oc = cp;
1043 		if ((c = fetch(&cp)) == sed_seof)
1044 			*p = '\0';
1045 		else if (c == '\\') {
1046 			oc = cp;
1047 			if ((c = fetch(&cp)) == 'n')
1048 				*p = '\n';
1049 			else {
1050 				check(p, pat, patsz, 32, null);
1051 				*p++ = '\\';
1052 				if (c == '(')
1053 					nbra++;
1054 				goto normchar;
1055 			}
1056 		} else if (c == '[') {
1057 			check(p, pat, patsz, 32, null);
1058 			*p++ = c;
1059 			d = WEOF;
1060 			do {
1061 				oc = cp;
1062 				c = fetch(&cp);
1063 				if (c == '\0')
1064 					goto normchar;
1065 				do {
1066 					check(p, pat, patsz, 32, null);
1067 					*p++ = *oc++;
1068 				} while (oc < cp);
1069 				if (d == '[' && (c == ':' || c == '.' ||
1070 							c == '=')) {
1071 					d = c;
1072 					do {
1073 						oc = cp;
1074 						c = fetch(&cp);
1075 						if (c == '\0')
1076 							goto normchar;
1077 						do {
1078 							check(p, pat, patsz,32,
1079 									null);
1080 							*p++ = *oc++;
1081 						} while (oc < cp);
1082 					} while (c != d || peek(&cp) != ']');
1083 					oc = cp;
1084 					c = fetch(&cp);
1085 					do {
1086 						check(p, pat, patsz, 32, null);
1087 						*p++ = *oc++;
1088 					} while (oc < cp);
1089 					c = WEOF; /* == reset d and continue */
1090 				}
1091 				d = c;
1092 			} while (c != ']');
1093 			p--;
1094 		} else {
1095 	normchar:	do {
1096 				check(p, pat, patsz, 32, null)
1097 				*p++ = *oc++;
1098 			} while (oc < cp);
1099 			p--;
1100 		}
1101 		check(p, pat, patsz, 32, null);
1102 	} while (*p++ != '\0');
1103 	re = scalloc(1, sizeof *re);
1104 	*ep = (char *)re;
1105 	if (*pat == '^')
1106 		**ep = 1;
1107 	if (*pat != '\0') {
1108 		int reflags = 0;
1109 
1110 #ifdef	REG_ANGLES
1111 		reflags |= REG_ANGLES;
1112 #endif	/* REG_ANGLES */
1113 #if defined (SU3) && defined (REG_AVOIDNULL)
1114 		reflags |= REG_AVOIDNULL;
1115 #endif	/* SU3 && AVOIDNULL */
1116 		if (regcomp(&re->r_preg, pat, reflags) != 0)
1117 			re = (struct re_emu *)badp;
1118 	} else
1119 		**ep = 2;
1120 	p = (char *)re;
1121 	if (p != badp && *pat)
1122 		p++;
1123 	return p;
1124 }
1125 #else	/* !SUS, !SU3, !S42 */
1126 static char *
sed_compile(char ** ep)1127 sed_compile(char **ep)
1128 {
1129 	extern char *compile(char *, char *, char *, int);
1130 	register char *p;
1131 	size_t sz;
1132 
1133 	for (sz = 0, p = cp; *p; p++)
1134 		if (*p == '[')
1135 			sz += 32;
1136 	sz += 2 * (p - cp) + 5;
1137 	*ep = smalloc(sz);
1138 	(*ep)[1] = '\0';
1139 	p = compile(NULL, &(*ep)[1], &(*ep)[sz], sed_seof);
1140 	if (p == &(*ep)[1])
1141 		return *ep;
1142 	**ep = circf;
1143 	return p;
1144 }
1145 #endif	/* !SUS, !SU3, !S42 */
1146 
1147 wint_t
wc_get(char ** sc,int move)1148 wc_get(char **sc, int move)
1149 {
1150 	wint_t	c;
1151 	char	*p = *sc;
1152 	wchar_t	wcbuf;
1153 	int	len;
1154 
1155 	if ((*p & 0200) == 0) {
1156 		c = *p;
1157 		p += (len = 1);
1158 		invchar = 0;
1159 	} else if ((len = mbtowc(&wcbuf, p, MB_LEN_MAX)) < 0) {
1160 		if (!executing)
1161 			fatal("invalid multibyte character: %s", p);
1162 		c = (*p++ & 0377);
1163 		mbtowc(NULL, NULL, 0);
1164 		invchar = 1;
1165 	} else if (len == 0) {
1166 		c = '\0';
1167 		p++;
1168 		invchar = 0;
1169 	} else {
1170 		c = wcbuf;
1171 		p += len;
1172 		invchar = 0;
1173 	}
1174 	if (move)
1175 		*sc = p;
1176 	return c;
1177 }
1178 
1179 /*
1180  * Note that this hash is not optimized to distribute the items
1181  * equally to all buckets. y commands typically handle only a
1182  * small part of the alphabet, thus most characters will have
1183  * no entry in the hash table. If no list exists in the bucket
1184  * for the hash of these characters, the function can return
1185  * quickly.
1186  */
1187 #define	yhash(c)	(c & 0177)
1188 
1189 struct yitem *
ylook(wint_t c,struct yitem ** yt,int make)1190 ylook(wint_t c, struct yitem **yt, int make)
1191 {
1192 	struct yitem	*yp;
1193 	int	h;
1194 
1195 	yp = yt[h = yhash(c)];
1196 	while (yp != NULL) {
1197 		if (yp->y_oc == c)
1198 			break;
1199 		yp = yp->y_nxt;
1200 	}
1201 	if (make && yp == NULL) {
1202 		yp = scalloc(1, sizeof *yp);
1203 		yp->y_oc = c;
1204 		yp->y_nxt = yt[h];
1205 		yt[h] = yp;
1206 	}
1207 	return yp;
1208 }
1209 
1210 void
growsp(const char * msg)1211 growsp(const char *msg)
1212 {
1213 	const int	incr = 128;
1214 	int	olbend, ogbend, ohend;
1215 
1216 	olbend = lbend;
1217 	ogbend = gbend;
1218 	ohend = hend;
1219 	if ((linebuf = realloc(linebuf, lbend += incr)) == NULL ||
1220 			(genbuf = realloc(genbuf, gbend += incr)) == NULL ||
1221 			(holdsp = realloc(holdsp, hend += incr)) == NULL)
1222 		fatal(msg ? msg : "Cannot malloc space");
1223 	while (olbend < lbend)
1224 		linebuf[olbend++] = '\0';
1225 	while (ogbend < gbend)
1226 		genbuf[ogbend++] = '\0';
1227 	while (ohend < hend)
1228 		holdsp[ohend++] = '\0';
1229 }
1230 
1231 static void
wfile(void)1232 wfile(void)
1233 {
1234 	int	i;
1235 
1236 #if !defined (SUS) && !defined (SU3)
1237 	if(*cp++ != ' ')
1238 		fatal(CGMES, linebuf);
1239 #else	/* SUS, SU3 */
1240 	while (*cp == ' ' || *cp == '\t')
1241 		cp++;
1242 #endif	/* SUS, SU3 */
1243 
1244 	text(&fname[nfiles]);
1245 	for(i = nfiles - 1; i >= 0; i--)
1246 		if(fname[i] != NULL && cmp(fname[nfiles], fname[i]) == 0) {
1247 			P(rep)->fcode = fcode[i];
1248 			free(fname[nfiles]);
1249 			return;
1250 		}
1251 
1252 	if((P(rep)->fcode = fopen(fname[nfiles], "w")) == NULL)
1253 		fatal("Cannot create %s", fname[nfiles]);
1254 	fcode[nfiles++] = P(rep)->fcode;
1255 	morefiles();
1256 }
1257 
1258 static void
morefiles(void)1259 morefiles(void)
1260 {
1261 	if ((fname = realloc(fname, (nfiles+1) * sizeof *fname)) == 0 ||
1262 	    (fcode = realloc(fcode, (nfiles+1) * sizeof *fcode)) == 0)
1263 		fatal("Too many files in w commands");
1264 	fname[nfiles] = 0;
1265 	fcode[nfiles] = 0;
1266 }
1267