xref: /plan9/sys/src/cmd/troff/n3.c (revision 14f51593fd82e19ba95969a8c07ff71131015979)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  * troff3.c
33e12c5d1SDavid du Colombier  *
43e12c5d1SDavid du Colombier  * macro and string routines, storage allocation
53e12c5d1SDavid du Colombier  */
63e12c5d1SDavid du Colombier 
73e12c5d1SDavid du Colombier #include "tdef.h"
83e12c5d1SDavid du Colombier #include "fns.h"
93e12c5d1SDavid du Colombier #include "ext.h"
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier Tchar	*argtop;
123e12c5d1SDavid du Colombier int	pagech = '%';
133e12c5d1SDavid du Colombier int	strflg;
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier #define	MHASHSIZE	128	/* must be 2**n */
163e12c5d1SDavid du Colombier #define	MHASH(x)	((x>>6)^x) & (MHASHSIZE-1)
173e12c5d1SDavid du Colombier Contab	*mhash[MHASHSIZE];
183e12c5d1SDavid du Colombier 
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier Blockp	*blist;		/* allocated blocks for macros and strings */
213e12c5d1SDavid du Colombier int	nblist;		/* how many there are */
22219b2ee8SDavid du Colombier int	bfree = -1;	/* first (possible) free block in the list */
23219b2ee8SDavid du Colombier 
24219b2ee8SDavid du Colombier Contab *contabp = NULL;
25219b2ee8SDavid du Colombier #define MDELTA 500
26219b2ee8SDavid du Colombier int	nm = 0;
27219b2ee8SDavid du Colombier 
28219b2ee8SDavid du Colombier int savname;		/* name of macro/string being defined */
29219b2ee8SDavid du Colombier int savslot;		/* place in Contab of savname */
30219b2ee8SDavid du Colombier int freeslot = -1;	/* first (possible) free slot in contab */
31219b2ee8SDavid du Colombier 
prcontab(Contab * p)32219b2ee8SDavid du Colombier void prcontab(Contab *p)
33219b2ee8SDavid du Colombier {
34219b2ee8SDavid du Colombier 	int i;
35219b2ee8SDavid du Colombier 	for (i = 0; i < nm; i++)
36219b2ee8SDavid du Colombier 		if (p)
37219b2ee8SDavid du Colombier 			if (p[i].rq != 0)
38219b2ee8SDavid du Colombier 				fprintf(stderr, "slot %d, %-2.2s\n", i, unpair(p[i].rq));
39219b2ee8SDavid du Colombier 			else
40219b2ee8SDavid du Colombier 				fprintf(stderr, "slot %d empty\n", i);
41219b2ee8SDavid du Colombier 		else
42219b2ee8SDavid du Colombier 			fprintf(stderr, "slot %d empty\n", i);
43219b2ee8SDavid du Colombier }
44219b2ee8SDavid du Colombier 
453e12c5d1SDavid du Colombier 
blockinit(void)463e12c5d1SDavid du Colombier void blockinit(void)
473e12c5d1SDavid du Colombier {
483e12c5d1SDavid du Colombier 	blist = (Blockp *) calloc(NBLIST, sizeof(Blockp));
493e12c5d1SDavid du Colombier 	if (blist == NULL) {
503e12c5d1SDavid du Colombier 		ERROR "not enough room for %d blocks", NBLIST WARN;
513e12c5d1SDavid du Colombier 		done2(1);
523e12c5d1SDavid du Colombier 	}
533e12c5d1SDavid du Colombier 	nblist = NBLIST;
543e12c5d1SDavid du Colombier 	blist[0].nextoff = blist[1].nextoff = -1;
553e12c5d1SDavid du Colombier 	blist[0].bp = (Tchar *) calloc(BLK, sizeof(Tchar));
563e12c5d1SDavid du Colombier 	blist[1].bp = (Tchar *) calloc(BLK, sizeof(Tchar));
573e12c5d1SDavid du Colombier 		/* -1 prevents blist[0] from being used; temporary fix */
583e12c5d1SDavid du Colombier 		/* for a design botch: offset==0 is overloaded. */
593e12c5d1SDavid du Colombier 		/* blist[1] reserved for .rd indicator -- also unused. */
603e12c5d1SDavid du Colombier 		/* but someone unwittingly looks at these, so allocate something */
61219b2ee8SDavid du Colombier 	bfree = 2;
623e12c5d1SDavid du Colombier }
633e12c5d1SDavid du Colombier 
643e12c5d1SDavid du Colombier 
grow(char * ptr,int num,int size)65219b2ee8SDavid du Colombier char *grow(char *ptr, int num, int size)	/* make array bigger */
66219b2ee8SDavid du Colombier {
67*14f51593SDavid du Colombier 	char *p;
68219b2ee8SDavid du Colombier 
69219b2ee8SDavid du Colombier 	if (ptr == NULL)
70219b2ee8SDavid du Colombier 		p = (char *) calloc(num, size);
71219b2ee8SDavid du Colombier 	else
72219b2ee8SDavid du Colombier 		p = (char *) realloc(ptr, num * size);
73219b2ee8SDavid du Colombier 	return p;
74219b2ee8SDavid du Colombier }
75219b2ee8SDavid du Colombier 
mnspace(void)76219b2ee8SDavid du Colombier void mnspace(void)
77219b2ee8SDavid du Colombier {
78219b2ee8SDavid du Colombier 	nm = sizeof(contab)/sizeof(Contab) + MDELTA;
79219b2ee8SDavid du Colombier 	freeslot = sizeof(contab)/sizeof(Contab) + 1;
80219b2ee8SDavid du Colombier 	contabp = (Contab *) grow((char *) contabp, nm, sizeof(Contab));
81219b2ee8SDavid du Colombier 	if (contabp == NULL) {
82219b2ee8SDavid du Colombier 		ERROR "not enough memory for namespace of %d marcos", nm WARN;
83219b2ee8SDavid du Colombier 		exit(1);
84219b2ee8SDavid du Colombier 	}
85219b2ee8SDavid du Colombier 	contabp = (Contab *) memcpy((char *) contabp, (char *)contab,
86219b2ee8SDavid du Colombier 							sizeof(contab));
87219b2ee8SDavid du Colombier 	if (contabp == NULL) {
88219b2ee8SDavid du Colombier 		ERROR "Cannot reinitialize macro/request name list" WARN;
89219b2ee8SDavid du Colombier 		exit(1);
90219b2ee8SDavid du Colombier 	}
91219b2ee8SDavid du Colombier 
92219b2ee8SDavid du Colombier }
93219b2ee8SDavid du Colombier 
caseig(void)943e12c5d1SDavid du Colombier void caseig(void)
953e12c5d1SDavid du Colombier {
963e12c5d1SDavid du Colombier 	int i;
973e12c5d1SDavid du Colombier 	Offset oldoff = offset;
983e12c5d1SDavid du Colombier 
993e12c5d1SDavid du Colombier 	offset = 0;
1003e12c5d1SDavid du Colombier 	i = copyb();
1013e12c5d1SDavid du Colombier 	offset = oldoff;
1023e12c5d1SDavid du Colombier 	if (i != '.')
1033e12c5d1SDavid du Colombier 		control(i, 1);
1043e12c5d1SDavid du Colombier }
1053e12c5d1SDavid du Colombier 
1063e12c5d1SDavid du Colombier 
casern(void)1073e12c5d1SDavid du Colombier void casern(void)
1083e12c5d1SDavid du Colombier {
109219b2ee8SDavid du Colombier 	int i, j, k;
1103e12c5d1SDavid du Colombier 
1113e12c5d1SDavid du Colombier 	lgf++;
1123e12c5d1SDavid du Colombier 	skip();
1133e12c5d1SDavid du Colombier 	if ((i = getrq()) == 0 || (oldmn = findmn(i)) < 0)
1143e12c5d1SDavid du Colombier 		return;
1153e12c5d1SDavid du Colombier 	skip();
1163e12c5d1SDavid du Colombier 	clrmn(findmn(j = getrq()));
1173e12c5d1SDavid du Colombier 	if (j) {
118219b2ee8SDavid du Colombier 		munhash(&contabp[oldmn]);
119219b2ee8SDavid du Colombier 		contabp[oldmn].rq = j;
120219b2ee8SDavid du Colombier 		maddhash(&contabp[oldmn]);
121219b2ee8SDavid du Colombier 		if (dip != d )
122219b2ee8SDavid du Colombier 			for (k = dilev; k; k--)
123219b2ee8SDavid du Colombier 				if (d[k].curd == i)
124219b2ee8SDavid du Colombier 					d[k].curd = j;
1253e12c5d1SDavid du Colombier 	}
1263e12c5d1SDavid du Colombier }
1273e12c5d1SDavid du Colombier 
maddhash(Contab * rp)1283e12c5d1SDavid du Colombier void maddhash(Contab *rp)
1293e12c5d1SDavid du Colombier {
1303e12c5d1SDavid du Colombier 	Contab **hp;
1313e12c5d1SDavid du Colombier 
1323e12c5d1SDavid du Colombier 	if (rp->rq == 0)
1333e12c5d1SDavid du Colombier 		return;
1343e12c5d1SDavid du Colombier 	hp = &mhash[MHASH(rp->rq)];
1353e12c5d1SDavid du Colombier 	rp->link = *hp;
1363e12c5d1SDavid du Colombier 	*hp = rp;
1373e12c5d1SDavid du Colombier }
1383e12c5d1SDavid du Colombier 
munhash(Contab * mp)1393e12c5d1SDavid du Colombier void munhash(Contab *mp)
1403e12c5d1SDavid du Colombier {
1413e12c5d1SDavid du Colombier 	Contab *p;
1423e12c5d1SDavid du Colombier 	Contab **lp;
1433e12c5d1SDavid du Colombier 
1443e12c5d1SDavid du Colombier 	if (mp->rq == 0)
1453e12c5d1SDavid du Colombier 		return;
1463e12c5d1SDavid du Colombier 	lp = &mhash[MHASH(mp->rq)];
1473e12c5d1SDavid du Colombier 	p = *lp;
1483e12c5d1SDavid du Colombier 	while (p) {
1493e12c5d1SDavid du Colombier 		if (p == mp) {
1503e12c5d1SDavid du Colombier 			*lp = p->link;
1513e12c5d1SDavid du Colombier 			p->link = 0;
1523e12c5d1SDavid du Colombier 			return;
1533e12c5d1SDavid du Colombier 		}
1543e12c5d1SDavid du Colombier 		lp = &p->link;
1553e12c5d1SDavid du Colombier 		p = p->link;
1563e12c5d1SDavid du Colombier 	}
1573e12c5d1SDavid du Colombier }
1583e12c5d1SDavid du Colombier 
mrehash(void)1593e12c5d1SDavid du Colombier void mrehash(void)
1603e12c5d1SDavid du Colombier {
1613e12c5d1SDavid du Colombier 	Contab *p;
1623e12c5d1SDavid du Colombier 	int i;
1633e12c5d1SDavid du Colombier 
1643e12c5d1SDavid du Colombier 	for (i=0; i < MHASHSIZE; i++)
1653e12c5d1SDavid du Colombier 		mhash[i] = 0;
166219b2ee8SDavid du Colombier 	for (p=contabp; p < &contabp[nm]; p++)
1673e12c5d1SDavid du Colombier 		p->link = 0;
168219b2ee8SDavid du Colombier 	for (p=contabp; p < &contabp[nm]; p++) {
1693e12c5d1SDavid du Colombier 		if (p->rq == 0)
1703e12c5d1SDavid du Colombier 			continue;
1713e12c5d1SDavid du Colombier 		i = MHASH(p->rq);
1723e12c5d1SDavid du Colombier 		p->link = mhash[i];
1733e12c5d1SDavid du Colombier 		mhash[i] = p;
1743e12c5d1SDavid du Colombier 	}
1753e12c5d1SDavid du Colombier }
1763e12c5d1SDavid du Colombier 
caserm(void)1773e12c5d1SDavid du Colombier void caserm(void)
1783e12c5d1SDavid du Colombier {
179*14f51593SDavid du Colombier 	int j, k;
1803e12c5d1SDavid du Colombier 
1813e12c5d1SDavid du Colombier 	lgf++;
182219b2ee8SDavid du Colombier g0:
183219b2ee8SDavid du Colombier 	while (!skip() && (j = getrq()) != 0) {
184219b2ee8SDavid du Colombier 		if (dip != d)
185219b2ee8SDavid du Colombier 			for (k = dilev; k; k--)
186219b2ee8SDavid du Colombier 				if (d[k].curd == j) {
187219b2ee8SDavid du Colombier 					ERROR "cannot remove diversion %s during definition",
188219b2ee8SDavid du Colombier 								unpair(j) WARN;
189219b2ee8SDavid du Colombier 					goto g0;
190219b2ee8SDavid du Colombier 				}
1913e12c5d1SDavid du Colombier 		clrmn(findmn(j));
192219b2ee8SDavid du Colombier 	}
1933e12c5d1SDavid du Colombier 	lgf--;
1943e12c5d1SDavid du Colombier }
1953e12c5d1SDavid du Colombier 
1963e12c5d1SDavid du Colombier 
caseas(void)1973e12c5d1SDavid du Colombier void caseas(void)
1983e12c5d1SDavid du Colombier {
1993e12c5d1SDavid du Colombier 	app++;
2003e12c5d1SDavid du Colombier 	caseds();
2013e12c5d1SDavid du Colombier }
2023e12c5d1SDavid du Colombier 
2033e12c5d1SDavid du Colombier 
caseds(void)2043e12c5d1SDavid du Colombier void caseds(void)
2053e12c5d1SDavid du Colombier {
2063e12c5d1SDavid du Colombier 	ds++;
2073e12c5d1SDavid du Colombier 	casede();
2083e12c5d1SDavid du Colombier }
2093e12c5d1SDavid du Colombier 
2103e12c5d1SDavid du Colombier 
caseam(void)2113e12c5d1SDavid du Colombier void caseam(void)
2123e12c5d1SDavid du Colombier {
2133e12c5d1SDavid du Colombier 	app++;
2143e12c5d1SDavid du Colombier 	casede();
2153e12c5d1SDavid du Colombier }
2163e12c5d1SDavid du Colombier 
2173e12c5d1SDavid du Colombier 
casede(void)2183e12c5d1SDavid du Colombier void casede(void)
2193e12c5d1SDavid du Colombier {
2203e12c5d1SDavid du Colombier 	int i, req;
2213e12c5d1SDavid du Colombier 	Offset savoff;
2223e12c5d1SDavid du Colombier 
2233e12c5d1SDavid du Colombier 	req = '.';
2243e12c5d1SDavid du Colombier 	lgf++;
2253e12c5d1SDavid du Colombier 	skip();
2263e12c5d1SDavid du Colombier 	if ((i = getrq()) == 0)
2273e12c5d1SDavid du Colombier 		goto de1;
2283e12c5d1SDavid du Colombier 	if ((offset = finds(i)) == 0)
2293e12c5d1SDavid du Colombier 		goto de1;
230219b2ee8SDavid du Colombier 	if (newmn)
231219b2ee8SDavid du Colombier 		savslot = newmn;
232219b2ee8SDavid du Colombier 	else
233219b2ee8SDavid du Colombier 		savslot = findmn(i);
234219b2ee8SDavid du Colombier 	savname = i;
2353e12c5d1SDavid du Colombier 	if (ds)
2363e12c5d1SDavid du Colombier 		copys();
2373e12c5d1SDavid du Colombier 	else
2383e12c5d1SDavid du Colombier 		req = copyb();
2393e12c5d1SDavid du Colombier 	clrmn(oldmn);
2403e12c5d1SDavid du Colombier 	if (newmn) {
241219b2ee8SDavid du Colombier 		if (contabp[newmn].rq)
242219b2ee8SDavid du Colombier 			munhash(&contabp[newmn]);
243219b2ee8SDavid du Colombier 		contabp[newmn].rq = i;
244219b2ee8SDavid du Colombier 		maddhash(&contabp[newmn]);
245219b2ee8SDavid du Colombier 
2463e12c5d1SDavid du Colombier 	}
2473e12c5d1SDavid du Colombier 	if (apptr) {
2483e12c5d1SDavid du Colombier 		savoff = offset;
2493e12c5d1SDavid du Colombier 		offset = apptr;
2503e12c5d1SDavid du Colombier 		wbf((Tchar) IMP);
251*14f51593SDavid du Colombier 		offset = savoff;	/* pointless */
2523e12c5d1SDavid du Colombier 	}
2533e12c5d1SDavid du Colombier 	offset = dip->op;
2543e12c5d1SDavid du Colombier 	if (req != '.')
2553e12c5d1SDavid du Colombier 		control(req, 1);
2563e12c5d1SDavid du Colombier de1:
2573e12c5d1SDavid du Colombier 	ds = app = 0;
2583e12c5d1SDavid du Colombier }
2593e12c5d1SDavid du Colombier 
2603e12c5d1SDavid du Colombier 
findmn(int i)2613e12c5d1SDavid du Colombier int findmn(int i)
2623e12c5d1SDavid du Colombier {
2633e12c5d1SDavid du Colombier 	Contab *p;
2643e12c5d1SDavid du Colombier 
2653e12c5d1SDavid du Colombier 	for (p = mhash[MHASH(i)]; p; p = p->link)
2663e12c5d1SDavid du Colombier 		if (i == p->rq)
267219b2ee8SDavid du Colombier 			return(p - contabp);
2683e12c5d1SDavid du Colombier 	return(-1);
2693e12c5d1SDavid du Colombier }
2703e12c5d1SDavid du Colombier 
2713e12c5d1SDavid du Colombier 
clrmn(int i)2723e12c5d1SDavid du Colombier void clrmn(int i)
2733e12c5d1SDavid du Colombier {
2743e12c5d1SDavid du Colombier 	if (i >= 0) {
275219b2ee8SDavid du Colombier 		if (contabp[i].mx)
276219b2ee8SDavid du Colombier 			ffree(contabp[i].mx);
277219b2ee8SDavid du Colombier 		munhash(&contabp[i]);
278219b2ee8SDavid du Colombier 		contabp[i].rq = 0;
279219b2ee8SDavid du Colombier 		contabp[i].mx = 0;
280219b2ee8SDavid du Colombier 		contabp[i].emx = 0;
281219b2ee8SDavid du Colombier 		contabp[i].f = 0;
282219b2ee8SDavid du Colombier 		if (contabp[i].divsiz != NULL) {
283219b2ee8SDavid du Colombier 			free(contabp[i].divsiz);
284219b2ee8SDavid du Colombier 			contabp[i].divsiz = NULL;
285219b2ee8SDavid du Colombier 		}
286219b2ee8SDavid du Colombier 		if (freeslot > i)
287219b2ee8SDavid du Colombier 			freeslot = i;
288219b2ee8SDavid du Colombier 	}
289219b2ee8SDavid du Colombier }
290219b2ee8SDavid du Colombier 
growcontab(void)291219b2ee8SDavid du Colombier void growcontab(void)
292219b2ee8SDavid du Colombier {
293219b2ee8SDavid du Colombier 	nm += MDELTA;
294219b2ee8SDavid du Colombier 	contabp = (Contab *) grow((char *) contabp , nm, sizeof(Contab));
295219b2ee8SDavid du Colombier 	if (contabp == NULL) {
296219b2ee8SDavid du Colombier 		ERROR "Too many (%d) string/macro names", nm WARN;
297219b2ee8SDavid du Colombier 		done2(02);
298219b2ee8SDavid du Colombier 	} else {
299219b2ee8SDavid du Colombier 		memset((char *)(contabp) + (nm - MDELTA) * sizeof(Contab),
300219b2ee8SDavid du Colombier 						0, MDELTA * sizeof(Contab));
301219b2ee8SDavid du Colombier 		mrehash();
3023e12c5d1SDavid du Colombier 	}
3033e12c5d1SDavid du Colombier }
3043e12c5d1SDavid du Colombier 
3053e12c5d1SDavid du Colombier 
finds(int mn)3063e12c5d1SDavid du Colombier Offset finds(int mn)
3073e12c5d1SDavid du Colombier {
3083e12c5d1SDavid du Colombier 	int i;
3093e12c5d1SDavid du Colombier 	Offset savip;
3103e12c5d1SDavid du Colombier 
3113e12c5d1SDavid du Colombier 	oldmn = findmn(mn);
3123e12c5d1SDavid du Colombier 	newmn = 0;
3133e12c5d1SDavid du Colombier 	apptr = 0;
314219b2ee8SDavid du Colombier 	if (app && oldmn >= 0 && contabp[oldmn].mx) {
3153e12c5d1SDavid du Colombier 		savip = ip;
316219b2ee8SDavid du Colombier 		ip = contabp[oldmn].emx;
3173e12c5d1SDavid du Colombier 		oldmn = -1;
3183e12c5d1SDavid du Colombier 		apptr = ip;
3193e12c5d1SDavid du Colombier 		if (!diflg)
3203e12c5d1SDavid du Colombier 			ip = incoff(ip);
3213e12c5d1SDavid du Colombier 		nextb = ip;
3223e12c5d1SDavid du Colombier 		ip = savip;
3233e12c5d1SDavid du Colombier 	} else {
324219b2ee8SDavid du Colombier 		for (i = freeslot; i < nm; i++) {
325219b2ee8SDavid du Colombier 			if (contabp[i].rq == 0)
3263e12c5d1SDavid du Colombier 				break;
3273e12c5d1SDavid du Colombier 		}
328219b2ee8SDavid du Colombier 		if (i == nm)
329219b2ee8SDavid du Colombier 			growcontab();
330219b2ee8SDavid du Colombier 		freeslot = i + 1;
331219b2ee8SDavid du Colombier 		if ((nextb = alloc()) == -1) {
3323e12c5d1SDavid du Colombier 			app = 0;
3333e12c5d1SDavid du Colombier 			if (macerr++ > 1)
3343e12c5d1SDavid du Colombier 				done2(02);
3353e12c5d1SDavid du Colombier 			if (nextb == 0)
336219b2ee8SDavid du Colombier 				ERROR "Not enough space for string/macro names" WARN;
3373e12c5d1SDavid du Colombier 			edone(04);
3383e12c5d1SDavid du Colombier 			return(offset = 0);
3393e12c5d1SDavid du Colombier 		}
340219b2ee8SDavid du Colombier 		contabp[i].mx = nextb;
3413e12c5d1SDavid du Colombier 		if (!diflg) {
3423e12c5d1SDavid du Colombier 			newmn = i;
3433e12c5d1SDavid du Colombier 			if (oldmn == -1)
344219b2ee8SDavid du Colombier 				contabp[i].rq = -1;
3453e12c5d1SDavid du Colombier 		} else {
346219b2ee8SDavid du Colombier 			contabp[i].rq = mn;
347219b2ee8SDavid du Colombier 			maddhash(&contabp[i]);
3483e12c5d1SDavid du Colombier 		}
3493e12c5d1SDavid du Colombier 	}
3503e12c5d1SDavid du Colombier 	app = 0;
3513e12c5d1SDavid du Colombier 	return(offset = nextb);
3523e12c5d1SDavid du Colombier }
3533e12c5d1SDavid du Colombier 
skip(void)3543e12c5d1SDavid du Colombier int skip(void)
3553e12c5d1SDavid du Colombier {
3563e12c5d1SDavid du Colombier 	Tchar i;
3573e12c5d1SDavid du Colombier 
358219b2ee8SDavid du Colombier 	while (cbits(i = getch()) == ' ' || ismot(i))
3593e12c5d1SDavid du Colombier 		;
3603e12c5d1SDavid du Colombier 	ch = i;
3613e12c5d1SDavid du Colombier 	return(nlflg);
3623e12c5d1SDavid du Colombier }
3633e12c5d1SDavid du Colombier 
3643e12c5d1SDavid du Colombier 
copyb(void)3653e12c5d1SDavid du Colombier int copyb(void)
3663e12c5d1SDavid du Colombier {
3673e12c5d1SDavid du Colombier 	int i, j, state;
3683e12c5d1SDavid du Colombier 	Tchar ii;
3693e12c5d1SDavid du Colombier 	int req, k;
3703e12c5d1SDavid du Colombier 	Offset savoff;
371219b2ee8SDavid du Colombier 	Uchar *p;
3723e12c5d1SDavid du Colombier 
3733e12c5d1SDavid du Colombier 	if (skip() || !(j = getrq()))
3743e12c5d1SDavid du Colombier 		j = '.';
3753e12c5d1SDavid du Colombier 	req = j;
3763e12c5d1SDavid du Colombier 	p = unpair(j);
3773e12c5d1SDavid du Colombier 	/* was: k = j >> BYTE; j &= BYTEMASK; */
3783e12c5d1SDavid du Colombier 	j = p[0];
3793e12c5d1SDavid du Colombier 	k = p[1];
3803e12c5d1SDavid du Colombier 	copyf++;
3813e12c5d1SDavid du Colombier 	flushi();
3823e12c5d1SDavid du Colombier 	nlflg = 0;
3833e12c5d1SDavid du Colombier 	state = 1;
384*14f51593SDavid du Colombier 	savoff = 0;
3853e12c5d1SDavid du Colombier 
3863e12c5d1SDavid du Colombier /* state 0	eat up
3873e12c5d1SDavid du Colombier  * state 1	look for .
3883e12c5d1SDavid du Colombier  * state 2	look for first char of end macro
3893e12c5d1SDavid du Colombier  * state 3	look for second char of end macro
3903e12c5d1SDavid du Colombier  */
3913e12c5d1SDavid du Colombier 
3923e12c5d1SDavid du Colombier 	while (1) {
3933e12c5d1SDavid du Colombier 		i = cbits(ii = getch());
3943e12c5d1SDavid du Colombier 		if (state == 3) {
3953e12c5d1SDavid du Colombier 			if (i == k)
3963e12c5d1SDavid du Colombier 				break;
3973e12c5d1SDavid du Colombier 			if (!k) {
3983e12c5d1SDavid du Colombier 				ch = ii;
3993e12c5d1SDavid du Colombier 				i = getach();
4003e12c5d1SDavid du Colombier 				ch = ii;
4013e12c5d1SDavid du Colombier 				if (!i)
4023e12c5d1SDavid du Colombier 					break;
4033e12c5d1SDavid du Colombier 			}
4043e12c5d1SDavid du Colombier 			state = 0;
4053e12c5d1SDavid du Colombier 			goto c0;
4063e12c5d1SDavid du Colombier 		}
4073e12c5d1SDavid du Colombier 		if (i == '\n') {
4083e12c5d1SDavid du Colombier 			state = 1;
4093e12c5d1SDavid du Colombier 			nlflg = 0;
4103e12c5d1SDavid du Colombier 			goto c0;
4113e12c5d1SDavid du Colombier 		}
4123e12c5d1SDavid du Colombier 		if (state == 1 && i == '.') {
4133e12c5d1SDavid du Colombier 			state++;
4143e12c5d1SDavid du Colombier 			savoff = offset;
4153e12c5d1SDavid du Colombier 			goto c0;
4163e12c5d1SDavid du Colombier 		}
4173e12c5d1SDavid du Colombier 		if (state == 2 && i == j) {
4183e12c5d1SDavid du Colombier 			state++;
4193e12c5d1SDavid du Colombier 			goto c0;
4203e12c5d1SDavid du Colombier 		}
4213e12c5d1SDavid du Colombier 		state = 0;
4223e12c5d1SDavid du Colombier c0:
4233e12c5d1SDavid du Colombier 		if (offset)
4243e12c5d1SDavid du Colombier 			wbf(ii);
4253e12c5d1SDavid du Colombier 	}
4263e12c5d1SDavid du Colombier 	if (offset) {
4273e12c5d1SDavid du Colombier 		offset = savoff;
4283e12c5d1SDavid du Colombier 		wbf((Tchar)0);
4293e12c5d1SDavid du Colombier 	}
4303e12c5d1SDavid du Colombier 	copyf--;
4313e12c5d1SDavid du Colombier 	return(req);
4323e12c5d1SDavid du Colombier }
4333e12c5d1SDavid du Colombier 
4343e12c5d1SDavid du Colombier 
copys(void)4353e12c5d1SDavid du Colombier void copys(void)
4363e12c5d1SDavid du Colombier {
4373e12c5d1SDavid du Colombier 	Tchar i;
4383e12c5d1SDavid du Colombier 
4393e12c5d1SDavid du Colombier 	copyf++;
4403e12c5d1SDavid du Colombier 	if (skip())
4413e12c5d1SDavid du Colombier 		goto c0;
4423e12c5d1SDavid du Colombier 	if (cbits(i = getch()) != '"')
4433e12c5d1SDavid du Colombier 		wbf(i);
4443e12c5d1SDavid du Colombier 	while (cbits(i = getch()) != '\n')
4453e12c5d1SDavid du Colombier 		wbf(i);
4463e12c5d1SDavid du Colombier c0:
4473e12c5d1SDavid du Colombier 	wbf((Tchar)0);
4483e12c5d1SDavid du Colombier 	copyf--;
4493e12c5d1SDavid du Colombier }
4503e12c5d1SDavid du Colombier 
4513e12c5d1SDavid du Colombier 
alloc(void)4523e12c5d1SDavid du Colombier Offset alloc(void)	/* return free Offset in nextb */
4533e12c5d1SDavid du Colombier {
4543e12c5d1SDavid du Colombier 	int i, j;
4553e12c5d1SDavid du Colombier 
456219b2ee8SDavid du Colombier 	for (i = bfree; i < nblist; i++)
4573e12c5d1SDavid du Colombier 		if (blist[i].nextoff == 0)
4583e12c5d1SDavid du Colombier 			break;
4593e12c5d1SDavid du Colombier 	if (i == nblist) {
4603e12c5d1SDavid du Colombier 		blist = (Blockp *) realloc((char *) blist, 2 * nblist * sizeof(Blockp));
4613e12c5d1SDavid du Colombier 		if (blist == NULL) {
4623e12c5d1SDavid du Colombier 			ERROR "can't grow blist for string/macro defns" WARN;
4633e12c5d1SDavid du Colombier 			done2(2);
4643e12c5d1SDavid du Colombier 		}
4653e12c5d1SDavid du Colombier 		nblist *= 2;
4663e12c5d1SDavid du Colombier 		for (j = i; j < nblist; j++) {
4673e12c5d1SDavid du Colombier 			blist[j].nextoff = 0;
4683e12c5d1SDavid du Colombier 			blist[j].bp = 0;
4693e12c5d1SDavid du Colombier 		}
4703e12c5d1SDavid du Colombier 	}
4713e12c5d1SDavid du Colombier 	blist[i].nextoff = -1;	/* this block is the end */
472219b2ee8SDavid du Colombier 	bfree = i + 1;
4733e12c5d1SDavid du Colombier 	if (blist[i].bp == 0)
4743e12c5d1SDavid du Colombier 		blist[i].bp = (Tchar *) calloc(BLK, sizeof(Tchar));
475219b2ee8SDavid du Colombier 	if (blist[i].bp == NULL) {
476219b2ee8SDavid du Colombier 		ERROR "can't allocate memory for string/macro definitions" WARN;
477219b2ee8SDavid du Colombier 		done2(2);
478219b2ee8SDavid du Colombier 	}
4793e12c5d1SDavid du Colombier 	nextb = (Offset) i * BLK;
4803e12c5d1SDavid du Colombier 	return nextb;
4813e12c5d1SDavid du Colombier }
4823e12c5d1SDavid du Colombier 
4833e12c5d1SDavid du Colombier 
ffree(Offset i)4843e12c5d1SDavid du Colombier void ffree(Offset i)	/* free list of blocks starting at blist(o) */
4853e12c5d1SDavid du Colombier {			/* (doesn't actually free the blocks, just the pointers) */
4863e12c5d1SDavid du Colombier 	int j;
4873e12c5d1SDavid du Colombier 
4883e12c5d1SDavid du Colombier 	for ( ; blist[j = bindex(i)].nextoff != -1; ) {
489219b2ee8SDavid du Colombier 		if (bfree > j)
490219b2ee8SDavid du Colombier 			bfree = j;
4913e12c5d1SDavid du Colombier 		i = blist[j].nextoff;
4923e12c5d1SDavid du Colombier 		blist[j].nextoff = 0;
4933e12c5d1SDavid du Colombier 	}
4943e12c5d1SDavid du Colombier 	blist[j].nextoff = 0;
4953e12c5d1SDavid du Colombier }
4963e12c5d1SDavid du Colombier 
4973e12c5d1SDavid du Colombier 
wbf(Tchar i)4983e12c5d1SDavid du Colombier void wbf(Tchar i)	/* store i into offset, get ready for next one */
4993e12c5d1SDavid du Colombier {
5003e12c5d1SDavid du Colombier 	int j, off;
5013e12c5d1SDavid du Colombier 
5023e12c5d1SDavid du Colombier 	if (!offset)
5033e12c5d1SDavid du Colombier 		return;
5043e12c5d1SDavid du Colombier 	j = bindex(offset);
505219b2ee8SDavid du Colombier 	if (i == 0)
506219b2ee8SDavid du Colombier 		contabp[savslot].emx = offset;
5073e12c5d1SDavid du Colombier 	off = boffset(offset);
508*14f51593SDavid du Colombier 	blist[j].bp[off] = i;
5093e12c5d1SDavid du Colombier 	offset++;
5103e12c5d1SDavid du Colombier 	if (pastend(offset)) {	/* off the end of this block */
5113e12c5d1SDavid du Colombier 		if (blist[j].nextoff == -1) {
5123e12c5d1SDavid du Colombier 			if ((nextb = alloc()) == -1) {
5133e12c5d1SDavid du Colombier 				ERROR "Out of temp file space" WARN;
5143e12c5d1SDavid du Colombier 				done2(01);
5153e12c5d1SDavid du Colombier 			}
5163e12c5d1SDavid du Colombier 			blist[j].nextoff = nextb;
5173e12c5d1SDavid du Colombier 		}
5183e12c5d1SDavid du Colombier 		offset = blist[j].nextoff;
5193e12c5d1SDavid du Colombier 	}
5203e12c5d1SDavid du Colombier }
5213e12c5d1SDavid du Colombier 
5223e12c5d1SDavid du Colombier 
rbf(void)5233e12c5d1SDavid du Colombier Tchar rbf(void)	/* return next char from blist[] block */
5243e12c5d1SDavid du Colombier {
5253e12c5d1SDavid du Colombier 	Tchar i, j;
5263e12c5d1SDavid du Colombier 
5273e12c5d1SDavid du Colombier 	if (ip == RD_OFFSET) {		/* for rdtty */
5283e12c5d1SDavid du Colombier 		if (j = rdtty())
5293e12c5d1SDavid du Colombier 			return(j);
5303e12c5d1SDavid du Colombier 		else
5313e12c5d1SDavid du Colombier 			return(popi());
5323e12c5d1SDavid du Colombier 	}
5333e12c5d1SDavid du Colombier 
5343e12c5d1SDavid du Colombier 	i = rbf0(ip);
5353e12c5d1SDavid du Colombier 	if (i == 0) {
5363e12c5d1SDavid du Colombier 		if (!app)
5373e12c5d1SDavid du Colombier 			i = popi();
5383e12c5d1SDavid du Colombier 		return(i);
5393e12c5d1SDavid du Colombier 	}
5403e12c5d1SDavid du Colombier 	ip = incoff(ip);
5413e12c5d1SDavid du Colombier 	return(i);
5423e12c5d1SDavid du Colombier }
5433e12c5d1SDavid du Colombier 
5443e12c5d1SDavid du Colombier 
xxxincoff(Offset p)5453e12c5d1SDavid du Colombier Offset xxxincoff(Offset p)		/* get next blist[] block */
5463e12c5d1SDavid du Colombier {
5473e12c5d1SDavid du Colombier 	p++;
5483e12c5d1SDavid du Colombier 	if (pastend(p)) {		/* off the end of this block */
5493e12c5d1SDavid du Colombier 		if ((p = blist[bindex(p-1)].nextoff) == -1) {	/* and nothing was allocated after it */
5503e12c5d1SDavid du Colombier 			ERROR "Bad storage allocation" WARN;
5513e12c5d1SDavid du Colombier 			done2(-5);
5523e12c5d1SDavid du Colombier 		}
5533e12c5d1SDavid du Colombier 	}
5543e12c5d1SDavid du Colombier 	return(p);
5553e12c5d1SDavid du Colombier }
5563e12c5d1SDavid du Colombier 
5573e12c5d1SDavid du Colombier 
popi(void)5583e12c5d1SDavid du Colombier Tchar popi(void)
5593e12c5d1SDavid du Colombier {
5603e12c5d1SDavid du Colombier 	Stack *p;
5613e12c5d1SDavid du Colombier 
5623e12c5d1SDavid du Colombier 	if (frame == stk)
5633e12c5d1SDavid du Colombier 		return(0);
5643e12c5d1SDavid du Colombier 	if (strflg)
5653e12c5d1SDavid du Colombier 		strflg--;
5663e12c5d1SDavid du Colombier 	p = nxf = frame;
5673e12c5d1SDavid du Colombier 	p->nargs = 0;
5683e12c5d1SDavid du Colombier 	frame = p->pframe;
5693e12c5d1SDavid du Colombier 	ip = p->pip;
5703e12c5d1SDavid du Colombier 	pendt = p->ppendt;
5713e12c5d1SDavid du Colombier 	lastpbp = p->lastpbp;
5723e12c5d1SDavid du Colombier 	return(p->pch);
5733e12c5d1SDavid du Colombier }
5743e12c5d1SDavid du Colombier 
5753e12c5d1SDavid du Colombier /*
5763e12c5d1SDavid du Colombier  *	test that the end of the allocation is above a certain location
5773e12c5d1SDavid du Colombier  *	in memory
5783e12c5d1SDavid du Colombier  */
5793e12c5d1SDavid du Colombier #define SPACETEST(base, size) \
5803e12c5d1SDavid du Colombier 	if ((char*)base + size >= (char*)stk+STACKSIZE) \
5813e12c5d1SDavid du Colombier 		ERROR "Stacksize overflow in n3" WARN
5823e12c5d1SDavid du Colombier 
pushi(Offset newip,int mname)5833e12c5d1SDavid du Colombier Offset pushi(Offset newip, int  mname)
5843e12c5d1SDavid du Colombier {
5853e12c5d1SDavid du Colombier 	Stack *p;
5863e12c5d1SDavid du Colombier 
5873e12c5d1SDavid du Colombier 	SPACETEST(nxf, sizeof(Stack));
5883e12c5d1SDavid du Colombier 	p = nxf;
5893e12c5d1SDavid du Colombier 	p->pframe = frame;
5903e12c5d1SDavid du Colombier 	p->pip = ip;
5913e12c5d1SDavid du Colombier 	p->ppendt = pendt;
5923e12c5d1SDavid du Colombier 	p->pch = ch;
5933e12c5d1SDavid du Colombier 	p->lastpbp = lastpbp;
5943e12c5d1SDavid du Colombier 	p->mname = mname;
5953e12c5d1SDavid du Colombier 	lastpbp = pbp;
5963e12c5d1SDavid du Colombier 	pendt = ch = 0;
5973e12c5d1SDavid du Colombier 	frame = nxf;
5983e12c5d1SDavid du Colombier 	if (nxf->nargs == 0)
5993e12c5d1SDavid du Colombier 		nxf += 1;
6003e12c5d1SDavid du Colombier 	else
6013e12c5d1SDavid du Colombier 		nxf = (Stack *)argtop;
6023e12c5d1SDavid du Colombier 	return(ip = newip);
6033e12c5d1SDavid du Colombier }
6043e12c5d1SDavid du Colombier 
6053e12c5d1SDavid du Colombier 
setbrk(int x)6063e12c5d1SDavid du Colombier void *setbrk(int x)
6073e12c5d1SDavid du Colombier {
6083e12c5d1SDavid du Colombier 	char *i;
6093e12c5d1SDavid du Colombier 
6103e12c5d1SDavid du Colombier 	if ((i = (char *) calloc(x, 1)) == 0) {
6113e12c5d1SDavid du Colombier 		ERROR "Core limit reached" WARN;
6123e12c5d1SDavid du Colombier 		edone(0100);
6133e12c5d1SDavid du Colombier 	}
6143e12c5d1SDavid du Colombier 	return(i);
6153e12c5d1SDavid du Colombier }
6163e12c5d1SDavid du Colombier 
6173e12c5d1SDavid du Colombier 
getsn(void)6183e12c5d1SDavid du Colombier int getsn(void)
6193e12c5d1SDavid du Colombier {
6203e12c5d1SDavid du Colombier 	int i;
6213e12c5d1SDavid du Colombier 
6223e12c5d1SDavid du Colombier 	if ((i = getach()) == 0)
6233e12c5d1SDavid du Colombier 		return(0);
6243e12c5d1SDavid du Colombier 	if (i == '(')
6253e12c5d1SDavid du Colombier 		return(getrq());
6263e12c5d1SDavid du Colombier 	else
6273e12c5d1SDavid du Colombier 		return(i);
6283e12c5d1SDavid du Colombier }
6293e12c5d1SDavid du Colombier 
6303e12c5d1SDavid du Colombier 
setstr(void)6313e12c5d1SDavid du Colombier Offset setstr(void)
6323e12c5d1SDavid du Colombier {
6333e12c5d1SDavid du Colombier 	int i, j;
6343e12c5d1SDavid du Colombier 
6353e12c5d1SDavid du Colombier 	lgf++;
636219b2ee8SDavid du Colombier 	if ((i = getsn()) == 0 || (j = findmn(i)) == -1 || !contabp[j].mx) {
6373e12c5d1SDavid du Colombier 		lgf--;
6383e12c5d1SDavid du Colombier 		return(0);
6393e12c5d1SDavid du Colombier 	} else {
6403e12c5d1SDavid du Colombier 		SPACETEST(nxf, sizeof(Stack));
6413e12c5d1SDavid du Colombier 		nxf->nargs = 0;
6423e12c5d1SDavid du Colombier 		strflg++;
6433e12c5d1SDavid du Colombier 		lgf--;
644219b2ee8SDavid du Colombier 		return pushi(contabp[j].mx, i);
6453e12c5d1SDavid du Colombier 	}
6463e12c5d1SDavid du Colombier }
6473e12c5d1SDavid du Colombier 
6483e12c5d1SDavid du Colombier 
6493e12c5d1SDavid du Colombier 
collect(void)6503e12c5d1SDavid du Colombier void collect(void)
6513e12c5d1SDavid du Colombier {
6523e12c5d1SDavid du Colombier 	int j;
6533e12c5d1SDavid du Colombier 	Tchar i, *strp, *lim, **argpp, **argppend;
6543e12c5d1SDavid du Colombier 	int quote;
6553e12c5d1SDavid du Colombier 	Stack *savnxf;
6563e12c5d1SDavid du Colombier 
6573e12c5d1SDavid du Colombier 	copyf++;
6583e12c5d1SDavid du Colombier 	nxf->nargs = 0;
6593e12c5d1SDavid du Colombier 	savnxf = nxf;
6603e12c5d1SDavid du Colombier 	if (skip())
6613e12c5d1SDavid du Colombier 		goto rtn;
6623e12c5d1SDavid du Colombier 
6633e12c5d1SDavid du Colombier 	{
6643e12c5d1SDavid du Colombier 		char *memp;
6653e12c5d1SDavid du Colombier 		memp = (char *)savnxf;
6663e12c5d1SDavid du Colombier 		/*
6673e12c5d1SDavid du Colombier 		 *	1 s structure for the macro descriptor
6683e12c5d1SDavid du Colombier 		 *	APERMAC Tchar *'s for pointers into the strings
6693e12c5d1SDavid du Colombier 		 *	space for the Tchar's themselves
6703e12c5d1SDavid du Colombier 		 */
6713e12c5d1SDavid du Colombier 		memp += sizeof(Stack);
6723e12c5d1SDavid du Colombier 		/*
6733e12c5d1SDavid du Colombier 		 *	CPERMAC = the total # of characters for ALL arguments
6743e12c5d1SDavid du Colombier 		 */
6753e12c5d1SDavid du Colombier #define	CPERMAC	200
6763e12c5d1SDavid du Colombier #define	APERMAC	9
6773e12c5d1SDavid du Colombier 		memp += APERMAC * sizeof(Tchar *);
6783e12c5d1SDavid du Colombier 		memp += CPERMAC * sizeof(Tchar);
6793e12c5d1SDavid du Colombier 		nxf = (Stack *)memp;
6803e12c5d1SDavid du Colombier 	}
6813e12c5d1SDavid du Colombier 	lim = (Tchar *)nxf;
6823e12c5d1SDavid du Colombier 	argpp = (Tchar **)(savnxf + 1);
6833e12c5d1SDavid du Colombier 	argppend = &argpp[APERMAC];
6843e12c5d1SDavid du Colombier 	SPACETEST(argppend, sizeof(Tchar *));
6853e12c5d1SDavid du Colombier 	strp = (Tchar *)argppend;
6863e12c5d1SDavid du Colombier 	/*
6873e12c5d1SDavid du Colombier 	 *	Zero out all the string pointers before filling them in.
6883e12c5d1SDavid du Colombier 	 */
6893e12c5d1SDavid du Colombier 	for (j = 0; j < APERMAC; j++)
6903e12c5d1SDavid du Colombier 		argpp[j] = 0;
6913e12c5d1SDavid du Colombier 	/* ERROR "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x, lim=0x%x",
6923e12c5d1SDavid du Colombier 	 * 	savnxf, nxf, argpp, strp, lim WARN;
6933e12c5d1SDavid du Colombier 	 */
6943e12c5d1SDavid du Colombier 	strflg = 0;
6953e12c5d1SDavid du Colombier 	while (argpp != argppend && !skip()) {
6963e12c5d1SDavid du Colombier 		*argpp++ = strp;
6973e12c5d1SDavid du Colombier 		quote = 0;
6983e12c5d1SDavid du Colombier 		if (cbits(i = getch()) == '"')
6993e12c5d1SDavid du Colombier 			quote++;
7003e12c5d1SDavid du Colombier 		else
7013e12c5d1SDavid du Colombier 			ch = i;
7023e12c5d1SDavid du Colombier 		while (1) {
7033e12c5d1SDavid du Colombier 			i = getch();
7043e12c5d1SDavid du Colombier /* fprintf(stderr, "collect %c %d\n", cbits(i), cbits(i)); */
7053e12c5d1SDavid du Colombier 			if (nlflg || (!quote && argpp != argppend && cbits(i) == ' '))
7063e12c5d1SDavid du Colombier 				break;	/* collects rest into $9 */
7073e12c5d1SDavid du Colombier 			if (   quote
7083e12c5d1SDavid du Colombier 			    && cbits(i) == '"'
7093e12c5d1SDavid du Colombier 			    && cbits(i = getch()) != '"') {
7103e12c5d1SDavid du Colombier 				ch = i;
7113e12c5d1SDavid du Colombier 				break;
7123e12c5d1SDavid du Colombier 			}
7133e12c5d1SDavid du Colombier 			*strp++ = i;
7143e12c5d1SDavid du Colombier 			if (strflg && strp >= lim) {
7153e12c5d1SDavid du Colombier 				/* ERROR "strp=0x%x, lim = 0x%x", strp, lim WARN; */
7163e12c5d1SDavid du Colombier 				ERROR "Macro argument too long" WARN;
7173e12c5d1SDavid du Colombier 				copyf--;
7183e12c5d1SDavid du Colombier 				edone(004);
7193e12c5d1SDavid du Colombier 			}
7203e12c5d1SDavid du Colombier 			SPACETEST(strp, 3 * sizeof(Tchar));
7213e12c5d1SDavid du Colombier 		}
7223e12c5d1SDavid du Colombier 		*strp++ = 0;
7233e12c5d1SDavid du Colombier 	}
7243e12c5d1SDavid du Colombier 	nxf = savnxf;
7253e12c5d1SDavid du Colombier 	nxf->nargs = argpp - (Tchar **)(savnxf + 1);
7263e12c5d1SDavid du Colombier 	argtop = strp;
7273e12c5d1SDavid du Colombier rtn:
7283e12c5d1SDavid du Colombier 	copyf--;
7293e12c5d1SDavid du Colombier }
7303e12c5d1SDavid du Colombier 
7313e12c5d1SDavid du Colombier 
seta(void)7323e12c5d1SDavid du Colombier void seta(void)
7333e12c5d1SDavid du Colombier {
7343e12c5d1SDavid du Colombier 	int i;
7353e12c5d1SDavid du Colombier 
7363e12c5d1SDavid du Colombier 	i = cbits(getch()) - '0';
7373e12c5d1SDavid du Colombier 	if (i > 0 && i <= APERMAC && i <= frame->nargs)
7383e12c5d1SDavid du Colombier 		pushback(*(((Tchar **)(frame + 1)) + i - 1));
7393e12c5d1SDavid du Colombier }
7403e12c5d1SDavid du Colombier 
7413e12c5d1SDavid du Colombier 
caseda(void)7423e12c5d1SDavid du Colombier void caseda(void)
7433e12c5d1SDavid du Colombier {
7443e12c5d1SDavid du Colombier 	app++;
7453e12c5d1SDavid du Colombier 	casedi();
7463e12c5d1SDavid du Colombier }
7473e12c5d1SDavid du Colombier 
casegd(void)748219b2ee8SDavid du Colombier void casegd(void)
749219b2ee8SDavid du Colombier {
750219b2ee8SDavid du Colombier 	int i, j;
751219b2ee8SDavid du Colombier 
752219b2ee8SDavid du Colombier 	skip();
753219b2ee8SDavid du Colombier 	if ((i = getrq()) == 0)
754219b2ee8SDavid du Colombier 		return;
755219b2ee8SDavid du Colombier 	if ((j = findmn(i)) >= 0) {
756219b2ee8SDavid du Colombier 		if (contabp[j].divsiz != NULL) {
757219b2ee8SDavid du Colombier 			numtabp[DN].val = contabp[j].divsiz->dix;
758219b2ee8SDavid du Colombier 			numtabp[DL].val = contabp[j].divsiz->diy;
759219b2ee8SDavid du Colombier 		}
760219b2ee8SDavid du Colombier 	}
761219b2ee8SDavid du Colombier }
762219b2ee8SDavid du Colombier 
763219b2ee8SDavid du Colombier #define FINDDIV(o) if ((o =  findmn(dip->curd)) < 0) \
764219b2ee8SDavid du Colombier 			ERROR "lost diversion %s", unpair(dip->curd) WARN
7653e12c5d1SDavid du Colombier 
casedi(void)7663e12c5d1SDavid du Colombier void casedi(void)
7673e12c5d1SDavid du Colombier {
7683e12c5d1SDavid du Colombier 	int i, j, *k;
7693e12c5d1SDavid du Colombier 
7703e12c5d1SDavid du Colombier 	lgf++;
7713e12c5d1SDavid du Colombier 	if (skip() || (i = getrq()) == 0) {
772219b2ee8SDavid du Colombier 		if (dip != d) {
773219b2ee8SDavid du Colombier 			FINDDIV(savslot);
7743e12c5d1SDavid du Colombier 			wbf((Tchar)0);
775219b2ee8SDavid du Colombier 		}
7763e12c5d1SDavid du Colombier 		if (dilev > 0) {
777219b2ee8SDavid du Colombier 			numtabp[DN].val = dip->dnl;
778219b2ee8SDavid du Colombier 			numtabp[DL].val = dip->maxl;
779219b2ee8SDavid du Colombier 			FINDDIV(j);
780219b2ee8SDavid du Colombier 			if ((contabp[j].divsiz = (Divsiz *) malloc(sizeof(Divsiz))) == NULL) {
78180ee5cbfSDavid du Colombier 				ERROR "Cannot alloc diversion size" WARN;
782219b2ee8SDavid du Colombier 				done2(1);
783219b2ee8SDavid du Colombier 			} else {
784219b2ee8SDavid du Colombier 				contabp[j].divsiz->dix = numtabp[DN].val;
785219b2ee8SDavid du Colombier 				contabp[j].divsiz->diy = numtabp[DL].val;
786219b2ee8SDavid du Colombier 			}
7873e12c5d1SDavid du Colombier 			dip = &d[--dilev];
7883e12c5d1SDavid du Colombier 			offset = dip->op;
7893e12c5d1SDavid du Colombier 		}
7903e12c5d1SDavid du Colombier 		goto rtn;
7913e12c5d1SDavid du Colombier 	}
7923e12c5d1SDavid du Colombier 	if (++dilev == NDI) {
7933e12c5d1SDavid du Colombier 		--dilev;
7943e12c5d1SDavid du Colombier 		ERROR "Diversions nested too deep" WARN;
7953e12c5d1SDavid du Colombier 		edone(02);
7963e12c5d1SDavid du Colombier 	}
797219b2ee8SDavid du Colombier 	if (dip != d) {
798219b2ee8SDavid du Colombier 		FINDDIV(j);
799219b2ee8SDavid du Colombier 		savslot = j;
8003e12c5d1SDavid du Colombier 		wbf((Tchar)0);
801219b2ee8SDavid du Colombier 	}
8023e12c5d1SDavid du Colombier 	diflg++;
8033e12c5d1SDavid du Colombier 	dip = &d[dilev];
8043e12c5d1SDavid du Colombier 	dip->op = finds(i);
8053e12c5d1SDavid du Colombier 	dip->curd = i;
8063e12c5d1SDavid du Colombier 	clrmn(oldmn);
8073e12c5d1SDavid du Colombier 	k = (int *) & dip->dnl;
8083e12c5d1SDavid du Colombier 	for (j = 0; j < 10; j++)
8093e12c5d1SDavid du Colombier 		k[j] = 0;	/*not op and curd*/
8103e12c5d1SDavid du Colombier rtn:
8113e12c5d1SDavid du Colombier 	app = 0;
8123e12c5d1SDavid du Colombier 	diflg = 0;
8133e12c5d1SDavid du Colombier }
8143e12c5d1SDavid du Colombier 
8153e12c5d1SDavid du Colombier 
casedt(void)8163e12c5d1SDavid du Colombier void casedt(void)
8173e12c5d1SDavid du Colombier {
8183e12c5d1SDavid du Colombier 	lgf++;
8193e12c5d1SDavid du Colombier 	dip->dimac = dip->ditrap = dip->ditf = 0;
8203e12c5d1SDavid du Colombier 	skip();
8213e12c5d1SDavid du Colombier 	dip->ditrap = vnumb((int *)0);
8223e12c5d1SDavid du Colombier 	if (nonumb)
8233e12c5d1SDavid du Colombier 		return;
8243e12c5d1SDavid du Colombier 	skip();
8253e12c5d1SDavid du Colombier 	dip->dimac = getrq();
8263e12c5d1SDavid du Colombier }
8273e12c5d1SDavid du Colombier 
828219b2ee8SDavid du Colombier #define LNSIZE 4000
casetl(void)8293e12c5d1SDavid du Colombier void casetl(void)
8303e12c5d1SDavid du Colombier {
8313e12c5d1SDavid du Colombier 	int j;
8323e12c5d1SDavid du Colombier 	int w[3];
8333e12c5d1SDavid du Colombier 	Tchar buf[LNSIZE];
8343e12c5d1SDavid du Colombier 	Tchar *tp;
8353e12c5d1SDavid du Colombier 	Tchar i, delim;
8363e12c5d1SDavid du Colombier 
8373e12c5d1SDavid du Colombier  	/*
8383e12c5d1SDavid du Colombier  	 * bug fix
8393e12c5d1SDavid du Colombier  	 *
8403e12c5d1SDavid du Colombier  	 * if .tl is the first thing in the file, the p1
8413e12c5d1SDavid du Colombier  	 * doesn't come out, also the pagenumber will be 0
8423e12c5d1SDavid du Colombier  	 *
8433e12c5d1SDavid du Colombier  	 * tends too confuse the device filter (and the user as well)
8443e12c5d1SDavid du Colombier  	 */
845219b2ee8SDavid du Colombier  	if (dip == d && numtabp[NL].val == -1)
8463e12c5d1SDavid du Colombier  		newline(1);
8473e12c5d1SDavid du Colombier 	dip->nls = 0;
8483e12c5d1SDavid du Colombier 	skip();
8493e12c5d1SDavid du Colombier 	if (ismot(delim = getch())) {
8503e12c5d1SDavid du Colombier 		ch = delim;
8513e12c5d1SDavid du Colombier 		delim = '\'';
8523e12c5d1SDavid du Colombier 	} else
8533e12c5d1SDavid du Colombier 		delim = cbits(delim);
8543e12c5d1SDavid du Colombier 	tp = buf;
855219b2ee8SDavid du Colombier 	numtabp[HP].val = 0;
8563e12c5d1SDavid du Colombier 	w[0] = w[1] = w[2] = 0;
8573e12c5d1SDavid du Colombier 	j = 0;
8583e12c5d1SDavid du Colombier 	while (cbits(i = getch()) != '\n') {
8593e12c5d1SDavid du Colombier 		if (cbits(i) == cbits(delim)) {
8603e12c5d1SDavid du Colombier 			if (j < 3)
861219b2ee8SDavid du Colombier 				w[j] = numtabp[HP].val;
862219b2ee8SDavid du Colombier 			numtabp[HP].val = 0;
863219b2ee8SDavid du Colombier 			if (w[j] != 0)
864219b2ee8SDavid du Colombier 				*tp++ = WORDSP;
8653e12c5d1SDavid du Colombier 			j++;
8663e12c5d1SDavid du Colombier 			*tp++ = 0;
8673e12c5d1SDavid du Colombier 		} else {
8683e12c5d1SDavid du Colombier 			if (cbits(i) == pagech) {
869219b2ee8SDavid du Colombier 				setn1(numtabp[PN].val, numtabp[findr('%')].fmt,
8703e12c5d1SDavid du Colombier 				      i&SFMASK);
8713e12c5d1SDavid du Colombier 				continue;
8723e12c5d1SDavid du Colombier 			}
873219b2ee8SDavid du Colombier 			numtabp[HP].val += width(i);
874219b2ee8SDavid du Colombier 			if (tp < &buf[LNSIZE-10]) {
875219b2ee8SDavid du Colombier 				if (cbits(i) == ' ' && *tp != WORDSP)
876219b2ee8SDavid du Colombier 					*tp++ = WORDSP;
8773e12c5d1SDavid du Colombier 				*tp++ = i;
878219b2ee8SDavid du Colombier 			} else {
879219b2ee8SDavid du Colombier 				ERROR "Overflow in casetl" WARN;
880219b2ee8SDavid du Colombier 			}
8813e12c5d1SDavid du Colombier 		}
8823e12c5d1SDavid du Colombier 	}
8833e12c5d1SDavid du Colombier 	if (j<3)
884219b2ee8SDavid du Colombier 		w[j] = numtabp[HP].val;
8853e12c5d1SDavid du Colombier 	*tp++ = 0;
8863e12c5d1SDavid du Colombier 	*tp++ = 0;
8873e12c5d1SDavid du Colombier 	*tp = 0;
8883e12c5d1SDavid du Colombier 	tp = buf;
8893e12c5d1SDavid du Colombier 	if (NROFF)
8903e12c5d1SDavid du Colombier 		horiz(po);
8913e12c5d1SDavid du Colombier 	while (i = *tp++)
8923e12c5d1SDavid du Colombier 		pchar(i);
8933e12c5d1SDavid du Colombier 	if (w[1] || w[2])
8943e12c5d1SDavid du Colombier 		horiz(j = quant((lt - w[1]) / 2 - w[0], HOR));
8953e12c5d1SDavid du Colombier 	while (i = *tp++)
8963e12c5d1SDavid du Colombier 		pchar(i);
8973e12c5d1SDavid du Colombier 	if (w[2]) {
8983e12c5d1SDavid du Colombier 		horiz(lt - w[0] - w[1] - w[2] - j);
8993e12c5d1SDavid du Colombier 		while (i = *tp++)
9003e12c5d1SDavid du Colombier 			pchar(i);
9013e12c5d1SDavid du Colombier 	}
9023e12c5d1SDavid du Colombier 	newline(0);
9033e12c5d1SDavid du Colombier 	if (dip != d) {
9043e12c5d1SDavid du Colombier 		if (dip->dnl > dip->hnl)
9053e12c5d1SDavid du Colombier 			dip->hnl = dip->dnl;
9063e12c5d1SDavid du Colombier 	} else {
907219b2ee8SDavid du Colombier 		if (numtabp[NL].val > dip->hnl)
908219b2ee8SDavid du Colombier 			dip->hnl = numtabp[NL].val;
9093e12c5d1SDavid du Colombier 	}
9103e12c5d1SDavid du Colombier }
9113e12c5d1SDavid du Colombier 
9123e12c5d1SDavid du Colombier 
casepc(void)9133e12c5d1SDavid du Colombier void casepc(void)
9143e12c5d1SDavid du Colombier {
9153e12c5d1SDavid du Colombier 	pagech = chget(IMP);
9163e12c5d1SDavid du Colombier }
9173e12c5d1SDavid du Colombier 
9183e12c5d1SDavid du Colombier 
casepm(void)9193e12c5d1SDavid du Colombier void casepm(void)
9203e12c5d1SDavid du Colombier {
9213e12c5d1SDavid du Colombier 	int i, k;
9223e12c5d1SDavid du Colombier 	int xx, cnt, tcnt, kk, tot;
9233e12c5d1SDavid du Colombier 	Offset j;
9243e12c5d1SDavid du Colombier 
9253e12c5d1SDavid du Colombier 	kk = cnt = tcnt = 0;
9263e12c5d1SDavid du Colombier 	tot = !skip();
9273e12c5d1SDavid du Colombier 	stackdump();
928219b2ee8SDavid du Colombier 	for (i = 0; i < nm; i++) {
929219b2ee8SDavid du Colombier 		if ((xx = contabp[i].rq) == 0 || contabp[i].mx == 0)
9303e12c5d1SDavid du Colombier 			continue;
9313e12c5d1SDavid du Colombier 		tcnt++;
932219b2ee8SDavid du Colombier 		j = contabp[i].mx;
9333e12c5d1SDavid du Colombier 		for (k = 1; (j = blist[bindex(j)].nextoff) != -1; )
9343e12c5d1SDavid du Colombier 			k++;
9353e12c5d1SDavid du Colombier 		cnt++;
9363e12c5d1SDavid du Colombier 		kk += k;
9373e12c5d1SDavid du Colombier 		if (!tot)
9383e12c5d1SDavid du Colombier 			fprintf(stderr, "%-2.2s %d\n", unpair(xx), k);
9393e12c5d1SDavid du Colombier 	}
9403e12c5d1SDavid du Colombier 	fprintf(stderr, "pm: total %d, macros %d, space %d\n", tcnt, cnt, kk);
9413e12c5d1SDavid du Colombier }
9423e12c5d1SDavid du Colombier 
stackdump(void)9433e12c5d1SDavid du Colombier void stackdump(void)	/* dumps stack of macros in process */
9443e12c5d1SDavid du Colombier {
9453e12c5d1SDavid du Colombier 	Stack *p;
9463e12c5d1SDavid du Colombier 
9473e12c5d1SDavid du Colombier 	if (frame != stk) {
9483e12c5d1SDavid du Colombier 		fprintf(stderr, "stack: ");
9493e12c5d1SDavid du Colombier 		for (p = frame; p != stk; p = p->pframe)
9503e12c5d1SDavid du Colombier 			fprintf(stderr, "%s ", unpair(p->mname));
9513e12c5d1SDavid du Colombier 		fprintf(stderr, "\n");
9523e12c5d1SDavid du Colombier 	}
9533e12c5d1SDavid du Colombier }
954