xref: /plan9-contrib/sys/src/cmd/ed.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  * Editor
33e12c5d1SDavid du Colombier  */
43e12c5d1SDavid du Colombier #include <u.h>
53e12c5d1SDavid du Colombier #include <libc.h>
63e12c5d1SDavid du Colombier #include <bio.h>
7*219b2ee8SDavid du Colombier #include <regexp.h>
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier enum
103e12c5d1SDavid du Colombier {
113e12c5d1SDavid du Colombier 	FNSIZE	= 128,		/* file name */
123e12c5d1SDavid du Colombier 	LBSIZE	= 4096,		/* max line size */
133e12c5d1SDavid du Colombier 	BLKSIZE	= 4096,		/* block size in temp file */
14*219b2ee8SDavid du Colombier 	NBLK	= 4095,		/* max size of temp file */
153e12c5d1SDavid du Colombier 	ESIZE	= 256,		/* max size of reg exp */
163e12c5d1SDavid du Colombier 	GBSIZE	= 256,		/* max size of global command */
173e12c5d1SDavid du Colombier 	MAXSUB	= 9,		/* max number of sub reg exp */
183e12c5d1SDavid du Colombier 	ESCFLG	= 0xFFFF,	/* escape Rune - user defined code */
193e12c5d1SDavid du Colombier 	EOF	= -1,
203e12c5d1SDavid du Colombier };
213e12c5d1SDavid du Colombier 
223e12c5d1SDavid du Colombier void	(*oldhup)(int);
233e12c5d1SDavid du Colombier void	(*oldquit)(int);
243e12c5d1SDavid du Colombier int*	addr1;
253e12c5d1SDavid du Colombier int*	addr2;
263e12c5d1SDavid du Colombier int	anymarks;
273e12c5d1SDavid du Colombier int	col;
283e12c5d1SDavid du Colombier long	count;
293e12c5d1SDavid du Colombier int*	dol;
303e12c5d1SDavid du Colombier int*	dot;
313e12c5d1SDavid du Colombier int	fchange;
323e12c5d1SDavid du Colombier char	file[FNSIZE];
333e12c5d1SDavid du Colombier Rune	genbuf[LBSIZE];
343e12c5d1SDavid du Colombier int	given;
353e12c5d1SDavid du Colombier Rune*	globp;
363e12c5d1SDavid du Colombier int	iblock;
373e12c5d1SDavid du Colombier int	ichanged;
383e12c5d1SDavid du Colombier int	io;
393e12c5d1SDavid du Colombier Biobuf	iobuf;
403e12c5d1SDavid du Colombier int	lastc;
413e12c5d1SDavid du Colombier char	line[70];
423e12c5d1SDavid du Colombier Rune*	linebp;
433e12c5d1SDavid du Colombier Rune	linebuf[LBSIZE];
443e12c5d1SDavid du Colombier int	listf;
453e12c5d1SDavid du Colombier int	listn;
463e12c5d1SDavid du Colombier Rune*	loc1;
473e12c5d1SDavid du Colombier Rune*	loc2;
483e12c5d1SDavid du Colombier int	names[26];
493e12c5d1SDavid du Colombier int	nleft;
503e12c5d1SDavid du Colombier int	oblock;
513e12c5d1SDavid du Colombier int	oflag;
523e12c5d1SDavid du Colombier Reprog	*pattern;
533e12c5d1SDavid du Colombier int	peekc;
543e12c5d1SDavid du Colombier int	pflag;
553e12c5d1SDavid du Colombier int	rescuing;
563e12c5d1SDavid du Colombier Rune	rhsbuf[LBSIZE/2];
573e12c5d1SDavid du Colombier char	savedfile[FNSIZE];
583e12c5d1SDavid du Colombier jmp_buf	savej;
593e12c5d1SDavid du Colombier int	subnewa;
603e12c5d1SDavid du Colombier int	subolda;
613e12c5d1SDavid du Colombier Resub	subexp[MAXSUB];
623e12c5d1SDavid du Colombier char*	tfname;
633e12c5d1SDavid du Colombier int	tline;
643e12c5d1SDavid du Colombier int	wrapp;
653e12c5d1SDavid du Colombier int*	zero;
663e12c5d1SDavid du Colombier 
673e12c5d1SDavid du Colombier char	Q[]	= "";
683e12c5d1SDavid du Colombier char	T[]	= "TMP";
693e12c5d1SDavid du Colombier char	WRERR[]	= "WRITE ERROR";
703e12c5d1SDavid du Colombier int	bpagesize = 20;
713e12c5d1SDavid du Colombier char	hex[]	= "0123456789abcdef";
723e12c5d1SDavid du Colombier char*	linp	= line;
733e12c5d1SDavid du Colombier ulong	nlall = 128;
743e12c5d1SDavid du Colombier int	tfile	= -1;
753e12c5d1SDavid du Colombier int	vflag	= 1;
763e12c5d1SDavid du Colombier 
773e12c5d1SDavid du Colombier void	add(int);
783e12c5d1SDavid du Colombier int*	address(void);
793e12c5d1SDavid du Colombier int	append(int(*)(void), int*);
803e12c5d1SDavid du Colombier void	browse(void);
813e12c5d1SDavid du Colombier void	callunix(void);
823e12c5d1SDavid du Colombier void	commands(void);
833e12c5d1SDavid du Colombier void	compile(int);
843e12c5d1SDavid du Colombier int	compsub(void);
853e12c5d1SDavid du Colombier void	dosub(void);
863e12c5d1SDavid du Colombier void	error(char*);
873e12c5d1SDavid du Colombier int	match(int*);
883e12c5d1SDavid du Colombier void	exfile(int);
893e12c5d1SDavid du Colombier void	filename(int);
903e12c5d1SDavid du Colombier Rune*	getblock(int, int);
913e12c5d1SDavid du Colombier int	getchr(void);
923e12c5d1SDavid du Colombier int	getcopy(void);
933e12c5d1SDavid du Colombier int	getfile(void);
943e12c5d1SDavid du Colombier Rune*	getline(int);
953e12c5d1SDavid du Colombier int	getnum(void);
963e12c5d1SDavid du Colombier int	getsub(void);
973e12c5d1SDavid du Colombier int	gettty(void);
983e12c5d1SDavid du Colombier void	global(int);
993e12c5d1SDavid du Colombier void	init(void);
1003e12c5d1SDavid du Colombier void	join(void);
1013e12c5d1SDavid du Colombier void	move(int);
1023e12c5d1SDavid du Colombier void	newline(void);
1033e12c5d1SDavid du Colombier void	nonzero(void);
1043e12c5d1SDavid du Colombier void	notifyf(void*, char*);
1053e12c5d1SDavid du Colombier Rune*	place(Rune*, Rune*, Rune*);
1063e12c5d1SDavid du Colombier void	printcom(void);
1073e12c5d1SDavid du Colombier void	putchr(int);
1083e12c5d1SDavid du Colombier void	putd(void);
1093e12c5d1SDavid du Colombier void	putfile(void);
1103e12c5d1SDavid du Colombier int	putline(void);
1113e12c5d1SDavid du Colombier void	putshst(Rune*);
1123e12c5d1SDavid du Colombier void	putst(char*);
1133e12c5d1SDavid du Colombier void	quit(void);
1143e12c5d1SDavid du Colombier void	rdelete(int*, int*);
1153e12c5d1SDavid du Colombier void	regerror(char *);
1163e12c5d1SDavid du Colombier void	reverse(int*, int*);
1173e12c5d1SDavid du Colombier void	setnoaddr(void);
1183e12c5d1SDavid du Colombier void	setwide(void);
1193e12c5d1SDavid du Colombier void	squeeze(int);
1203e12c5d1SDavid du Colombier void	substitute(int);
1213e12c5d1SDavid du Colombier 
1223e12c5d1SDavid du Colombier void
1233e12c5d1SDavid du Colombier main(int argc, char *argv[])
1243e12c5d1SDavid du Colombier {
1253e12c5d1SDavid du Colombier 	char *p1, *p2;
1263e12c5d1SDavid du Colombier 
1273e12c5d1SDavid du Colombier 	notify(notifyf);
1283e12c5d1SDavid du Colombier 	ARGBEGIN {
1293e12c5d1SDavid du Colombier 	case 'o':
1303e12c5d1SDavid du Colombier 		oflag = 1;
1313e12c5d1SDavid du Colombier 		vflag = 0;
1323e12c5d1SDavid du Colombier 		break;
1333e12c5d1SDavid du Colombier 	} ARGEND
1343e12c5d1SDavid du Colombier 
1353e12c5d1SDavid du Colombier 	USED(argc);
1363e12c5d1SDavid du Colombier 	if(*argv && (strcmp(*argv, "-") == 0)) {
1373e12c5d1SDavid du Colombier 		argv++;
1383e12c5d1SDavid du Colombier 		vflag = 0;
1393e12c5d1SDavid du Colombier 	}
1403e12c5d1SDavid du Colombier 	if(oflag) {
1413e12c5d1SDavid du Colombier 		p1 = "/fd/1";
1423e12c5d1SDavid du Colombier 		p2 = savedfile;
1433e12c5d1SDavid du Colombier 		while(*p2++ = *p1++)
1443e12c5d1SDavid du Colombier 			;
1453e12c5d1SDavid du Colombier 		globp = L"a";
1463e12c5d1SDavid du Colombier 	} else
1473e12c5d1SDavid du Colombier 	if(*argv) {
1483e12c5d1SDavid du Colombier 		p1 = *argv;
1493e12c5d1SDavid du Colombier 		p2 = savedfile;
1503e12c5d1SDavid du Colombier 		while(*p2++ = *p1++)
1513e12c5d1SDavid du Colombier 			if(p2 >= &savedfile[sizeof(savedfile)])
1523e12c5d1SDavid du Colombier 				p2--;
1533e12c5d1SDavid du Colombier 		globp = L"r";
1543e12c5d1SDavid du Colombier 	}
1553e12c5d1SDavid du Colombier 	zero = malloc((nlall+5)*sizeof(int*));
1563e12c5d1SDavid du Colombier 	tfname = mktemp("/tmp/eXXXXX");
1573e12c5d1SDavid du Colombier 	init();
1583e12c5d1SDavid du Colombier 	setjmp(savej);
1593e12c5d1SDavid du Colombier 	commands();
1603e12c5d1SDavid du Colombier 	quit();
1613e12c5d1SDavid du Colombier }
1623e12c5d1SDavid du Colombier 
1633e12c5d1SDavid du Colombier void
1643e12c5d1SDavid du Colombier commands(void)
1653e12c5d1SDavid du Colombier {
1663e12c5d1SDavid du Colombier 	int *a1, c, temp;
1673e12c5d1SDavid du Colombier 	char lastsep;
168*219b2ee8SDavid du Colombier 	Dir d;
1693e12c5d1SDavid du Colombier 
1703e12c5d1SDavid du Colombier 	for(;;) {
1713e12c5d1SDavid du Colombier 		if(pflag) {
1723e12c5d1SDavid du Colombier 			pflag = 0;
1733e12c5d1SDavid du Colombier 			addr1 = addr2 = dot;
1743e12c5d1SDavid du Colombier 			printcom();
1753e12c5d1SDavid du Colombier 		}
1763e12c5d1SDavid du Colombier 		c = '\n';
1773e12c5d1SDavid du Colombier 		for(addr1 = 0;;) {
1783e12c5d1SDavid du Colombier 			lastsep = c;
1793e12c5d1SDavid du Colombier 			a1 = address();
1803e12c5d1SDavid du Colombier 			c = getchr();
1813e12c5d1SDavid du Colombier 			if(c != ',' && c != ';')
1823e12c5d1SDavid du Colombier 				break;
1833e12c5d1SDavid du Colombier 			if(lastsep == ',')
1843e12c5d1SDavid du Colombier 				error(Q);
1853e12c5d1SDavid du Colombier 			if(a1 == 0) {
1863e12c5d1SDavid du Colombier 				a1 = zero+1;
1873e12c5d1SDavid du Colombier 				if(a1 > dol)
1883e12c5d1SDavid du Colombier 					a1--;
1893e12c5d1SDavid du Colombier 			}
1903e12c5d1SDavid du Colombier 			addr1 = a1;
1913e12c5d1SDavid du Colombier 			if(c == ';')
1923e12c5d1SDavid du Colombier 				dot = a1;
1933e12c5d1SDavid du Colombier 		}
1943e12c5d1SDavid du Colombier 		if(lastsep != '\n' && a1 == 0)
1953e12c5d1SDavid du Colombier 			a1 = dol;
1963e12c5d1SDavid du Colombier 		if((addr2=a1) == 0) {
1973e12c5d1SDavid du Colombier 			given = 0;
1983e12c5d1SDavid du Colombier 			addr2 = dot;
1993e12c5d1SDavid du Colombier 		} else
2003e12c5d1SDavid du Colombier 			given = 1;
2013e12c5d1SDavid du Colombier 		if(addr1 == 0)
2023e12c5d1SDavid du Colombier 			addr1 = addr2;
2033e12c5d1SDavid du Colombier 		switch(c) {
2043e12c5d1SDavid du Colombier 
2053e12c5d1SDavid du Colombier 		case 'a':
2063e12c5d1SDavid du Colombier 			add(0);
2073e12c5d1SDavid du Colombier 			continue;
2083e12c5d1SDavid du Colombier 
2093e12c5d1SDavid du Colombier 		case 'b':
2103e12c5d1SDavid du Colombier 			nonzero();
2113e12c5d1SDavid du Colombier 			browse();
2123e12c5d1SDavid du Colombier 			continue;
2133e12c5d1SDavid du Colombier 
2143e12c5d1SDavid du Colombier 		case 'c':
2153e12c5d1SDavid du Colombier 			nonzero();
2163e12c5d1SDavid du Colombier 			newline();
2173e12c5d1SDavid du Colombier 			rdelete(addr1, addr2);
2183e12c5d1SDavid du Colombier 			append(gettty, addr1-1);
2193e12c5d1SDavid du Colombier 			continue;
2203e12c5d1SDavid du Colombier 
2213e12c5d1SDavid du Colombier 		case 'd':
2223e12c5d1SDavid du Colombier 			nonzero();
2233e12c5d1SDavid du Colombier 			newline();
2243e12c5d1SDavid du Colombier 			rdelete(addr1, addr2);
2253e12c5d1SDavid du Colombier 			continue;
2263e12c5d1SDavid du Colombier 
2273e12c5d1SDavid du Colombier 		case 'E':
2283e12c5d1SDavid du Colombier 			fchange = 0;
2293e12c5d1SDavid du Colombier 			c = 'e';
2303e12c5d1SDavid du Colombier 		case 'e':
2313e12c5d1SDavid du Colombier 			setnoaddr();
2323e12c5d1SDavid du Colombier 			if(vflag && fchange) {
2333e12c5d1SDavid du Colombier 				fchange = 0;
2343e12c5d1SDavid du Colombier 				error(Q);
2353e12c5d1SDavid du Colombier 			}
2363e12c5d1SDavid du Colombier 			filename(c);
2373e12c5d1SDavid du Colombier 			init();
2383e12c5d1SDavid du Colombier 			addr2 = zero;
2393e12c5d1SDavid du Colombier 			goto caseread;
2403e12c5d1SDavid du Colombier 
2413e12c5d1SDavid du Colombier 		case 'f':
2423e12c5d1SDavid du Colombier 			setnoaddr();
2433e12c5d1SDavid du Colombier 			filename(c);
2443e12c5d1SDavid du Colombier 			putst(savedfile);
2453e12c5d1SDavid du Colombier 			continue;
2463e12c5d1SDavid du Colombier 
2473e12c5d1SDavid du Colombier 		case 'g':
2483e12c5d1SDavid du Colombier 			global(1);
2493e12c5d1SDavid du Colombier 			continue;
2503e12c5d1SDavid du Colombier 
2513e12c5d1SDavid du Colombier 		case 'i':
2523e12c5d1SDavid du Colombier 			add(-1);
2533e12c5d1SDavid du Colombier 			continue;
2543e12c5d1SDavid du Colombier 
2553e12c5d1SDavid du Colombier 
2563e12c5d1SDavid du Colombier 		case 'j':
2573e12c5d1SDavid du Colombier 			if(!given)
2583e12c5d1SDavid du Colombier 				addr2++;
2593e12c5d1SDavid du Colombier 			newline();
2603e12c5d1SDavid du Colombier 			join();
2613e12c5d1SDavid du Colombier 			continue;
2623e12c5d1SDavid du Colombier 
2633e12c5d1SDavid du Colombier 		case 'k':
2643e12c5d1SDavid du Colombier 			nonzero();
2653e12c5d1SDavid du Colombier 			c = getchr();
2663e12c5d1SDavid du Colombier 			if(c < 'a' || c > 'z')
2673e12c5d1SDavid du Colombier 				error(Q);
2683e12c5d1SDavid du Colombier 			newline();
2693e12c5d1SDavid du Colombier 			names[c-'a'] = *addr2 & ~01;
2703e12c5d1SDavid du Colombier 			anymarks |= 01;
2713e12c5d1SDavid du Colombier 			continue;
2723e12c5d1SDavid du Colombier 
2733e12c5d1SDavid du Colombier 		case 'm':
2743e12c5d1SDavid du Colombier 			move(0);
2753e12c5d1SDavid du Colombier 			continue;
2763e12c5d1SDavid du Colombier 
2773e12c5d1SDavid du Colombier 		case 'n':
2783e12c5d1SDavid du Colombier 			listn++;
2793e12c5d1SDavid du Colombier 			newline();
2803e12c5d1SDavid du Colombier 			printcom();
2813e12c5d1SDavid du Colombier 			continue;
2823e12c5d1SDavid du Colombier 
2833e12c5d1SDavid du Colombier 		case '\n':
2843e12c5d1SDavid du Colombier 			if(a1==0) {
2853e12c5d1SDavid du Colombier 				a1 = dot+1;
2863e12c5d1SDavid du Colombier 				addr2 = a1;
2873e12c5d1SDavid du Colombier 				addr1 = a1;
2883e12c5d1SDavid du Colombier 			}
2893e12c5d1SDavid du Colombier 			if(lastsep==';')
2903e12c5d1SDavid du Colombier 				addr1 = a1;
2913e12c5d1SDavid du Colombier 			printcom();
2923e12c5d1SDavid du Colombier 			continue;
2933e12c5d1SDavid du Colombier 
2943e12c5d1SDavid du Colombier 		case 'l':
2953e12c5d1SDavid du Colombier 			listf++;
2963e12c5d1SDavid du Colombier 		case 'p':
2973e12c5d1SDavid du Colombier 		case 'P':
2983e12c5d1SDavid du Colombier 			newline();
2993e12c5d1SDavid du Colombier 			printcom();
3003e12c5d1SDavid du Colombier 			continue;
3013e12c5d1SDavid du Colombier 
3023e12c5d1SDavid du Colombier 		case 'Q':
3033e12c5d1SDavid du Colombier 			fchange = 0;
3043e12c5d1SDavid du Colombier 		case 'q':
3053e12c5d1SDavid du Colombier 			setnoaddr();
3063e12c5d1SDavid du Colombier 			newline();
3073e12c5d1SDavid du Colombier 			quit();
3083e12c5d1SDavid du Colombier 
3093e12c5d1SDavid du Colombier 		case 'r':
3103e12c5d1SDavid du Colombier 			filename(c);
3113e12c5d1SDavid du Colombier 		caseread:
3123e12c5d1SDavid du Colombier 			if((io=open(file, OREAD)) < 0) {
3133e12c5d1SDavid du Colombier 				lastc = '\n';
3143e12c5d1SDavid du Colombier 				error(file);
3153e12c5d1SDavid du Colombier 			}
316*219b2ee8SDavid du Colombier 			if(dirfstat(io, &d) >= 0){
317*219b2ee8SDavid du Colombier 				if(d.mode & CHAPPEND)
318*219b2ee8SDavid du Colombier 					print("warning: %s is append only\n", file);
319*219b2ee8SDavid du Colombier 			}
3203e12c5d1SDavid du Colombier 			Binit(&iobuf, io, OREAD);
3213e12c5d1SDavid du Colombier 			setwide();
3223e12c5d1SDavid du Colombier 			squeeze(0);
3233e12c5d1SDavid du Colombier 			c = zero != dol;
3243e12c5d1SDavid du Colombier 			append(getfile, addr2);
3253e12c5d1SDavid du Colombier 			exfile(OREAD);
3263e12c5d1SDavid du Colombier 
3273e12c5d1SDavid du Colombier 			fchange = c;
3283e12c5d1SDavid du Colombier 			continue;
3293e12c5d1SDavid du Colombier 
3303e12c5d1SDavid du Colombier 		case 's':
3313e12c5d1SDavid du Colombier 			nonzero();
3323e12c5d1SDavid du Colombier 			substitute(globp != 0);
3333e12c5d1SDavid du Colombier 			continue;
3343e12c5d1SDavid du Colombier 
3353e12c5d1SDavid du Colombier 		case 't':
3363e12c5d1SDavid du Colombier 			move(1);
3373e12c5d1SDavid du Colombier 			continue;
3383e12c5d1SDavid du Colombier 
3393e12c5d1SDavid du Colombier 		case 'u':
3403e12c5d1SDavid du Colombier 			nonzero();
3413e12c5d1SDavid du Colombier 			newline();
3423e12c5d1SDavid du Colombier 			if((*addr2&~01) != subnewa)
3433e12c5d1SDavid du Colombier 				error(Q);
3443e12c5d1SDavid du Colombier 			*addr2 = subolda;
3453e12c5d1SDavid du Colombier 			dot = addr2;
3463e12c5d1SDavid du Colombier 			continue;
3473e12c5d1SDavid du Colombier 
3483e12c5d1SDavid du Colombier 		case 'v':
3493e12c5d1SDavid du Colombier 			global(0);
3503e12c5d1SDavid du Colombier 			continue;
3513e12c5d1SDavid du Colombier 
3523e12c5d1SDavid du Colombier 		case 'W':
3533e12c5d1SDavid du Colombier 			wrapp++;
3543e12c5d1SDavid du Colombier 		case 'w':
3553e12c5d1SDavid du Colombier 			setwide();
3563e12c5d1SDavid du Colombier 			squeeze(dol>zero);
3573e12c5d1SDavid du Colombier 			temp = getchr();
3583e12c5d1SDavid du Colombier 			if(temp != 'q' && temp != 'Q') {
3593e12c5d1SDavid du Colombier 				peekc = temp;
3603e12c5d1SDavid du Colombier 				temp = 0;
3613e12c5d1SDavid du Colombier 			}
3623e12c5d1SDavid du Colombier 			filename(c);
3633e12c5d1SDavid du Colombier 			if(!wrapp ||
3643e12c5d1SDavid du Colombier 			  ((io = open(file, OWRITE)) == -1) ||
3653e12c5d1SDavid du Colombier 			  ((seek(io, 0L, 2)) == -1))
3663e12c5d1SDavid du Colombier 				if((io = create(file, OWRITE, 0666)) < 0)
3673e12c5d1SDavid du Colombier 					error(file);
3683e12c5d1SDavid du Colombier 			Binit(&iobuf, io, OWRITE);
3693e12c5d1SDavid du Colombier 			wrapp = 0;
3703e12c5d1SDavid du Colombier 			if(dol > zero)
3713e12c5d1SDavid du Colombier 				putfile();
3723e12c5d1SDavid du Colombier 			exfile(OWRITE);
3733e12c5d1SDavid du Colombier 			if(addr1<=zero+1 && addr2==dol)
3743e12c5d1SDavid du Colombier 				fchange = 0;
3753e12c5d1SDavid du Colombier 			if(temp == 'Q')
3763e12c5d1SDavid du Colombier 				fchange = 0;
3773e12c5d1SDavid du Colombier 			if(temp)
3783e12c5d1SDavid du Colombier 				quit();
3793e12c5d1SDavid du Colombier 			continue;
3803e12c5d1SDavid du Colombier 
3813e12c5d1SDavid du Colombier 		case '=':
3823e12c5d1SDavid du Colombier 			setwide();
3833e12c5d1SDavid du Colombier 			squeeze(0);
3843e12c5d1SDavid du Colombier 			newline();
3853e12c5d1SDavid du Colombier 			count = addr2 - zero;
3863e12c5d1SDavid du Colombier 			putd();
3873e12c5d1SDavid du Colombier 			putchr(L'\n');
3883e12c5d1SDavid du Colombier 			continue;
3893e12c5d1SDavid du Colombier 
3903e12c5d1SDavid du Colombier 		case '!':
3913e12c5d1SDavid du Colombier 			callunix();
3923e12c5d1SDavid du Colombier 			continue;
3933e12c5d1SDavid du Colombier 
3943e12c5d1SDavid du Colombier 		case EOF:
3953e12c5d1SDavid du Colombier 			return;
3963e12c5d1SDavid du Colombier 
3973e12c5d1SDavid du Colombier 		}
3983e12c5d1SDavid du Colombier 		error(Q);
3993e12c5d1SDavid du Colombier 	}
4003e12c5d1SDavid du Colombier }
4013e12c5d1SDavid du Colombier 
4023e12c5d1SDavid du Colombier void
4033e12c5d1SDavid du Colombier printcom(void)
4043e12c5d1SDavid du Colombier {
4053e12c5d1SDavid du Colombier 	int *a1;
4063e12c5d1SDavid du Colombier 
4073e12c5d1SDavid du Colombier 	nonzero();
4083e12c5d1SDavid du Colombier 	a1 = addr1;
4093e12c5d1SDavid du Colombier 	do {
4103e12c5d1SDavid du Colombier 		if(listn) {
4113e12c5d1SDavid du Colombier 			count = a1-zero;
4123e12c5d1SDavid du Colombier 			putd();
4133e12c5d1SDavid du Colombier 			putchr(L'\t');
4143e12c5d1SDavid du Colombier 		}
4153e12c5d1SDavid du Colombier 		putshst(getline(*a1++));
4163e12c5d1SDavid du Colombier 	} while(a1 <= addr2);
4173e12c5d1SDavid du Colombier 	dot = addr2;
4183e12c5d1SDavid du Colombier 	listf = 0;
4193e12c5d1SDavid du Colombier 	listn = 0;
4203e12c5d1SDavid du Colombier 	pflag = 0;
4213e12c5d1SDavid du Colombier }
4223e12c5d1SDavid du Colombier 
4233e12c5d1SDavid du Colombier int*
4243e12c5d1SDavid du Colombier address(void)
4253e12c5d1SDavid du Colombier {
4263e12c5d1SDavid du Colombier 	int sign, *a, opcnt, nextopand, *b, c;
4273e12c5d1SDavid du Colombier 
4283e12c5d1SDavid du Colombier 	nextopand = -1;
4293e12c5d1SDavid du Colombier 	sign = 1;
4303e12c5d1SDavid du Colombier 	opcnt = 0;
4313e12c5d1SDavid du Colombier 	a = dot;
4323e12c5d1SDavid du Colombier 	do {
4333e12c5d1SDavid du Colombier 		do {
4343e12c5d1SDavid du Colombier 			c = getchr();
4353e12c5d1SDavid du Colombier 		} while(c == ' ' || c == '\t');
4363e12c5d1SDavid du Colombier 		if(c >= '0' && c <= '9') {
4373e12c5d1SDavid du Colombier 			peekc = c;
4383e12c5d1SDavid du Colombier 			if(!opcnt)
4393e12c5d1SDavid du Colombier 				a = zero;
4403e12c5d1SDavid du Colombier 			a += sign*getnum();
4413e12c5d1SDavid du Colombier 		} else
4423e12c5d1SDavid du Colombier 		switch(c) {
4433e12c5d1SDavid du Colombier 		case '$':
4443e12c5d1SDavid du Colombier 			a = dol;
4453e12c5d1SDavid du Colombier 		case '.':
4463e12c5d1SDavid du Colombier 			if(opcnt)
4473e12c5d1SDavid du Colombier 				error(Q);
4483e12c5d1SDavid du Colombier 			break;
4493e12c5d1SDavid du Colombier 		case '\'':
4503e12c5d1SDavid du Colombier 			c = getchr();
4513e12c5d1SDavid du Colombier 			if(opcnt || c < 'a' || c > 'z')
4523e12c5d1SDavid du Colombier 				error(Q);
4533e12c5d1SDavid du Colombier 			a = zero;
4543e12c5d1SDavid du Colombier 			do {
4553e12c5d1SDavid du Colombier 				a++;
4563e12c5d1SDavid du Colombier 			} while(a <= dol && names[c-'a'] != (*a & ~01));
4573e12c5d1SDavid du Colombier 			break;
4583e12c5d1SDavid du Colombier 		case '?':
4593e12c5d1SDavid du Colombier 			sign = -sign;
4603e12c5d1SDavid du Colombier 		case '/':
4613e12c5d1SDavid du Colombier 			compile(c);
4623e12c5d1SDavid du Colombier 			b = a;
4633e12c5d1SDavid du Colombier 			for(;;) {
4643e12c5d1SDavid du Colombier 				a += sign;
4653e12c5d1SDavid du Colombier 				if(a <= zero)
4663e12c5d1SDavid du Colombier 					a = dol;
4673e12c5d1SDavid du Colombier 				if(a > dol)
4683e12c5d1SDavid du Colombier 					a = zero;
4693e12c5d1SDavid du Colombier 				if(match(a))
4703e12c5d1SDavid du Colombier 					break;
4713e12c5d1SDavid du Colombier 				if(a == b)
4723e12c5d1SDavid du Colombier 					error(Q);
4733e12c5d1SDavid du Colombier 			}
4743e12c5d1SDavid du Colombier 			break;
4753e12c5d1SDavid du Colombier 		default:
4763e12c5d1SDavid du Colombier 			if(nextopand == opcnt) {
4773e12c5d1SDavid du Colombier 				a += sign;
4783e12c5d1SDavid du Colombier 				if(a < zero || dol < a)
4793e12c5d1SDavid du Colombier 					continue;       /* error(Q); */
4803e12c5d1SDavid du Colombier 			}
4813e12c5d1SDavid du Colombier 			if(c != '+' && c != '-' && c != '^') {
4823e12c5d1SDavid du Colombier 				peekc = c;
4833e12c5d1SDavid du Colombier 				if(opcnt == 0)
4843e12c5d1SDavid du Colombier 					a = 0;
4853e12c5d1SDavid du Colombier 				return a;
4863e12c5d1SDavid du Colombier 			}
4873e12c5d1SDavid du Colombier 			sign = 1;
4883e12c5d1SDavid du Colombier 			if(c != '+')
4893e12c5d1SDavid du Colombier 				sign = -sign;
4903e12c5d1SDavid du Colombier 			nextopand = ++opcnt;
4913e12c5d1SDavid du Colombier 			continue;
4923e12c5d1SDavid du Colombier 		}
4933e12c5d1SDavid du Colombier 		sign = 1;
4943e12c5d1SDavid du Colombier 		opcnt++;
4953e12c5d1SDavid du Colombier 	} while(zero <= a && a <= dol);
4963e12c5d1SDavid du Colombier 	error(Q);
4973e12c5d1SDavid du Colombier 	return 0;
4983e12c5d1SDavid du Colombier }
4993e12c5d1SDavid du Colombier 
5003e12c5d1SDavid du Colombier int
5013e12c5d1SDavid du Colombier getnum(void)
5023e12c5d1SDavid du Colombier {
5033e12c5d1SDavid du Colombier 	int r, c;
5043e12c5d1SDavid du Colombier 
5053e12c5d1SDavid du Colombier 	r = 0;
5063e12c5d1SDavid du Colombier 	for(;;) {
5073e12c5d1SDavid du Colombier 		c = getchr();
5083e12c5d1SDavid du Colombier 		if(c < '0' || c > '9')
5093e12c5d1SDavid du Colombier 			break;
5103e12c5d1SDavid du Colombier 		r = r*10 + (c-'0');
5113e12c5d1SDavid du Colombier 	}
5123e12c5d1SDavid du Colombier 	peekc = c;
5133e12c5d1SDavid du Colombier 	return r;
5143e12c5d1SDavid du Colombier }
5153e12c5d1SDavid du Colombier 
5163e12c5d1SDavid du Colombier void
5173e12c5d1SDavid du Colombier setwide(void)
5183e12c5d1SDavid du Colombier {
5193e12c5d1SDavid du Colombier 	if(!given) {
5203e12c5d1SDavid du Colombier 		addr1 = zero + (dol>zero);
5213e12c5d1SDavid du Colombier 		addr2 = dol;
5223e12c5d1SDavid du Colombier 	}
5233e12c5d1SDavid du Colombier }
5243e12c5d1SDavid du Colombier 
5253e12c5d1SDavid du Colombier void
5263e12c5d1SDavid du Colombier setnoaddr(void)
5273e12c5d1SDavid du Colombier {
5283e12c5d1SDavid du Colombier 	if(given)
5293e12c5d1SDavid du Colombier 		error(Q);
5303e12c5d1SDavid du Colombier }
5313e12c5d1SDavid du Colombier 
5323e12c5d1SDavid du Colombier void
5333e12c5d1SDavid du Colombier nonzero(void)
5343e12c5d1SDavid du Colombier {
5353e12c5d1SDavid du Colombier 	squeeze(1);
5363e12c5d1SDavid du Colombier }
5373e12c5d1SDavid du Colombier 
5383e12c5d1SDavid du Colombier void
5393e12c5d1SDavid du Colombier squeeze(int i)
5403e12c5d1SDavid du Colombier {
5413e12c5d1SDavid du Colombier 	if(addr1 < zero+i || addr2 > dol || addr1 > addr2)
5423e12c5d1SDavid du Colombier 		error(Q);
5433e12c5d1SDavid du Colombier }
5443e12c5d1SDavid du Colombier 
5453e12c5d1SDavid du Colombier void
5463e12c5d1SDavid du Colombier newline(void)
5473e12c5d1SDavid du Colombier {
5483e12c5d1SDavid du Colombier 	int c;
5493e12c5d1SDavid du Colombier 
5503e12c5d1SDavid du Colombier 	c = getchr();
5513e12c5d1SDavid du Colombier 	if(c == '\n' || c == EOF)
5523e12c5d1SDavid du Colombier 		return;
5533e12c5d1SDavid du Colombier 	if(c == 'p' || c == 'l' || c == 'n') {
5543e12c5d1SDavid du Colombier 		pflag++;
5553e12c5d1SDavid du Colombier 		if(c == 'l')
5563e12c5d1SDavid du Colombier 			listf++;
5573e12c5d1SDavid du Colombier 		else
5583e12c5d1SDavid du Colombier 		if(c == 'n')
5593e12c5d1SDavid du Colombier 			listn++;
5603e12c5d1SDavid du Colombier 		c = getchr();
5613e12c5d1SDavid du Colombier 		if(c == '\n')
5623e12c5d1SDavid du Colombier 			return;
5633e12c5d1SDavid du Colombier 	}
5643e12c5d1SDavid du Colombier 	error(Q);
5653e12c5d1SDavid du Colombier }
5663e12c5d1SDavid du Colombier 
5673e12c5d1SDavid du Colombier void
5683e12c5d1SDavid du Colombier filename(int comm)
5693e12c5d1SDavid du Colombier {
5703e12c5d1SDavid du Colombier 	char *p1, *p2;
5713e12c5d1SDavid du Colombier 	Rune rune;
5723e12c5d1SDavid du Colombier 	int c;
5733e12c5d1SDavid du Colombier 
5743e12c5d1SDavid du Colombier 	count = 0;
5753e12c5d1SDavid du Colombier 	c = getchr();
5763e12c5d1SDavid du Colombier 	if(c == '\n' || c == EOF) {
5773e12c5d1SDavid du Colombier 		p1 = savedfile;
5783e12c5d1SDavid du Colombier 		if(*p1 == 0 && comm != 'f')
5793e12c5d1SDavid du Colombier 			error(Q);
5803e12c5d1SDavid du Colombier 		p2 = file;
5813e12c5d1SDavid du Colombier 		while(*p2++ = *p1++)
5823e12c5d1SDavid du Colombier 			;
5833e12c5d1SDavid du Colombier 		return;
5843e12c5d1SDavid du Colombier 	}
5853e12c5d1SDavid du Colombier 	if(c != ' ')
5863e12c5d1SDavid du Colombier 		error(Q);
5873e12c5d1SDavid du Colombier 	while((c=getchr()) == ' ')
5883e12c5d1SDavid du Colombier 		;
5893e12c5d1SDavid du Colombier 	if(c == '\n')
5903e12c5d1SDavid du Colombier 		error(Q);
5913e12c5d1SDavid du Colombier 	p1 = file;
5923e12c5d1SDavid du Colombier 	do {
5933e12c5d1SDavid du Colombier 		if(p1 >= &file[sizeof(file)-6] || c == ' ' || c == EOF)
5943e12c5d1SDavid du Colombier 			error(Q);
5953e12c5d1SDavid du Colombier 		rune = c;
5963e12c5d1SDavid du Colombier 		p1 += runetochar(p1, &rune);
5973e12c5d1SDavid du Colombier 	} while((c=getchr()) != '\n');
5983e12c5d1SDavid du Colombier 	*p1 = 0;
5993e12c5d1SDavid du Colombier 	if(savedfile[0] == 0 || comm == 'e' || comm == 'f') {
6003e12c5d1SDavid du Colombier 		p1 = savedfile;
6013e12c5d1SDavid du Colombier 		p2 = file;
6023e12c5d1SDavid du Colombier 		while(*p1++ = *p2++)
6033e12c5d1SDavid du Colombier 			;
6043e12c5d1SDavid du Colombier 	}
6053e12c5d1SDavid du Colombier }
6063e12c5d1SDavid du Colombier 
6073e12c5d1SDavid du Colombier void
6083e12c5d1SDavid du Colombier exfile(int om)
6093e12c5d1SDavid du Colombier {
6103e12c5d1SDavid du Colombier 
6113e12c5d1SDavid du Colombier 	if(om == OWRITE)
6123e12c5d1SDavid du Colombier 		if(Bflush(&iobuf) < 0)
6133e12c5d1SDavid du Colombier 			error(Q);
6143e12c5d1SDavid du Colombier 	close(io);
6153e12c5d1SDavid du Colombier 	io = -1;
6163e12c5d1SDavid du Colombier 	if(vflag) {
6173e12c5d1SDavid du Colombier 		putd();
6183e12c5d1SDavid du Colombier 		putchr(L'\n');
6193e12c5d1SDavid du Colombier 	}
6203e12c5d1SDavid du Colombier }
6213e12c5d1SDavid du Colombier 
6223e12c5d1SDavid du Colombier void
6233e12c5d1SDavid du Colombier error1(char *s)
6243e12c5d1SDavid du Colombier {
6253e12c5d1SDavid du Colombier 	int c;
6263e12c5d1SDavid du Colombier 
6273e12c5d1SDavid du Colombier 	wrapp = 0;
6283e12c5d1SDavid du Colombier 	listf = 0;
6293e12c5d1SDavid du Colombier 	listn = 0;
6303e12c5d1SDavid du Colombier 	count = 0;
6313e12c5d1SDavid du Colombier 	seek(0, 0, 2);
6323e12c5d1SDavid du Colombier 	pflag = 0;
6333e12c5d1SDavid du Colombier 	if(globp)
6343e12c5d1SDavid du Colombier 		lastc = '\n';
6353e12c5d1SDavid du Colombier 	globp = 0;
6363e12c5d1SDavid du Colombier 	peekc = lastc;
6373e12c5d1SDavid du Colombier 	if(lastc)
6383e12c5d1SDavid du Colombier 		for(;;) {
6393e12c5d1SDavid du Colombier 			c = getchr();
6403e12c5d1SDavid du Colombier 			if(c == '\n' || c == EOF)
6413e12c5d1SDavid du Colombier 				break;
6423e12c5d1SDavid du Colombier 		}
6433e12c5d1SDavid du Colombier 	if(io > 0) {
6443e12c5d1SDavid du Colombier 		close(io);
6453e12c5d1SDavid du Colombier 		io = -1;
6463e12c5d1SDavid du Colombier 	}
6473e12c5d1SDavid du Colombier 	putchr(L'?');
6483e12c5d1SDavid du Colombier 	putst(s);
6493e12c5d1SDavid du Colombier }
6503e12c5d1SDavid du Colombier 
6513e12c5d1SDavid du Colombier void
6523e12c5d1SDavid du Colombier error(char *s)
6533e12c5d1SDavid du Colombier {
6543e12c5d1SDavid du Colombier 	error1(s);
6553e12c5d1SDavid du Colombier 	longjmp(savej, 1);
6563e12c5d1SDavid du Colombier }
6573e12c5d1SDavid du Colombier 
6583e12c5d1SDavid du Colombier void
6593e12c5d1SDavid du Colombier rescue(void)
6603e12c5d1SDavid du Colombier {
6613e12c5d1SDavid du Colombier 	rescuing = 1;
6623e12c5d1SDavid du Colombier 	if(dol > zero) {
6633e12c5d1SDavid du Colombier 		addr1 = zero+1;
6643e12c5d1SDavid du Colombier 		addr2 = dol;
6653e12c5d1SDavid du Colombier 		io = create("ed.hup", OWRITE, 0666);
6663e12c5d1SDavid du Colombier 		if(io > 0)
6673e12c5d1SDavid du Colombier 			putfile();
6683e12c5d1SDavid du Colombier 	}
6693e12c5d1SDavid du Colombier 	fchange = 0;
6703e12c5d1SDavid du Colombier 	quit();
6713e12c5d1SDavid du Colombier }
6723e12c5d1SDavid du Colombier 
6733e12c5d1SDavid du Colombier void
6743e12c5d1SDavid du Colombier notifyf(void *a, char *s)
6753e12c5d1SDavid du Colombier {
6763e12c5d1SDavid du Colombier 	if(strcmp(s, "interrupt") == 0){
6773e12c5d1SDavid du Colombier 		if(rescuing)
6783e12c5d1SDavid du Colombier 			noted(NCONT);
6793e12c5d1SDavid du Colombier 		putchr(L'\n');
6803e12c5d1SDavid du Colombier 		lastc = '\n';
6813e12c5d1SDavid du Colombier 		error1(Q);
6823e12c5d1SDavid du Colombier 		notejmp(a, savej, 0);
6833e12c5d1SDavid du Colombier 	}
6843e12c5d1SDavid du Colombier 	if(strcmp(s, "hangup") == 0){
6853e12c5d1SDavid du Colombier 		if(rescuing)
6863e12c5d1SDavid du Colombier 			noted(NDFLT);
6873e12c5d1SDavid du Colombier 		rescue();
6883e12c5d1SDavid du Colombier 	}
6893e12c5d1SDavid du Colombier 	fprint(2, "ed: note: %s\n", s);
6903e12c5d1SDavid du Colombier 	abort();
6913e12c5d1SDavid du Colombier }
6923e12c5d1SDavid du Colombier 
6933e12c5d1SDavid du Colombier int
6943e12c5d1SDavid du Colombier getchr(void)
6953e12c5d1SDavid du Colombier {
6963e12c5d1SDavid du Colombier 	char s[UTFmax];
6973e12c5d1SDavid du Colombier 	int i;
6983e12c5d1SDavid du Colombier 	Rune r;
6993e12c5d1SDavid du Colombier 
7003e12c5d1SDavid du Colombier 	if(lastc = peekc) {
7013e12c5d1SDavid du Colombier 		peekc = 0;
7023e12c5d1SDavid du Colombier 		return lastc;
7033e12c5d1SDavid du Colombier 	}
7043e12c5d1SDavid du Colombier 	if(globp) {
7053e12c5d1SDavid du Colombier 		if((lastc=*globp++) != 0)
7063e12c5d1SDavid du Colombier 			return lastc;
7073e12c5d1SDavid du Colombier 		globp = 0;
7083e12c5d1SDavid du Colombier 		return EOF;
7093e12c5d1SDavid du Colombier 	}
7103e12c5d1SDavid du Colombier 	for(i=0;;) {
7113e12c5d1SDavid du Colombier 		if(read(0, s+i, 1) <= 0)
7123e12c5d1SDavid du Colombier 			return lastc = EOF;
7133e12c5d1SDavid du Colombier 		i++;
7143e12c5d1SDavid du Colombier 		if(fullrune(s, i))
7153e12c5d1SDavid du Colombier 			break;
7163e12c5d1SDavid du Colombier 
7173e12c5d1SDavid du Colombier 	}
7183e12c5d1SDavid du Colombier 	chartorune(&r, s);
7193e12c5d1SDavid du Colombier 	lastc = r;
7203e12c5d1SDavid du Colombier 	return lastc;
7213e12c5d1SDavid du Colombier }
7223e12c5d1SDavid du Colombier 
7233e12c5d1SDavid du Colombier int
7243e12c5d1SDavid du Colombier gety(void)
7253e12c5d1SDavid du Colombier {
7263e12c5d1SDavid du Colombier 	int c;
7273e12c5d1SDavid du Colombier 	Rune *gf, *p;
7283e12c5d1SDavid du Colombier 
7293e12c5d1SDavid du Colombier 	p = linebuf;
7303e12c5d1SDavid du Colombier 	gf = globp;
7313e12c5d1SDavid du Colombier 	for(;;) {
7323e12c5d1SDavid du Colombier 		c = getchr();
7333e12c5d1SDavid du Colombier 		if(c == '\n') {
7343e12c5d1SDavid du Colombier 			*p = 0;
7353e12c5d1SDavid du Colombier 			return 0;
7363e12c5d1SDavid du Colombier 		}
7373e12c5d1SDavid du Colombier 		if(c == EOF) {
7383e12c5d1SDavid du Colombier 			if(gf)
7393e12c5d1SDavid du Colombier 				peekc = c;
7403e12c5d1SDavid du Colombier 			return c;
7413e12c5d1SDavid du Colombier 		}
7423e12c5d1SDavid du Colombier 		if(c == 0)
7433e12c5d1SDavid du Colombier 			continue;
7443e12c5d1SDavid du Colombier 		*p++ = c;
7453e12c5d1SDavid du Colombier 		if(p >= &linebuf[LBSIZE-2])
7463e12c5d1SDavid du Colombier 			error(Q);
7473e12c5d1SDavid du Colombier 	}
7483e12c5d1SDavid du Colombier 	return 0;
7493e12c5d1SDavid du Colombier }
7503e12c5d1SDavid du Colombier 
7513e12c5d1SDavid du Colombier int
7523e12c5d1SDavid du Colombier gettty(void)
7533e12c5d1SDavid du Colombier {
7543e12c5d1SDavid du Colombier 	int rc;
7553e12c5d1SDavid du Colombier 
7563e12c5d1SDavid du Colombier 	rc = gety();
7573e12c5d1SDavid du Colombier 	if(rc)
7583e12c5d1SDavid du Colombier 		return rc;
7593e12c5d1SDavid du Colombier 	if(linebuf[0] == '.' && linebuf[1] == 0)
7603e12c5d1SDavid du Colombier 		return EOF;
7613e12c5d1SDavid du Colombier 	return 0;
7623e12c5d1SDavid du Colombier }
7633e12c5d1SDavid du Colombier 
7643e12c5d1SDavid du Colombier int
7653e12c5d1SDavid du Colombier getfile(void)
7663e12c5d1SDavid du Colombier {
7673e12c5d1SDavid du Colombier 	int c;
7683e12c5d1SDavid du Colombier 	Rune *lp;
7693e12c5d1SDavid du Colombier 
7703e12c5d1SDavid du Colombier 	lp = linebuf;
7713e12c5d1SDavid du Colombier 	do {
7723e12c5d1SDavid du Colombier 		c = Bgetrune(&iobuf);
7733e12c5d1SDavid du Colombier 		if(c < 0) {
7743e12c5d1SDavid du Colombier 			if(lp > linebuf) {
7753e12c5d1SDavid du Colombier 				putst("'\\n' appended");
7763e12c5d1SDavid du Colombier 				c = '\n';
7773e12c5d1SDavid du Colombier 			} else
7783e12c5d1SDavid du Colombier 				return EOF;
7793e12c5d1SDavid du Colombier 		}
7803e12c5d1SDavid du Colombier 		if(lp >= &linebuf[LBSIZE]) {
7813e12c5d1SDavid du Colombier 			lastc = '\n';
7823e12c5d1SDavid du Colombier 			error(Q);
7833e12c5d1SDavid du Colombier 		}
7843e12c5d1SDavid du Colombier 		*lp++ = c;
7853e12c5d1SDavid du Colombier 		count++;
7863e12c5d1SDavid du Colombier 	} while(c != '\n');
7873e12c5d1SDavid du Colombier 	lp[-1] = 0;
7883e12c5d1SDavid du Colombier 	return 0;
7893e12c5d1SDavid du Colombier }
7903e12c5d1SDavid du Colombier 
7913e12c5d1SDavid du Colombier void
7923e12c5d1SDavid du Colombier putfile(void)
7933e12c5d1SDavid du Colombier {
7943e12c5d1SDavid du Colombier 	int *a1;
7953e12c5d1SDavid du Colombier 	Rune *lp;
7963e12c5d1SDavid du Colombier 	long c;
7973e12c5d1SDavid du Colombier 
7983e12c5d1SDavid du Colombier 	a1 = addr1;
7993e12c5d1SDavid du Colombier 	do {
8003e12c5d1SDavid du Colombier 		lp = getline(*a1++);
8013e12c5d1SDavid du Colombier 		for(;;) {
8023e12c5d1SDavid du Colombier 			count++;
8033e12c5d1SDavid du Colombier 			c = *lp++;
8043e12c5d1SDavid du Colombier 			if(c == 0) {
8053e12c5d1SDavid du Colombier 				if(Bputrune(&iobuf, '\n') < 0)
8063e12c5d1SDavid du Colombier 					error(Q);
8073e12c5d1SDavid du Colombier 				break;
8083e12c5d1SDavid du Colombier 			}
8093e12c5d1SDavid du Colombier 			if(Bputrune(&iobuf, c) < 0)
8103e12c5d1SDavid du Colombier 				error(Q);
8113e12c5d1SDavid du Colombier 		}
8123e12c5d1SDavid du Colombier 	} while(a1 <= addr2);
8133e12c5d1SDavid du Colombier 	if(Bflush(&iobuf) < 0)
8143e12c5d1SDavid du Colombier 		error(Q);
8153e12c5d1SDavid du Colombier }
8163e12c5d1SDavid du Colombier 
8173e12c5d1SDavid du Colombier int
8183e12c5d1SDavid du Colombier append(int (*f)(void), int *a)
8193e12c5d1SDavid du Colombier {
8203e12c5d1SDavid du Colombier 	int *a1, *a2, *rdot, nline, tl;
8213e12c5d1SDavid du Colombier 
8223e12c5d1SDavid du Colombier 	nline = 0;
8233e12c5d1SDavid du Colombier 	dot = a;
8243e12c5d1SDavid du Colombier 	while((*f)() == 0) {
8253e12c5d1SDavid du Colombier 		if((dol-zero) >= nlall) {
8263e12c5d1SDavid du Colombier 			nlall += 512;
8273e12c5d1SDavid du Colombier 			a1 = realloc(zero, (nlall+5)*sizeof(int*));
8283e12c5d1SDavid du Colombier 			if(a1 == 0) {
8293e12c5d1SDavid du Colombier 				error("MEM?");
8303e12c5d1SDavid du Colombier 				rescue();
8313e12c5d1SDavid du Colombier 			}
8323e12c5d1SDavid du Colombier 			tl = a1 - zero;	/* relocate pointers */
8333e12c5d1SDavid du Colombier 			zero += tl;
8343e12c5d1SDavid du Colombier 			addr1 += tl;
8353e12c5d1SDavid du Colombier 			addr2 += tl;
8363e12c5d1SDavid du Colombier 			dol += tl;
8373e12c5d1SDavid du Colombier 			dot += tl;
8383e12c5d1SDavid du Colombier 		}
8393e12c5d1SDavid du Colombier 		tl = putline();
8403e12c5d1SDavid du Colombier 		nline++;
8413e12c5d1SDavid du Colombier 		a1 = ++dol;
8423e12c5d1SDavid du Colombier 		a2 = a1+1;
8433e12c5d1SDavid du Colombier 		rdot = ++dot;
8443e12c5d1SDavid du Colombier 		while(a1 > rdot)
8453e12c5d1SDavid du Colombier 			*--a2 = *--a1;
8463e12c5d1SDavid du Colombier 		*rdot = tl;
8473e12c5d1SDavid du Colombier 	}
8483e12c5d1SDavid du Colombier 	return nline;
8493e12c5d1SDavid du Colombier }
8503e12c5d1SDavid du Colombier 
8513e12c5d1SDavid du Colombier void
8523e12c5d1SDavid du Colombier add(int i)
8533e12c5d1SDavid du Colombier {
8543e12c5d1SDavid du Colombier 	if(i && (given || dol > zero)) {
8553e12c5d1SDavid du Colombier 		addr1--;
8563e12c5d1SDavid du Colombier 		addr2--;
8573e12c5d1SDavid du Colombier 	}
8583e12c5d1SDavid du Colombier 	squeeze(0);
8593e12c5d1SDavid du Colombier 	newline();
8603e12c5d1SDavid du Colombier 	append(gettty, addr2);
8613e12c5d1SDavid du Colombier }
8623e12c5d1SDavid du Colombier 
8633e12c5d1SDavid du Colombier void
8643e12c5d1SDavid du Colombier browse(void)
8653e12c5d1SDavid du Colombier {
8663e12c5d1SDavid du Colombier 	int forward, n;
8673e12c5d1SDavid du Colombier 	static bformat, bnum; /* 0 */
8683e12c5d1SDavid du Colombier 
8693e12c5d1SDavid du Colombier 	forward = 1;
8703e12c5d1SDavid du Colombier 	peekc = getchr();
8713e12c5d1SDavid du Colombier 	if(peekc != '\n'){
8723e12c5d1SDavid du Colombier 		if(peekc == '-' || peekc == '+') {
8733e12c5d1SDavid du Colombier 			if(peekc == '-')
8743e12c5d1SDavid du Colombier 				forward = 0;
8753e12c5d1SDavid du Colombier 			getchr();
8763e12c5d1SDavid du Colombier 		}
8773e12c5d1SDavid du Colombier 		n = getnum();
8783e12c5d1SDavid du Colombier 		if(n > 0)
8793e12c5d1SDavid du Colombier 			bpagesize = n;
8803e12c5d1SDavid du Colombier 	}
8813e12c5d1SDavid du Colombier 	newline();
8823e12c5d1SDavid du Colombier 	if(pflag) {
8833e12c5d1SDavid du Colombier 		bformat = listf;
8843e12c5d1SDavid du Colombier 		bnum = listn;
8853e12c5d1SDavid du Colombier 	} else {
8863e12c5d1SDavid du Colombier 		listf = bformat;
8873e12c5d1SDavid du Colombier 		listn = bnum;
8883e12c5d1SDavid du Colombier 	}
8893e12c5d1SDavid du Colombier 	if(forward) {
8903e12c5d1SDavid du Colombier 		addr1 = addr2;
8913e12c5d1SDavid du Colombier 		addr2 += bpagesize;
8923e12c5d1SDavid du Colombier 		if(addr2 > dol)
8933e12c5d1SDavid du Colombier 			addr2 = dol;
8943e12c5d1SDavid du Colombier 	} else {
8953e12c5d1SDavid du Colombier 		addr1 = addr2-bpagesize;
8963e12c5d1SDavid du Colombier 		if(addr1 <= zero)
8973e12c5d1SDavid du Colombier 			addr1 = zero+1;
8983e12c5d1SDavid du Colombier 	}
8993e12c5d1SDavid du Colombier 	printcom();
9003e12c5d1SDavid du Colombier }
9013e12c5d1SDavid du Colombier 
9023e12c5d1SDavid du Colombier void
9033e12c5d1SDavid du Colombier callunix(void)
9043e12c5d1SDavid du Colombier {
9053e12c5d1SDavid du Colombier 	int c;
9063e12c5d1SDavid du Colombier 	Rune rune;
9073e12c5d1SDavid du Colombier 	Waitmsg w;
9083e12c5d1SDavid du Colombier 	char buf[512];
9093e12c5d1SDavid du Colombier 	char *p;
9103e12c5d1SDavid du Colombier 
9113e12c5d1SDavid du Colombier 	setnoaddr();
9123e12c5d1SDavid du Colombier 	p = buf;
9133e12c5d1SDavid du Colombier 	while((c=getchr()) != EOF && c != '\n')
9143e12c5d1SDavid du Colombier 		if(p < &buf[sizeof(buf) - 6]) {
9153e12c5d1SDavid du Colombier 			rune = c;
9163e12c5d1SDavid du Colombier 			p += runetochar(p, &rune);
9173e12c5d1SDavid du Colombier 		}
9183e12c5d1SDavid du Colombier 	*p = 0;
9193e12c5d1SDavid du Colombier 	if(fork() == 0) {
9203e12c5d1SDavid du Colombier 		execl("/bin/rc", "rc", "-c", buf, 0);
9213e12c5d1SDavid du Colombier 		exits("execl failed");
9223e12c5d1SDavid du Colombier 	}
9233e12c5d1SDavid du Colombier 	wait(&w);
9243e12c5d1SDavid du Colombier 	if(vflag)
9253e12c5d1SDavid du Colombier 		putst("!");
9263e12c5d1SDavid du Colombier }
9273e12c5d1SDavid du Colombier 
9283e12c5d1SDavid du Colombier void
9293e12c5d1SDavid du Colombier quit(void)
9303e12c5d1SDavid du Colombier {
9313e12c5d1SDavid du Colombier 	if(vflag && fchange && dol!=zero) {
9323e12c5d1SDavid du Colombier 		fchange = 0;
9333e12c5d1SDavid du Colombier 		error(Q);
9343e12c5d1SDavid du Colombier 	}
9353e12c5d1SDavid du Colombier 	remove(tfname);
9363e12c5d1SDavid du Colombier 	exits(0);
9373e12c5d1SDavid du Colombier }
9383e12c5d1SDavid du Colombier 
9393e12c5d1SDavid du Colombier void
9403e12c5d1SDavid du Colombier onquit(int sig)
9413e12c5d1SDavid du Colombier {
9423e12c5d1SDavid du Colombier 	USED(sig);
9433e12c5d1SDavid du Colombier 	quit();
9443e12c5d1SDavid du Colombier }
9453e12c5d1SDavid du Colombier 
9463e12c5d1SDavid du Colombier void
9473e12c5d1SDavid du Colombier rdelete(int *ad1, int *ad2)
9483e12c5d1SDavid du Colombier {
9493e12c5d1SDavid du Colombier 	int *a1, *a2, *a3;
9503e12c5d1SDavid du Colombier 
9513e12c5d1SDavid du Colombier 	a1 = ad1;
9523e12c5d1SDavid du Colombier 	a2 = ad2+1;
9533e12c5d1SDavid du Colombier 	a3 = dol;
9543e12c5d1SDavid du Colombier 	dol -= a2 - a1;
9553e12c5d1SDavid du Colombier 	do {
9563e12c5d1SDavid du Colombier 		*a1++ = *a2++;
9573e12c5d1SDavid du Colombier 	} while(a2 <= a3);
9583e12c5d1SDavid du Colombier 	a1 = ad1;
9593e12c5d1SDavid du Colombier 	if(a1 > dol)
9603e12c5d1SDavid du Colombier 		a1 = dol;
9613e12c5d1SDavid du Colombier 	dot = a1;
9623e12c5d1SDavid du Colombier 	fchange = 1;
9633e12c5d1SDavid du Colombier }
9643e12c5d1SDavid du Colombier 
9653e12c5d1SDavid du Colombier void
9663e12c5d1SDavid du Colombier gdelete(void)
9673e12c5d1SDavid du Colombier {
9683e12c5d1SDavid du Colombier 	int *a1, *a2, *a3;
9693e12c5d1SDavid du Colombier 
9703e12c5d1SDavid du Colombier 	a3 = dol;
9713e12c5d1SDavid du Colombier 	for(a1=zero; (*a1&01)==0; a1++)
9723e12c5d1SDavid du Colombier 		if(a1>=a3)
9733e12c5d1SDavid du Colombier 			return;
9743e12c5d1SDavid du Colombier 	for(a2=a1+1; a2<=a3;) {
9753e12c5d1SDavid du Colombier 		if(*a2 & 01) {
9763e12c5d1SDavid du Colombier 			a2++;
9773e12c5d1SDavid du Colombier 			dot = a1;
9783e12c5d1SDavid du Colombier 		} else
9793e12c5d1SDavid du Colombier 			*a1++ = *a2++;
9803e12c5d1SDavid du Colombier 	}
9813e12c5d1SDavid du Colombier 	dol = a1-1;
9823e12c5d1SDavid du Colombier 	if(dot > dol)
9833e12c5d1SDavid du Colombier 		dot = dol;
9843e12c5d1SDavid du Colombier 	fchange = 1;
9853e12c5d1SDavid du Colombier }
9863e12c5d1SDavid du Colombier 
9873e12c5d1SDavid du Colombier Rune*
9883e12c5d1SDavid du Colombier getline(int tl)
9893e12c5d1SDavid du Colombier {
9903e12c5d1SDavid du Colombier 	Rune *lp, *bp;
9913e12c5d1SDavid du Colombier 	int nl;
9923e12c5d1SDavid du Colombier 
9933e12c5d1SDavid du Colombier 	lp = linebuf;
9943e12c5d1SDavid du Colombier 	bp = getblock(tl, OREAD);
9953e12c5d1SDavid du Colombier 	nl = nleft;
9963e12c5d1SDavid du Colombier 	tl &= ~((BLKSIZE/2) - 1);
9973e12c5d1SDavid du Colombier 	while(*lp++ = *bp++) {
9983e12c5d1SDavid du Colombier 		nl -= sizeof(Rune);
9993e12c5d1SDavid du Colombier 		if(nl == 0) {
10003e12c5d1SDavid du Colombier 			bp = getblock(tl += BLKSIZE/2, OREAD);
10013e12c5d1SDavid du Colombier 			nl = nleft;
10023e12c5d1SDavid du Colombier 		}
10033e12c5d1SDavid du Colombier 	}
10043e12c5d1SDavid du Colombier 	return linebuf;
10053e12c5d1SDavid du Colombier }
10063e12c5d1SDavid du Colombier 
10073e12c5d1SDavid du Colombier int
10083e12c5d1SDavid du Colombier putline(void)
10093e12c5d1SDavid du Colombier {
10103e12c5d1SDavid du Colombier 	Rune *lp, *bp;
10113e12c5d1SDavid du Colombier 	int nl, tl;
10123e12c5d1SDavid du Colombier 
10133e12c5d1SDavid du Colombier 	fchange = 1;
10143e12c5d1SDavid du Colombier 	lp = linebuf;
10153e12c5d1SDavid du Colombier 	tl = tline;
10163e12c5d1SDavid du Colombier 	bp = getblock(tl, OWRITE);
10173e12c5d1SDavid du Colombier 	nl = nleft;
10183e12c5d1SDavid du Colombier 	tl &= ~((BLKSIZE/2)-1);
10193e12c5d1SDavid du Colombier 	while(*bp = *lp++) {
10203e12c5d1SDavid du Colombier 		if(*bp++ == '\n') {
10213e12c5d1SDavid du Colombier 			bp[-1] = 0;
10223e12c5d1SDavid du Colombier 			linebp = lp;
10233e12c5d1SDavid du Colombier 			break;
10243e12c5d1SDavid du Colombier 		}
10253e12c5d1SDavid du Colombier 		nl -= sizeof(Rune);
10263e12c5d1SDavid du Colombier 		if(nl == 0) {
10273e12c5d1SDavid du Colombier 			tl += BLKSIZE/2;
10283e12c5d1SDavid du Colombier 			bp = getblock(tl, OWRITE);
10293e12c5d1SDavid du Colombier 			nl = nleft;
10303e12c5d1SDavid du Colombier 		}
10313e12c5d1SDavid du Colombier 	}
10323e12c5d1SDavid du Colombier 	nl = tline;
10333e12c5d1SDavid du Colombier 	tline += ((lp-linebuf) + 03) & 077776;
10343e12c5d1SDavid du Colombier 	return nl;
10353e12c5d1SDavid du Colombier }
10363e12c5d1SDavid du Colombier 
10373e12c5d1SDavid du Colombier void
10383e12c5d1SDavid du Colombier blkio(int b, uchar *buf, long (*iofcn)(int, void *, long))
10393e12c5d1SDavid du Colombier {
10403e12c5d1SDavid du Colombier 	seek(tfile, b*BLKSIZE, 0);
10413e12c5d1SDavid du Colombier 	if((*iofcn)(tfile, buf, BLKSIZE) != BLKSIZE) {
10423e12c5d1SDavid du Colombier 		error(T);
10433e12c5d1SDavid du Colombier 	}
10443e12c5d1SDavid du Colombier }
10453e12c5d1SDavid du Colombier 
10463e12c5d1SDavid du Colombier Rune*
10473e12c5d1SDavid du Colombier getblock(int atl, int iof)
10483e12c5d1SDavid du Colombier {
10493e12c5d1SDavid du Colombier 	int bno, off;
10503e12c5d1SDavid du Colombier 
10513e12c5d1SDavid du Colombier 	static uchar ibuff[BLKSIZE];
10523e12c5d1SDavid du Colombier 	static uchar obuff[BLKSIZE];
10533e12c5d1SDavid du Colombier 
10543e12c5d1SDavid du Colombier 	bno = atl / (BLKSIZE/2);
10553e12c5d1SDavid du Colombier 	off = (atl<<1) & (BLKSIZE-1) & ~03;
10563e12c5d1SDavid du Colombier 	if(bno >= NBLK) {
10573e12c5d1SDavid du Colombier 		lastc = '\n';
10583e12c5d1SDavid du Colombier 		error(T);
10593e12c5d1SDavid du Colombier 	}
10603e12c5d1SDavid du Colombier 	nleft = BLKSIZE - off;
10613e12c5d1SDavid du Colombier 	if(bno == iblock) {
10623e12c5d1SDavid du Colombier 		ichanged |= iof;
10633e12c5d1SDavid du Colombier 		return (Rune*)(ibuff+off);
10643e12c5d1SDavid du Colombier 	}
10653e12c5d1SDavid du Colombier 	if(bno == oblock)
10663e12c5d1SDavid du Colombier 		return (Rune*)(obuff+off);
10673e12c5d1SDavid du Colombier 	if(iof == OREAD) {
10683e12c5d1SDavid du Colombier 		if(ichanged)
10693e12c5d1SDavid du Colombier 			blkio(iblock, ibuff, write);
10703e12c5d1SDavid du Colombier 		ichanged = 0;
10713e12c5d1SDavid du Colombier 		iblock = bno;
10723e12c5d1SDavid du Colombier 		blkio(bno, ibuff, read);
10733e12c5d1SDavid du Colombier 		return (Rune*)(ibuff+off);
10743e12c5d1SDavid du Colombier 	}
10753e12c5d1SDavid du Colombier 	if(oblock >= 0)
10763e12c5d1SDavid du Colombier 		blkio(oblock, obuff, write);
10773e12c5d1SDavid du Colombier 	oblock = bno;
10783e12c5d1SDavid du Colombier 	return (Rune*)(obuff+off);
10793e12c5d1SDavid du Colombier }
10803e12c5d1SDavid du Colombier 
10813e12c5d1SDavid du Colombier void
10823e12c5d1SDavid du Colombier init(void)
10833e12c5d1SDavid du Colombier {
10843e12c5d1SDavid du Colombier 	int *markp;
10853e12c5d1SDavid du Colombier 
10863e12c5d1SDavid du Colombier 	close(tfile);
10873e12c5d1SDavid du Colombier 	tline = 2;
10883e12c5d1SDavid du Colombier 	for(markp = names; markp < &names[26]; )
10893e12c5d1SDavid du Colombier 		*markp++ = 0;
10903e12c5d1SDavid du Colombier 	subnewa = 0;
10913e12c5d1SDavid du Colombier 	anymarks = 0;
10923e12c5d1SDavid du Colombier 	iblock = -1;
10933e12c5d1SDavid du Colombier 	oblock = -1;
10943e12c5d1SDavid du Colombier 	ichanged = 0;
10953e12c5d1SDavid du Colombier 	if((tfile = create(tfname, ORDWR, 0600)) < 0){
10963e12c5d1SDavid du Colombier 		error1(T);
10973e12c5d1SDavid du Colombier 		exits(0);
10983e12c5d1SDavid du Colombier 	}
10993e12c5d1SDavid du Colombier 	dot = dol = zero;
11003e12c5d1SDavid du Colombier }
11013e12c5d1SDavid du Colombier 
11023e12c5d1SDavid du Colombier void
11033e12c5d1SDavid du Colombier global(int k)
11043e12c5d1SDavid du Colombier {
11053e12c5d1SDavid du Colombier 	Rune *gp, globuf[GBSIZE];
11063e12c5d1SDavid du Colombier 	int c, *a1;
11073e12c5d1SDavid du Colombier 
11083e12c5d1SDavid du Colombier 	if(globp)
11093e12c5d1SDavid du Colombier 		error(Q);
11103e12c5d1SDavid du Colombier 	setwide();
11113e12c5d1SDavid du Colombier 	squeeze(dol > zero);
11123e12c5d1SDavid du Colombier 	c = getchr();
11133e12c5d1SDavid du Colombier 	if(c == '\n')
11143e12c5d1SDavid du Colombier 		error(Q);
11153e12c5d1SDavid du Colombier 	compile(c);
11163e12c5d1SDavid du Colombier 	gp = globuf;
11173e12c5d1SDavid du Colombier 	while((c=getchr()) != '\n') {
11183e12c5d1SDavid du Colombier 		if(c == EOF)
11193e12c5d1SDavid du Colombier 			error(Q);
11203e12c5d1SDavid du Colombier 		if(c == '\\') {
11213e12c5d1SDavid du Colombier 			c = getchr();
11223e12c5d1SDavid du Colombier 			if(c != '\n')
11233e12c5d1SDavid du Colombier 				*gp++ = '\\';
11243e12c5d1SDavid du Colombier 		}
11253e12c5d1SDavid du Colombier 		*gp++ = c;
11263e12c5d1SDavid du Colombier 		if(gp >= &globuf[GBSIZE-2])
11273e12c5d1SDavid du Colombier 			error(Q);
11283e12c5d1SDavid du Colombier 	}
11293e12c5d1SDavid du Colombier 	if(gp == globuf)
11303e12c5d1SDavid du Colombier 		*gp++ = 'p';
11313e12c5d1SDavid du Colombier 	*gp++ = '\n';
11323e12c5d1SDavid du Colombier 	*gp = 0;
11333e12c5d1SDavid du Colombier 	for(a1=zero; a1<=dol; a1++) {
11343e12c5d1SDavid du Colombier 		*a1 &= ~01;
11353e12c5d1SDavid du Colombier 		if(a1 >= addr1 && a1 <= addr2 && match(a1) == k)
11363e12c5d1SDavid du Colombier 			*a1 |= 01;
11373e12c5d1SDavid du Colombier 	}
11383e12c5d1SDavid du Colombier 
11393e12c5d1SDavid du Colombier 	/*
11403e12c5d1SDavid du Colombier 	 * Special case: g/.../d (avoid n^2 algorithm)
11413e12c5d1SDavid du Colombier 	 */
11423e12c5d1SDavid du Colombier 	if(globuf[0] == 'd' && globuf[1] == '\n' && globuf[2] == 0) {
11433e12c5d1SDavid du Colombier 		gdelete();
11443e12c5d1SDavid du Colombier 		return;
11453e12c5d1SDavid du Colombier 	}
11463e12c5d1SDavid du Colombier 	for(a1=zero; a1<=dol; a1++) {
11473e12c5d1SDavid du Colombier 		if(*a1 & 01) {
11483e12c5d1SDavid du Colombier 			*a1 &= ~01;
11493e12c5d1SDavid du Colombier 			dot = a1;
11503e12c5d1SDavid du Colombier 			globp = globuf;
11513e12c5d1SDavid du Colombier 			commands();
11523e12c5d1SDavid du Colombier 			a1 = zero;
11533e12c5d1SDavid du Colombier 		}
11543e12c5d1SDavid du Colombier 	}
11553e12c5d1SDavid du Colombier }
11563e12c5d1SDavid du Colombier 
11573e12c5d1SDavid du Colombier void
11583e12c5d1SDavid du Colombier join(void)
11593e12c5d1SDavid du Colombier {
11603e12c5d1SDavid du Colombier 	Rune *gp, *lp;
11613e12c5d1SDavid du Colombier 	int *a1;
11623e12c5d1SDavid du Colombier 
11633e12c5d1SDavid du Colombier 	nonzero();
11643e12c5d1SDavid du Colombier 	gp = genbuf;
11653e12c5d1SDavid du Colombier 	for(a1=addr1; a1<=addr2; a1++) {
11663e12c5d1SDavid du Colombier 		lp = getline(*a1);
11673e12c5d1SDavid du Colombier 		while(*gp = *lp++)
11683e12c5d1SDavid du Colombier 			if(gp++ >= &genbuf[LBSIZE-2])
11693e12c5d1SDavid du Colombier 				error(Q);
11703e12c5d1SDavid du Colombier 	}
11713e12c5d1SDavid du Colombier 	lp = linebuf;
11723e12c5d1SDavid du Colombier 	gp = genbuf;
11733e12c5d1SDavid du Colombier 	while(*lp++ = *gp++)
11743e12c5d1SDavid du Colombier 		;
11753e12c5d1SDavid du Colombier 	*addr1 = putline();
11763e12c5d1SDavid du Colombier 	if(addr1 < addr2)
11773e12c5d1SDavid du Colombier 		rdelete(addr1+1, addr2);
11783e12c5d1SDavid du Colombier 	dot = addr1;
11793e12c5d1SDavid du Colombier }
11803e12c5d1SDavid du Colombier 
11813e12c5d1SDavid du Colombier void
11823e12c5d1SDavid du Colombier substitute(int inglob)
11833e12c5d1SDavid du Colombier {
11843e12c5d1SDavid du Colombier 	int *mp, *a1, nl, gsubf, n;
11853e12c5d1SDavid du Colombier 
11863e12c5d1SDavid du Colombier 	n = getnum();	/* OK even if n==0 */
11873e12c5d1SDavid du Colombier 	gsubf = compsub();
11883e12c5d1SDavid du Colombier 	for(a1 = addr1; a1 <= addr2; a1++) {
11893e12c5d1SDavid du Colombier 		if(match(a1)){
11903e12c5d1SDavid du Colombier 			int *ozero;
11913e12c5d1SDavid du Colombier 			int m = n;
11923e12c5d1SDavid du Colombier 
11933e12c5d1SDavid du Colombier 			do {
11943e12c5d1SDavid du Colombier 				int span = loc2-loc1;
11953e12c5d1SDavid du Colombier 
11963e12c5d1SDavid du Colombier 				if(--m <= 0) {
11973e12c5d1SDavid du Colombier 					dosub();
11983e12c5d1SDavid du Colombier 					if(!gsubf)
11993e12c5d1SDavid du Colombier 						break;
12003e12c5d1SDavid du Colombier 					if(span == 0) {	/* null RE match */
12013e12c5d1SDavid du Colombier 						if(*loc2 == 0)
12023e12c5d1SDavid du Colombier 							break;
12033e12c5d1SDavid du Colombier 						loc2++;
12043e12c5d1SDavid du Colombier 					}
12053e12c5d1SDavid du Colombier 				}
12063e12c5d1SDavid du Colombier 			} while(match(0));
12073e12c5d1SDavid du Colombier 			if(m <= 0) {
12083e12c5d1SDavid du Colombier 				inglob |= 01;
12093e12c5d1SDavid du Colombier 				subnewa = putline();
12103e12c5d1SDavid du Colombier 				*a1 &= ~01;
12113e12c5d1SDavid du Colombier 				if(anymarks) {
12123e12c5d1SDavid du Colombier 					for(mp=names; mp<&names[26]; mp++)
12133e12c5d1SDavid du Colombier 						if(*mp == *a1)
12143e12c5d1SDavid du Colombier 							*mp = subnewa;
12153e12c5d1SDavid du Colombier 				}
12163e12c5d1SDavid du Colombier 				subolda = *a1;
12173e12c5d1SDavid du Colombier 				*a1 = subnewa;
12183e12c5d1SDavid du Colombier 				ozero = zero;
12193e12c5d1SDavid du Colombier 				nl = append(getsub, a1);
12203e12c5d1SDavid du Colombier 				addr2 += nl;
12213e12c5d1SDavid du Colombier 				nl += zero-ozero;
12223e12c5d1SDavid du Colombier 				a1 += nl;
12233e12c5d1SDavid du Colombier 			}
12243e12c5d1SDavid du Colombier 		}
12253e12c5d1SDavid du Colombier 	}
12263e12c5d1SDavid du Colombier 	if(inglob == 0)
12273e12c5d1SDavid du Colombier 		error(Q);
12283e12c5d1SDavid du Colombier }
12293e12c5d1SDavid du Colombier 
12303e12c5d1SDavid du Colombier int
12313e12c5d1SDavid du Colombier compsub(void)
12323e12c5d1SDavid du Colombier {
12333e12c5d1SDavid du Colombier 	int seof, c;
12343e12c5d1SDavid du Colombier 	Rune *p;
12353e12c5d1SDavid du Colombier 
12363e12c5d1SDavid du Colombier 	seof = getchr();
12373e12c5d1SDavid du Colombier 	if(seof == '\n' || seof == ' ')
12383e12c5d1SDavid du Colombier 		error(Q);
12393e12c5d1SDavid du Colombier 	compile(seof);
12403e12c5d1SDavid du Colombier 	p = rhsbuf;
12413e12c5d1SDavid du Colombier 	for(;;) {
12423e12c5d1SDavid du Colombier 		c = getchr();
12433e12c5d1SDavid du Colombier 		if(c == '\\') {
12443e12c5d1SDavid du Colombier 			c = getchr();
12453e12c5d1SDavid du Colombier 			*p++ = ESCFLG;
12463e12c5d1SDavid du Colombier 			if(p >= &rhsbuf[LBSIZE/2])
12473e12c5d1SDavid du Colombier 				error(Q);
12483e12c5d1SDavid du Colombier 		} else
12493e12c5d1SDavid du Colombier 		if(c == '\n' && (!globp || !globp[0])) {
12503e12c5d1SDavid du Colombier 			peekc = c;
12513e12c5d1SDavid du Colombier 			pflag++;
12523e12c5d1SDavid du Colombier 			break;
12533e12c5d1SDavid du Colombier 		} else
12543e12c5d1SDavid du Colombier 		if(c == seof)
12553e12c5d1SDavid du Colombier 			break;
12563e12c5d1SDavid du Colombier 		*p++ = c;
12573e12c5d1SDavid du Colombier 		if(p >= &rhsbuf[LBSIZE/2])
12583e12c5d1SDavid du Colombier 			error(Q);
12593e12c5d1SDavid du Colombier 	}
12603e12c5d1SDavid du Colombier 	*p = 0;
12613e12c5d1SDavid du Colombier 	peekc = getchr();
12623e12c5d1SDavid du Colombier 	if(peekc == 'g') {
12633e12c5d1SDavid du Colombier 		peekc = 0;
12643e12c5d1SDavid du Colombier 		newline();
12653e12c5d1SDavid du Colombier 		return 1;
12663e12c5d1SDavid du Colombier 	}
12673e12c5d1SDavid du Colombier 	newline();
12683e12c5d1SDavid du Colombier 	return 0;
12693e12c5d1SDavid du Colombier }
12703e12c5d1SDavid du Colombier 
12713e12c5d1SDavid du Colombier int
12723e12c5d1SDavid du Colombier getsub(void)
12733e12c5d1SDavid du Colombier {
12743e12c5d1SDavid du Colombier 	Rune *p1, *p2;
12753e12c5d1SDavid du Colombier 
12763e12c5d1SDavid du Colombier 	p1 = linebuf;
12773e12c5d1SDavid du Colombier 	if((p2 = linebp) == 0)
12783e12c5d1SDavid du Colombier 		return EOF;
12793e12c5d1SDavid du Colombier 	while(*p1++ = *p2++)
12803e12c5d1SDavid du Colombier 		;
12813e12c5d1SDavid du Colombier 	linebp = 0;
12823e12c5d1SDavid du Colombier 	return 0;
12833e12c5d1SDavid du Colombier }
12843e12c5d1SDavid du Colombier 
12853e12c5d1SDavid du Colombier void
12863e12c5d1SDavid du Colombier dosub(void)
12873e12c5d1SDavid du Colombier {
12883e12c5d1SDavid du Colombier 	Rune *lp, *sp, *rp;
12893e12c5d1SDavid du Colombier 	int c, n;
12903e12c5d1SDavid du Colombier 
12913e12c5d1SDavid du Colombier 	lp = linebuf;
12923e12c5d1SDavid du Colombier 	sp = genbuf;
12933e12c5d1SDavid du Colombier 	rp = rhsbuf;
12943e12c5d1SDavid du Colombier 	while(lp < loc1)
12953e12c5d1SDavid du Colombier 		*sp++ = *lp++;
12963e12c5d1SDavid du Colombier 	while(c = *rp++) {
12973e12c5d1SDavid du Colombier 		if(c == '&'){
12983e12c5d1SDavid du Colombier 			sp = place(sp, loc1, loc2);
12993e12c5d1SDavid du Colombier 			continue;
13003e12c5d1SDavid du Colombier 		}
13013e12c5d1SDavid du Colombier 		if(c == ESCFLG && (c = *rp++) >= '1' && c < MAXSUB+'0') {
13023e12c5d1SDavid du Colombier 			n = c-'0';
13033e12c5d1SDavid du Colombier 			if(subexp[n].rsp && subexp[n].rep) {
13043e12c5d1SDavid du Colombier 				sp = place(sp, subexp[n].rsp, subexp[n].rep);
13053e12c5d1SDavid du Colombier 				continue;
13063e12c5d1SDavid du Colombier 			}
13073e12c5d1SDavid du Colombier 			error(Q);
13083e12c5d1SDavid du Colombier 		}
13093e12c5d1SDavid du Colombier 		*sp++ = c;
13103e12c5d1SDavid du Colombier 		if(sp >= &genbuf[LBSIZE])
13113e12c5d1SDavid du Colombier 			error(Q);
13123e12c5d1SDavid du Colombier 	}
13133e12c5d1SDavid du Colombier 	lp = loc2;
13143e12c5d1SDavid du Colombier 	loc2 = sp - genbuf + linebuf;
13153e12c5d1SDavid du Colombier 	while(*sp++ = *lp++)
13163e12c5d1SDavid du Colombier 		if(sp >= &genbuf[LBSIZE])
13173e12c5d1SDavid du Colombier 			error(Q);
13183e12c5d1SDavid du Colombier 	lp = linebuf;
13193e12c5d1SDavid du Colombier 	sp = genbuf;
13203e12c5d1SDavid du Colombier 	while(*lp++ = *sp++)
13213e12c5d1SDavid du Colombier 		;
13223e12c5d1SDavid du Colombier }
13233e12c5d1SDavid du Colombier 
13243e12c5d1SDavid du Colombier Rune*
13253e12c5d1SDavid du Colombier place(Rune *sp, Rune *l1, Rune *l2)
13263e12c5d1SDavid du Colombier {
13273e12c5d1SDavid du Colombier 
13283e12c5d1SDavid du Colombier 	while(l1 < l2) {
13293e12c5d1SDavid du Colombier 		*sp++ = *l1++;
13303e12c5d1SDavid du Colombier 		if(sp >= &genbuf[LBSIZE])
13313e12c5d1SDavid du Colombier 			error(Q);
13323e12c5d1SDavid du Colombier 	}
13333e12c5d1SDavid du Colombier 	return sp;
13343e12c5d1SDavid du Colombier }
13353e12c5d1SDavid du Colombier 
13363e12c5d1SDavid du Colombier void
13373e12c5d1SDavid du Colombier move(int cflag)
13383e12c5d1SDavid du Colombier {
13393e12c5d1SDavid du Colombier 	int *adt, *ad1, *ad2;
13403e12c5d1SDavid du Colombier 
13413e12c5d1SDavid du Colombier 	nonzero();
13423e12c5d1SDavid du Colombier 	if((adt = address())==0)	/* address() guarantees addr is in range */
13433e12c5d1SDavid du Colombier 		error(Q);
13443e12c5d1SDavid du Colombier 	newline();
13453e12c5d1SDavid du Colombier 	if(cflag) {
13463e12c5d1SDavid du Colombier 		int *ozero, delta;
13473e12c5d1SDavid du Colombier 		ad1 = dol;
13483e12c5d1SDavid du Colombier 		ozero = zero;
13493e12c5d1SDavid du Colombier 		append(getcopy, ad1++);
13503e12c5d1SDavid du Colombier 		ad2 = dol;
13513e12c5d1SDavid du Colombier 		delta = zero - ozero;
13523e12c5d1SDavid du Colombier 		ad1 += delta;
13533e12c5d1SDavid du Colombier 		adt += delta;
13543e12c5d1SDavid du Colombier 	} else {
13553e12c5d1SDavid du Colombier 		ad2 = addr2;
13563e12c5d1SDavid du Colombier 		for(ad1 = addr1; ad1 <= ad2;)
13573e12c5d1SDavid du Colombier 			*ad1++ &= ~01;
13583e12c5d1SDavid du Colombier 		ad1 = addr1;
13593e12c5d1SDavid du Colombier 	}
13603e12c5d1SDavid du Colombier 	ad2++;
13613e12c5d1SDavid du Colombier 	if(adt<ad1) {
13623e12c5d1SDavid du Colombier 		dot = adt + (ad2-ad1);
13633e12c5d1SDavid du Colombier 		if((++adt)==ad1)
13643e12c5d1SDavid du Colombier 			return;
13653e12c5d1SDavid du Colombier 		reverse(adt, ad1);
13663e12c5d1SDavid du Colombier 		reverse(ad1, ad2);
13673e12c5d1SDavid du Colombier 		reverse(adt, ad2);
13683e12c5d1SDavid du Colombier 	} else
13693e12c5d1SDavid du Colombier 	if(adt >= ad2) {
13703e12c5d1SDavid du Colombier 		dot = adt++;
13713e12c5d1SDavid du Colombier 		reverse(ad1, ad2);
13723e12c5d1SDavid du Colombier 		reverse(ad2, adt);
13733e12c5d1SDavid du Colombier 		reverse(ad1, adt);
13743e12c5d1SDavid du Colombier 	} else
13753e12c5d1SDavid du Colombier 		error(Q);
13763e12c5d1SDavid du Colombier 	fchange = 1;
13773e12c5d1SDavid du Colombier }
13783e12c5d1SDavid du Colombier 
13793e12c5d1SDavid du Colombier void
13803e12c5d1SDavid du Colombier reverse(int *a1, int *a2)
13813e12c5d1SDavid du Colombier {
13823e12c5d1SDavid du Colombier 	int t;
13833e12c5d1SDavid du Colombier 
13843e12c5d1SDavid du Colombier 	for(;;) {
13853e12c5d1SDavid du Colombier 		t = *--a2;
13863e12c5d1SDavid du Colombier 		if(a2 <= a1)
13873e12c5d1SDavid du Colombier 			return;
13883e12c5d1SDavid du Colombier 		*a2 = *a1;
13893e12c5d1SDavid du Colombier 		*a1++ = t;
13903e12c5d1SDavid du Colombier 	}
13913e12c5d1SDavid du Colombier }
13923e12c5d1SDavid du Colombier 
13933e12c5d1SDavid du Colombier int
13943e12c5d1SDavid du Colombier getcopy(void)
13953e12c5d1SDavid du Colombier {
13963e12c5d1SDavid du Colombier 	if(addr1 > addr2)
13973e12c5d1SDavid du Colombier 		return EOF;
13983e12c5d1SDavid du Colombier 	getline(*addr1++);
13993e12c5d1SDavid du Colombier 	return 0;
14003e12c5d1SDavid du Colombier }
14013e12c5d1SDavid du Colombier 
14023e12c5d1SDavid du Colombier void
14033e12c5d1SDavid du Colombier compile(int eof)
14043e12c5d1SDavid du Colombier {
14053e12c5d1SDavid du Colombier 	Rune c;
14063e12c5d1SDavid du Colombier 	char *ep;
14073e12c5d1SDavid du Colombier 	char expbuf[ESIZE];
14083e12c5d1SDavid du Colombier 
14093e12c5d1SDavid du Colombier 	if((c = getchr()) == '\n') {
14103e12c5d1SDavid du Colombier 		peekc = c;
14113e12c5d1SDavid du Colombier 		c = eof;
14123e12c5d1SDavid du Colombier 	}
14133e12c5d1SDavid du Colombier 	if(c == eof) {
14143e12c5d1SDavid du Colombier 		if(!pattern)
14153e12c5d1SDavid du Colombier 			error(Q);
14163e12c5d1SDavid du Colombier 		return;
14173e12c5d1SDavid du Colombier 	}
14183e12c5d1SDavid du Colombier 	if(pattern) {
14193e12c5d1SDavid du Colombier 		free(pattern);
14203e12c5d1SDavid du Colombier 		pattern = 0;
14213e12c5d1SDavid du Colombier 	}
14223e12c5d1SDavid du Colombier 	ep = expbuf;
14233e12c5d1SDavid du Colombier 	do {
14243e12c5d1SDavid du Colombier 		if(c == '\\') {
14253e12c5d1SDavid du Colombier 			if(ep >= expbuf+sizeof(expbuf)) {
14263e12c5d1SDavid du Colombier 				error(Q);
14273e12c5d1SDavid du Colombier 				return;
14283e12c5d1SDavid du Colombier 			}
14293e12c5d1SDavid du Colombier 			ep += runetochar(ep, &c);
14303e12c5d1SDavid du Colombier 			if((c = getchr()) == '\n') {
14313e12c5d1SDavid du Colombier 				error(Q);
14323e12c5d1SDavid du Colombier 				return;
14333e12c5d1SDavid du Colombier 			}
14343e12c5d1SDavid du Colombier 		}
14353e12c5d1SDavid du Colombier 		if(ep >= expbuf+sizeof(expbuf)) {
14363e12c5d1SDavid du Colombier 			error(Q);
14373e12c5d1SDavid du Colombier 			return;
14383e12c5d1SDavid du Colombier 		}
14393e12c5d1SDavid du Colombier 		ep += runetochar(ep, &c);
14403e12c5d1SDavid du Colombier 	} while((c = getchr()) != eof && c != '\n');
14413e12c5d1SDavid du Colombier 	if(c == '\n')
14423e12c5d1SDavid du Colombier 		peekc = c;
14433e12c5d1SDavid du Colombier 	*ep = 0;
14443e12c5d1SDavid du Colombier 	pattern = regcomp(expbuf);
14453e12c5d1SDavid du Colombier }
14463e12c5d1SDavid du Colombier 
14473e12c5d1SDavid du Colombier int
14483e12c5d1SDavid du Colombier match(int *addr)
14493e12c5d1SDavid du Colombier {
14503e12c5d1SDavid du Colombier 	if(!pattern)
14513e12c5d1SDavid du Colombier 		return 0;
14523e12c5d1SDavid du Colombier 	if(addr){
14533e12c5d1SDavid du Colombier 		if(addr == zero)
14543e12c5d1SDavid du Colombier 			return 0;
14553e12c5d1SDavid du Colombier 		subexp[0].rsp = getline(*addr);
14563e12c5d1SDavid du Colombier 	} else
14573e12c5d1SDavid du Colombier 		subexp[0].rsp = loc2;
14583e12c5d1SDavid du Colombier 	subexp[0].rep = 0;
14593e12c5d1SDavid du Colombier 	if(rregexec(pattern, linebuf, subexp, MAXSUB)) {
14603e12c5d1SDavid du Colombier 		loc1 = subexp[0].rsp;
14613e12c5d1SDavid du Colombier 		loc2 = subexp[0].rep;
14623e12c5d1SDavid du Colombier 		return 1;
14633e12c5d1SDavid du Colombier 	}
14643e12c5d1SDavid du Colombier 	loc1 = loc2 = 0;
14653e12c5d1SDavid du Colombier 	return 0;
14663e12c5d1SDavid du Colombier 
14673e12c5d1SDavid du Colombier }
14683e12c5d1SDavid du Colombier 
14693e12c5d1SDavid du Colombier void
14703e12c5d1SDavid du Colombier putd(void)
14713e12c5d1SDavid du Colombier {
14723e12c5d1SDavid du Colombier 	int r;
14733e12c5d1SDavid du Colombier 
14743e12c5d1SDavid du Colombier 	r = count%10;
14753e12c5d1SDavid du Colombier 	count /= 10;
14763e12c5d1SDavid du Colombier 	if(count)
14773e12c5d1SDavid du Colombier 		putd();
14783e12c5d1SDavid du Colombier 	putchr(r + L'0');
14793e12c5d1SDavid du Colombier }
14803e12c5d1SDavid du Colombier 
14813e12c5d1SDavid du Colombier void
14823e12c5d1SDavid du Colombier putst(char *sp)
14833e12c5d1SDavid du Colombier {
14843e12c5d1SDavid du Colombier 	Rune r;
14853e12c5d1SDavid du Colombier 
14863e12c5d1SDavid du Colombier 	col = 0;
14873e12c5d1SDavid du Colombier 	for(;;) {
14883e12c5d1SDavid du Colombier 		sp += chartorune(&r, sp);
14893e12c5d1SDavid du Colombier 		if(r == 0)
14903e12c5d1SDavid du Colombier 			break;
14913e12c5d1SDavid du Colombier 		putchr(r);
14923e12c5d1SDavid du Colombier 	}
14933e12c5d1SDavid du Colombier 	putchr(L'\n');
14943e12c5d1SDavid du Colombier }
14953e12c5d1SDavid du Colombier 
14963e12c5d1SDavid du Colombier void
14973e12c5d1SDavid du Colombier putshst(Rune *sp)
14983e12c5d1SDavid du Colombier {
14993e12c5d1SDavid du Colombier 	col = 0;
15003e12c5d1SDavid du Colombier 	while(*sp)
15013e12c5d1SDavid du Colombier 		putchr(*sp++);
15023e12c5d1SDavid du Colombier 	putchr(L'\n');
15033e12c5d1SDavid du Colombier }
15043e12c5d1SDavid du Colombier 
15053e12c5d1SDavid du Colombier void
15063e12c5d1SDavid du Colombier putchr(int ac)
15073e12c5d1SDavid du Colombier {
15083e12c5d1SDavid du Colombier 	char *lp;
15093e12c5d1SDavid du Colombier 	int c;
15103e12c5d1SDavid du Colombier 	Rune rune;
15113e12c5d1SDavid du Colombier 
15123e12c5d1SDavid du Colombier 	lp = linp;
15133e12c5d1SDavid du Colombier 	c = ac;
15143e12c5d1SDavid du Colombier 	if(listf) {
15153e12c5d1SDavid du Colombier 		if(c == '\n') {
15163e12c5d1SDavid du Colombier 			if(linp != line && linp[-1] == ' ') {
15173e12c5d1SDavid du Colombier 				*lp++ = '\\';
15183e12c5d1SDavid du Colombier 				*lp++ = 'n';
15193e12c5d1SDavid du Colombier 			}
15203e12c5d1SDavid du Colombier 		} else {
15213e12c5d1SDavid du Colombier 			if(col > (72-6-2)) {
15223e12c5d1SDavid du Colombier 				col = 8;
15233e12c5d1SDavid du Colombier 				*lp++ = '\\';
15243e12c5d1SDavid du Colombier 				*lp++ = '\n';
15253e12c5d1SDavid du Colombier 				*lp++ = '\t';
15263e12c5d1SDavid du Colombier 			}
15273e12c5d1SDavid du Colombier 			col++;
15283e12c5d1SDavid du Colombier 			if(c=='\b' || c=='\t' || c=='\\') {
15293e12c5d1SDavid du Colombier 				*lp++ = '\\';
15303e12c5d1SDavid du Colombier 				if(c == '\b')
15313e12c5d1SDavid du Colombier 					c = 'b';
15323e12c5d1SDavid du Colombier 				else
15333e12c5d1SDavid du Colombier 				if(c == '\t')
15343e12c5d1SDavid du Colombier 					c = 't';
15353e12c5d1SDavid du Colombier 				col++;
15363e12c5d1SDavid du Colombier 			} else
15373e12c5d1SDavid du Colombier 			if(c<' ' || c>='\177') {
15383e12c5d1SDavid du Colombier 				*lp++ = '\\';
15393e12c5d1SDavid du Colombier 				*lp++ = 'x';
15403e12c5d1SDavid du Colombier 				*lp++ =  hex[c>>12];
15413e12c5d1SDavid du Colombier 				*lp++ =  hex[c>>8&0xF];
15423e12c5d1SDavid du Colombier 				*lp++ =  hex[c>>4&0xF];
15433e12c5d1SDavid du Colombier 				c     =  hex[c&0xF];
15443e12c5d1SDavid du Colombier 				col += 5;
15453e12c5d1SDavid du Colombier 			}
15463e12c5d1SDavid du Colombier 		}
15473e12c5d1SDavid du Colombier 	}
15483e12c5d1SDavid du Colombier 
15493e12c5d1SDavid du Colombier 	rune = c;
15503e12c5d1SDavid du Colombier 	lp += runetochar(lp, &rune);
15513e12c5d1SDavid du Colombier 
15523e12c5d1SDavid du Colombier 	if(c == '\n' || lp >= &line[sizeof(line)-5]) {
15533e12c5d1SDavid du Colombier 		linp = line;
15543e12c5d1SDavid du Colombier 		write(oflag? 2: 1, line, lp-line);
15553e12c5d1SDavid du Colombier 		return;
15563e12c5d1SDavid du Colombier 	}
15573e12c5d1SDavid du Colombier 	linp = lp;
15583e12c5d1SDavid du Colombier }
15593e12c5d1SDavid du Colombier 
15603e12c5d1SDavid du Colombier char*
15613e12c5d1SDavid du Colombier mktemp(char *as)
15623e12c5d1SDavid du Colombier {
15633e12c5d1SDavid du Colombier 	char *s;
15643e12c5d1SDavid du Colombier 	unsigned pid;
15653e12c5d1SDavid du Colombier 	int i;
15663e12c5d1SDavid du Colombier 
15673e12c5d1SDavid du Colombier 	pid = getpid();
15683e12c5d1SDavid du Colombier 	s = as;
15693e12c5d1SDavid du Colombier 	while(*s++)
15703e12c5d1SDavid du Colombier 		;
15713e12c5d1SDavid du Colombier 	s--;
15723e12c5d1SDavid du Colombier 	while(*--s == 'X') {
15733e12c5d1SDavid du Colombier 		*s = pid % 10 + '0';
15743e12c5d1SDavid du Colombier 		pid /= 10;
15753e12c5d1SDavid du Colombier 	}
15763e12c5d1SDavid du Colombier 	s++;
15773e12c5d1SDavid du Colombier 	i = 'a';
15783e12c5d1SDavid du Colombier 	while(access(as, 0) != -1) {
15793e12c5d1SDavid du Colombier 		if(i == 'z')
15803e12c5d1SDavid du Colombier 			return "/";
15813e12c5d1SDavid du Colombier 		*s = i++;
15823e12c5d1SDavid du Colombier 	}
15833e12c5d1SDavid du Colombier 	return as;
15843e12c5d1SDavid du Colombier }
15853e12c5d1SDavid du Colombier 
15863e12c5d1SDavid du Colombier void
15873e12c5d1SDavid du Colombier regerror(char *s)
15883e12c5d1SDavid du Colombier {
15893e12c5d1SDavid du Colombier 	USED(s);
15903e12c5d1SDavid du Colombier 	error(Q);
15913e12c5d1SDavid du Colombier }
1592