xref: /plan9/sys/src/cmd/troff/n2.c (revision 14f51593fd82e19ba95969a8c07ff71131015979)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  * n2.c
33e12c5d1SDavid du Colombier  *
43e12c5d1SDavid du Colombier  * output, cleanup
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 #include <setjmp.h>
113e12c5d1SDavid du Colombier 
12219b2ee8SDavid du Colombier #ifdef STRICT
13219b2ee8SDavid du Colombier 	/* not in ANSI or POSIX */
14219b2ee8SDavid du Colombier FILE*	popen(char*, char*);
15219b2ee8SDavid du Colombier #endif
163e12c5d1SDavid du Colombier 
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier extern	jmp_buf	sjbuf;
193e12c5d1SDavid du Colombier int	toolate;
203e12c5d1SDavid du Colombier int	error;
213e12c5d1SDavid du Colombier 
223e12c5d1SDavid du Colombier char	obuf[2*BUFSIZ];
233e12c5d1SDavid du Colombier char	*obufp = obuf;
243e12c5d1SDavid du Colombier 
25219b2ee8SDavid du Colombier 	/* pipe command structure; allows redicously long commends for .pi */
26219b2ee8SDavid du Colombier struct Pipe {
27219b2ee8SDavid du Colombier 	char	*buf;
28219b2ee8SDavid du Colombier 	int	tick;
29219b2ee8SDavid du Colombier 	int	cnt;
30219b2ee8SDavid du Colombier } Pipe;
31219b2ee8SDavid du Colombier 
32219b2ee8SDavid du Colombier 
333e12c5d1SDavid du Colombier int	xon	= 0;	/* records if in middle of \X */
343e12c5d1SDavid du Colombier 
pchar(Tchar i)353e12c5d1SDavid du Colombier int pchar(Tchar i)
363e12c5d1SDavid du Colombier {
373e12c5d1SDavid du Colombier 	int j;
383e12c5d1SDavid du Colombier 	static int hx = 0;	/* records if have seen HX */
393e12c5d1SDavid du Colombier 
403e12c5d1SDavid du Colombier 	if (hx) {
413e12c5d1SDavid du Colombier 		hx = 0;
423e12c5d1SDavid du Colombier 		j = absmot(i);
433e12c5d1SDavid du Colombier 		if (isnmot(i)) {
443e12c5d1SDavid du Colombier 			if (j > dip->blss)
453e12c5d1SDavid du Colombier 				dip->blss = j;
463e12c5d1SDavid du Colombier 		} else {
473e12c5d1SDavid du Colombier 			if (j > dip->alss)
483e12c5d1SDavid du Colombier 				dip->alss = j;
493e12c5d1SDavid du Colombier 			ralss = dip->alss;
503e12c5d1SDavid du Colombier 		}
513e12c5d1SDavid du Colombier 		return 0;
523e12c5d1SDavid du Colombier 	}
533e12c5d1SDavid du Colombier 	if (ismot(i)) {
543e12c5d1SDavid du Colombier 		pchar1(i);
553e12c5d1SDavid du Colombier 		return 0;
563e12c5d1SDavid du Colombier 	}
573e12c5d1SDavid du Colombier 	switch (j = cbits(i)) {
583e12c5d1SDavid du Colombier 	case 0:
593e12c5d1SDavid du Colombier 	case IMP:
603e12c5d1SDavid du Colombier 	case RIGHT:
613e12c5d1SDavid du Colombier 	case LEFT:
623e12c5d1SDavid du Colombier 		return 0;
633e12c5d1SDavid du Colombier 	case HX:
643e12c5d1SDavid du Colombier 		hx = 1;
653e12c5d1SDavid du Colombier 		return 0;
663e12c5d1SDavid du Colombier 	case XON:
673e12c5d1SDavid du Colombier 		xon++;
683e12c5d1SDavid du Colombier 		break;
693e12c5d1SDavid du Colombier 	case XOFF:
703e12c5d1SDavid du Colombier 		xon--;
713e12c5d1SDavid du Colombier 		break;
723e12c5d1SDavid du Colombier 	case PRESC:
733e12c5d1SDavid du Colombier 		if (!xon && !tflg && dip == &d[0])
743e12c5d1SDavid du Colombier 			j = eschar;	/* fall through */
753e12c5d1SDavid du Colombier 	default:
763e12c5d1SDavid du Colombier 		setcbits(i, trtab[j]);
773e12c5d1SDavid du Colombier 	}
78*223a736eSDavid du Colombier 	if (NROFF & xon)	/* rob fix for man2html */
79*223a736eSDavid du Colombier 		return 0;
803e12c5d1SDavid du Colombier 	pchar1(i);
813e12c5d1SDavid du Colombier 	return 0;
823e12c5d1SDavid du Colombier }
833e12c5d1SDavid du Colombier 
843e12c5d1SDavid du Colombier 
pchar1(Tchar i)853e12c5d1SDavid du Colombier void pchar1(Tchar i)
863e12c5d1SDavid du Colombier {
873e12c5d1SDavid du Colombier 	int j;
883e12c5d1SDavid du Colombier 
893e12c5d1SDavid du Colombier 	j = cbits(i);
903e12c5d1SDavid du Colombier 	if (dip != &d[0]) {
913e12c5d1SDavid du Colombier 		wbf(i);
923e12c5d1SDavid du Colombier 		dip->op = offset;
933e12c5d1SDavid du Colombier 		return;
943e12c5d1SDavid du Colombier 	}
953e12c5d1SDavid du Colombier 	if (!tflg && !print) {
963e12c5d1SDavid du Colombier 		if (j == '\n')
973e12c5d1SDavid du Colombier 			dip->alss = dip->blss = 0;
983e12c5d1SDavid du Colombier 		return;
993e12c5d1SDavid du Colombier 	}
1003e12c5d1SDavid du Colombier 	if (j == FILLER && !xon)
1013e12c5d1SDavid du Colombier 		return;
1023e12c5d1SDavid du Colombier 	if (tflg) {	/* transparent mode, undiverted */
1033e12c5d1SDavid du Colombier 		if (print)			/* assumes that it's ok to print */
1043e12c5d1SDavid du Colombier 			/* OUT "%c", j PUT;	/* i.e., is ascii */
1053e12c5d1SDavid du Colombier 			outascii(i);
1063e12c5d1SDavid du Colombier 		return;
1073e12c5d1SDavid du Colombier 	}
1083e12c5d1SDavid du Colombier 	if (TROFF && ascii)
1093e12c5d1SDavid du Colombier 		outascii(i);
1103e12c5d1SDavid du Colombier 	else
1113e12c5d1SDavid du Colombier 		ptout(i);
1123e12c5d1SDavid du Colombier }
1133e12c5d1SDavid du Colombier 
1143e12c5d1SDavid du Colombier 
outweird(int k)115219b2ee8SDavid du Colombier void outweird(int k)	/* like ptchname() but ascii */
116219b2ee8SDavid du Colombier {
117219b2ee8SDavid du Colombier 	char *chn = chname(k);
118219b2ee8SDavid du Colombier 
119219b2ee8SDavid du Colombier 	switch (chn[0]) {
120219b2ee8SDavid du Colombier 	case MBchar:
121219b2ee8SDavid du Colombier 		OUT "%s", chn+1 PUT;	/* \n not needed? */
122219b2ee8SDavid du Colombier 		break;
123219b2ee8SDavid du Colombier 	case Number:
124219b2ee8SDavid du Colombier 		OUT "\\N'%s'", chn+1 PUT;
125219b2ee8SDavid du Colombier 		break;
126219b2ee8SDavid du Colombier 	case Troffchar:
127219b2ee8SDavid du Colombier 		if (strlen(chn+1) == 2)
128219b2ee8SDavid du Colombier 			OUT "\\(%s", chn+1 PUT;
129219b2ee8SDavid du Colombier 		else
130219b2ee8SDavid du Colombier 			OUT "\\C'%s'", chn+1 PUT;
131219b2ee8SDavid du Colombier 		break;
132219b2ee8SDavid du Colombier 	default:
133219b2ee8SDavid du Colombier 		OUT " %s? ", chn PUT;
134219b2ee8SDavid du Colombier 		break;
135219b2ee8SDavid du Colombier 	}
136219b2ee8SDavid du Colombier }
137219b2ee8SDavid du Colombier 
outascii(Tchar i)1383e12c5d1SDavid du Colombier void outascii(Tchar i)	/* print i in best-guess ascii */
1393e12c5d1SDavid du Colombier {
1403e12c5d1SDavid du Colombier 	int j = cbits(i);
1413e12c5d1SDavid du Colombier 
1423e12c5d1SDavid du Colombier /* is this ever called with NROFF set? probably doesn't work at all. */
1433e12c5d1SDavid du Colombier 
1443e12c5d1SDavid du Colombier 	if (ismot(i))
1453e12c5d1SDavid du Colombier 		oput(' ');
1463e12c5d1SDavid du Colombier 	else if (j < ALPHABET && j >= ' ' || j == '\n' || j == '\t')
1473e12c5d1SDavid du Colombier 		oput(j);
1483e12c5d1SDavid du Colombier 	else if (j == DRAWFCN)
1493e12c5d1SDavid du Colombier 		oputs("\\D");
1503e12c5d1SDavid du Colombier 	else if (j == HYPHEN)
1513e12c5d1SDavid du Colombier 		oput('-');
1523e12c5d1SDavid du Colombier 	else if (j == MINUS)	/* special pleading for strange encodings */
1533e12c5d1SDavid du Colombier 		oputs("\\-");
1543e12c5d1SDavid du Colombier 	else if (j == PRESC)
1553e12c5d1SDavid du Colombier 		oputs("\\e");
1563e12c5d1SDavid du Colombier 	else if (j == FILLER)
1573e12c5d1SDavid du Colombier 		oputs("\\&");
1583e12c5d1SDavid du Colombier 	else if (j == UNPAD)
1593e12c5d1SDavid du Colombier 		oputs("\\ ");
1603e12c5d1SDavid du Colombier 	else if (j == OHC)	/* this will never occur;  stripped out earlier */
1613e12c5d1SDavid du Colombier 		oputs("\\%");
1623e12c5d1SDavid du Colombier 	else if (j == XON)
1633e12c5d1SDavid du Colombier 		oputs("\\X");
1643e12c5d1SDavid du Colombier 	else if (j == XOFF)
1653e12c5d1SDavid du Colombier 		oputs(" ");
1663e12c5d1SDavid du Colombier 	else if (j == LIG_FI)
1673e12c5d1SDavid du Colombier 		oputs("fi");
1683e12c5d1SDavid du Colombier 	else if (j == LIG_FL)
1693e12c5d1SDavid du Colombier 		oputs("fl");
1703e12c5d1SDavid du Colombier 	else if (j == LIG_FF)
1713e12c5d1SDavid du Colombier 		oputs("ff");
1723e12c5d1SDavid du Colombier 	else if (j == LIG_FFI)
1733e12c5d1SDavid du Colombier 		oputs("ffi");
1743e12c5d1SDavid du Colombier 	else if (j == LIG_FFL)
1753e12c5d1SDavid du Colombier 		oputs("ffl");
1763e12c5d1SDavid du Colombier 	else if (j == WORDSP) {		/* nothing at all */
1773e12c5d1SDavid du Colombier 		if (xon)		/* except in \X */
1783e12c5d1SDavid du Colombier 			oput(' ');
179219b2ee8SDavid du Colombier 
1803e12c5d1SDavid du Colombier 	} else
1813e12c5d1SDavid du Colombier 		outweird(j);
1823e12c5d1SDavid du Colombier }
1833e12c5d1SDavid du Colombier 
flusho(void)1843e12c5d1SDavid du Colombier int flusho(void)
1853e12c5d1SDavid du Colombier {
186219b2ee8SDavid du Colombier 	if (NROFF && !toolate && t.twinit)
1873e12c5d1SDavid du Colombier 			fwrite(t.twinit, strlen(t.twinit), 1, ptid);
1883e12c5d1SDavid du Colombier 
1893e12c5d1SDavid du Colombier 	if (obufp > obuf) {
190219b2ee8SDavid du Colombier 		if (pipeflg && !toolate) {
191219b2ee8SDavid du Colombier 			/* fprintf(stderr, "Pipe to <%s>\n", Pipe.buf); */
192219b2ee8SDavid du Colombier 			if (!Pipe.buf[0] || (ptid = popen(Pipe.buf, "w")) == NULL)
193219b2ee8SDavid du Colombier 				ERROR "pipe %s not created.", Pipe.buf WARN;
194219b2ee8SDavid du Colombier 			if (Pipe.buf)
195219b2ee8SDavid du Colombier 				free(Pipe.buf);
196219b2ee8SDavid du Colombier 		}
197219b2ee8SDavid du Colombier 		if (!toolate)
198219b2ee8SDavid du Colombier 			toolate++;
1993e12c5d1SDavid du Colombier 		*obufp = 0;
2003e12c5d1SDavid du Colombier 		fputs(obuf, ptid);
2013e12c5d1SDavid du Colombier 		fflush(ptid);
2023e12c5d1SDavid du Colombier 		obufp = obuf;
2033e12c5d1SDavid du Colombier 	}
2043e12c5d1SDavid du Colombier 	return 1;
2053e12c5d1SDavid du Colombier }
2063e12c5d1SDavid du Colombier 
2073e12c5d1SDavid du Colombier 
caseex(void)2083e12c5d1SDavid du Colombier void caseex(void)
2093e12c5d1SDavid du Colombier {
2103e12c5d1SDavid du Colombier 	done(0);
2113e12c5d1SDavid du Colombier }
2123e12c5d1SDavid du Colombier 
2133e12c5d1SDavid du Colombier 
done(int x)2143e12c5d1SDavid du Colombier void done(int x)
2153e12c5d1SDavid du Colombier {
2163e12c5d1SDavid du Colombier 	int i;
2173e12c5d1SDavid du Colombier 
2183e12c5d1SDavid du Colombier 	error |= x;
2193e12c5d1SDavid du Colombier 	app = ds = lgf = 0;
2203e12c5d1SDavid du Colombier 	if (i = em) {
2213e12c5d1SDavid du Colombier 		donef = -1;
222219b2ee8SDavid du Colombier 		eschar = '\\';
2233e12c5d1SDavid du Colombier 		em = 0;
2243e12c5d1SDavid du Colombier 		if (control(i, 0))
2253e12c5d1SDavid du Colombier 			longjmp(sjbuf, 1);
2263e12c5d1SDavid du Colombier 	}
2273e12c5d1SDavid du Colombier 	if (!nfo)
2283e12c5d1SDavid du Colombier 		done3(0);
2293e12c5d1SDavid du Colombier 	mflg = 0;
2303e12c5d1SDavid du Colombier 	dip = &d[0];
2313e12c5d1SDavid du Colombier 	if (woff)	/* BUG!!! This isn't set anywhere */
2323e12c5d1SDavid du Colombier 		wbf((Tchar)0);
2333e12c5d1SDavid du Colombier 	if (pendw)
2343e12c5d1SDavid du Colombier 		getword(1);
2353e12c5d1SDavid du Colombier 	pendnf = 0;
2363e12c5d1SDavid du Colombier 	if (donef == 1)
2373e12c5d1SDavid du Colombier 		done1(0);
2383e12c5d1SDavid du Colombier 	donef = 1;
2393e12c5d1SDavid du Colombier 	ip = 0;
2403e12c5d1SDavid du Colombier 	frame = stk;
2413e12c5d1SDavid du Colombier 	nxf = frame + 1;
2423e12c5d1SDavid du Colombier 	if (!ejf)
2433e12c5d1SDavid du Colombier 		tbreak();
2443e12c5d1SDavid du Colombier 	nflush++;
2453e12c5d1SDavid du Colombier 	eject((Stack *)0);
2463e12c5d1SDavid du Colombier 	longjmp(sjbuf, 1);
2473e12c5d1SDavid du Colombier }
2483e12c5d1SDavid du Colombier 
2493e12c5d1SDavid du Colombier 
done1(int x)2503e12c5d1SDavid du Colombier void done1(int x)
2513e12c5d1SDavid du Colombier {
2523e12c5d1SDavid du Colombier 	error |= x;
253219b2ee8SDavid du Colombier 	if (numtabp[NL].val) {
2543e12c5d1SDavid du Colombier 		trap = 0;
2553e12c5d1SDavid du Colombier 		eject((Stack *)0);
2563e12c5d1SDavid du Colombier 		longjmp(sjbuf, 1);
2573e12c5d1SDavid du Colombier 	}
2583e12c5d1SDavid du Colombier 	if (!ascii)
2593e12c5d1SDavid du Colombier 		pttrailer();
2603e12c5d1SDavid du Colombier 	done2(0);
2613e12c5d1SDavid du Colombier }
2623e12c5d1SDavid du Colombier 
2633e12c5d1SDavid du Colombier 
done2(int x)2643e12c5d1SDavid du Colombier void done2(int x)
2653e12c5d1SDavid du Colombier {
2663e12c5d1SDavid du Colombier 	ptlead();
2673e12c5d1SDavid du Colombier 	if (TROFF && !ascii)
2683e12c5d1SDavid du Colombier 		ptstop();
2693e12c5d1SDavid du Colombier 	flusho();
2703e12c5d1SDavid du Colombier 	done3(x);
2713e12c5d1SDavid du Colombier }
2723e12c5d1SDavid du Colombier 
done3(int x)2733e12c5d1SDavid du Colombier void done3(int x)
2743e12c5d1SDavid du Colombier {
2753e12c5d1SDavid du Colombier 	error |= x;
2763e12c5d1SDavid du Colombier 	flusho();
2773e12c5d1SDavid du Colombier 	if (NROFF)
2783e12c5d1SDavid du Colombier 		twdone();
2793e12c5d1SDavid du Colombier 	if (pipeflg)
2803e12c5d1SDavid du Colombier 		pclose(ptid);
2813e12c5d1SDavid du Colombier 	exit(error);
2823e12c5d1SDavid du Colombier }
2833e12c5d1SDavid du Colombier 
2843e12c5d1SDavid du Colombier 
edone(int x)2853e12c5d1SDavid du Colombier void edone(int x)
2863e12c5d1SDavid du Colombier {
2873e12c5d1SDavid du Colombier 	frame = stk;
2883e12c5d1SDavid du Colombier 	nxf = frame + 1;
2893e12c5d1SDavid du Colombier 	ip = 0;
2903e12c5d1SDavid du Colombier 	done(x);
2913e12c5d1SDavid du Colombier }
2923e12c5d1SDavid du Colombier 
2933e12c5d1SDavid du Colombier 
casepi(void)2943e12c5d1SDavid du Colombier void casepi(void)
2953e12c5d1SDavid du Colombier {
296219b2ee8SDavid du Colombier 	int j;
2973e12c5d1SDavid du Colombier 	char buf[NTM];
2983e12c5d1SDavid du Colombier 
299219b2ee8SDavid du Colombier 	if (Pipe.buf == NULL) {
300219b2ee8SDavid du Colombier 		if ((Pipe.buf = (char *)calloc(NTM, sizeof(char))) == NULL) {
301219b2ee8SDavid du Colombier 			ERROR "No buf space for pipe cmd" WARN;
3023e12c5d1SDavid du Colombier 			return;
3033e12c5d1SDavid du Colombier 		}
304219b2ee8SDavid du Colombier 		Pipe.tick = 1;
305219b2ee8SDavid du Colombier 	} else
306219b2ee8SDavid du Colombier 		Pipe.buf[Pipe.cnt++] = '|';
307219b2ee8SDavid du Colombier 
308219b2ee8SDavid du Colombier 	getline(buf, NTM);
309219b2ee8SDavid du Colombier 	j = strlen(buf);
310219b2ee8SDavid du Colombier 	if (toolate) {
311219b2ee8SDavid du Colombier 		ERROR "Cannot create pipe to %s", buf WARN;
312219b2ee8SDavid du Colombier 		return;
313219b2ee8SDavid du Colombier 	}
314219b2ee8SDavid du Colombier 	Pipe.cnt += j;
315219b2ee8SDavid du Colombier 	if (j >= NTM +1) {
316219b2ee8SDavid du Colombier 		Pipe.tick++;
317219b2ee8SDavid du Colombier 		if ((Pipe.buf = (char *)realloc(Pipe.buf, Pipe.tick * NTM * sizeof(char))) == NULL) {
318219b2ee8SDavid du Colombier 			ERROR "No more buf space for pipe cmd" WARN;
319219b2ee8SDavid du Colombier 			return;
320219b2ee8SDavid du Colombier 		}
321219b2ee8SDavid du Colombier 	}
322219b2ee8SDavid du Colombier 	strcat(Pipe.buf, buf);
3233e12c5d1SDavid du Colombier 	pipeflg++;
3243e12c5d1SDavid du Colombier }
325