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