Home | History | Annotate | Download | only in sed
      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 (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*	Copyright (c) 1984 AT&T	*/
     27 /*	  All Rights Reserved  	*/
     28 
     29 #include <stdio.h>
     30 #include <sys/param.h>
     31 #include "sed.h"
     32 
     33 #define	NWFILES		11	/* 10 plus one for standard output */
     34 FILE	*fin;
     35 FILE    *fcode[NWFILES];
     36 char    *lastre;
     37 char    sseof;
     38 union reptr     *ptrend;
     39 int     eflag;
     40 extern	int	nbra;
     41 char    linebuf[LBSIZE+1];
     42 int     gflag;
     43 int     nlno;
     44 char    *fname[NWFILES];
     45 int     nfiles;
     46 union reptr ptrspace[PTRSIZE];
     47 union reptr *rep;
     48 char    *cp;
     49 char    respace[RESIZE];
     50 struct label ltab[LABSIZE];
     51 struct label    *lab;
     52 struct label    *labend;
     53 int     depth;
     54 int     eargc;
     55 char    **eargv;
     56 union reptr     **cmpend[DEPTH];
     57 
     58 #define CCEOF	22
     59 
     60 struct label    *labtab = ltab;
     61 
     62 char	ETMES[]		= "Extra text at end of command: %s";
     63 char	SMMES[]		= "Space missing before filename: %s";
     64 char    TMMES[]		= "Too much command text: %s";
     65 char    LTL[]  		= "Label too long: %s";
     66 char    AD0MES[]	= "No addresses allowed: %s";
     67 char    AD1MES[]	= "Only one address allowed: %s";
     68 char	TOOBIG[]	= "Suffix too large - 512 max: %s";
     69 
     70 extern int sed;	  /* IMPORTANT flag !!! */
     71 extern char *comple();
     72 
     73 extern char *malloc();
     74 
     75 static void dechain(void);
     76 static void fcomp(void);
     77 
     78 int
     79 main(int argc, 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 	return (0);
    171 }
    172 
    173 static void
    174 fcomp(void)
    175 {
    176 
    177 	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[9]))
    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[9]))
    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 
    576 char    *compsub(rhsbuf)
    577 char    *rhsbuf;
    578 {
    579 	char   *p, *q;
    580 
    581 	p = rhsbuf;
    582 	q = cp;
    583 	for(;;) {
    584 		if(p > &respace[RESIZE-1])
    585 			comperr(TMMES);
    586 		if((*p = *q++) == '\\') {
    587 			p++;
    588 			if(p > &respace[RESIZE-1])
    589 				comperr(TMMES);
    590 			*p = *q++;
    591 			if(*p > nbra + '0' && *p <= '9')
    592 				comperr("``\\digit'' out of range: %s");
    593 			p++;
    594 			continue;
    595 		}
    596 		if(*p == sseof) {
    597 			*p++ = '\0';
    598 			cp = q;
    599 			return(p);
    600 		}
    601   		if(*p++ == '\0')
    602 			comperr("Ending delimiter missing on substitution: %s");
    603 
    604 	}
    605 }
    606 
    607 int
    608 rline(lbuf, lbend)
    609 char    *lbuf;
    610 char	*lbend;
    611 {
    612 	char   *p, *q;
    613 	int	t;
    614 	static char     *saveq;
    615 
    616 	p = lbuf;
    617 
    618 	if(eflag) {
    619 		if(eflag > 0) {
    620 			eflag = -1;
    621 			if(--eargc <= 0)
    622 				exit(2);
    623 			q = *++eargv;
    624 			while((t = *q++) != '\0') {
    625 				if(t == '\n') {
    626 					saveq = q;
    627 					goto out1;
    628 				}
    629 				if (p < lbend)
    630 					*p++ = t;
    631 				if(t == '\\') {
    632 					if((t = *q++) == '\0') {
    633 						saveq = 0;
    634 						return(-1);
    635 					}
    636 					if (p < lbend)
    637 						*p++ = t;
    638 				}
    639 			}
    640 			saveq = 0;
    641 
    642 		out1:
    643 			if (p == lbend)
    644 				comperr("Command line too long");
    645 			*p = '\0';
    646 			return(1);
    647 		}
    648 		if((q = saveq) == 0)    return(-1);
    649 
    650 		while((t = *q++) != '\0') {
    651 			if(t == '\n') {
    652 				saveq = q;
    653 				goto out2;
    654 			}
    655 			if(p < lbend)
    656 				*p++ = t;
    657 			if(t == '\\') {
    658 				if((t = *q++) == '\0') {
    659 					saveq = 0;
    660 					return(-1);
    661 				}
    662 				if (p < lbend)
    663 					*p++ = t;
    664 			}
    665 		}
    666 		saveq = 0;
    667 
    668 	out2:
    669 		if (p == lbend)
    670 			comperr("Command line too long");
    671 		*p = '\0';
    672 		return(1);
    673 	}
    674 
    675 	while((t = getc(fin)) != EOF) {
    676 		if(t == '\n') {
    677 			if (p == lbend)
    678 				comperr("Command line too long");
    679 			*p = '\0';
    680 			return(1);
    681 		}
    682 		if (p < lbend)
    683 			*p++ = t;
    684 		if(t == '\\') {
    685 			if((t = getc(fin)) == EOF)
    686 				break;
    687 			if(p < lbend)
    688 				*p++ = t;
    689 		}
    690 	}
    691 	if(ferror(fin)) {
    692 		perror("sed: Error reading pattern file");
    693 		exit(2);
    694 	}
    695 	return(-1);
    696 }
    697 
    698 char    *address(expbuf)
    699 char    *expbuf;
    700 {
    701 	char   *rcp;
    702 	long long	lno;
    703 
    704 	if(*cp == '$') {
    705 		if (expbuf > &respace[RESIZE-2])
    706 			comperr(TMMES);
    707 		cp++;
    708 		*expbuf++ = CEND;
    709 		*expbuf++ = CCEOF;
    710 		return(expbuf);
    711 	}
    712 	if (*cp == '/' || *cp == '\\' ) {
    713 		if ( *cp == '\\' )
    714 			cp++;
    715 		sseof = *cp++;
    716 		return(comple((char *) 0, expbuf, &respace[RESIZE-1], sseof));
    717 	}
    718 
    719 	rcp = cp;
    720 	lno = 0;
    721 
    722 	while(*rcp >= '0' && *rcp <= '9')
    723 		lno = lno*10 + *rcp++ - '0';
    724 
    725 	if(rcp > cp) {
    726 		if (expbuf > &respace[RESIZE-3])
    727 			comperr(TMMES);
    728 		*expbuf++ = CLNUM;
    729 		*expbuf++ = nlno;
    730 		tlno[nlno++] = lno;
    731 		if(nlno >= NLINES)
    732 			comperr("Too many line numbers: %s");
    733 		*expbuf++ = CCEOF;
    734 		cp = rcp;
    735 		return(expbuf);
    736 	}
    737 	return(0);
    738 }
    739 
    740 char    *text(textbuf, tbend)
    741 char    *textbuf;
    742 char	*tbend;
    743 {
    744 	char   *p, *q;
    745 
    746 	p = textbuf;
    747 	q = cp;
    748 #ifndef S5EMUL
    749 	/*
    750 	 * Strip off indentation from text to be inserted.
    751 	 */
    752 	while(*q == '\t' || *q == ' ')	q++;
    753 #endif
    754 	for(;;) {
    755 
    756 		if(p > tbend)
    757 			return(NULL);	/* overflowed the buffer */
    758 		if((*p = *q++) == '\\')
    759 			*p = *q++;
    760 		if(*p == '\0') {
    761 			cp = --q;
    762 			return(++p);
    763 		}
    764 #ifndef S5EMUL
    765 		/*
    766 		 * Strip off indentation from text to be inserted.
    767 		 */
    768 		if(*p == '\n') {
    769 			while(*q == '\t' || *q == ' ')	q++;
    770 		}
    771 #endif
    772 		p++;
    773 	}
    774 }
    775 
    776 
    777 struct label    *search(ptr)
    778 struct label    *ptr;
    779 {
    780 	struct label    *rp;
    781 
    782 	rp = labtab;
    783 	while(rp < ptr) {
    784 		if(strcmp(rp->asc, ptr->asc) == 0)
    785 			return(rp);
    786 		rp++;
    787 	}
    788 
    789 	return(0);
    790 }
    791 
    792 
    793 static void
    794 dechain(void)
    795 {
    796 	struct label    *lptr;
    797 	union reptr     *rptr, *trptr;
    798 
    799 	for(lptr = labtab; lptr < lab; lptr++) {
    800 
    801 		if(lptr->address == 0) {
    802 			(void) fprintf(stderr, "sed: Undefined label: %s\n", lptr->asc);
    803 			exit(2);
    804 		}
    805 
    806 		if(lptr->chain) {
    807 			rptr = lptr->chain;
    808 			while(trptr = rptr->r2.lb1) {
    809 				rptr->r2.lb1 = lptr->address;
    810 				rptr = trptr;
    811 			}
    812 			rptr->r2.lb1 = lptr->address;
    813 		}
    814 	}
    815 }
    816 
    817 char *ycomp(expbuf)
    818 char    *expbuf;
    819 {
    820 	char	c;
    821 	char *ep, *tsp;
    822 	int i;
    823 	char    *sp;
    824 
    825 	ep = expbuf;
    826 	if(ep + 0377 > &respace[RESIZE-1])
    827 		comperr(TMMES);
    828 	sp = cp;
    829 	for(tsp = cp; (c = *tsp) != sseof; tsp++) {
    830 		if(c == '\\')
    831 			tsp++;
    832 		if(c == '\0' || c == '\n')
    833 			comperr("Ending delimiter missing on string: %s");
    834 	}
    835 	tsp++;
    836 
    837 	while((c = *sp++) != sseof) {
    838 		c &= 0377;
    839 		if(c == '\\' && *sp == 'n') {
    840 			sp++;
    841 			c = '\n';
    842 		}
    843 		if((ep[c] = *tsp++) == '\\' && *tsp == 'n') {
    844 			ep[c] = '\n';
    845 			tsp++;
    846 		}
    847 		if(ep[c] == sseof || ep[c] == '\0')
    848 			comperr("Transform strings not the same size: %s");
    849 	}
    850 	if(*tsp != sseof) {
    851 		if(*tsp == '\0')
    852 			comperr("Ending delimiter missing on string: %s");
    853 		else
    854 			comperr("Transform strings not the same size: %s");
    855 	}
    856 	cp = ++tsp;
    857 
    858 	for(i = 0; i < 0400; i++)
    859 		if(ep[i] == 0)
    860 			ep[i] = i;
    861 
    862 	return(ep + 0400);
    863 }
    864 
    865 void
    866 comperr(char *msg)
    867 {
    868 	(void) fprintf(stderr, "sed: ");
    869 	(void) fprintf(stderr, msg, linebuf);
    870 	(void) putc('\n', stderr);
    871 	exit(2);
    872 }
    873