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