xref: /plan9/sys/src/cmd/troff/n2.c (revision 14f51593fd82e19ba95969a8c07ff71131015979)
1 /*
2  * n2.c
3  *
4  * output, cleanup
5  */
6 
7 #include "tdef.h"
8 #include "fns.h"
9 #include "ext.h"
10 #include <setjmp.h>
11 
12 #ifdef STRICT
13 	/* not in ANSI or POSIX */
14 FILE*	popen(char*, char*);
15 #endif
16 
17 
18 extern	jmp_buf	sjbuf;
19 int	toolate;
20 int	error;
21 
22 char	obuf[2*BUFSIZ];
23 char	*obufp = obuf;
24 
25 	/* pipe command structure; allows redicously long commends for .pi */
26 struct Pipe {
27 	char	*buf;
28 	int	tick;
29 	int	cnt;
30 } Pipe;
31 
32 
33 int	xon	= 0;	/* records if in middle of \X */
34 
pchar(Tchar i)35 int pchar(Tchar i)
36 {
37 	int j;
38 	static int hx = 0;	/* records if have seen HX */
39 
40 	if (hx) {
41 		hx = 0;
42 		j = absmot(i);
43 		if (isnmot(i)) {
44 			if (j > dip->blss)
45 				dip->blss = j;
46 		} else {
47 			if (j > dip->alss)
48 				dip->alss = j;
49 			ralss = dip->alss;
50 		}
51 		return 0;
52 	}
53 	if (ismot(i)) {
54 		pchar1(i);
55 		return 0;
56 	}
57 	switch (j = cbits(i)) {
58 	case 0:
59 	case IMP:
60 	case RIGHT:
61 	case LEFT:
62 		return 0;
63 	case HX:
64 		hx = 1;
65 		return 0;
66 	case XON:
67 		xon++;
68 		break;
69 	case XOFF:
70 		xon--;
71 		break;
72 	case PRESC:
73 		if (!xon && !tflg && dip == &d[0])
74 			j = eschar;	/* fall through */
75 	default:
76 		setcbits(i, trtab[j]);
77 	}
78 	if (NROFF & xon)	/* rob fix for man2html */
79 		return 0;
80 	pchar1(i);
81 	return 0;
82 }
83 
84 
pchar1(Tchar i)85 void pchar1(Tchar i)
86 {
87 	int j;
88 
89 	j = cbits(i);
90 	if (dip != &d[0]) {
91 		wbf(i);
92 		dip->op = offset;
93 		return;
94 	}
95 	if (!tflg && !print) {
96 		if (j == '\n')
97 			dip->alss = dip->blss = 0;
98 		return;
99 	}
100 	if (j == FILLER && !xon)
101 		return;
102 	if (tflg) {	/* transparent mode, undiverted */
103 		if (print)			/* assumes that it's ok to print */
104 			/* OUT "%c", j PUT;	/* i.e., is ascii */
105 			outascii(i);
106 		return;
107 	}
108 	if (TROFF && ascii)
109 		outascii(i);
110 	else
111 		ptout(i);
112 }
113 
114 
outweird(int k)115 void outweird(int k)	/* like ptchname() but ascii */
116 {
117 	char *chn = chname(k);
118 
119 	switch (chn[0]) {
120 	case MBchar:
121 		OUT "%s", chn+1 PUT;	/* \n not needed? */
122 		break;
123 	case Number:
124 		OUT "\\N'%s'", chn+1 PUT;
125 		break;
126 	case Troffchar:
127 		if (strlen(chn+1) == 2)
128 			OUT "\\(%s", chn+1 PUT;
129 		else
130 			OUT "\\C'%s'", chn+1 PUT;
131 		break;
132 	default:
133 		OUT " %s? ", chn PUT;
134 		break;
135 	}
136 }
137 
outascii(Tchar i)138 void outascii(Tchar i)	/* print i in best-guess ascii */
139 {
140 	int j = cbits(i);
141 
142 /* is this ever called with NROFF set? probably doesn't work at all. */
143 
144 	if (ismot(i))
145 		oput(' ');
146 	else if (j < ALPHABET && j >= ' ' || j == '\n' || j == '\t')
147 		oput(j);
148 	else if (j == DRAWFCN)
149 		oputs("\\D");
150 	else if (j == HYPHEN)
151 		oput('-');
152 	else if (j == MINUS)	/* special pleading for strange encodings */
153 		oputs("\\-");
154 	else if (j == PRESC)
155 		oputs("\\e");
156 	else if (j == FILLER)
157 		oputs("\\&");
158 	else if (j == UNPAD)
159 		oputs("\\ ");
160 	else if (j == OHC)	/* this will never occur;  stripped out earlier */
161 		oputs("\\%");
162 	else if (j == XON)
163 		oputs("\\X");
164 	else if (j == XOFF)
165 		oputs(" ");
166 	else if (j == LIG_FI)
167 		oputs("fi");
168 	else if (j == LIG_FL)
169 		oputs("fl");
170 	else if (j == LIG_FF)
171 		oputs("ff");
172 	else if (j == LIG_FFI)
173 		oputs("ffi");
174 	else if (j == LIG_FFL)
175 		oputs("ffl");
176 	else if (j == WORDSP) {		/* nothing at all */
177 		if (xon)		/* except in \X */
178 			oput(' ');
179 
180 	} else
181 		outweird(j);
182 }
183 
flusho(void)184 int flusho(void)
185 {
186 	if (NROFF && !toolate && t.twinit)
187 			fwrite(t.twinit, strlen(t.twinit), 1, ptid);
188 
189 	if (obufp > obuf) {
190 		if (pipeflg && !toolate) {
191 			/* fprintf(stderr, "Pipe to <%s>\n", Pipe.buf); */
192 			if (!Pipe.buf[0] || (ptid = popen(Pipe.buf, "w")) == NULL)
193 				ERROR "pipe %s not created.", Pipe.buf WARN;
194 			if (Pipe.buf)
195 				free(Pipe.buf);
196 		}
197 		if (!toolate)
198 			toolate++;
199 		*obufp = 0;
200 		fputs(obuf, ptid);
201 		fflush(ptid);
202 		obufp = obuf;
203 	}
204 	return 1;
205 }
206 
207 
caseex(void)208 void caseex(void)
209 {
210 	done(0);
211 }
212 
213 
done(int x)214 void done(int x)
215 {
216 	int i;
217 
218 	error |= x;
219 	app = ds = lgf = 0;
220 	if (i = em) {
221 		donef = -1;
222 		eschar = '\\';
223 		em = 0;
224 		if (control(i, 0))
225 			longjmp(sjbuf, 1);
226 	}
227 	if (!nfo)
228 		done3(0);
229 	mflg = 0;
230 	dip = &d[0];
231 	if (woff)	/* BUG!!! This isn't set anywhere */
232 		wbf((Tchar)0);
233 	if (pendw)
234 		getword(1);
235 	pendnf = 0;
236 	if (donef == 1)
237 		done1(0);
238 	donef = 1;
239 	ip = 0;
240 	frame = stk;
241 	nxf = frame + 1;
242 	if (!ejf)
243 		tbreak();
244 	nflush++;
245 	eject((Stack *)0);
246 	longjmp(sjbuf, 1);
247 }
248 
249 
done1(int x)250 void done1(int x)
251 {
252 	error |= x;
253 	if (numtabp[NL].val) {
254 		trap = 0;
255 		eject((Stack *)0);
256 		longjmp(sjbuf, 1);
257 	}
258 	if (!ascii)
259 		pttrailer();
260 	done2(0);
261 }
262 
263 
done2(int x)264 void done2(int x)
265 {
266 	ptlead();
267 	if (TROFF && !ascii)
268 		ptstop();
269 	flusho();
270 	done3(x);
271 }
272 
done3(int x)273 void done3(int x)
274 {
275 	error |= x;
276 	flusho();
277 	if (NROFF)
278 		twdone();
279 	if (pipeflg)
280 		pclose(ptid);
281 	exit(error);
282 }
283 
284 
edone(int x)285 void edone(int x)
286 {
287 	frame = stk;
288 	nxf = frame + 1;
289 	ip = 0;
290 	done(x);
291 }
292 
293 
casepi(void)294 void casepi(void)
295 {
296 	int j;
297 	char buf[NTM];
298 
299 	if (Pipe.buf == NULL) {
300 		if ((Pipe.buf = (char *)calloc(NTM, sizeof(char))) == NULL) {
301 			ERROR "No buf space for pipe cmd" WARN;
302 			return;
303 		}
304 		Pipe.tick = 1;
305 	} else
306 		Pipe.buf[Pipe.cnt++] = '|';
307 
308 	getline(buf, NTM);
309 	j = strlen(buf);
310 	if (toolate) {
311 		ERROR "Cannot create pipe to %s", buf WARN;
312 		return;
313 	}
314 	Pipe.cnt += j;
315 	if (j >= NTM +1) {
316 		Pipe.tick++;
317 		if ((Pipe.buf = (char *)realloc(Pipe.buf, Pipe.tick * NTM * sizeof(char))) == NULL) {
318 			ERROR "No more buf space for pipe cmd" WARN;
319 			return;
320 		}
321 	}
322 	strcat(Pipe.buf, buf);
323 	pipeflg++;
324 }
325