xref: /csrg-svn/old/roff/common_source/n3.c (revision 31687)
17067Srrh #ifndef lint
2*31687Sbostic static char sccsid[] = "@(#)n3.c	4.4 06/25/87";
37067Srrh #endif lint
47067Srrh 
57067Srrh #include "tdef.h"
67067Srrh extern
77067Srrh #include "d.h"
87067Srrh extern
97067Srrh #include "v.h"
107067Srrh #ifdef NROFF
117067Srrh extern
127067Srrh #include "tw.h"
137067Srrh #endif
147067Srrh #include "sdef.h"
157067Srrh 
167067Srrh /*
177067Srrh troff3.c
187067Srrh 
197067Srrh macro and string routines, storage allocation
207067Srrh */
217067Srrh 
227067Srrh unsigned blist[NBLIST];
237067Srrh extern struct s *frame, *stk, *nxf;
247067Srrh extern filep ip;
257067Srrh extern filep offset;
267067Srrh extern filep nextb;
277067Srrh extern char *enda;
287067Srrh 
297067Srrh extern int ch;
307067Srrh extern int ibf;
317067Srrh extern int lgf;
327067Srrh extern int copyf;
337067Srrh extern int ch0;
347067Srrh extern int app;
357067Srrh extern int ds;
367067Srrh extern int nlflg;
377067Srrh extern int *argtop;
387067Srrh extern int *ap;
397067Srrh extern int nchar;
407067Srrh extern int pendt;
417067Srrh extern int rchar;
427067Srrh extern int dilev;
437067Srrh extern int nonumb;
447067Srrh extern int lt;
457067Srrh extern int nrbits;
467067Srrh extern int nform;
477067Srrh extern int fmt[];
487067Srrh extern int oldmn;
497067Srrh extern int newmn;
507067Srrh extern int macerr;
517067Srrh extern filep apptr;
527067Srrh extern int diflg;
537067Srrh extern filep woff;
547067Srrh extern filep roff;
557067Srrh extern int wbfi;
567067Srrh extern int po;
577067Srrh extern int *cp;
587067Srrh extern int xxx;
597067Srrh int pagech = '%';
607067Srrh int strflg;
617067Srrh extern struct contab {
627067Srrh 	int rq;
637067Srrh 	union {
647067Srrh 		int (*f)();
657067Srrh 		unsigned mx;
667067Srrh 	}x;
677067Srrh }contab[NM];
687067Srrh #ifndef VMUNIX
697067Srrh int wbuf[BLK];
707067Srrh int rbuf[BLK];
717067Srrh #else
727067Srrh int *wbuf;
737067Srrh int *rbuf;
747067Srrh int Buf[NBLIST*BLK + NEV*EVS];
757067Srrh #endif
767067Srrh 
777067Srrh caseig(){
787067Srrh 	register i;
797067Srrh 
807067Srrh 	offset = 0;
817067Srrh 	if((i = copyb()) != '.')control(i,1);
827067Srrh }
837067Srrh casern(){
847067Srrh 	register i,j;
857067Srrh 
867067Srrh 	lgf++;
877067Srrh 	skip();
887067Srrh 	if(((i=getrq())==0) || ((oldmn=findmn(i)) < 0))return;
897067Srrh 	skip();
907067Srrh 	clrmn(findmn(j=getrq()));
917067Srrh 	if(j)contab[oldmn].rq = (contab[oldmn].rq & MMASK) | j;
927067Srrh }
937067Srrh caserm(){
947067Srrh 	lgf++;
957067Srrh 	while(!skip()){
967067Srrh 		clrmn(findmn(getrq()));
977067Srrh 	}
987067Srrh }
997067Srrh caseas(){
1007067Srrh 	app++;
1017067Srrh 	caseds();
1027067Srrh }
1037067Srrh caseds(){
1047067Srrh 	ds++;
1057067Srrh 	casede();
1067067Srrh }
1077067Srrh caseam(){
1087067Srrh 	app++;
1097067Srrh 	casede();
1107067Srrh }
1117067Srrh casede(){
1127067Srrh 	register i, req;
1137067Srrh 	register filep savoff;
1147067Srrh 	extern filep finds();
1157067Srrh 
1167067Srrh 	if(dip != d)wbfl();
1177067Srrh 	req = '.';
1187067Srrh 	lgf++;
1197067Srrh 	skip();
1207067Srrh 	if((i=getrq())==0)goto de1;
1217067Srrh 	if((offset=finds(i)) == 0)goto de1;
1227067Srrh 	if(ds)copys();
1237067Srrh 		else req = copyb();
1247067Srrh 	wbfl();
1257067Srrh 	clrmn(oldmn);
1267067Srrh 	if(newmn)contab[newmn].rq = i | MMASK;
1277067Srrh 	if(apptr){
1287067Srrh 		savoff = offset;
1297067Srrh 		offset = apptr;
1307067Srrh 		wbt(IMP);
1317067Srrh 		offset = savoff;
1327067Srrh 	}
1337067Srrh 	offset = dip->op;
1347067Srrh 	if(req != '.')control(req,1);
1357067Srrh de1:
1367067Srrh 	ds = app = 0;
1377067Srrh 	return;
1387067Srrh }
1397067Srrh findmn(i)
1407067Srrh int i;
1417067Srrh {
1427067Srrh 	register j;
1437067Srrh 
1447067Srrh 	for(j=0;j<NM;j++){
1457067Srrh 		if(i == (contab[j].rq & ~MMASK))break;
1467067Srrh 	}
1477067Srrh 	if(j==NM)j = -1;
1487067Srrh 	return(j);
1497067Srrh }
1507067Srrh clrmn(i)
1517067Srrh int i;
1527067Srrh {
1537067Srrh 	extern filep boff();
1547067Srrh 	if(i >= 0){
1557067Srrh 		if(contab[i].rq & MMASK)ffree(((filep)contab[i].x.mx)<<BLKBITS);
1567067Srrh 		contab[i].rq = 0;
1577067Srrh 		contab[i].x.mx = 0;
1587067Srrh 	}
1597067Srrh }
1607067Srrh filep finds(mn)
1617067Srrh int mn;
1627067Srrh {
1637067Srrh 	register i;
1647067Srrh 	extern filep boff();
1657067Srrh 	register filep savip;
1667067Srrh 	extern filep alloc();
1677067Srrh 	extern filep incoff();
1687067Srrh 
1697067Srrh 	oldmn = findmn(mn);
1707067Srrh 	newmn = 0;
1717067Srrh 	apptr = (filep)0;
1727067Srrh 	if(app && (oldmn >= 0) && (contab[oldmn].rq & MMASK)){
1737067Srrh 			savip = ip;
1747067Srrh 			ip = (((filep)contab[oldmn].x.mx)<<BLKBITS);
1757067Srrh 			oldmn = -1;
1767067Srrh 			while((i=rbf()) != 0);
1777067Srrh 			apptr = ip;
1787067Srrh 			if(!diflg)ip = incoff(ip);
1797067Srrh 			nextb = ip;
1807067Srrh 			ip = savip;
1817067Srrh 	}else{
1827067Srrh 		for(i=0;i<NM;i++){
1837067Srrh 			if(contab[i].rq == 0)break;
1847067Srrh 		}
1857067Srrh 		if((i==NM) ||
1867067Srrh 		   (nextb = alloc()) == 0){
1877067Srrh 			app = 0;
1887067Srrh 			if(macerr++ > 1)done2(02);
1897067Srrh 			prstr("Too many string/macro names.\n");
1907067Srrh 			edone(04);
1917067Srrh 			return(offset = 0);
1927067Srrh 		}
1937067Srrh 			contab[i].x.mx = (unsigned)(nextb>>BLKBITS);
1947067Srrh 		if(!diflg){
1957067Srrh 			newmn = i;
1967067Srrh 			if(oldmn == -1)contab[i].rq = -1;
1977067Srrh 		}else{
1987067Srrh 			contab[i].rq = mn | MMASK;
1997067Srrh 		}
2007067Srrh 	}
2017067Srrh 
2027067Srrh 	app = 0;
2037067Srrh 	return(offset = nextb);
2047067Srrh }
2057067Srrh skip(){
2067067Srrh 	register i;
2077067Srrh 
2087067Srrh 	while(((i=getch()) & CMASK) == ' ');
2097067Srrh 	ch=i;
2107067Srrh 	return(nlflg);
2117067Srrh }
2127067Srrh copyb()
2137067Srrh {
2147067Srrh 	register i, j, k;
2157067Srrh 	int ii, req, state;
2167067Srrh 	filep savoff;
2177067Srrh 
2187067Srrh 	if(skip() || !(j=getrq()))j = '.';
2197067Srrh 	req = j;
2207067Srrh 	k = j>>BYTE;
2217067Srrh 	j &= BMASK;
2227067Srrh 	copyf++;
2237067Srrh 	flushi();
2247067Srrh 	nlflg = 0;
2257067Srrh 	state = 1;
2267067Srrh 	while(1){
2277067Srrh 		i = (ii = getch()) & CMASK;
2287067Srrh 		if(state == 3){
2297067Srrh 			if(i == k)break;
2307067Srrh 			if(!k){
2317067Srrh 				ch = ii;
2327067Srrh 				i = getach();
2337067Srrh 				ch = ii;
2347067Srrh 				if(!i)break;
2357067Srrh 			}
2367067Srrh 			state = 0;
2377067Srrh 			goto c0;
2387067Srrh 		}
2397067Srrh 		if(i == '\n'){
2407067Srrh 			state = 1;
2417067Srrh 			nlflg = 0;
2427067Srrh 			goto c0;
2437067Srrh 		}
2447067Srrh 		if((state == 1) && (i == '.')){
2457067Srrh 			state++;
2467067Srrh 			savoff = offset;
2477067Srrh 			goto c0;
2487067Srrh 		}
2497067Srrh 		if((state == 2) && (i == j)){
2507067Srrh 			state++;
2517067Srrh 			goto c0;
2527067Srrh 		}
2537067Srrh 		state = 0;
2547067Srrh c0:
2557067Srrh 		if(offset)wbf(ii);
2567067Srrh 	}
2577067Srrh 	if(offset){
2587067Srrh 		wbfl();
2597067Srrh 		offset = savoff;
2607067Srrh 		wbt(0);
2617067Srrh 	}
2627067Srrh 	copyf--;
2637067Srrh 	return(req);
2647067Srrh }
2657067Srrh copys()
2667067Srrh {
2677067Srrh 	register i;
2687067Srrh 
2697067Srrh 	copyf++;
2707067Srrh 	if(skip())goto c0;
2717067Srrh 	if(((i=getch()) & CMASK) != '"')wbf(i);
2727067Srrh 	while(((i=getch()) & CMASK) != '\n')wbf(i);
2737067Srrh c0:
2747067Srrh 	wbt(0);
2757067Srrh 	copyf--;
2767067Srrh }
2777067Srrh filep alloc()
2787067Srrh {
2797067Srrh 	register i;
2807067Srrh 	extern filep boff();
2817067Srrh 	filep j;
2827067Srrh 
2837067Srrh 	for(i=0;i<NBLIST;i++){
2847067Srrh 		if(blist[i] == 0)break;
2857067Srrh 	}
2867067Srrh 	if(i==NBLIST){
2877067Srrh 		j = 0;
2887067Srrh 	}else{
2897067Srrh 		blist[i] = -1;
2907067Srrh 		if((j = boff(i)) < NEV*EVS)j = 0;
2917067Srrh 	}
2927067Srrh 	return(nextb = j);
2937067Srrh }
2947067Srrh ffree(i)
2957067Srrh filep i;
2967067Srrh {
2977067Srrh 	register j;
2987067Srrh 
2997067Srrh 	while((blist[j = blisti(i)]) != -1){
3007067Srrh 		i = ((filep)blist[j])<<BLKBITS;
3017067Srrh 		blist[j] = 0;
3027067Srrh 	}
3037067Srrh 	blist[j] = 0;
3047067Srrh }
3057067Srrh filep boff(i)
3067067Srrh int i;
3077067Srrh {
3087067Srrh 	return(((filep)i)*BLK + NEV*EVS);
3097067Srrh }
3107067Srrh wbt(i)
3117067Srrh int i;
3127067Srrh {
3137067Srrh 	wbf(i);
3147067Srrh 	wbfl();
3157067Srrh }
3167067Srrh wbf(i)
3177067Srrh int i;
3187067Srrh {
3197067Srrh 	register j;
3207067Srrh 
3217067Srrh 	if(!offset)return;
3227067Srrh 	if(!woff){
3237067Srrh 		woff = offset;
3247067Srrh #ifdef VMUNIX
3257067Srrh 		wbuf = &Buf[woff];
3267067Srrh #endif
3277067Srrh 		wbfi = 0;
3287067Srrh 	}
3297067Srrh 	wbuf[wbfi++] = i;
3307067Srrh 	if(!((++offset) & (BLK-1))){
3317067Srrh 		wbfl();
3327067Srrh 		if(blist[j = blisti(--offset)] == -1){
3337067Srrh 			if(alloc() == 0){
3347067Srrh 				prstr("Out of temp file space.\n");
3357067Srrh 				done2(01);
3367067Srrh 			}
3377067Srrh 			blist[j] = (unsigned)(nextb>>BLKBITS);
3387067Srrh 		}
3397067Srrh 		offset = ((filep)blist[j])<<BLKBITS;
3407067Srrh 	}
3417067Srrh 	if(wbfi >= BLK)wbfl();
3427067Srrh }
3437067Srrh wbfl(){
3447067Srrh 	if(woff == 0)return;
3457067Srrh #ifndef VMUNIX
3467067Srrh 	lseek(ibf, ((long)woff) * sizeof(int), 0);
3477067Srrh 	write(ibf, (char *)wbuf, wbfi * sizeof(int));
3487067Srrh #endif
3497067Srrh 	if((woff & (~(BLK-1))) == (roff & (~(BLK-1))))roff = -1;
3507067Srrh 	woff = 0;
3517067Srrh }
3527067Srrh blisti(i)
3537067Srrh filep i;
3547067Srrh {
3557067Srrh 	return((i-NEV*EVS)/(BLK));
3567067Srrh }
3577067Srrh rbf(){
3587067Srrh 	register i;
3597067Srrh 	extern filep incoff();
3607067Srrh 
3617067Srrh 	if((i=rbf0(ip)) == 0){
3627067Srrh 		if(!app)i = popi();
3637067Srrh 	}else{
3647067Srrh 		ip = incoff(ip);
3657067Srrh 	}
3667067Srrh 	return(i);
3677067Srrh }
3687067Srrh rbf0(p)
3697067Srrh filep p;
3707067Srrh {
3717067Srrh 	register filep i;
3727067Srrh 
3737067Srrh 	if((i = (p & (~(BLK-1)))) != roff){
3747067Srrh 		roff = i;
3757067Srrh #ifndef VMUNIX
3767067Srrh 		lseek(ibf, ((long)roff) * sizeof(int), 0);
3777067Srrh 		if(read(ibf, (char *)rbuf, BLK * sizeof(int)) == 0)return(0);
3787067Srrh #else
3797067Srrh 		rbuf = &Buf[roff];
3807067Srrh #endif
3817067Srrh 	}
3827067Srrh 	return(rbuf[p & (BLK-1)]);
3837067Srrh }
3847067Srrh filep incoff(p)
3857067Srrh filep p;
3867067Srrh {
3877067Srrh 	register i;
3887067Srrh 	register filep j;
3897067Srrh 	if(!((j = (++p)) & (BLK-1))){
3907067Srrh 		if((i = blist[blisti(--p)]) == -1){
3917067Srrh 			prstr("Bad storage allocation.\n");
3927067Srrh 			done2(-5);
3937067Srrh 		}
3947067Srrh 		j = ((filep)i)<<BLKBITS;
3957067Srrh 	}
3967067Srrh 	return(j);
3977067Srrh }
3987067Srrh popi(){
3997067Srrh 	register struct s *p;
4007067Srrh 
4017067Srrh 	if(frame == stk)return(0);
4027067Srrh 	if(strflg)strflg--;
4037067Srrh 	p = nxf = frame;
4047067Srrh 	p->nargs = 0;
4057067Srrh 	frame = p->pframe;
4067067Srrh 	ip = p->pip;
4077067Srrh 	nchar = p->pnchar;
4087067Srrh 	rchar = p->prchar;
4097067Srrh 	pendt = p->ppendt;
4107067Srrh 	ap = p->pap;
4117067Srrh 	cp = p->pcp;
4127067Srrh 	ch0 = p->pch0;
4137067Srrh 	return(p->pch);
4147067Srrh }
4158921Srrh 
4168921Srrh /*
4178921Srrh  *	test that the end of the allocation is above a certain location
4188921Srrh  *	in memory
4198921Srrh  */
4208921Srrh #define SPACETEST(base, size) while ((enda - (size)) <= (char *)(base)){setbrk(DELTA);}
4218921Srrh 
4227067Srrh pushi(newip)
4237067Srrh filep newip;
4247067Srrh {
4257067Srrh 	register struct s *p;
4268921Srrh 	extern char	*setbrk();
4277067Srrh 
4288921Srrh 	SPACETEST(nxf, sizeof(struct s));
4297067Srrh 	p = nxf;
4307067Srrh 	p->pframe = frame;
4317067Srrh 	p->pip = ip;
4327067Srrh 	p->pnchar = nchar;
4337067Srrh 	p->prchar = rchar;
4347067Srrh 	p->ppendt = pendt;
4357067Srrh 	p->pap = ap;
4367067Srrh 	p->pcp = cp;
4377067Srrh 	p->pch0 = ch0;
4387067Srrh 	p->pch = ch;
4397067Srrh 	cp = ap = 0;
4407067Srrh 	nchar = rchar = pendt = ch0 = ch = 0;
4417067Srrh 	frame = nxf;
4428921Srrh 	if (nxf->nargs == 0)
4438921Srrh 		nxf += 1;
4448921Srrh 	else
4458921Srrh 		nxf = (struct s *)argtop;
4467067Srrh 	return(ip = newip);
4477067Srrh }
4488921Srrh 
4498921Srrh 
4508921Srrh char	*setbrk(x)
4518921Srrh int	x;
4527067Srrh {
4538921Srrh 	register char	*i;
4548921Srrh 	char	*sbrk();
4557067Srrh 
456*31687Sbostic 	x += sizeof(int) - 1;
457*31687Sbostic 	x &= ~(sizeof(int) - 1);
458*31687Sbostic 	if ((u_int)(i = sbrk(x)) == -1) {
4597067Srrh 		prstrfl("Core limit reached.\n");
4607067Srrh 		edone(0100);
4618921Srrh 	} else {
4627067Srrh 		enda = i + x;
4637067Srrh 	}
4647067Srrh 	return(i);
4657067Srrh }
4668921Srrh 
4678921Srrh 
4688921Srrh getsn()
4698921Srrh {
4707067Srrh 	register i;
4717067Srrh 
4728921Srrh 	if ((i = getach()) == 0)
4738921Srrh 		return(0);
4748921Srrh 	if (i == '(')
4758921Srrh 		return(getrq());
4768921Srrh 	else
4778921Srrh 		return(i);
4787067Srrh }
4798921Srrh 
4808921Srrh 
4818921Srrh setstr()
4828921Srrh {
4837067Srrh 	register i;
4847067Srrh 
4857067Srrh 	lgf++;
4868921Srrh 	if (    ((i = getsn()) == 0)
4878921Srrh 	     || ((i = findmn(i)) == -1)
4888921Srrh 	     ||  !(contab[i].rq & MMASK)) {
4897067Srrh 		lgf--;
4907067Srrh 		return(0);
4918921Srrh 	} else {
4928921Srrh 		SPACETEST(nxf, sizeof(struct s));
4937067Srrh 		nxf->nargs = 0;
4947067Srrh 		strflg++;
4957067Srrh 		lgf--;
4967067Srrh 		return(pushi(((filep)contab[i].x.mx)<<BLKBITS));
4977067Srrh 	}
4987067Srrh }
4998921Srrh 
5008921Srrh typedef	int	tchar;
5018921Srrh #define	cbits(x)	((x) & CMASK)
5028921Srrh 
5037067Srrh collect()
5047067Srrh {
5058921Srrh 	register j;
5068921Srrh 	tchar i;
5078921Srrh 	register tchar *strp;
5088921Srrh 	tchar * lim;
5098921Srrh 	tchar * *argpp, **argppend;
5108921Srrh 	int	quote;
5117067Srrh 	struct s *savnxf;
5127067Srrh 
5137067Srrh 	copyf++;
5147067Srrh 	nxf->nargs = 0;
5157067Srrh 	savnxf = nxf;
5168921Srrh 	if (skip())
5178921Srrh 		goto rtn;
5188921Srrh 
5198921Srrh 	{
5208921Srrh 		char *memp;
5218921Srrh 		memp = (char *)savnxf;
5228921Srrh 		/*
5238921Srrh 		 *	1 s structure for the macro descriptor
5248921Srrh 		 *	APERMAC tchar *'s for pointers into the strings
5258921Srrh 		 *	space for the tchar's themselves
5268921Srrh 		 */
5278921Srrh 		memp += sizeof(struct s);
5288921Srrh 		/*
5298921Srrh 		 *	CPERMAC (the total # of characters for ALL arguments)
5308921Srrh 		 *	to a macros, has been carefully chosen
5318921Srrh 		 *	so that the distance between stack frames is < DELTA
5328921Srrh 		 */
5338921Srrh #define	CPERMAC	200
5348921Srrh #define	APERMAC	9
5358921Srrh 		memp += APERMAC * sizeof(tchar *);
5368921Srrh 		memp += CPERMAC * sizeof(tchar);
5378921Srrh 		nxf = (struct s*)memp;
5388921Srrh 	}
5398921Srrh 	lim = (tchar *)nxf;
5408921Srrh 	argpp = (tchar **)(savnxf + 1);
5418921Srrh 	argppend = &argpp[APERMAC];
5428921Srrh 	SPACETEST(argppend, sizeof(tchar *));
5438921Srrh 	strp = (tchar *)argppend;
5448921Srrh 	/*
5458921Srrh 	 *	Zero out all the string pointers before filling them in.
5468921Srrh 	 */
5478921Srrh 	for (j = 0; j < APERMAC; j++){
5488921Srrh 		argpp[j] = (tchar *)0;
5498921Srrh 	}
5508921Srrh #if 0
5518921Srrh 	fprintf(stderr, "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x,lim=0x%x,enda=0x%x\n",
5528921Srrh 		savnxf, nxf, argpp, strp, lim, enda);
5538921Srrh #endif 0
5547067Srrh 	strflg = 0;
5558921Srrh 	while ((argpp != argppend) && (!skip())) {
5567067Srrh 		*argpp++ = strp;
5577067Srrh 		quote = 0;
5588921Srrh 		if (cbits(i = getch()) == '"')
5598921Srrh 			quote++;
5608921Srrh 		else
5618921Srrh 			ch = i;
5628921Srrh 		while (1) {
5637067Srrh 			i = getch();
5648921Srrh 			if ( nlflg ||  (!quote && cbits(i) == ' '))
5658921Srrh 				break;
5668921Srrh 			if (   quote
5678921Srrh 			    && (cbits(i) == '"')
5688921Srrh 			    && (cbits(i = getch()) != '"')) {
5697067Srrh 				ch = i;
5707067Srrh 				break;
5717067Srrh 			}
5727067Srrh 			*strp++ = i;
5738921Srrh 			if (strflg && (strp >= lim)) {
5748921Srrh #if 0
5758921Srrh 				fprintf(stderr, "strp=0x%x, lim = 0x%x\n",
5768921Srrh 					strp, lim);
5778921Srrh #endif 0
5787067Srrh 				prstrfl("Macro argument too long.\n");
5797067Srrh 				copyf--;
5807067Srrh 				edone(004);
5817067Srrh 			}
5828921Srrh 			SPACETEST(strp, 3 * sizeof(tchar));
5837067Srrh 		}
5847067Srrh 		*strp++ = 0;
5857067Srrh 	}
5867067Srrh 	nxf = savnxf;
5878921Srrh 	nxf->nargs = argpp - (tchar **)(savnxf + 1);
5887067Srrh 	argtop = strp;
5897067Srrh rtn:
5907067Srrh 	copyf--;
5917067Srrh }
5928921Srrh 
5938921Srrh 
5947067Srrh seta()
5957067Srrh {
5967067Srrh 	register i;
5977067Srrh 
5987067Srrh 	if(((i = (getch() & CMASK) - '0') > 0) &&
5998921Srrh 		(i <= APERMAC) && (i <= frame->nargs))ap = *((int **)frame + i-1 + (sizeof(struct s)/sizeof(int **)));
6007067Srrh }
6017067Srrh caseda(){
6027067Srrh 	app++;
6037067Srrh 	casedi();
6047067Srrh }
6057067Srrh casedi(){
6067067Srrh 	register i, j;
6077067Srrh 	register *k;
6087067Srrh 
6097067Srrh 	lgf++;
6107067Srrh 	if(skip() || ((i=getrq()) == 0)){
6117067Srrh 		if(dip != d)wbt(0);
6127067Srrh 		if(dilev > 0){
6137067Srrh 			v.dn = dip->dnl;
6147067Srrh 			v.dl = dip->maxl;
6157067Srrh 			dip = &d[--dilev];
6167067Srrh 			offset = dip->op;
6177067Srrh 		}
6187067Srrh 		goto rtn;
6197067Srrh 	}
6207067Srrh 	if(++dilev == NDI){
6217067Srrh 		--dilev;
6227067Srrh 		prstr("Cannot divert.\n");
6237067Srrh 		edone(02);
6247067Srrh 	}
6257067Srrh 	if(dip != d)wbt(0);
6267067Srrh 	diflg++;
6277067Srrh 	dip = &d[dilev];
6287067Srrh 	dip->op = finds(i);
6297067Srrh 	dip->curd = i;
6307067Srrh 	clrmn(oldmn);
6317067Srrh 	k = (int *)&dip->dnl;
6327067Srrh 	for(j=0; j<10; j++)k[j] = 0;	/*not op and curd*/
6337067Srrh rtn:
6347067Srrh 	app = 0;
6357067Srrh 	diflg = 0;
6367067Srrh }
6377067Srrh casedt(){
6387067Srrh 	lgf++;
6397067Srrh 	dip->dimac = dip->ditrap = dip->ditf = 0;
6407067Srrh 	skip();
6417067Srrh 	dip->ditrap = vnumb((int *)0);
6427067Srrh 	if(nonumb)return;
6437067Srrh 	skip();
6447067Srrh 	dip->dimac = getrq();
6457067Srrh }
6467067Srrh casetl(){
6477067Srrh 	register i, j;
6487067Srrh 	int w1, w2, w3, delim;
6497067Srrh 	filep begin;
6507067Srrh 	extern width(), pchar();
6517067Srrh 
6527067Srrh 	dip->nls = 0;
6537067Srrh 	skip();
6547067Srrh 	if(dip != d)wbfl();
6557067Srrh 	if((offset = begin = alloc()) == 0)return;
6567067Srrh 	if((delim = getch()) & MOT){
6577067Srrh 		ch = delim;
6587067Srrh 		delim = '\'';
6597067Srrh 	}else delim &= CMASK;
6607067Srrh 	if(!nlflg)
6617067Srrh 		while(((i = getch()) & CMASK) != '\n'){
6627067Srrh 			if((i & CMASK) == delim)i = IMP;
6637067Srrh 			wbf(i);
6647067Srrh 		}
6657067Srrh 	wbf(IMP);wbf(IMP);wbt(0);
6667067Srrh 
6677067Srrh 	w1 = hseg(width,begin);
6687067Srrh 	w2 = hseg(width,(filep)0);
6697067Srrh 	w3 = hseg(width,(filep)0);
6707067Srrh 	offset = dip->op;
6717067Srrh #ifdef NROFF
6727067Srrh 	if(!offset)horiz(po);
6737067Srrh #endif
6747067Srrh 	hseg(pchar,begin);
6757067Srrh 	if(w2 || w3)horiz(j=quant((lt - w2)/2-w1,HOR));
6767067Srrh 	hseg(pchar,(filep)0);
6777067Srrh 	if(w3){
6787067Srrh 		horiz(lt-w1-w2-w3-j);
6797067Srrh 		hseg(pchar,(filep)0);
6807067Srrh 	}
6817067Srrh 	newline(0);
6827067Srrh 	if(dip != d){if(dip->dnl > dip->hnl)dip->hnl = dip->dnl;}
6837067Srrh 	else{if(v.nl > dip->hnl)dip->hnl = v.nl;}
6847067Srrh 	ffree(begin);
6857067Srrh }
6867067Srrh casepc(){
6877067Srrh 	pagech = chget(IMP);
6887067Srrh }
6897067Srrh hseg(f,p)
6907067Srrh int (*f)();
6917067Srrh filep p;
6927067Srrh {
6937067Srrh 	register acc, i;
6947067Srrh 	static filep q;
6957067Srrh 
6967067Srrh 	acc = 0;
6977067Srrh 	if(p)q = p;
6987067Srrh 	while(1){
6997067Srrh 		i = rbf0(q);
7007067Srrh 		q = incoff(q);
7017067Srrh 		if(!i || (i == IMP))return(acc);
7027067Srrh 		if((i & CMASK) == pagech){
7037067Srrh 			nrbits = i & ~CMASK;
7047067Srrh 			nform = fmt[findr('%')];
7057067Srrh 			acc += fnumb(v.pn,f);
7067067Srrh 		}else acc += (*f)(i);
7077067Srrh 	}
7087067Srrh }
7097067Srrh casepm(){
7107067Srrh 	register i, k;
7117067Srrh 	register char *p;
7127067Srrh 	int xx, cnt, kk, tot;
7137067Srrh 	filep j;
7147067Srrh 	char *kvt();
7157067Srrh 	char pmline[10];
7167067Srrh 
7177067Srrh 	kk = cnt = 0;
7187067Srrh 	tot = !skip();
7197067Srrh 	for(i = 0; i<NM; i++){
7207067Srrh 		if(!((xx = contab[i].rq) & MMASK))continue;
7217067Srrh 		p = pmline;
7227067Srrh 		j = (((filep)contab[i].x.mx)<<BLKBITS);
7237067Srrh 		k = 1;
7247067Srrh 		while((j = blist[blisti(j)]) != -1){k++; j <<= BLKBITS;}
7257067Srrh 		cnt++;
7267067Srrh 		kk += k;
7277067Srrh 		if(!tot){
7287067Srrh 			*p++ = xx & 0177;
7297067Srrh 			if(!(*p++ = (xx >> BYTE) & 0177))*(p-1) = ' ';
7307067Srrh 			*p++ = ' ';
7317067Srrh 			kvt(k,p);
7327067Srrh 			prstr(pmline);
7337067Srrh 		}
7347067Srrh 	}
7357067Srrh 	if(tot || (cnt > 1)){
7367067Srrh 		kvt(kk,pmline);
7377067Srrh 		prstr(pmline);
7387067Srrh 	}
7397067Srrh }
7407067Srrh char *kvt(k,p)
7417067Srrh int k;
7427067Srrh char *p;
7437067Srrh {
7447067Srrh 	if(k>=100)*p++ = k/100 + '0';
7457067Srrh 	if(k>=10)*p++ = (k%100)/10 + '0';
7467067Srrh 	*p++ = k%10 + '0';
7477067Srrh 	*p++ = '\n';
7487067Srrh 	*p = 0;
7497067Srrh 	return(p);
7507067Srrh }
7517067Srrh dummy(){}
752