xref: /titanic_52/usr/src/ucbcmd/sed/sed0.c (revision bdfc6d18da790deeec2e0eb09c625902defe2498)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 /*
27  * Copyright (c) 1996, by Sun Microsystems, Inc.
28  * All rights reserved.
29  */
30 
31 #ident	"%Z%%M%	%I%	%E% SMI"	/* from S5R3.1 1.10 */
32 
33 #include <stdio.h>
34 #include <sys/param.h>
35 #include "sed.h"
36 #define	NWFILES		11	/* 10 plus one for standard output */
37 FILE	*fin;
38 FILE    *fcode[NWFILES];
39 char    *lastre;
40 char    sseof;
41 union reptr     *ptrend;
42 int     eflag;
43 extern     nbra;
44 char    linebuf[LBSIZE+1];
45 int     gflag;
46 int     nlno;
47 char    *fname[NWFILES];
48 int     nfiles;
49 union reptr ptrspace[PTRSIZE];
50 union reptr *rep;
51 char    *cp;
52 char    respace[RESIZE];
53 struct label ltab[LABSIZE];
54 struct label    *lab;
55 struct label    *labend;
56 int     depth;
57 int     eargc;
58 char    **eargv;
59 union reptr     **cmpend[DEPTH];
60 
61 #define CCEOF	22
62 
63 struct label    *labtab = ltab;
64 
65 char	ETMES[]		= "Extra text at end of command: %s";
66 char	SMMES[]		= "Space missing before filename: %s";
67 char    TMMES[]		= "Too much command text: %s";
68 char    LTL[]  		= "Label too long: %s";
69 char    AD0MES[]	= "No addresses allowed: %s";
70 char    AD1MES[]	= "Only one address allowed: %s";
71 char	TOOBIG[]	= "Suffix too large - 512 max: %s";
72 
73 extern	sed;	  /* IMPORTANT flag !!! */
74 extern char *comple();
75 
76 extern char *malloc();
77 
78 main(argc, argv)
79 char    *argv[];
80 {
81 	int flag_found = 0;
82 
83 	sed = 1;
84 	eargc = argc;
85 	eargv = argv;
86 
87 	aptr = abuf;
88 	lab = labtab + 1;       /* 0 reserved for end-pointer */
89 	rep = ptrspace;
90 	rep->r1.ad1 = respace;
91 	lcomend = &genbuf[71];
92 	ptrend = &ptrspace[PTRSIZE];
93 	labend = &labtab[LABSIZE];
94 	lnum = 0;
95 	pending = 0;
96 	depth = 0;
97 	spend = linebuf;
98 	hspend = holdsp;	/* Avoid "bus error" under "H" cmd. */
99 	fcode[0] = stdout;
100 	fname[0] = "";
101 	nfiles = 1;
102 
103 	if(eargc == 1)
104 		exit(0);
105 
106 
107 	setlocale(LC_ALL, "");		/* get locale environment */
108 
109 	while (--eargc > 0 && (++eargv)[0][0] == '-')
110 		switch (eargv[0][1]) {
111 
112 		case 'n':
113 			nflag++;
114 			continue;
115 
116 		case 'f':
117 			flag_found = 1;
118 			if(eargc-- <= 0)	exit(2);
119 
120 			if((fin = fopen(*++eargv, "r")) == NULL) {
121 				(void) fprintf(stderr, "sed: ");
122 				perror(*eargv);
123 				exit(2);
124 			}
125 
126 			fcomp();
127 			(void) fclose(fin);
128 			continue;
129 
130 		case 'e':
131 			flag_found = 1;
132 			eflag++;
133 			fcomp();
134 			eflag = 0;
135 			continue;
136 
137 		case 'g':
138 			gflag++;
139 			continue;
140 
141 		default:
142 			(void) fprintf(stderr, "sed: Unknown flag: %c\n", eargv[0][1]);
143 			exit(2);
144 		}
145 
146 
147 	if(rep == ptrspace && !flag_found) {
148 		eargv--;
149 		eargc++;
150 		eflag++;
151 		fcomp();
152 		eargv++;
153 		eargc--;
154 		eflag = 0;
155 	}
156 
157 	if(depth)
158 		comperr("Too many {'s");
159 
160 	labtab->address = rep;
161 
162 	dechain();
163 
164 	if(eargc <= 0)
165 		execute((char *)NULL);
166 	else while(--eargc >= 0) {
167 		execute(*eargv++);
168 	}
169 	(void) fclose(stdout);
170 	exit(0);
171 	/*NOTREACHED*/
172 }
173 
174 fcomp()
175 {
176 
177 	register char   *p, *op, *tp;
178 	char    *address();
179 	union reptr     *pt, *pt1;
180 	int     i, ii;
181 	struct label    *lpt;
182 	char fnamebuf[MAXPATHLEN];
183 
184 	op = lastre;
185 
186 	if(rline(linebuf, &linebuf[LBSIZE+1]) < 0)  return;
187 	if(*linebuf == '#') {
188 		if(linebuf[1] == 'n')
189 			nflag = 1;
190 	}
191 	else {
192 		cp = linebuf;
193 		goto comploop;
194 	}
195 
196 	for(;;) {
197 		if(rline(linebuf, &linebuf[LBSIZE+1]) < 0)  break;
198 
199 		cp = linebuf;
200 
201 comploop:
202 /*      (void) fprintf(stderr, "cp: %s\n", cp);	/*DEBUG*/
203 		while(*cp == ' ' || *cp == '\t')	cp++;
204 		if(*cp == '\0' || *cp == '#')	 continue;
205 		if(*cp == ';') {
206 			cp++;
207 			goto comploop;
208 		}
209 
210 		p = address(rep->r1.ad1);
211 
212 		if(p == rep->r1.ad1) {
213 			if(op)
214 				rep->r1.ad1 = op;
215 			else
216 				comperr("First RE may not be null: %s");
217 		} else if(p == 0) {
218 			p = rep->r1.ad1;
219 			rep->r1.ad1 = 0;
220 		} else {
221 			op = rep->r1.ad1;
222 			if(*cp == ',' || *cp == ';') {
223 				cp++;
224 				rep->r1.ad2 = p;
225 				p = address(rep->r1.ad2);
226 				if(p == 0)
227 					comperr("Illegal line number: %s");
228 				if(p == rep->r1.ad2)
229 					rep->r1.ad2 = op;
230 				else
231 					op = rep->r1.ad2;
232 
233 			} else
234 				rep->r1.ad2 = 0;
235 		}
236 
237 		if(p > &respace[RESIZE-1])
238 			comperr(TMMES);
239 
240 		while(*cp == ' ' || *cp == '\t')	cp++;
241 
242 swit:
243 		switch(*cp++) {
244 
245 			default:
246 				comperr("Unrecognized command: %s");
247 
248 			case '!':
249 				rep->r1.negfl = 1;
250 				goto swit;
251 
252 			case '{':
253 				rep->r1.command = BCOM;
254 				rep->r1.negfl = !(rep->r1.negfl);
255 				cmpend[depth++] = &rep->r2.lb1;
256 				if(++rep >= ptrend)
257 					comperr("Too many commands: %s");
258 				rep->r1.ad1 = p;
259 				if(*cp == '\0') continue;
260 
261 				goto comploop;
262 
263 			case '}':
264 				if(rep->r1.ad1)
265 					comperr(AD0MES);
266 
267 				if(--depth < 0)
268 					comperr("Too many }'s");
269 				*cmpend[depth] = rep;
270 
271 				rep->r1.ad1 = p;
272 				continue;
273 
274 			case '=':
275 				rep->r1.command = EQCOM;
276 				if(rep->r1.ad2)
277 					comperr(AD1MES);
278 				break;
279 
280 			case ':':
281 				if(rep->r1.ad1)
282 					comperr(AD0MES);
283 
284 				while(*cp++ == ' ');
285 				cp--;
286 
287 
288 				tp = lab->asc;
289 				while((*tp++ = *cp++))
290 					if(tp >= &(lab->asc[8]))
291 						comperr(LTL);
292 				*--tp = '\0';
293 
294 				if(lpt = search(lab)) {
295 					if(lpt->address)
296 						comperr("Duplicate labels: %s");
297 				} else {
298 					lab->chain = 0;
299 					lpt = lab;
300 					if(++lab >= labend)
301 						comperr("Too many labels: %s");
302 				}
303 				lpt->address = rep;
304 				rep->r1.ad1 = p;
305 
306 				continue;
307 
308 			case 'a':
309 				rep->r1.command = ACOM;
310 				if(rep->r1.ad2)
311 					comperr(AD1MES);
312 				if(*cp == '\\') cp++;
313 				if(*cp++ != '\n')
314 					comperr(ETMES);
315 				rep->r1.re1 = p;
316 				if ((p = text(rep->r1.re1, &respace[RESIZE-1])) == NULL)
317 					comperr(TMMES);
318 				break;
319 			case 'c':
320 				rep->r1.command = CCOM;
321 				if(*cp == '\\') cp++;
322 				if(*cp++ != ('\n'))
323 					comperr(ETMES);
324 				rep->r1.re1 = p;
325 				if ((p = text(rep->r1.re1, &respace[RESIZE-1])) == NULL)
326 					comperr(TMMES);
327 				break;
328 			case 'i':
329 				rep->r1.command = ICOM;
330 				if(rep->r1.ad2)
331 					comperr(AD1MES);
332 				if(*cp == '\\') cp++;
333 				if(*cp++ != ('\n'))
334 					comperr(ETMES);
335 				rep->r1.re1 = p;
336 				if ((p = text(rep->r1.re1, &respace[RESIZE-1])) == NULL)
337 					comperr(TMMES);
338 				break;
339 
340 			case 'g':
341 				rep->r1.command = GCOM;
342 				break;
343 
344 			case 'G':
345 				rep->r1.command = CGCOM;
346 				break;
347 
348 			case 'h':
349 				rep->r1.command = HCOM;
350 				break;
351 
352 			case 'H':
353 				rep->r1.command = CHCOM;
354 				break;
355 
356 			case 't':
357 				rep->r1.command = TCOM;
358 				goto jtcommon;
359 
360 			case 'b':
361 				rep->r1.command = BCOM;
362 jtcommon:
363 				while(*cp++ == ' ');
364 				cp--;
365 
366 				if(*cp == '\0') {
367 					if(pt = labtab->chain) {
368 						while(pt1 = pt->r2.lb1)
369 							pt = pt1;
370 						pt->r2.lb1 = rep;
371 					} else
372 						labtab->chain = rep;
373 					break;
374 				}
375 				tp = lab->asc;
376 				while((*tp++ = *cp++))
377 					if(tp >= &(lab->asc[8]))
378 						comperr(LTL);
379 				cp--;
380 				*--tp = '\0';
381 
382 				if(lpt = search(lab)) {
383 					if(lpt->address) {
384 						rep->r2.lb1 = lpt->address;
385 					} else {
386 						pt = lpt->chain;
387 						while(pt1 = pt->r2.lb1)
388 							pt = pt1;
389 						pt->r2.lb1 = rep;
390 					}
391 				} else {
392 					lab->chain = rep;
393 					lab->address = 0;
394 					if(++lab >= labend)
395 						comperr("Too many labels: %s");
396 				}
397 				break;
398 
399 			case 'n':
400 				rep->r1.command = NCOM;
401 				break;
402 
403 			case 'N':
404 				rep->r1.command = CNCOM;
405 				break;
406 
407 			case 'p':
408 				rep->r1.command = PCOM;
409 				break;
410 
411 			case 'P':
412 				rep->r1.command = CPCOM;
413 				break;
414 
415 			case 'r':
416 				rep->r1.command = RCOM;
417 				if(rep->r1.ad2)
418 					comperr(AD1MES);
419 				if(*cp++ != ' ')
420 					comperr(SMMES);
421 				rep->r1.re1 = p;
422 				if ((p = text(rep->r1.re1, &respace[RESIZE-1])) == NULL)
423 					comperr(TMMES);
424 				break;
425 
426 			case 'd':
427 				rep->r1.command = DCOM;
428 				break;
429 
430 			case 'D':
431 				rep->r1.command = CDCOM;
432 				rep->r2.lb1 = ptrspace;
433 				break;
434 
435 			case 'q':
436 				rep->r1.command = QCOM;
437 				if(rep->r1.ad2)
438 					comperr(AD1MES);
439 				break;
440 
441 			case 'l':
442 				rep->r1.command = LCOM;
443 				break;
444 
445 			case 's':
446 				rep->r1.command = SCOM;
447 				sseof = *cp++;
448 				rep->r1.re1 = p;
449 				p = comple((char *) 0, rep->r1.re1, &respace[RESIZE-1], sseof);
450 				if(p == rep->r1.re1) {
451 					if(op)
452 						rep->r1.re1 = op;
453 					else
454 						comperr("First RE may not be null: %s");
455 				} else
456 					op = rep->r1.re1;
457 				rep->r1.rhs = p;
458 
459 				p = compsub(rep->r1.rhs);
460 
461 				if(*cp == 'g') {
462 					cp++;
463 					rep->r1.gfl = 999;
464 				} else if(gflag)
465 					rep->r1.gfl = 999;
466 
467 				if(*cp >= '1' && *cp <= '9')
468 					{i = *cp - '0';
469 					cp++;
470 					while(1)
471 						{ii = *cp;
472 						if(ii < '0' || ii > '9') break;
473 						i = i*10 + ii - '0';
474 						if(i > 512)
475 							comperr(TOOBIG);
476 						cp++;
477 						}
478 					rep->r1.gfl = i;
479 					}
480 
481 				if(*cp == 'p') {
482 					cp++;
483 					rep->r1.pfl = 1;
484 				}
485 
486 				if(*cp == 'P') {
487 					cp++;
488 					rep->r1.pfl = 2;
489 				}
490 
491 				if(*cp == 'w') {
492 					cp++;
493 					if(*cp++ !=  ' ')
494 						comperr(SMMES);
495 					if (text(fnamebuf, &fnamebuf[MAXPATHLEN]) == NULL)
496 						comperr("File name too long: %s");
497 					for(i = nfiles - 1; i >= 0; i--)
498 						if(strcmp(fnamebuf,fname[i]) == 0) {
499 							rep->r1.fcode = fcode[i];
500 							goto done;
501 						}
502 					if(nfiles >= NWFILES)
503 						comperr("Too many files in w commands: %s");
504 
505 					i = strlen(fnamebuf) + 1;
506 					if ((fname[nfiles] = malloc((unsigned)i)) == NULL) {
507 						(void) fprintf(stderr, "sed: Out of memory\n");
508 						exit(2);
509 					}
510 					(void) strcpy(fname[nfiles], fnamebuf);
511 					if((rep->r1.fcode = fopen(fname[nfiles], "w")) == NULL) {
512 						(void) fprintf(stderr, "sed: Cannot open ");
513 						perror(fname[nfiles]);
514 						exit(2);
515 					}
516 					fcode[nfiles++] = rep->r1.fcode;
517 				}
518 				break;
519 
520 			case 'w':
521 				rep->r1.command = WCOM;
522 				if(*cp++ != ' ')
523 					comperr(SMMES);
524 				if (text(fnamebuf, &fnamebuf[MAXPATHLEN]) == NULL)
525 					comperr("File name too long: %s");
526 				for(i = nfiles - 1; i >= 0; i--)
527 					if(strcmp(fnamebuf, fname[i]) == 0) {
528 						rep->r1.fcode = fcode[i];
529 						goto done;
530 					}
531 				if(nfiles >= NWFILES)
532 					comperr("Too many files in w commands: %s");
533 
534 				i = strlen(fnamebuf) + 1;
535 				if ((fname[nfiles] = malloc((unsigned)i)) == NULL) {
536 					(void) fprintf(stderr, "sed: Out of memory\n");
537 					exit(2);
538 				}
539 				(void) strcpy(fname[nfiles], fnamebuf);
540 				if((rep->r1.fcode = fopen(fname[nfiles], "w")) == NULL) {
541 					(void) fprintf(stderr, "sed: Cannot create ");
542 					perror(fname[nfiles]);
543 					exit(2);
544 				}
545 				fcode[nfiles++] = rep->r1.fcode;
546 				break;
547 
548 			case 'x':
549 				rep->r1.command = XCOM;
550 				break;
551 
552 			case 'y':
553 				rep->r1.command = YCOM;
554 				sseof = *cp++;
555 				rep->r1.re1 = p;
556 				p = ycomp(rep->r1.re1);
557 				break;
558 
559 		}
560 done:
561 		if(++rep >= ptrend)
562 			comperr("Too many commands, last: %s");
563 
564 		rep->r1.ad1 = p;
565 
566 		if(*cp++ != '\0') {
567 			if(cp[-1] == ';')
568 				goto comploop;
569 			comperr(ETMES);
570 		}
571 	}
572 	rep->r1.command = 0;
573 	lastre = op;
574 }
575 char    *compsub(rhsbuf)
576 char    *rhsbuf;
577 {
578 	register char   *p, *q;
579 
580 	p = rhsbuf;
581 	q = cp;
582 	for(;;) {
583 		if(p > &respace[RESIZE-1])
584 			comperr(TMMES);
585 		if((*p = *q++) == '\\') {
586 			p++;
587 			if(p > &respace[RESIZE-1])
588 				comperr(TMMES);
589 			*p = *q++;
590 			if(*p > nbra + '0' && *p <= '9')
591 				comperr("``\\digit'' out of range: %s");
592 			p++;
593 			continue;
594 		}
595 		if(*p == sseof) {
596 			*p++ = '\0';
597 			cp = q;
598 			return(p);
599 		}
600   		if(*p++ == '\0')
601 			comperr("Ending delimiter missing on substitution: %s");
602 
603 	}
604 }
605 
606 rline(lbuf, lbend)
607 char    *lbuf;
608 char	*lbend;
609 {
610 	register char   *p, *q;
611 	register	t;
612 	static char     *saveq;
613 
614 	p = lbuf;
615 
616 	if(eflag) {
617 		if(eflag > 0) {
618 			eflag = -1;
619 			if(--eargc <= 0)
620 				exit(2);
621 			q = *++eargv;
622 			while((t = *q++) != '\0') {
623 				if(t == '\n') {
624 					saveq = q;
625 					goto out1;
626 				}
627 				if (p < lbend)
628 					*p++ = t;
629 				if(t == '\\') {
630 					if((t = *q++) == '\0') {
631 						saveq = 0;
632 						return(-1);
633 					}
634 					if (p < lbend)
635 						*p++ = t;
636 				}
637 			}
638 			saveq = 0;
639 
640 		out1:
641 			if (p == lbend)
642 				comperr("Command line too long");
643 			*p = '\0';
644 			return(1);
645 		}
646 		if((q = saveq) == 0)    return(-1);
647 
648 		while((t = *q++) != '\0') {
649 			if(t == '\n') {
650 				saveq = q;
651 				goto out2;
652 			}
653 			if(p < lbend)
654 				*p++ = t;
655 			if(t == '\\') {
656 				if((t = *q++) == '\0') {
657 					saveq = 0;
658 					return(-1);
659 				}
660 				if (p < lbend)
661 					*p++ = t;
662 			}
663 		}
664 		saveq = 0;
665 
666 	out2:
667 		if (p == lbend)
668 			comperr("Command line too long");
669 		*p = '\0';
670 		return(1);
671 	}
672 
673 	while((t = getc(fin)) != EOF) {
674 		if(t == '\n') {
675 			if (p == lbend)
676 				comperr("Command line too long");
677 			*p = '\0';
678 			return(1);
679 		}
680 		if (p < lbend)
681 			*p++ = t;
682 		if(t == '\\') {
683 			if((t = getc(fin)) == EOF)
684 				break;
685 			if(p < lbend)
686 				*p++ = t;
687 		}
688 	}
689 	if(ferror(fin)) {
690 		perror("sed: Error reading pattern file");
691 		exit(2);
692 	}
693 	return(-1);
694 }
695 
696 char    *address(expbuf)
697 char    *expbuf;
698 {
699 	register char   *rcp;
700 	long long	lno;
701 
702 	if(*cp == '$') {
703 		if (expbuf > &respace[RESIZE-2])
704 			comperr(TMMES);
705 		cp++;
706 		*expbuf++ = CEND;
707 		*expbuf++ = CCEOF;
708 		return(expbuf);
709 	}
710 	if (*cp == '/' || *cp == '\\' ) {
711 		if ( *cp == '\\' )
712 			cp++;
713 		sseof = *cp++;
714 		return(comple((char *) 0, expbuf, &respace[RESIZE-1], sseof));
715 	}
716 
717 	rcp = cp;
718 	lno = 0;
719 
720 	while(*rcp >= '0' && *rcp <= '9')
721 		lno = lno*10 + *rcp++ - '0';
722 
723 	if(rcp > cp) {
724 		if (expbuf > &respace[RESIZE-3])
725 			comperr(TMMES);
726 		*expbuf++ = CLNUM;
727 		*expbuf++ = nlno;
728 		tlno[nlno++] = lno;
729 		if(nlno >= NLINES)
730 			comperr("Too many line numbers: %s");
731 		*expbuf++ = CCEOF;
732 		cp = rcp;
733 		return(expbuf);
734 	}
735 	return(0);
736 }
737 
738 char    *text(textbuf, tbend)
739 char    *textbuf;
740 char	*tbend;
741 {
742 	register char   *p, *q;
743 
744 	p = textbuf;
745 	q = cp;
746 #ifndef S5EMUL
747 	/*
748 	 * Strip off indentation from text to be inserted.
749 	 */
750 	while(*q == '\t' || *q == ' ')	q++;
751 #endif
752 	for(;;) {
753 
754 		if(p > tbend)
755 			return(NULL);	/* overflowed the buffer */
756 		if((*p = *q++) == '\\')
757 			*p = *q++;
758 		if(*p == '\0') {
759 			cp = --q;
760 			return(++p);
761 		}
762 #ifndef S5EMUL
763 		/*
764 		 * Strip off indentation from text to be inserted.
765 		 */
766 		if(*p == '\n') {
767 			while(*q == '\t' || *q == ' ')	q++;
768 		}
769 #endif
770 		p++;
771 	}
772 }
773 
774 
775 struct label    *search(ptr)
776 struct label    *ptr;
777 {
778 	struct label    *rp;
779 
780 	rp = labtab;
781 	while(rp < ptr) {
782 		if(strcmp(rp->asc, ptr->asc) == 0)
783 			return(rp);
784 		rp++;
785 	}
786 
787 	return(0);
788 }
789 
790 
791 dechain()
792 {
793 	struct label    *lptr;
794 	union reptr     *rptr, *trptr;
795 
796 	for(lptr = labtab; lptr < lab; lptr++) {
797 
798 		if(lptr->address == 0) {
799 			(void) fprintf(stderr, "sed: Undefined label: %s\n", lptr->asc);
800 			exit(2);
801 		}
802 
803 		if(lptr->chain) {
804 			rptr = lptr->chain;
805 			while(trptr = rptr->r2.lb1) {
806 				rptr->r2.lb1 = lptr->address;
807 				rptr = trptr;
808 			}
809 			rptr->r2.lb1 = lptr->address;
810 		}
811 	}
812 }
813 
814 char *ycomp(expbuf)
815 char    *expbuf;
816 {
817 	register char   c;
818 	register char *ep, *tsp;
819 	register int i;
820 	char    *sp;
821 
822 	ep = expbuf;
823 	if(ep + 0377 > &respace[RESIZE-1])
824 		comperr(TMMES);
825 	sp = cp;
826 	for(tsp = cp; (c = *tsp) != sseof; tsp++) {
827 		if(c == '\\')
828 			tsp++;
829 		if(c == '\0' || c == '\n')
830 			comperr("Ending delimiter missing on string: %s");
831 	}
832 	tsp++;
833 
834 	while((c = *sp++) != sseof) {
835 		c &= 0377;
836 		if(c == '\\' && *sp == 'n') {
837 			sp++;
838 			c = '\n';
839 		}
840 		if((ep[c] = *tsp++) == '\\' && *tsp == 'n') {
841 			ep[c] = '\n';
842 			tsp++;
843 		}
844 		if(ep[c] == sseof || ep[c] == '\0')
845 			comperr("Transform strings not the same size: %s");
846 	}
847 	if(*tsp != sseof) {
848 		if(*tsp == '\0')
849 			comperr("Ending delimiter missing on string: %s");
850 		else
851 			comperr("Transform strings not the same size: %s");
852 	}
853 	cp = ++tsp;
854 
855 	for(i = 0; i < 0400; i++)
856 		if(ep[i] == 0)
857 			ep[i] = i;
858 
859 	return(ep + 0400);
860 }
861 comperr(msg)
862 char *msg;
863 {
864 	(void) fprintf(stderr, "sed: ");
865 	(void) fprintf(stderr, msg, linebuf);
866 	(void) putc('\n', stderr);
867 	exit(2);
868 }
869