123881Sjaap #ifndef lint
2*45477Skarels /*
330220Sjaap static char sccsid[] = "@(#)n3.c	2.3 (CWI) 86/11/27";
4*45477Skarels */
5*45477Skarels static char sccsid[] = "@(#)n3.c	2.4 (Berkeley) 11/03/90";
623881Sjaap #endif lint
723903Sjaap /*      @(#)n3.c	1.1     */
823903Sjaap /*
923903Sjaap  * troff3.c
1023903Sjaap  *
1123903Sjaap  * macro and string routines, storage allocation
1223903Sjaap  */
1323881Sjaap 
1423903Sjaap 
1523881Sjaap #include "tdef.h"
1623881Sjaap #ifdef NROFF
1723881Sjaap #include "tw.h"
1823881Sjaap #endif
1923881Sjaap #include <sgtty.h>
2023881Sjaap #include "ext.h"
2123903Sjaap 
2223903Sjaap #define	MHASH(x)	((x>>6)^x)&0177
2323903Sjaap struct	contab *mhash[128];	/* 128 == the 0177 on line above */
2423903Sjaap #define	blisti(i)	(((i)-NEV*(int)sizeof(env))/BLK)
2523881Sjaap filep	blist[NBLIST];
2623881Sjaap tchar	*argtop;
2723881Sjaap int	pagech = '%';
2823881Sjaap int	strflg;
2923881Sjaap 
3023881Sjaap 	tchar *wbuf;
3123903Sjaap 	tchar corebuf[NEV*sizeof(env)/sizeof(tchar) + NBLIST*BLK+ 1];
3223881Sjaap 
caseig()3323881Sjaap caseig()
3423881Sjaap {
3523881Sjaap 	register i;
3623881Sjaap 
3723881Sjaap 	offset = 0;
3823881Sjaap 	if ((i = copyb()) != '.')
3923881Sjaap 		control(i, 1);
4023881Sjaap }
4123881Sjaap 
4223881Sjaap 
casern()4323881Sjaap casern()
4423881Sjaap {
4523881Sjaap 	register i, j;
4623881Sjaap 
4723881Sjaap 	lgf++;
4823881Sjaap 	skip();
4923881Sjaap 	if ((i = getrq()) == 0 || (oldmn = findmn(i)) < 0)
5023881Sjaap 		return;
5123881Sjaap 	skip();
5223881Sjaap 	clrmn(findmn(j = getrq()));
5323903Sjaap 	if (j) {
5423903Sjaap 		munhash(&contab[oldmn]);
5523903Sjaap 		contab[oldmn].rq = j;
5623903Sjaap 		maddhash(&contab[oldmn]);
5723903Sjaap 	}
5823881Sjaap }
5923881Sjaap 
maddhash(rp)6023903Sjaap maddhash(rp)
6123903Sjaap register struct contab *rp;
6223903Sjaap {
6323903Sjaap 	register struct contab **hp;
6423881Sjaap 
6523903Sjaap 	if (rp->rq == 0)
6623903Sjaap 		return;
6723903Sjaap 	hp = &mhash[MHASH(rp->rq)];
6823903Sjaap 	rp->link = *hp;
6923903Sjaap 	*hp = rp;
7023903Sjaap }
7123903Sjaap 
munhash(mp)7223903Sjaap munhash(mp)
7323903Sjaap register struct contab *mp;
7423903Sjaap {
7523903Sjaap 	register struct contab *p;
7623903Sjaap 	register struct contab **lp;
7723903Sjaap 
7823903Sjaap 	if (mp->rq == 0)
7923903Sjaap 		return;
8023903Sjaap 	lp = &mhash[MHASH(mp->rq)];
8123903Sjaap 	p = *lp;
8223903Sjaap 	while (p) {
8323903Sjaap 		if (p == mp) {
8423903Sjaap 			*lp = p->link;
8523903Sjaap 			p->link = 0;
8623903Sjaap 			return;
8723903Sjaap 		}
8823903Sjaap 		lp = &p->link;
8923903Sjaap 		p = p->link;
9023903Sjaap 	}
9123903Sjaap }
9223903Sjaap 
mrehash()9323903Sjaap mrehash()
9423903Sjaap {
9523903Sjaap 	register struct contab *p;
9623903Sjaap 	register i;
9723903Sjaap 
9823903Sjaap 	for (i=0; i<128; i++)
9923903Sjaap 		mhash[i] = 0;
10023903Sjaap 	for (p=contab; p < &contab[NM]; p++)
10123903Sjaap 		p->link = 0;
10223903Sjaap 	for (p=contab; p < &contab[NM]; p++) {
10323903Sjaap 		if (p->rq == 0)
10423903Sjaap 			continue;
10523903Sjaap 		i = MHASH(p->rq);
10623903Sjaap 		p->link = mhash[i];
10723903Sjaap 		mhash[i] = p;
10823903Sjaap 	}
10923903Sjaap }
11023903Sjaap 
caserm()11123881Sjaap caserm()
11223881Sjaap {
11323903Sjaap 	int j;
11423903Sjaap 
11523881Sjaap 	lgf++;
11623903Sjaap 	while (!skip() && (j = getrq()) != 0)
11723903Sjaap 		clrmn(findmn(j));
11823903Sjaap 	lgf--;
11923881Sjaap }
12023881Sjaap 
12123881Sjaap 
caseas()12223881Sjaap caseas()
12323881Sjaap {
12423881Sjaap 	app++;
12523881Sjaap 	caseds();
12623881Sjaap }
12723881Sjaap 
12823881Sjaap 
caseds()12923881Sjaap caseds()
13023881Sjaap {
13123881Sjaap 	ds++;
13223881Sjaap 	casede();
13323881Sjaap }
13423881Sjaap 
13523881Sjaap 
caseam()13623881Sjaap caseam()
13723881Sjaap {
13823881Sjaap 	app++;
13923881Sjaap 	casede();
14023881Sjaap }
14123881Sjaap 
14223881Sjaap 
casede()14323881Sjaap casede()
14423881Sjaap {
14523881Sjaap 	register i, req;
14623881Sjaap 	register filep savoff;
14723881Sjaap 	extern filep finds();
14823881Sjaap 
14923881Sjaap 	if (dip != d)
15023881Sjaap 		wbfl();
15123881Sjaap 	req = '.';
15223881Sjaap 	lgf++;
15323881Sjaap 	skip();
15423881Sjaap 	if ((i = getrq()) == 0)
15523881Sjaap 		goto de1;
15623881Sjaap 	if ((offset = finds(i)) == 0)
15723881Sjaap 		goto de1;
15823881Sjaap 	if (ds)
15923881Sjaap 		copys();
16023881Sjaap 	else
16123881Sjaap 		req = copyb();
16223881Sjaap 	wbfl();
16323881Sjaap 	clrmn(oldmn);
16423903Sjaap 	if (newmn) {
16523903Sjaap 		if (contab[newmn].rq)
16623903Sjaap 			munhash(&contab[newmn]);
16723903Sjaap 		contab[newmn].rq = i;
16823903Sjaap 		maddhash(&contab[newmn]);
16923903Sjaap 	}
17023881Sjaap 	if (apptr) {
17123881Sjaap 		savoff = offset;
17223881Sjaap 		offset = apptr;
17323881Sjaap 		wbt((tchar) IMP);
17423881Sjaap 		offset = savoff;
17523881Sjaap 	}
17623881Sjaap 	offset = dip->op;
17723881Sjaap 	if (req != '.')
17823881Sjaap 		control(req, 1);
17923881Sjaap de1:
18023881Sjaap 	ds = app = 0;
18123881Sjaap 	return;
18223881Sjaap }
18323881Sjaap 
18423881Sjaap 
findmn(i)18523881Sjaap findmn(i)
18623881Sjaap register int	i;
18723881Sjaap {
18823881Sjaap 	register struct contab *p;
18923881Sjaap 
19023903Sjaap 	for (p = mhash[MHASH(i)]; p; p = p->link)
19123903Sjaap 		if (i == p->rq)
19223903Sjaap 			return(p - contab);
19323903Sjaap 	return(-1);
19423881Sjaap }
19523881Sjaap 
19623881Sjaap 
clrmn(i)19723881Sjaap clrmn(i)
19823881Sjaap register int	i;
19923881Sjaap {
20023881Sjaap 	if (i >= 0) {
20123903Sjaap 		if (contab[i].mx)
20223903Sjaap 			ffree((filep)contab[i].mx);
20323903Sjaap 		munhash(&contab[i]);
20423881Sjaap 		contab[i].rq = 0;
20523903Sjaap 		contab[i].mx = 0;
20623903Sjaap 		contab[i].f = 0;
20723881Sjaap 	}
20823881Sjaap }
20923881Sjaap 
21023881Sjaap 
finds(mn)21123881Sjaap filep finds(mn)
21223881Sjaap register int	mn;
21323881Sjaap {
21423881Sjaap 	register i;
21523881Sjaap 	register filep savip;
21623881Sjaap 	extern filep alloc();
21723881Sjaap 	extern filep incoff();
21823881Sjaap 
21923881Sjaap 	oldmn = findmn(mn);
22023881Sjaap 	newmn = 0;
22123881Sjaap 	apptr = (filep)0;
22223903Sjaap 	if (app && oldmn >= 0 && contab[oldmn].mx) {
22323881Sjaap 		savip = ip;
22423903Sjaap 		ip = (filep)contab[oldmn].mx;
22523881Sjaap 		oldmn = -1;
22623881Sjaap 		while ((i = rbf()) != 0)
22723881Sjaap 			;
22823881Sjaap 		apptr = ip;
22923881Sjaap 		if (!diflg)
23023881Sjaap 			ip = incoff(ip);
23123881Sjaap 		nextb = ip;
23223881Sjaap 		ip = savip;
23323881Sjaap 	} else {
23423881Sjaap 		for (i = 0; i < NM; i++) {
23523881Sjaap 			if (contab[i].rq == 0)
23623881Sjaap 				break;
23723881Sjaap 		}
23823881Sjaap 		if (i == NM || (nextb = alloc()) == 0) {
23923881Sjaap 			app = 0;
24023881Sjaap 			if (macerr++ > 1)
24123881Sjaap 				done2(02);
24223903Sjaap 			errprint("Too many (%d) string/macro names", NM);
24323881Sjaap 			edone(04);
24423881Sjaap 			return(offset = 0);
24523881Sjaap 		}
24623903Sjaap 		contab[i].mx = (unsigned) nextb;
24723881Sjaap 		if (!diflg) {
24823881Sjaap 			newmn = i;
24923881Sjaap 			if (oldmn == -1)
25023881Sjaap 				contab[i].rq = -1;
25123881Sjaap 		} else {
25223903Sjaap 			contab[i].rq = mn;
25323903Sjaap 			maddhash(&contab[i]);
25423881Sjaap 		}
25523881Sjaap 	}
25623881Sjaap 	app = 0;
25723881Sjaap 	return(offset = nextb);
25823881Sjaap }
25923881Sjaap 
26023881Sjaap 
skip()26123881Sjaap skip()
26223881Sjaap {
26323903Sjaap 	register tchar i;
26423881Sjaap 
26523881Sjaap 	while (cbits(i = getch()) == ' ')
26623881Sjaap 		;
26723881Sjaap 	ch = i;
26823881Sjaap 	return(nlflg);
26923881Sjaap }
27023881Sjaap 
27123881Sjaap 
copyb()27223881Sjaap copyb()
27323881Sjaap {
27423903Sjaap 	register i, j, state;
27523903Sjaap 	register tchar ii;
27623903Sjaap 	int	req, k;
27723881Sjaap 	filep savoff;
27823881Sjaap 
27923881Sjaap 	if (skip() || !(j = getrq()))
28023881Sjaap 		j = '.';
28123881Sjaap 	req = j;
28223881Sjaap 	k = j >> BYTE;
28323903Sjaap 	j &= BYTEMASK;
28423881Sjaap 	copyf++;
28523881Sjaap 	flushi();
28623881Sjaap 	nlflg = 0;
28723881Sjaap 	state = 1;
28823881Sjaap 	while (1) {
28923881Sjaap 		i = cbits(ii = getch());
29023881Sjaap 		if (state == 3) {
29123881Sjaap 			if (i == k)
29223881Sjaap 				break;
29323881Sjaap 			if (!k) {
29423881Sjaap 				ch = ii;
29523881Sjaap 				i = getach();
29623881Sjaap 				ch = ii;
29723881Sjaap 				if (!i)
29823881Sjaap 					break;
29923881Sjaap 			}
30023881Sjaap 			state = 0;
30123881Sjaap 			goto c0;
30223881Sjaap 		}
30323881Sjaap 		if (i == '\n') {
30423881Sjaap 			state = 1;
30523881Sjaap 			nlflg = 0;
30623881Sjaap 			goto c0;
30723881Sjaap 		}
30823881Sjaap 		if (state == 1 && i == '.') {
30923881Sjaap 			state++;
31023881Sjaap 			savoff = offset;
31123881Sjaap 			goto c0;
31223881Sjaap 		}
31323881Sjaap 		if ((state == 2) && (i == j)) {
31423881Sjaap 			state++;
31523881Sjaap 			goto c0;
31623881Sjaap 		}
31723881Sjaap 		state = 0;
31823881Sjaap c0:
31923881Sjaap 		if (offset)
32023881Sjaap 			wbf(ii);
32123881Sjaap 	}
32223881Sjaap 	if (offset) {
32323881Sjaap 		wbfl();
32423881Sjaap 		offset = savoff;
32523881Sjaap 		wbt((tchar)0);
32623881Sjaap 	}
32723881Sjaap 	copyf--;
32823881Sjaap 	return(req);
32923881Sjaap }
33023881Sjaap 
33123881Sjaap 
copys()33223881Sjaap copys()
33323881Sjaap {
33423903Sjaap 	register tchar i;
33523881Sjaap 
33623881Sjaap 	copyf++;
33723881Sjaap 	if (skip())
33823881Sjaap 		goto c0;
33923881Sjaap 	if (cbits(i = getch()) != '"')
34023881Sjaap 		wbf(i);
34123881Sjaap 	while (cbits(i = getch()) != '\n')
34223881Sjaap 		wbf(i);
34323881Sjaap c0:
34423881Sjaap 	wbt((tchar)0);
34523881Sjaap 	copyf--;
34623881Sjaap }
34723881Sjaap 
34823881Sjaap 
alloc()34923881Sjaap filep alloc()
35023881Sjaap {
35123881Sjaap 	register i;
35223903Sjaap 	register filep j;
35323881Sjaap 
35423881Sjaap 	for (i = 0; i < NBLIST; i++) {
35523881Sjaap 		if (blist[i] == 0)
35623881Sjaap 			break;
35723881Sjaap 	}
35823881Sjaap 	if (i == NBLIST) {
35923881Sjaap 		j = 0;
36023881Sjaap 	} else {
36123881Sjaap 		blist[i] = -1;
36223903Sjaap 		if ((j = ((filep)i * BLK + NEV*(int)sizeof(env))) < NEV*(int)sizeof(env))
36323881Sjaap 			j = 0;
36423881Sjaap 	}
36523881Sjaap 	return(nextb = j);
36623881Sjaap }
36723881Sjaap 
36823881Sjaap 
ffree(i)36923881Sjaap ffree(i)
37023881Sjaap filep i;
37123881Sjaap {
37223881Sjaap 	register j;
37323881Sjaap 
37423903Sjaap 	while (blist[j = blisti(i)] != (unsigned) ~0) {
37523903Sjaap 		i = (filep) blist[j];
37623881Sjaap 		blist[j] = 0;
37723881Sjaap 	}
37823881Sjaap 	blist[j] = 0;
37923881Sjaap }
38023881Sjaap 
wbt(i)38123881Sjaap wbt(i)
38223881Sjaap tchar i;
38323881Sjaap {
38423881Sjaap 	wbf(i);
38523881Sjaap 	wbfl();
38623881Sjaap }
38723881Sjaap 
38823881Sjaap 
wbf(i)38923881Sjaap wbf(i)
39023903Sjaap register tchar i;
39123881Sjaap {
39223881Sjaap 	register j;
39323881Sjaap 
39423881Sjaap 	if (!offset)
39523881Sjaap 		return;
39623881Sjaap 	if (!woff) {
39723881Sjaap 		woff = offset;
39823881Sjaap 		wbuf = &corebuf[woff];	/* INCORE only */
39923881Sjaap 		wbfi = 0;
40023881Sjaap 	}
40123881Sjaap 	wbuf[wbfi++] = i;
40223881Sjaap 	if (!((++offset) & (BLK - 1))) {
40323881Sjaap 		wbfl();
40423903Sjaap 		j = blisti(--offset);
40523903Sjaap 		if (j < 0 || j >= NBLIST) {
40623903Sjaap 			errprint("Out of temp file space");
40723903Sjaap 			done2(01);
40823903Sjaap 		}
40923903Sjaap 		if (blist[j] == (unsigned) ~0) {
41023881Sjaap 			if (alloc() == 0) {
41123903Sjaap 				errprint("Out of temp file space");
41223881Sjaap 				done2(01);
41323881Sjaap 			}
41423881Sjaap 			blist[j] = (unsigned)(nextb);
41523881Sjaap 		}
41623881Sjaap 		offset = ((filep)blist[j]);
41723881Sjaap 	}
41823881Sjaap 	if (wbfi >= BLK)
41923881Sjaap 		wbfl();
42023881Sjaap }
42123881Sjaap 
42223881Sjaap 
wbfl()42323881Sjaap wbfl()
42423881Sjaap {
42523881Sjaap 	if (woff == 0)
42623881Sjaap 		return;
42723881Sjaap 	if ((woff & (~(BLK - 1))) == (roff & (~(BLK - 1))))
42823881Sjaap 		roff = -1;
42923881Sjaap 	woff = 0;
43023881Sjaap }
43123881Sjaap 
43223881Sjaap 
rbf()43323881Sjaap tchar rbf()
43423881Sjaap {
43523903Sjaap 	register tchar i;
43623881Sjaap 	register filep j, p;
43723881Sjaap 	extern filep incoff();
43823881Sjaap 
43923903Sjaap 	if (ip == NBLIST*BLK) {		/* for rdtty */
44023903Sjaap 		if (j = rdtty())
44123903Sjaap 			return(j);
44223903Sjaap 		else
44323903Sjaap 			return(popi());
44423903Sjaap 	}
44523881Sjaap 	/* this is an inline expansion of rbf0: dirty! */
44623903Sjaap 	i = corebuf[ip];
44723881Sjaap 	/* end of rbf0 */
44823881Sjaap 	if (i == 0) {
44923881Sjaap 		if (!app)
45023881Sjaap 			i = popi();
45123903Sjaap 		return(i);
45223903Sjaap 	}
45323903Sjaap 	/* this is an inline expansion of incoff: also dirty */
45423903Sjaap 	p = ++ip;
45523903Sjaap 	if ((p & (BLK - 1)) == 0) {
45623903Sjaap 		if ((ip = blist[blisti(p-1)]) == (unsigned) ~0) {
45723903Sjaap 			ip = 0;
45823903Sjaap 			errprint("Bad storage allocation");
45923903Sjaap 			done2(-5);
46023881Sjaap 		}
46123903Sjaap 		/* this was meant to protect against people removing
46223903Sjaap 		/* the macro they were standing on, but it's too
46323903Sjaap 		/* sensitive to block boundaries.
46423903Sjaap 		/* if (ip == 0) {
46523903Sjaap 		/*	errprint("Block removed while in use");
46623903Sjaap 		/*	done2(-6);
46723903Sjaap 		/* }
46823903Sjaap 		*/
46923881Sjaap 	}
47023881Sjaap 	return(i);
47123881Sjaap }
47223881Sjaap 
47323881Sjaap 
rbf0(p)47423881Sjaap tchar rbf0(p)
47523881Sjaap register filep p;
47623881Sjaap {
47723903Sjaap 	return(corebuf[p]);
47823881Sjaap }
47923881Sjaap 
48023881Sjaap 
incoff(p)48123881Sjaap filep incoff(p)
48223881Sjaap register filep p;
48323881Sjaap {
48423903Sjaap 	p++;
48523903Sjaap 	if ((p & (BLK - 1)) == 0) {
48623903Sjaap 		if ((p = blist[blisti(p-1)]) == (unsigned) ~0) {
48723903Sjaap 			errprint("Bad storage allocation");
48823881Sjaap 			done2(-5);
48923881Sjaap 		}
49023881Sjaap 	}
49123903Sjaap 	return(p);
49223881Sjaap }
49323881Sjaap 
49423881Sjaap 
popi()49523881Sjaap tchar popi()
49623881Sjaap {
49723881Sjaap 	register struct s *p;
49823881Sjaap 
49923881Sjaap 	if (frame == stk)
50023881Sjaap 		return(0);
50123881Sjaap 	if (strflg)
50223881Sjaap 		strflg--;
50323881Sjaap 	p = nxf = frame;
50423881Sjaap 	p->nargs = 0;
50523881Sjaap 	frame = p->pframe;
50623881Sjaap 	ip = p->pip;
50723881Sjaap 	pendt = p->ppendt;
50823903Sjaap 	lastpbp = p->lastpbp;
50923881Sjaap 	return(p->pch);
51023881Sjaap }
51123881Sjaap 
51223881Sjaap /*
51323881Sjaap  *	test that the end of the allocation is above a certain location
51423881Sjaap  *	in memory
51523881Sjaap  */
516*45477Skarels #ifdef notdef
51723881Sjaap #define SPACETEST(base, size) while ((enda - (size)) <= (char *)(base)){setbrk(DELTA);}
518*45477Skarels #else
519*45477Skarels #define SPACETEST(base, size)
520*45477Skarels #endif
52123881Sjaap 
pushi(newip,mname)52223903Sjaap pushi(newip, mname)
52323881Sjaap filep newip;
52423903Sjaap int mname;
52523881Sjaap {
52623881Sjaap 	register struct s *p;
52723881Sjaap 
52823881Sjaap 	SPACETEST(nxf, sizeof(struct s));
52923881Sjaap 	p = nxf;
53023881Sjaap 	p->pframe = frame;
53123881Sjaap 	p->pip = ip;
53223881Sjaap 	p->ppendt = pendt;
53323881Sjaap 	p->pch = ch;
53423903Sjaap 	p->lastpbp = lastpbp;
53523903Sjaap 	p->mname = mname;
53623903Sjaap 	lastpbp = pbp;
53723903Sjaap 	pendt = ch = 0;
53823881Sjaap 	frame = nxf;
53923881Sjaap 	if (nxf->nargs == 0)
54023881Sjaap 		nxf += 1;
54123881Sjaap 	else
54223881Sjaap 		nxf = (struct s *)argtop;
54323881Sjaap 	return(ip = newip);
54423881Sjaap }
54523881Sjaap 
getsn()54623881Sjaap getsn()
54723881Sjaap {
54823881Sjaap 	register i;
54923881Sjaap 
55023881Sjaap 	if ((i = getach()) == 0)
55123881Sjaap 		return(0);
55223881Sjaap 	if (i == '(')
55323881Sjaap 		return(getrq());
55423881Sjaap 	else
55523881Sjaap 		return(i);
55623881Sjaap }
55723881Sjaap 
55823881Sjaap 
setstr()55923881Sjaap setstr()
56023881Sjaap {
56123903Sjaap 	register i, j;
56223881Sjaap 
56323881Sjaap 	lgf++;
56423903Sjaap 	if ((i = getsn()) == 0 || (j = findmn(i)) == -1 || !contab[j].mx) {
56523881Sjaap 		lgf--;
56623881Sjaap 		return(0);
56723881Sjaap 	} else {
56823881Sjaap 		SPACETEST(nxf, sizeof(struct s));
56923881Sjaap 		nxf->nargs = 0;
57023881Sjaap 		strflg++;
57123881Sjaap 		lgf--;
57223903Sjaap 		return pushi((filep)contab[j].mx, i);
57323881Sjaap 	}
57423881Sjaap }
57523881Sjaap 
57623881Sjaap 
57723881Sjaap 
collect()57823881Sjaap collect()
57923881Sjaap {
58023881Sjaap 	register j;
58123903Sjaap 	register tchar i;
58223881Sjaap 	register tchar *strp;
58323881Sjaap 	tchar * lim;
58423881Sjaap 	tchar * *argpp, **argppend;
58523881Sjaap 	int	quote;
58623881Sjaap 	struct s *savnxf;
58723881Sjaap 
58823881Sjaap 	copyf++;
58923881Sjaap 	nxf->nargs = 0;
59023881Sjaap 	savnxf = nxf;
59123881Sjaap 	if (skip())
59223881Sjaap 		goto rtn;
59323881Sjaap 
59423881Sjaap 	{
59523881Sjaap 		char *memp;
59623881Sjaap 		memp = (char *)savnxf;
59723881Sjaap 		/*
59823881Sjaap 		 *	1 s structure for the macro descriptor
59923881Sjaap 		 *	APERMAC tchar *'s for pointers into the strings
60023881Sjaap 		 *	space for the tchar's themselves
60123881Sjaap 		 */
60223881Sjaap 		memp += sizeof(struct s);
60323881Sjaap 		/*
60423881Sjaap 		 *	CPERMAC (the total # of characters for ALL arguments)
60523881Sjaap 		 *	to a macros, has been carefully chosen
60623881Sjaap 		 *	so that the distance between stack frames is < DELTA
60723881Sjaap 		 */
60823881Sjaap #define	CPERMAC	200
60923881Sjaap #define	APERMAC	9
61023881Sjaap 		memp += APERMAC * sizeof(tchar *);
61123881Sjaap 		memp += CPERMAC * sizeof(tchar);
61223881Sjaap 		nxf = (struct s*)memp;
61323881Sjaap 	}
61423881Sjaap 	lim = (tchar *)nxf;
61523881Sjaap 	argpp = (tchar **)(savnxf + 1);
61623881Sjaap 	argppend = &argpp[APERMAC];
61723881Sjaap 	SPACETEST(argppend, sizeof(tchar *));
61823881Sjaap 	strp = (tchar *)argppend;
61923881Sjaap 	/*
62023881Sjaap 	 *	Zero out all the string pointers before filling them in.
62123881Sjaap 	 */
62223881Sjaap 	for (j = 0; j < APERMAC; j++){
62323881Sjaap 		argpp[j] = (tchar *)0;
62423881Sjaap 	}
62523881Sjaap #if 0
62623903Sjaap 	errprint("savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x,lim=0x%x,enda=0x%x",
62723881Sjaap 		savnxf, nxf, argpp, strp, lim, enda);
62823881Sjaap #endif 0
62923881Sjaap 	strflg = 0;
63023881Sjaap 	while ((argpp != argppend) && (!skip())) {
63123881Sjaap 		*argpp++ = strp;
63223881Sjaap 		quote = 0;
63323881Sjaap 		if (cbits(i = getch()) == '"')
63423881Sjaap 			quote++;
63523881Sjaap 		else
63623881Sjaap 			ch = i;
63723881Sjaap 		while (1) {
63823881Sjaap 			i = getch();
63923903Sjaap 			if (nlflg || (!quote && cbits(i) == ' '))
64023881Sjaap 				break;
64123881Sjaap 			if (   quote
64223881Sjaap 			    && (cbits(i) == '"')
64323881Sjaap 			    && (cbits(i = getch()) != '"')) {
64423881Sjaap 				ch = i;
64523881Sjaap 				break;
64623881Sjaap 			}
64723881Sjaap 			*strp++ = i;
64823903Sjaap 			if (strflg && strp >= lim) {
64923903Sjaap 				errprint("Macro argument too long");
65023881Sjaap 				copyf--;
65123881Sjaap 				edone(004);
65223881Sjaap 			}
65323881Sjaap 			SPACETEST(strp, 3 * sizeof(tchar));
65423881Sjaap 		}
65523881Sjaap 		*strp++ = 0;
65623881Sjaap 	}
65723881Sjaap 	nxf = savnxf;
65823881Sjaap 	nxf->nargs = argpp - (tchar **)(savnxf + 1);
65923881Sjaap 	argtop = strp;
66023881Sjaap rtn:
66123881Sjaap 	copyf--;
66223881Sjaap }
66323881Sjaap 
66423881Sjaap 
seta()66523881Sjaap seta()
66623881Sjaap {
66723881Sjaap 	register i;
66823881Sjaap 
66923881Sjaap 	i = cbits(getch()) - '0';
67023903Sjaap 	if (i > 0 && i <= APERMAC && i <= frame->nargs)
67123903Sjaap 		pushback(*(((tchar **)(frame + 1)) + i - 1));
67223881Sjaap }
67323881Sjaap 
67423881Sjaap 
caseda()67523881Sjaap caseda()
67623881Sjaap {
67723881Sjaap 	app++;
67823881Sjaap 	casedi();
67923881Sjaap }
68023881Sjaap 
68123881Sjaap 
casedi()68223881Sjaap casedi()
68323881Sjaap {
68423881Sjaap 	register i, j;
68523881Sjaap 	register *k;
68623881Sjaap 
68723881Sjaap 	lgf++;
68823903Sjaap 	if (skip() || (i = getrq()) == 0) {
68923881Sjaap 		if (dip != d)
69023881Sjaap 			wbt((tchar)0);
69123881Sjaap 		if (dilev > 0) {
69223903Sjaap 			numtab[DN].val = dip->dnl;
69323903Sjaap 			numtab[DL].val = dip->maxl;
69423881Sjaap 			dip = &d[--dilev];
69523881Sjaap 			offset = dip->op;
69623881Sjaap 		}
69723881Sjaap 		goto rtn;
69823881Sjaap 	}
69923881Sjaap 	if (++dilev == NDI) {
70023881Sjaap 		--dilev;
70123903Sjaap 		errprint("Diversions nested too deep");
70223881Sjaap 		edone(02);
70323881Sjaap 	}
70423881Sjaap 	if (dip != d)
70523881Sjaap 		wbt((tchar)0);
70623881Sjaap 	diflg++;
70723881Sjaap 	dip = &d[dilev];
70823881Sjaap 	dip->op = finds(i);
70923881Sjaap 	dip->curd = i;
71023881Sjaap 	clrmn(oldmn);
71123881Sjaap 	k = (int *) & dip->dnl;
71223881Sjaap 	for (j = 0; j < 10; j++)
71323881Sjaap 		k[j] = 0;	/*not op and curd*/
71423881Sjaap rtn:
71523881Sjaap 	app = 0;
71623881Sjaap 	diflg = 0;
71723881Sjaap }
71823881Sjaap 
71923881Sjaap 
casedt()72023881Sjaap casedt()
72123881Sjaap {
72223881Sjaap 	lgf++;
72323881Sjaap 	dip->dimac = dip->ditrap = dip->ditf = 0;
72423881Sjaap 	skip();
72523881Sjaap 	dip->ditrap = vnumb((int *)0);
72623881Sjaap 	if (nonumb)
72723881Sjaap 		return;
72823881Sjaap 	skip();
72923881Sjaap 	dip->dimac = getrq();
73023881Sjaap }
73123881Sjaap 
73223881Sjaap 
casetl()73323881Sjaap casetl()
73423881Sjaap {
73523881Sjaap 	register j;
73623903Sjaap 	int w[3];
73723903Sjaap 	tchar buf[LNSIZE];
73823903Sjaap 	register tchar *tp;
73923881Sjaap 	tchar i, delim;
74023881Sjaap 
74124287Sjaap 	/*
74224287Sjaap 	 * bug fix
74324287Sjaap 	 *
74424287Sjaap 	 * if .tl is the first thing in the file, the p1
74524287Sjaap 	 * doesn't come out, also the pagenumber will be 0
74624287Sjaap 	 *
74724287Sjaap 	 * tends too confuse the device filter (and the user as well)
74824287Sjaap 	 */
74924287Sjaap 	if( dip == d && numtab[NL].val == -1)
75024287Sjaap 		newline(1);
75124287Sjaap 
75224287Sjaap 	/* end fix */
75323881Sjaap 	dip->nls = 0;
75423881Sjaap 	skip();
75523881Sjaap 	if (ismot(delim = getch())) {
75623881Sjaap 		ch = delim;
75723881Sjaap 		delim = '\'';
75823881Sjaap 	} else
75923881Sjaap 		delim = cbits(delim);
76023903Sjaap 	tp = buf;
76123903Sjaap 	numtab[HP].val = 0;
76223903Sjaap 	w[0] = w[1] = w[2] = 0;
76323903Sjaap 	j = 0;
76423903Sjaap 	while (cbits(i = getch()) != '\n') {
76523903Sjaap 		if (cbits(i) == cbits(delim)) {
76623903Sjaap 			if (j < 3)
76723903Sjaap 				w[j] = numtab[HP].val;
76823903Sjaap 			numtab[HP].val = 0;
76923903Sjaap 			j++;
77023903Sjaap 			*tp++ = 0;
77123903Sjaap 		} else {
77223903Sjaap 			if (cbits(i) == pagech) {
77323903Sjaap 				setn1(numtab[PN].val, numtab[findr('%')].fmt,
77423903Sjaap 				      i&SFMASK);
77523903Sjaap 				continue;
77623903Sjaap 			}
77723903Sjaap 			numtab[HP].val += width(i);
77823903Sjaap 			if (tp < &buf[LNSIZE-10])
77923903Sjaap 				*tp++ = i;
78023881Sjaap 		}
78123903Sjaap 	}
78223903Sjaap 	if (j<3)
78323903Sjaap 		w[j] = numtab[HP].val;
78423903Sjaap 	*tp++ = 0;
78523903Sjaap 	*tp++ = 0;
78623903Sjaap 	*tp++ = 0;
78723903Sjaap 	tp = buf;
78823881Sjaap #ifdef NROFF
78923903Sjaap 	horiz(po);
79023881Sjaap #endif
79123903Sjaap 	while (i = *tp++)
79223903Sjaap 		pchar(i);
79323903Sjaap 	if (w[1] || w[2])
79423903Sjaap 		horiz(j = quant((lt - w[1]) / 2 - w[0], HOR));
79523903Sjaap 	while (i = *tp++)
79623903Sjaap 		pchar(i);
79723903Sjaap 	if (w[2]) {
79823903Sjaap 		horiz(lt - w[0] - w[1] - w[2] - j);
79923903Sjaap 		while (i = *tp++)
80023903Sjaap 			pchar(i);
80123881Sjaap 	}
80223881Sjaap 	newline(0);
80323881Sjaap 	if (dip != d) {
80423881Sjaap 		if (dip->dnl > dip->hnl)
80523881Sjaap 			dip->hnl = dip->dnl;
80623881Sjaap 	} else {
80723903Sjaap 		if (numtab[NL].val > dip->hnl)
80823903Sjaap 			dip->hnl = numtab[NL].val;
80923881Sjaap 	}
81023881Sjaap }
81123881Sjaap 
81223881Sjaap 
casepc()81323881Sjaap casepc()
81423881Sjaap {
81523881Sjaap 	pagech = chget(IMP);
81623881Sjaap }
81723881Sjaap 
81823881Sjaap 
casepm()81923881Sjaap casepm()
82023881Sjaap {
82123881Sjaap 	register i, k;
82223881Sjaap 	register char	*p;
82323881Sjaap 	int	xx, cnt, tcnt, kk, tot;
82423881Sjaap 	filep j;
82523881Sjaap 	char	pmline[10];
82623881Sjaap 
82723881Sjaap 	kk = cnt = tcnt = 0;
82823881Sjaap 	tot = !skip();
82923881Sjaap 	for (i = 0; i < NM; i++) {
83030220Sjaap 		if ((xx = contab[i].rq) == 0 || contab[i].mx == 0)
83123881Sjaap 			continue;
83223903Sjaap 		tcnt++;
83323881Sjaap 		p = pmline;
83423903Sjaap 		j = (filep) contab[i].mx;
83523881Sjaap 		k = 1;
83623903Sjaap 		while ((j = blist[blisti(j)]) != (unsigned) ~0) {
83723881Sjaap 			k++;
83823881Sjaap 		}
83923881Sjaap 		cnt++;
84023881Sjaap 		kk += k;
84123881Sjaap 		if (!tot) {
84223881Sjaap 			*p++ = xx & 0177;
84323881Sjaap 			if (!(*p++ = (xx >> BYTE) & 0177))
84423881Sjaap 				*(p - 1) = ' ';
84523881Sjaap 			*p++ = 0;
84623903Sjaap 			fdprintf(stderr, "%s %d\n", pmline, k);
84723881Sjaap 		}
84823881Sjaap 	}
84923903Sjaap 	fdprintf(stderr, "pm: total %d, macros %d, space %d\n", tcnt, cnt, kk);
85023881Sjaap }
85123881Sjaap 
stackdump()85223903Sjaap stackdump()	/* dumps stack of macros in process */
85323903Sjaap {
85423903Sjaap 	struct s *p;
85523881Sjaap 
85623903Sjaap 	if (p != stk) {
85723903Sjaap 		for (p = frame; p != stk; p = p->pframe)
85823903Sjaap 			fdprintf(stderr, "%c%c ", p->mname&0177, (p->mname>>BYTE)&0177);
85923903Sjaap 		fdprintf(stderr, "\n");
86023903Sjaap 	}
86123881Sjaap }
862