xref: /freebsd/contrib/mandoc/mdoc_man.c (revision 61d06d6bd19dafe8ea971dd43e8328fa1b473456)
1*61d06d6bSBaptiste Daroussin /*	$Id: mdoc_man.c,v 1.126 2018/04/11 17:11:13 schwarze Exp $ */
2*61d06d6bSBaptiste Daroussin /*
3*61d06d6bSBaptiste Daroussin  * Copyright (c) 2011-2018 Ingo Schwarze <schwarze@openbsd.org>
4*61d06d6bSBaptiste Daroussin  *
5*61d06d6bSBaptiste Daroussin  * Permission to use, copy, modify, and distribute this software for any
6*61d06d6bSBaptiste Daroussin  * purpose with or without fee is hereby granted, provided that the above
7*61d06d6bSBaptiste Daroussin  * copyright notice and this permission notice appear in all copies.
8*61d06d6bSBaptiste Daroussin  *
9*61d06d6bSBaptiste Daroussin  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*61d06d6bSBaptiste Daroussin  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*61d06d6bSBaptiste Daroussin  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*61d06d6bSBaptiste Daroussin  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*61d06d6bSBaptiste Daroussin  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*61d06d6bSBaptiste Daroussin  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*61d06d6bSBaptiste Daroussin  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*61d06d6bSBaptiste Daroussin  */
17*61d06d6bSBaptiste Daroussin #include "config.h"
18*61d06d6bSBaptiste Daroussin 
19*61d06d6bSBaptiste Daroussin #include <sys/types.h>
20*61d06d6bSBaptiste Daroussin 
21*61d06d6bSBaptiste Daroussin #include <assert.h>
22*61d06d6bSBaptiste Daroussin #include <stdio.h>
23*61d06d6bSBaptiste Daroussin #include <stdlib.h>
24*61d06d6bSBaptiste Daroussin #include <string.h>
25*61d06d6bSBaptiste Daroussin 
26*61d06d6bSBaptiste Daroussin #include "mandoc_aux.h"
27*61d06d6bSBaptiste Daroussin #include "mandoc.h"
28*61d06d6bSBaptiste Daroussin #include "roff.h"
29*61d06d6bSBaptiste Daroussin #include "mdoc.h"
30*61d06d6bSBaptiste Daroussin #include "man.h"
31*61d06d6bSBaptiste Daroussin #include "out.h"
32*61d06d6bSBaptiste Daroussin #include "main.h"
33*61d06d6bSBaptiste Daroussin 
34*61d06d6bSBaptiste Daroussin #define	DECL_ARGS const struct roff_meta *meta, struct roff_node *n
35*61d06d6bSBaptiste Daroussin 
36*61d06d6bSBaptiste Daroussin typedef	int	(*int_fp)(DECL_ARGS);
37*61d06d6bSBaptiste Daroussin typedef	void	(*void_fp)(DECL_ARGS);
38*61d06d6bSBaptiste Daroussin 
39*61d06d6bSBaptiste Daroussin struct	manact {
40*61d06d6bSBaptiste Daroussin 	int_fp		  cond; /* DON'T run actions */
41*61d06d6bSBaptiste Daroussin 	int_fp		  pre; /* pre-node action */
42*61d06d6bSBaptiste Daroussin 	void_fp		  post; /* post-node action */
43*61d06d6bSBaptiste Daroussin 	const char	 *prefix; /* pre-node string constant */
44*61d06d6bSBaptiste Daroussin 	const char	 *suffix; /* post-node string constant */
45*61d06d6bSBaptiste Daroussin };
46*61d06d6bSBaptiste Daroussin 
47*61d06d6bSBaptiste Daroussin static	int	  cond_body(DECL_ARGS);
48*61d06d6bSBaptiste Daroussin static	int	  cond_head(DECL_ARGS);
49*61d06d6bSBaptiste Daroussin static  void	  font_push(char);
50*61d06d6bSBaptiste Daroussin static	void	  font_pop(void);
51*61d06d6bSBaptiste Daroussin static	int	  man_strlen(const char *);
52*61d06d6bSBaptiste Daroussin static	void	  mid_it(void);
53*61d06d6bSBaptiste Daroussin static	void	  post__t(DECL_ARGS);
54*61d06d6bSBaptiste Daroussin static	void	  post_aq(DECL_ARGS);
55*61d06d6bSBaptiste Daroussin static	void	  post_bd(DECL_ARGS);
56*61d06d6bSBaptiste Daroussin static	void	  post_bf(DECL_ARGS);
57*61d06d6bSBaptiste Daroussin static	void	  post_bk(DECL_ARGS);
58*61d06d6bSBaptiste Daroussin static	void	  post_bl(DECL_ARGS);
59*61d06d6bSBaptiste Daroussin static	void	  post_dl(DECL_ARGS);
60*61d06d6bSBaptiste Daroussin static	void	  post_en(DECL_ARGS);
61*61d06d6bSBaptiste Daroussin static	void	  post_enc(DECL_ARGS);
62*61d06d6bSBaptiste Daroussin static	void	  post_eo(DECL_ARGS);
63*61d06d6bSBaptiste Daroussin static	void	  post_fa(DECL_ARGS);
64*61d06d6bSBaptiste Daroussin static	void	  post_fd(DECL_ARGS);
65*61d06d6bSBaptiste Daroussin static	void	  post_fl(DECL_ARGS);
66*61d06d6bSBaptiste Daroussin static	void	  post_fn(DECL_ARGS);
67*61d06d6bSBaptiste Daroussin static	void	  post_fo(DECL_ARGS);
68*61d06d6bSBaptiste Daroussin static	void	  post_font(DECL_ARGS);
69*61d06d6bSBaptiste Daroussin static	void	  post_in(DECL_ARGS);
70*61d06d6bSBaptiste Daroussin static	void	  post_it(DECL_ARGS);
71*61d06d6bSBaptiste Daroussin static	void	  post_lb(DECL_ARGS);
72*61d06d6bSBaptiste Daroussin static	void	  post_nm(DECL_ARGS);
73*61d06d6bSBaptiste Daroussin static	void	  post_percent(DECL_ARGS);
74*61d06d6bSBaptiste Daroussin static	void	  post_pf(DECL_ARGS);
75*61d06d6bSBaptiste Daroussin static	void	  post_sect(DECL_ARGS);
76*61d06d6bSBaptiste Daroussin static	void	  post_vt(DECL_ARGS);
77*61d06d6bSBaptiste Daroussin static	int	  pre__t(DECL_ARGS);
78*61d06d6bSBaptiste Daroussin static	int	  pre_an(DECL_ARGS);
79*61d06d6bSBaptiste Daroussin static	int	  pre_ap(DECL_ARGS);
80*61d06d6bSBaptiste Daroussin static	int	  pre_aq(DECL_ARGS);
81*61d06d6bSBaptiste Daroussin static	int	  pre_bd(DECL_ARGS);
82*61d06d6bSBaptiste Daroussin static	int	  pre_bf(DECL_ARGS);
83*61d06d6bSBaptiste Daroussin static	int	  pre_bk(DECL_ARGS);
84*61d06d6bSBaptiste Daroussin static	int	  pre_bl(DECL_ARGS);
85*61d06d6bSBaptiste Daroussin static	void	  pre_br(DECL_ARGS);
86*61d06d6bSBaptiste Daroussin static	int	  pre_dl(DECL_ARGS);
87*61d06d6bSBaptiste Daroussin static	int	  pre_en(DECL_ARGS);
88*61d06d6bSBaptiste Daroussin static	int	  pre_enc(DECL_ARGS);
89*61d06d6bSBaptiste Daroussin static	int	  pre_em(DECL_ARGS);
90*61d06d6bSBaptiste Daroussin static	int	  pre_skip(DECL_ARGS);
91*61d06d6bSBaptiste Daroussin static	int	  pre_eo(DECL_ARGS);
92*61d06d6bSBaptiste Daroussin static	int	  pre_ex(DECL_ARGS);
93*61d06d6bSBaptiste Daroussin static	int	  pre_fa(DECL_ARGS);
94*61d06d6bSBaptiste Daroussin static	int	  pre_fd(DECL_ARGS);
95*61d06d6bSBaptiste Daroussin static	int	  pre_fl(DECL_ARGS);
96*61d06d6bSBaptiste Daroussin static	int	  pre_fn(DECL_ARGS);
97*61d06d6bSBaptiste Daroussin static	int	  pre_fo(DECL_ARGS);
98*61d06d6bSBaptiste Daroussin static	void	  pre_ft(DECL_ARGS);
99*61d06d6bSBaptiste Daroussin static	int	  pre_Ft(DECL_ARGS);
100*61d06d6bSBaptiste Daroussin static	int	  pre_in(DECL_ARGS);
101*61d06d6bSBaptiste Daroussin static	int	  pre_it(DECL_ARGS);
102*61d06d6bSBaptiste Daroussin static	int	  pre_lk(DECL_ARGS);
103*61d06d6bSBaptiste Daroussin static	int	  pre_li(DECL_ARGS);
104*61d06d6bSBaptiste Daroussin static	int	  pre_nm(DECL_ARGS);
105*61d06d6bSBaptiste Daroussin static	int	  pre_no(DECL_ARGS);
106*61d06d6bSBaptiste Daroussin static	int	  pre_ns(DECL_ARGS);
107*61d06d6bSBaptiste Daroussin static	void	  pre_onearg(DECL_ARGS);
108*61d06d6bSBaptiste Daroussin static	int	  pre_pp(DECL_ARGS);
109*61d06d6bSBaptiste Daroussin static	int	  pre_rs(DECL_ARGS);
110*61d06d6bSBaptiste Daroussin static	int	  pre_sm(DECL_ARGS);
111*61d06d6bSBaptiste Daroussin static	void	  pre_sp(DECL_ARGS);
112*61d06d6bSBaptiste Daroussin static	int	  pre_sect(DECL_ARGS);
113*61d06d6bSBaptiste Daroussin static	int	  pre_sy(DECL_ARGS);
114*61d06d6bSBaptiste Daroussin static	void	  pre_syn(const struct roff_node *);
115*61d06d6bSBaptiste Daroussin static	void	  pre_ta(DECL_ARGS);
116*61d06d6bSBaptiste Daroussin static	int	  pre_vt(DECL_ARGS);
117*61d06d6bSBaptiste Daroussin static	int	  pre_xr(DECL_ARGS);
118*61d06d6bSBaptiste Daroussin static	void	  print_word(const char *);
119*61d06d6bSBaptiste Daroussin static	void	  print_line(const char *, int);
120*61d06d6bSBaptiste Daroussin static	void	  print_block(const char *, int);
121*61d06d6bSBaptiste Daroussin static	void	  print_offs(const char *, int);
122*61d06d6bSBaptiste Daroussin static	void	  print_width(const struct mdoc_bl *,
123*61d06d6bSBaptiste Daroussin 			const struct roff_node *);
124*61d06d6bSBaptiste Daroussin static	void	  print_count(int *);
125*61d06d6bSBaptiste Daroussin static	void	  print_node(DECL_ARGS);
126*61d06d6bSBaptiste Daroussin 
127*61d06d6bSBaptiste Daroussin static	const void_fp roff_manacts[ROFF_MAX] = {
128*61d06d6bSBaptiste Daroussin 	pre_br,		/* br */
129*61d06d6bSBaptiste Daroussin 	pre_onearg,	/* ce */
130*61d06d6bSBaptiste Daroussin 	pre_ft,		/* ft */
131*61d06d6bSBaptiste Daroussin 	pre_onearg,	/* ll */
132*61d06d6bSBaptiste Daroussin 	pre_onearg,	/* mc */
133*61d06d6bSBaptiste Daroussin 	pre_onearg,	/* po */
134*61d06d6bSBaptiste Daroussin 	pre_onearg,	/* rj */
135*61d06d6bSBaptiste Daroussin 	pre_sp,		/* sp */
136*61d06d6bSBaptiste Daroussin 	pre_ta,		/* ta */
137*61d06d6bSBaptiste Daroussin 	pre_onearg,	/* ti */
138*61d06d6bSBaptiste Daroussin };
139*61d06d6bSBaptiste Daroussin 
140*61d06d6bSBaptiste Daroussin static	const struct manact __manacts[MDOC_MAX - MDOC_Dd] = {
141*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Dd */
142*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Dt */
143*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Os */
144*61d06d6bSBaptiste Daroussin 	{ NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */
145*61d06d6bSBaptiste Daroussin 	{ NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */
146*61d06d6bSBaptiste Daroussin 	{ NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
147*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_dl, post_dl, NULL, NULL }, /* D1 */
148*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
149*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_bd, post_bd, NULL, NULL }, /* Bd */
150*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ed */
151*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_bl, post_bl, NULL, NULL }, /* Bl */
152*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* El */
153*61d06d6bSBaptiste Daroussin 	{ NULL, pre_it, post_it, NULL, NULL }, /* It */
154*61d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Ad */
155*61d06d6bSBaptiste Daroussin 	{ NULL, pre_an, NULL, NULL, NULL }, /* An */
156*61d06d6bSBaptiste Daroussin 	{ NULL, pre_ap, NULL, NULL, NULL }, /* Ap */
157*61d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Ar */
158*61d06d6bSBaptiste Daroussin 	{ NULL, pre_sy, post_font, NULL, NULL }, /* Cd */
159*61d06d6bSBaptiste Daroussin 	{ NULL, pre_sy, post_font, NULL, NULL }, /* Cm */
160*61d06d6bSBaptiste Daroussin 	{ NULL, pre_li, post_font, NULL, NULL }, /* Dv */
161*61d06d6bSBaptiste Daroussin 	{ NULL, pre_li, post_font, NULL, NULL }, /* Er */
162*61d06d6bSBaptiste Daroussin 	{ NULL, pre_li, post_font, NULL, NULL }, /* Ev */
163*61d06d6bSBaptiste Daroussin 	{ NULL, pre_ex, NULL, NULL, NULL }, /* Ex */
164*61d06d6bSBaptiste Daroussin 	{ NULL, pre_fa, post_fa, NULL, NULL }, /* Fa */
165*61d06d6bSBaptiste Daroussin 	{ NULL, pre_fd, post_fd, NULL, NULL }, /* Fd */
166*61d06d6bSBaptiste Daroussin 	{ NULL, pre_fl, post_fl, NULL, NULL }, /* Fl */
167*61d06d6bSBaptiste Daroussin 	{ NULL, pre_fn, post_fn, NULL, NULL }, /* Fn */
168*61d06d6bSBaptiste Daroussin 	{ NULL, pre_Ft, post_font, NULL, NULL }, /* Ft */
169*61d06d6bSBaptiste Daroussin 	{ NULL, pre_sy, post_font, NULL, NULL }, /* Ic */
170*61d06d6bSBaptiste Daroussin 	{ NULL, pre_in, post_in, NULL, NULL }, /* In */
171*61d06d6bSBaptiste Daroussin 	{ NULL, pre_li, post_font, NULL, NULL }, /* Li */
172*61d06d6bSBaptiste Daroussin 	{ cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
173*61d06d6bSBaptiste Daroussin 	{ NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
174*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
175*61d06d6bSBaptiste Daroussin 	{ NULL, pre_Ft, post_font, NULL, NULL }, /* Ot */
176*61d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Pa */
177*61d06d6bSBaptiste Daroussin 	{ NULL, pre_ex, NULL, NULL, NULL }, /* Rv */
178*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* St */
179*61d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Va */
180*61d06d6bSBaptiste Daroussin 	{ NULL, pre_vt, post_vt, NULL, NULL }, /* Vt */
181*61d06d6bSBaptiste Daroussin 	{ NULL, pre_xr, NULL, NULL, NULL }, /* Xr */
182*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %A */
183*61d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_percent, NULL, NULL }, /* %B */
184*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %D */
185*61d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_percent, NULL, NULL }, /* %I */
186*61d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_percent, NULL, NULL }, /* %J */
187*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %N */
188*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %O */
189*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %P */
190*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %R */
191*61d06d6bSBaptiste Daroussin 	{ NULL, pre__t, post__t, NULL, NULL }, /* %T */
192*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %V */
193*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ac */
194*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_aq, post_aq, NULL, NULL }, /* Ao */
195*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_aq, post_aq, NULL, NULL }, /* Aq */
196*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* At */
197*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Bc */
198*61d06d6bSBaptiste Daroussin 	{ NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */
199*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
200*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
201*61d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Bsx */
202*61d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Bx */
203*61d06d6bSBaptiste Daroussin 	{ NULL, pre_skip, NULL, NULL, NULL }, /* Db */
204*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Dc */
205*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Do */
206*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Dq */
207*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ec */
208*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ef */
209*61d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Em */
210*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_eo, post_eo, NULL, NULL }, /* Eo */
211*61d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Fx */
212*61d06d6bSBaptiste Daroussin 	{ NULL, pre_sy, post_font, NULL, NULL }, /* Ms */
213*61d06d6bSBaptiste Daroussin 	{ NULL, pre_no, NULL, NULL, NULL }, /* No */
214*61d06d6bSBaptiste Daroussin 	{ NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
215*61d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Nx */
216*61d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Ox */
217*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Pc */
218*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_pf, NULL, NULL }, /* Pf */
219*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
220*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */
221*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Qc */
222*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Ql */
223*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */
224*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */
225*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Re */
226*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_rs, NULL, NULL, NULL }, /* Rs */
227*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Sc */
228*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* So */
229*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Sq */
230*61d06d6bSBaptiste Daroussin 	{ NULL, pre_sm, NULL, NULL, NULL }, /* Sm */
231*61d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Sx */
232*61d06d6bSBaptiste Daroussin 	{ NULL, pre_sy, post_font, NULL, NULL }, /* Sy */
233*61d06d6bSBaptiste Daroussin 	{ NULL, pre_li, post_font, NULL, NULL }, /* Tn */
234*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ux */
235*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Xc */
236*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Xo */
237*61d06d6bSBaptiste Daroussin 	{ NULL, pre_fo, post_fo, NULL, NULL }, /* Fo */
238*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Fc */
239*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */
240*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Oc */
241*61d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Bk */
242*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ek */
243*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Bt */
244*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Hf */
245*61d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Fr */
246*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ud */
247*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_lb, NULL, NULL }, /* Lb */
248*61d06d6bSBaptiste Daroussin 	{ NULL, pre_pp, NULL, NULL, NULL }, /* Lp */
249*61d06d6bSBaptiste Daroussin 	{ NULL, pre_lk, NULL, NULL, NULL }, /* Lk */
250*61d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Mt */
251*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */
252*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */
253*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Brc */
254*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %C */
255*61d06d6bSBaptiste Daroussin 	{ NULL, pre_skip, NULL, NULL, NULL }, /* Es */
256*61d06d6bSBaptiste Daroussin 	{ cond_body, pre_en, post_en, NULL, NULL }, /* En */
257*61d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Dx */
258*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %Q */
259*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %U */
260*61d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ta */
261*61d06d6bSBaptiste Daroussin };
262*61d06d6bSBaptiste Daroussin static	const struct manact *const manacts = __manacts - MDOC_Dd;
263*61d06d6bSBaptiste Daroussin 
264*61d06d6bSBaptiste Daroussin static	int		outflags;
265*61d06d6bSBaptiste Daroussin #define	MMAN_spc	(1 << 0)  /* blank character before next word */
266*61d06d6bSBaptiste Daroussin #define	MMAN_spc_force	(1 << 1)  /* even before trailing punctuation */
267*61d06d6bSBaptiste Daroussin #define	MMAN_nl		(1 << 2)  /* break man(7) code line */
268*61d06d6bSBaptiste Daroussin #define	MMAN_br		(1 << 3)  /* break output line */
269*61d06d6bSBaptiste Daroussin #define	MMAN_sp		(1 << 4)  /* insert a blank output line */
270*61d06d6bSBaptiste Daroussin #define	MMAN_PP		(1 << 5)  /* reset indentation etc. */
271*61d06d6bSBaptiste Daroussin #define	MMAN_Sm		(1 << 6)  /* horizontal spacing mode */
272*61d06d6bSBaptiste Daroussin #define	MMAN_Bk		(1 << 7)  /* word keep mode */
273*61d06d6bSBaptiste Daroussin #define	MMAN_Bk_susp	(1 << 8)  /* suspend this (after a macro) */
274*61d06d6bSBaptiste Daroussin #define	MMAN_An_split	(1 << 9)  /* author mode is "split" */
275*61d06d6bSBaptiste Daroussin #define	MMAN_An_nosplit	(1 << 10) /* author mode is "nosplit" */
276*61d06d6bSBaptiste Daroussin #define	MMAN_PD		(1 << 11) /* inter-paragraph spacing disabled */
277*61d06d6bSBaptiste Daroussin #define	MMAN_nbrword	(1 << 12) /* do not break the next word */
278*61d06d6bSBaptiste Daroussin 
279*61d06d6bSBaptiste Daroussin #define	BL_STACK_MAX	32
280*61d06d6bSBaptiste Daroussin 
281*61d06d6bSBaptiste Daroussin static	int		Bl_stack[BL_STACK_MAX];  /* offsets [chars] */
282*61d06d6bSBaptiste Daroussin static	int		Bl_stack_post[BL_STACK_MAX];  /* add final .RE */
283*61d06d6bSBaptiste Daroussin static	int		Bl_stack_len;  /* number of nested Bl blocks */
284*61d06d6bSBaptiste Daroussin static	int		TPremain;  /* characters before tag is full */
285*61d06d6bSBaptiste Daroussin 
286*61d06d6bSBaptiste Daroussin static	struct {
287*61d06d6bSBaptiste Daroussin 	char	*head;
288*61d06d6bSBaptiste Daroussin 	char	*tail;
289*61d06d6bSBaptiste Daroussin 	size_t	 size;
290*61d06d6bSBaptiste Daroussin }	fontqueue;
291*61d06d6bSBaptiste Daroussin 
292*61d06d6bSBaptiste Daroussin 
293*61d06d6bSBaptiste Daroussin static int
294*61d06d6bSBaptiste Daroussin man_strlen(const char *cp)
295*61d06d6bSBaptiste Daroussin {
296*61d06d6bSBaptiste Daroussin 	size_t	 rsz;
297*61d06d6bSBaptiste Daroussin 	int	 skip, sz;
298*61d06d6bSBaptiste Daroussin 
299*61d06d6bSBaptiste Daroussin 	sz = 0;
300*61d06d6bSBaptiste Daroussin 	skip = 0;
301*61d06d6bSBaptiste Daroussin 	for (;;) {
302*61d06d6bSBaptiste Daroussin 		rsz = strcspn(cp, "\\");
303*61d06d6bSBaptiste Daroussin 		if (rsz) {
304*61d06d6bSBaptiste Daroussin 			cp += rsz;
305*61d06d6bSBaptiste Daroussin 			if (skip) {
306*61d06d6bSBaptiste Daroussin 				skip = 0;
307*61d06d6bSBaptiste Daroussin 				rsz--;
308*61d06d6bSBaptiste Daroussin 			}
309*61d06d6bSBaptiste Daroussin 			sz += rsz;
310*61d06d6bSBaptiste Daroussin 		}
311*61d06d6bSBaptiste Daroussin 		if ('\0' == *cp)
312*61d06d6bSBaptiste Daroussin 			break;
313*61d06d6bSBaptiste Daroussin 		cp++;
314*61d06d6bSBaptiste Daroussin 		switch (mandoc_escape(&cp, NULL, NULL)) {
315*61d06d6bSBaptiste Daroussin 		case ESCAPE_ERROR:
316*61d06d6bSBaptiste Daroussin 			return sz;
317*61d06d6bSBaptiste Daroussin 		case ESCAPE_UNICODE:
318*61d06d6bSBaptiste Daroussin 		case ESCAPE_NUMBERED:
319*61d06d6bSBaptiste Daroussin 		case ESCAPE_SPECIAL:
320*61d06d6bSBaptiste Daroussin 		case ESCAPE_OVERSTRIKE:
321*61d06d6bSBaptiste Daroussin 			if (skip)
322*61d06d6bSBaptiste Daroussin 				skip = 0;
323*61d06d6bSBaptiste Daroussin 			else
324*61d06d6bSBaptiste Daroussin 				sz++;
325*61d06d6bSBaptiste Daroussin 			break;
326*61d06d6bSBaptiste Daroussin 		case ESCAPE_SKIPCHAR:
327*61d06d6bSBaptiste Daroussin 			skip = 1;
328*61d06d6bSBaptiste Daroussin 			break;
329*61d06d6bSBaptiste Daroussin 		default:
330*61d06d6bSBaptiste Daroussin 			break;
331*61d06d6bSBaptiste Daroussin 		}
332*61d06d6bSBaptiste Daroussin 	}
333*61d06d6bSBaptiste Daroussin 	return sz;
334*61d06d6bSBaptiste Daroussin }
335*61d06d6bSBaptiste Daroussin 
336*61d06d6bSBaptiste Daroussin static void
337*61d06d6bSBaptiste Daroussin font_push(char newfont)
338*61d06d6bSBaptiste Daroussin {
339*61d06d6bSBaptiste Daroussin 
340*61d06d6bSBaptiste Daroussin 	if (fontqueue.head + fontqueue.size <= ++fontqueue.tail) {
341*61d06d6bSBaptiste Daroussin 		fontqueue.size += 8;
342*61d06d6bSBaptiste Daroussin 		fontqueue.head = mandoc_realloc(fontqueue.head,
343*61d06d6bSBaptiste Daroussin 		    fontqueue.size);
344*61d06d6bSBaptiste Daroussin 	}
345*61d06d6bSBaptiste Daroussin 	*fontqueue.tail = newfont;
346*61d06d6bSBaptiste Daroussin 	print_word("");
347*61d06d6bSBaptiste Daroussin 	printf("\\f");
348*61d06d6bSBaptiste Daroussin 	putchar(newfont);
349*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
350*61d06d6bSBaptiste Daroussin }
351*61d06d6bSBaptiste Daroussin 
352*61d06d6bSBaptiste Daroussin static void
353*61d06d6bSBaptiste Daroussin font_pop(void)
354*61d06d6bSBaptiste Daroussin {
355*61d06d6bSBaptiste Daroussin 
356*61d06d6bSBaptiste Daroussin 	if (fontqueue.tail > fontqueue.head)
357*61d06d6bSBaptiste Daroussin 		fontqueue.tail--;
358*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
359*61d06d6bSBaptiste Daroussin 	print_word("");
360*61d06d6bSBaptiste Daroussin 	printf("\\f");
361*61d06d6bSBaptiste Daroussin 	putchar(*fontqueue.tail);
362*61d06d6bSBaptiste Daroussin }
363*61d06d6bSBaptiste Daroussin 
364*61d06d6bSBaptiste Daroussin static void
365*61d06d6bSBaptiste Daroussin print_word(const char *s)
366*61d06d6bSBaptiste Daroussin {
367*61d06d6bSBaptiste Daroussin 
368*61d06d6bSBaptiste Daroussin 	if ((MMAN_PP | MMAN_sp | MMAN_br | MMAN_nl) & outflags) {
369*61d06d6bSBaptiste Daroussin 		/*
370*61d06d6bSBaptiste Daroussin 		 * If we need a newline, print it now and start afresh.
371*61d06d6bSBaptiste Daroussin 		 */
372*61d06d6bSBaptiste Daroussin 		if (MMAN_PP & outflags) {
373*61d06d6bSBaptiste Daroussin 			if (MMAN_sp & outflags) {
374*61d06d6bSBaptiste Daroussin 				if (MMAN_PD & outflags) {
375*61d06d6bSBaptiste Daroussin 					printf("\n.PD");
376*61d06d6bSBaptiste Daroussin 					outflags &= ~MMAN_PD;
377*61d06d6bSBaptiste Daroussin 				}
378*61d06d6bSBaptiste Daroussin 			} else if ( ! (MMAN_PD & outflags)) {
379*61d06d6bSBaptiste Daroussin 				printf("\n.PD 0");
380*61d06d6bSBaptiste Daroussin 				outflags |= MMAN_PD;
381*61d06d6bSBaptiste Daroussin 			}
382*61d06d6bSBaptiste Daroussin 			printf("\n.PP\n");
383*61d06d6bSBaptiste Daroussin 		} else if (MMAN_sp & outflags)
384*61d06d6bSBaptiste Daroussin 			printf("\n.sp\n");
385*61d06d6bSBaptiste Daroussin 		else if (MMAN_br & outflags)
386*61d06d6bSBaptiste Daroussin 			printf("\n.br\n");
387*61d06d6bSBaptiste Daroussin 		else if (MMAN_nl & outflags)
388*61d06d6bSBaptiste Daroussin 			putchar('\n');
389*61d06d6bSBaptiste Daroussin 		outflags &= ~(MMAN_PP|MMAN_sp|MMAN_br|MMAN_nl|MMAN_spc);
390*61d06d6bSBaptiste Daroussin 		if (1 == TPremain)
391*61d06d6bSBaptiste Daroussin 			printf(".br\n");
392*61d06d6bSBaptiste Daroussin 		TPremain = 0;
393*61d06d6bSBaptiste Daroussin 	} else if (MMAN_spc & outflags) {
394*61d06d6bSBaptiste Daroussin 		/*
395*61d06d6bSBaptiste Daroussin 		 * If we need a space, only print it if
396*61d06d6bSBaptiste Daroussin 		 * (1) it is forced by `No' or
397*61d06d6bSBaptiste Daroussin 		 * (2) what follows is not terminating punctuation or
398*61d06d6bSBaptiste Daroussin 		 * (3) what follows is longer than one character.
399*61d06d6bSBaptiste Daroussin 		 */
400*61d06d6bSBaptiste Daroussin 		if (MMAN_spc_force & outflags || '\0' == s[0] ||
401*61d06d6bSBaptiste Daroussin 		    NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) {
402*61d06d6bSBaptiste Daroussin 			if (MMAN_Bk & outflags &&
403*61d06d6bSBaptiste Daroussin 			    ! (MMAN_Bk_susp & outflags))
404*61d06d6bSBaptiste Daroussin 				putchar('\\');
405*61d06d6bSBaptiste Daroussin 			putchar(' ');
406*61d06d6bSBaptiste Daroussin 			if (TPremain)
407*61d06d6bSBaptiste Daroussin 				TPremain--;
408*61d06d6bSBaptiste Daroussin 		}
409*61d06d6bSBaptiste Daroussin 	}
410*61d06d6bSBaptiste Daroussin 
411*61d06d6bSBaptiste Daroussin 	/*
412*61d06d6bSBaptiste Daroussin 	 * Reassign needing space if we're not following opening
413*61d06d6bSBaptiste Daroussin 	 * punctuation.
414*61d06d6bSBaptiste Daroussin 	 */
415*61d06d6bSBaptiste Daroussin 	if (MMAN_Sm & outflags && ('\0' == s[0] ||
416*61d06d6bSBaptiste Daroussin 	    (('(' != s[0] && '[' != s[0]) || '\0' != s[1])))
417*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_spc;
418*61d06d6bSBaptiste Daroussin 	else
419*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
420*61d06d6bSBaptiste Daroussin 	outflags &= ~(MMAN_spc_force | MMAN_Bk_susp);
421*61d06d6bSBaptiste Daroussin 
422*61d06d6bSBaptiste Daroussin 	for ( ; *s; s++) {
423*61d06d6bSBaptiste Daroussin 		switch (*s) {
424*61d06d6bSBaptiste Daroussin 		case ASCII_NBRSP:
425*61d06d6bSBaptiste Daroussin 			printf("\\ ");
426*61d06d6bSBaptiste Daroussin 			break;
427*61d06d6bSBaptiste Daroussin 		case ASCII_HYPH:
428*61d06d6bSBaptiste Daroussin 			putchar('-');
429*61d06d6bSBaptiste Daroussin 			break;
430*61d06d6bSBaptiste Daroussin 		case ASCII_BREAK:
431*61d06d6bSBaptiste Daroussin 			printf("\\:");
432*61d06d6bSBaptiste Daroussin 			break;
433*61d06d6bSBaptiste Daroussin 		case ' ':
434*61d06d6bSBaptiste Daroussin 			if (MMAN_nbrword & outflags) {
435*61d06d6bSBaptiste Daroussin 				printf("\\ ");
436*61d06d6bSBaptiste Daroussin 				break;
437*61d06d6bSBaptiste Daroussin 			}
438*61d06d6bSBaptiste Daroussin 			/* FALLTHROUGH */
439*61d06d6bSBaptiste Daroussin 		default:
440*61d06d6bSBaptiste Daroussin 			putchar((unsigned char)*s);
441*61d06d6bSBaptiste Daroussin 			break;
442*61d06d6bSBaptiste Daroussin 		}
443*61d06d6bSBaptiste Daroussin 		if (TPremain)
444*61d06d6bSBaptiste Daroussin 			TPremain--;
445*61d06d6bSBaptiste Daroussin 	}
446*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_nbrword;
447*61d06d6bSBaptiste Daroussin }
448*61d06d6bSBaptiste Daroussin 
449*61d06d6bSBaptiste Daroussin static void
450*61d06d6bSBaptiste Daroussin print_line(const char *s, int newflags)
451*61d06d6bSBaptiste Daroussin {
452*61d06d6bSBaptiste Daroussin 
453*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
454*61d06d6bSBaptiste Daroussin 	print_word(s);
455*61d06d6bSBaptiste Daroussin 	outflags |= newflags;
456*61d06d6bSBaptiste Daroussin }
457*61d06d6bSBaptiste Daroussin 
458*61d06d6bSBaptiste Daroussin static void
459*61d06d6bSBaptiste Daroussin print_block(const char *s, int newflags)
460*61d06d6bSBaptiste Daroussin {
461*61d06d6bSBaptiste Daroussin 
462*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_PP;
463*61d06d6bSBaptiste Daroussin 	if (MMAN_sp & outflags) {
464*61d06d6bSBaptiste Daroussin 		outflags &= ~(MMAN_sp | MMAN_br);
465*61d06d6bSBaptiste Daroussin 		if (MMAN_PD & outflags) {
466*61d06d6bSBaptiste Daroussin 			print_line(".PD", 0);
467*61d06d6bSBaptiste Daroussin 			outflags &= ~MMAN_PD;
468*61d06d6bSBaptiste Daroussin 		}
469*61d06d6bSBaptiste Daroussin 	} else if (! (MMAN_PD & outflags))
470*61d06d6bSBaptiste Daroussin 		print_line(".PD 0", MMAN_PD);
471*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
472*61d06d6bSBaptiste Daroussin 	print_word(s);
473*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_Bk_susp | newflags;
474*61d06d6bSBaptiste Daroussin }
475*61d06d6bSBaptiste Daroussin 
476*61d06d6bSBaptiste Daroussin static void
477*61d06d6bSBaptiste Daroussin print_offs(const char *v, int keywords)
478*61d06d6bSBaptiste Daroussin {
479*61d06d6bSBaptiste Daroussin 	char		  buf[24];
480*61d06d6bSBaptiste Daroussin 	struct roffsu	  su;
481*61d06d6bSBaptiste Daroussin 	const char	 *end;
482*61d06d6bSBaptiste Daroussin 	int		  sz;
483*61d06d6bSBaptiste Daroussin 
484*61d06d6bSBaptiste Daroussin 	print_line(".RS", MMAN_Bk_susp);
485*61d06d6bSBaptiste Daroussin 
486*61d06d6bSBaptiste Daroussin 	/* Convert v into a number (of characters). */
487*61d06d6bSBaptiste Daroussin 	if (NULL == v || '\0' == *v || (keywords && !strcmp(v, "left")))
488*61d06d6bSBaptiste Daroussin 		sz = 0;
489*61d06d6bSBaptiste Daroussin 	else if (keywords && !strcmp(v, "indent"))
490*61d06d6bSBaptiste Daroussin 		sz = 6;
491*61d06d6bSBaptiste Daroussin 	else if (keywords && !strcmp(v, "indent-two"))
492*61d06d6bSBaptiste Daroussin 		sz = 12;
493*61d06d6bSBaptiste Daroussin 	else {
494*61d06d6bSBaptiste Daroussin 		end = a2roffsu(v, &su, SCALE_EN);
495*61d06d6bSBaptiste Daroussin 		if (end == NULL || *end != '\0')
496*61d06d6bSBaptiste Daroussin 			sz = man_strlen(v);
497*61d06d6bSBaptiste Daroussin 		else if (SCALE_EN == su.unit)
498*61d06d6bSBaptiste Daroussin 			sz = su.scale;
499*61d06d6bSBaptiste Daroussin 		else {
500*61d06d6bSBaptiste Daroussin 			/*
501*61d06d6bSBaptiste Daroussin 			 * XXX
502*61d06d6bSBaptiste Daroussin 			 * If we are inside an enclosing list,
503*61d06d6bSBaptiste Daroussin 			 * there is no easy way to add the two
504*61d06d6bSBaptiste Daroussin 			 * indentations because they are provided
505*61d06d6bSBaptiste Daroussin 			 * in terms of different units.
506*61d06d6bSBaptiste Daroussin 			 */
507*61d06d6bSBaptiste Daroussin 			print_word(v);
508*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_nl;
509*61d06d6bSBaptiste Daroussin 			return;
510*61d06d6bSBaptiste Daroussin 		}
511*61d06d6bSBaptiste Daroussin 	}
512*61d06d6bSBaptiste Daroussin 
513*61d06d6bSBaptiste Daroussin 	/*
514*61d06d6bSBaptiste Daroussin 	 * We are inside an enclosing list.
515*61d06d6bSBaptiste Daroussin 	 * Add the two indentations.
516*61d06d6bSBaptiste Daroussin 	 */
517*61d06d6bSBaptiste Daroussin 	if (Bl_stack_len)
518*61d06d6bSBaptiste Daroussin 		sz += Bl_stack[Bl_stack_len - 1];
519*61d06d6bSBaptiste Daroussin 
520*61d06d6bSBaptiste Daroussin 	(void)snprintf(buf, sizeof(buf), "%dn", sz);
521*61d06d6bSBaptiste Daroussin 	print_word(buf);
522*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
523*61d06d6bSBaptiste Daroussin }
524*61d06d6bSBaptiste Daroussin 
525*61d06d6bSBaptiste Daroussin /*
526*61d06d6bSBaptiste Daroussin  * Set up the indentation for a list item; used from pre_it().
527*61d06d6bSBaptiste Daroussin  */
528*61d06d6bSBaptiste Daroussin static void
529*61d06d6bSBaptiste Daroussin print_width(const struct mdoc_bl *bl, const struct roff_node *child)
530*61d06d6bSBaptiste Daroussin {
531*61d06d6bSBaptiste Daroussin 	char		  buf[24];
532*61d06d6bSBaptiste Daroussin 	struct roffsu	  su;
533*61d06d6bSBaptiste Daroussin 	const char	 *end;
534*61d06d6bSBaptiste Daroussin 	int		  numeric, remain, sz, chsz;
535*61d06d6bSBaptiste Daroussin 
536*61d06d6bSBaptiste Daroussin 	numeric = 1;
537*61d06d6bSBaptiste Daroussin 	remain = 0;
538*61d06d6bSBaptiste Daroussin 
539*61d06d6bSBaptiste Daroussin 	/* Convert the width into a number (of characters). */
540*61d06d6bSBaptiste Daroussin 	if (bl->width == NULL)
541*61d06d6bSBaptiste Daroussin 		sz = (bl->type == LIST_hang) ? 6 : 0;
542*61d06d6bSBaptiste Daroussin 	else {
543*61d06d6bSBaptiste Daroussin 		end = a2roffsu(bl->width, &su, SCALE_MAX);
544*61d06d6bSBaptiste Daroussin 		if (end == NULL || *end != '\0')
545*61d06d6bSBaptiste Daroussin 			sz = man_strlen(bl->width);
546*61d06d6bSBaptiste Daroussin 		else if (SCALE_EN == su.unit)
547*61d06d6bSBaptiste Daroussin 			sz = su.scale;
548*61d06d6bSBaptiste Daroussin 		else {
549*61d06d6bSBaptiste Daroussin 			sz = 0;
550*61d06d6bSBaptiste Daroussin 			numeric = 0;
551*61d06d6bSBaptiste Daroussin 		}
552*61d06d6bSBaptiste Daroussin 	}
553*61d06d6bSBaptiste Daroussin 
554*61d06d6bSBaptiste Daroussin 	/* XXX Rough estimation, might have multiple parts. */
555*61d06d6bSBaptiste Daroussin 	if (bl->type == LIST_enum)
556*61d06d6bSBaptiste Daroussin 		chsz = (bl->count > 8) + 1;
557*61d06d6bSBaptiste Daroussin 	else if (child != NULL && child->type == ROFFT_TEXT)
558*61d06d6bSBaptiste Daroussin 		chsz = man_strlen(child->string);
559*61d06d6bSBaptiste Daroussin 	else
560*61d06d6bSBaptiste Daroussin 		chsz = 0;
561*61d06d6bSBaptiste Daroussin 
562*61d06d6bSBaptiste Daroussin 	/* Maybe we are inside an enclosing list? */
563*61d06d6bSBaptiste Daroussin 	mid_it();
564*61d06d6bSBaptiste Daroussin 
565*61d06d6bSBaptiste Daroussin 	/*
566*61d06d6bSBaptiste Daroussin 	 * Save our own indentation,
567*61d06d6bSBaptiste Daroussin 	 * such that child lists can use it.
568*61d06d6bSBaptiste Daroussin 	 */
569*61d06d6bSBaptiste Daroussin 	Bl_stack[Bl_stack_len++] = sz + 2;
570*61d06d6bSBaptiste Daroussin 
571*61d06d6bSBaptiste Daroussin 	/* Set up the current list. */
572*61d06d6bSBaptiste Daroussin 	if (chsz > sz && bl->type != LIST_tag)
573*61d06d6bSBaptiste Daroussin 		print_block(".HP", 0);
574*61d06d6bSBaptiste Daroussin 	else {
575*61d06d6bSBaptiste Daroussin 		print_block(".TP", 0);
576*61d06d6bSBaptiste Daroussin 		remain = sz + 2;
577*61d06d6bSBaptiste Daroussin 	}
578*61d06d6bSBaptiste Daroussin 	if (numeric) {
579*61d06d6bSBaptiste Daroussin 		(void)snprintf(buf, sizeof(buf), "%dn", sz + 2);
580*61d06d6bSBaptiste Daroussin 		print_word(buf);
581*61d06d6bSBaptiste Daroussin 	} else
582*61d06d6bSBaptiste Daroussin 		print_word(bl->width);
583*61d06d6bSBaptiste Daroussin 	TPremain = remain;
584*61d06d6bSBaptiste Daroussin }
585*61d06d6bSBaptiste Daroussin 
586*61d06d6bSBaptiste Daroussin static void
587*61d06d6bSBaptiste Daroussin print_count(int *count)
588*61d06d6bSBaptiste Daroussin {
589*61d06d6bSBaptiste Daroussin 	char		  buf[24];
590*61d06d6bSBaptiste Daroussin 
591*61d06d6bSBaptiste Daroussin 	(void)snprintf(buf, sizeof(buf), "%d.\\&", ++*count);
592*61d06d6bSBaptiste Daroussin 	print_word(buf);
593*61d06d6bSBaptiste Daroussin }
594*61d06d6bSBaptiste Daroussin 
595*61d06d6bSBaptiste Daroussin void
596*61d06d6bSBaptiste Daroussin man_man(void *arg, const struct roff_man *man)
597*61d06d6bSBaptiste Daroussin {
598*61d06d6bSBaptiste Daroussin 
599*61d06d6bSBaptiste Daroussin 	/*
600*61d06d6bSBaptiste Daroussin 	 * Dump the keep buffer.
601*61d06d6bSBaptiste Daroussin 	 * We're guaranteed by now that this exists (is non-NULL).
602*61d06d6bSBaptiste Daroussin 	 * Flush stdout afterward, just in case.
603*61d06d6bSBaptiste Daroussin 	 */
604*61d06d6bSBaptiste Daroussin 	fputs(mparse_getkeep(man_mparse(man)), stdout);
605*61d06d6bSBaptiste Daroussin 	fflush(stdout);
606*61d06d6bSBaptiste Daroussin }
607*61d06d6bSBaptiste Daroussin 
608*61d06d6bSBaptiste Daroussin void
609*61d06d6bSBaptiste Daroussin man_mdoc(void *arg, const struct roff_man *mdoc)
610*61d06d6bSBaptiste Daroussin {
611*61d06d6bSBaptiste Daroussin 	struct roff_node *n;
612*61d06d6bSBaptiste Daroussin 
613*61d06d6bSBaptiste Daroussin 	printf(".\\\" Automatically generated from an mdoc input file."
614*61d06d6bSBaptiste Daroussin 	    "  Do not edit.\n");
615*61d06d6bSBaptiste Daroussin 	for (n = mdoc->first->child; n != NULL; n = n->next) {
616*61d06d6bSBaptiste Daroussin 		if (n->type != ROFFT_COMMENT)
617*61d06d6bSBaptiste Daroussin 			break;
618*61d06d6bSBaptiste Daroussin 		printf(".\\\"%s\n", n->string);
619*61d06d6bSBaptiste Daroussin 	}
620*61d06d6bSBaptiste Daroussin 
621*61d06d6bSBaptiste Daroussin 	printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
622*61d06d6bSBaptiste Daroussin 	    mdoc->meta.title,
623*61d06d6bSBaptiste Daroussin 	    (mdoc->meta.msec == NULL ? "" : mdoc->meta.msec),
624*61d06d6bSBaptiste Daroussin 	    mdoc->meta.date, mdoc->meta.os, mdoc->meta.vol);
625*61d06d6bSBaptiste Daroussin 
626*61d06d6bSBaptiste Daroussin 	/* Disable hyphenation and if nroff, disable justification. */
627*61d06d6bSBaptiste Daroussin 	printf(".nh\n.if n .ad l");
628*61d06d6bSBaptiste Daroussin 
629*61d06d6bSBaptiste Daroussin 	outflags = MMAN_nl | MMAN_Sm;
630*61d06d6bSBaptiste Daroussin 	if (0 == fontqueue.size) {
631*61d06d6bSBaptiste Daroussin 		fontqueue.size = 8;
632*61d06d6bSBaptiste Daroussin 		fontqueue.head = fontqueue.tail = mandoc_malloc(8);
633*61d06d6bSBaptiste Daroussin 		*fontqueue.tail = 'R';
634*61d06d6bSBaptiste Daroussin 	}
635*61d06d6bSBaptiste Daroussin 	for (; n != NULL; n = n->next)
636*61d06d6bSBaptiste Daroussin 		print_node(&mdoc->meta, n);
637*61d06d6bSBaptiste Daroussin 	putchar('\n');
638*61d06d6bSBaptiste Daroussin }
639*61d06d6bSBaptiste Daroussin 
640*61d06d6bSBaptiste Daroussin static void
641*61d06d6bSBaptiste Daroussin print_node(DECL_ARGS)
642*61d06d6bSBaptiste Daroussin {
643*61d06d6bSBaptiste Daroussin 	const struct manact	*act;
644*61d06d6bSBaptiste Daroussin 	struct roff_node	*sub;
645*61d06d6bSBaptiste Daroussin 	int			 cond, do_sub;
646*61d06d6bSBaptiste Daroussin 
647*61d06d6bSBaptiste Daroussin 	if (n->flags & NODE_NOPRT)
648*61d06d6bSBaptiste Daroussin 		return;
649*61d06d6bSBaptiste Daroussin 
650*61d06d6bSBaptiste Daroussin 	/*
651*61d06d6bSBaptiste Daroussin 	 * Break the line if we were parsed subsequent the current node.
652*61d06d6bSBaptiste Daroussin 	 * This makes the page structure be more consistent.
653*61d06d6bSBaptiste Daroussin 	 */
654*61d06d6bSBaptiste Daroussin 	if (MMAN_spc & outflags && NODE_LINE & n->flags)
655*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_nl;
656*61d06d6bSBaptiste Daroussin 
657*61d06d6bSBaptiste Daroussin 	act = NULL;
658*61d06d6bSBaptiste Daroussin 	cond = 0;
659*61d06d6bSBaptiste Daroussin 	do_sub = 1;
660*61d06d6bSBaptiste Daroussin 	n->flags &= ~NODE_ENDED;
661*61d06d6bSBaptiste Daroussin 
662*61d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_TEXT) {
663*61d06d6bSBaptiste Daroussin 		/*
664*61d06d6bSBaptiste Daroussin 		 * Make sure that we don't happen to start with a
665*61d06d6bSBaptiste Daroussin 		 * control character at the start of a line.
666*61d06d6bSBaptiste Daroussin 		 */
667*61d06d6bSBaptiste Daroussin 		if (MMAN_nl & outflags &&
668*61d06d6bSBaptiste Daroussin 		    ('.' == *n->string || '\'' == *n->string)) {
669*61d06d6bSBaptiste Daroussin 			print_word("");
670*61d06d6bSBaptiste Daroussin 			printf("\\&");
671*61d06d6bSBaptiste Daroussin 			outflags &= ~MMAN_spc;
672*61d06d6bSBaptiste Daroussin 		}
673*61d06d6bSBaptiste Daroussin 		if (n->flags & NODE_DELIMC)
674*61d06d6bSBaptiste Daroussin 			outflags &= ~(MMAN_spc | MMAN_spc_force);
675*61d06d6bSBaptiste Daroussin 		else if (outflags & MMAN_Sm)
676*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_spc_force;
677*61d06d6bSBaptiste Daroussin 		print_word(n->string);
678*61d06d6bSBaptiste Daroussin 		if (n->flags & NODE_DELIMO)
679*61d06d6bSBaptiste Daroussin 			outflags &= ~(MMAN_spc | MMAN_spc_force);
680*61d06d6bSBaptiste Daroussin 		else if (outflags & MMAN_Sm)
681*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_spc;
682*61d06d6bSBaptiste Daroussin 	} else if (n->tok < ROFF_MAX) {
683*61d06d6bSBaptiste Daroussin 		(*roff_manacts[n->tok])(meta, n);
684*61d06d6bSBaptiste Daroussin 		return;
685*61d06d6bSBaptiste Daroussin 	} else {
686*61d06d6bSBaptiste Daroussin 		assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
687*61d06d6bSBaptiste Daroussin 		/*
688*61d06d6bSBaptiste Daroussin 		 * Conditionally run the pre-node action handler for a
689*61d06d6bSBaptiste Daroussin 		 * node.
690*61d06d6bSBaptiste Daroussin 		 */
691*61d06d6bSBaptiste Daroussin 		act = manacts + n->tok;
692*61d06d6bSBaptiste Daroussin 		cond = act->cond == NULL || (*act->cond)(meta, n);
693*61d06d6bSBaptiste Daroussin 		if (cond && act->pre != NULL &&
694*61d06d6bSBaptiste Daroussin 		    (n->end == ENDBODY_NOT || n->child != NULL))
695*61d06d6bSBaptiste Daroussin 			do_sub = (*act->pre)(meta, n);
696*61d06d6bSBaptiste Daroussin 	}
697*61d06d6bSBaptiste Daroussin 
698*61d06d6bSBaptiste Daroussin 	/*
699*61d06d6bSBaptiste Daroussin 	 * Conditionally run all child nodes.
700*61d06d6bSBaptiste Daroussin 	 * Note that this iterates over children instead of using
701*61d06d6bSBaptiste Daroussin 	 * recursion.  This prevents unnecessary depth in the stack.
702*61d06d6bSBaptiste Daroussin 	 */
703*61d06d6bSBaptiste Daroussin 	if (do_sub)
704*61d06d6bSBaptiste Daroussin 		for (sub = n->child; sub; sub = sub->next)
705*61d06d6bSBaptiste Daroussin 			print_node(meta, sub);
706*61d06d6bSBaptiste Daroussin 
707*61d06d6bSBaptiste Daroussin 	/*
708*61d06d6bSBaptiste Daroussin 	 * Lastly, conditionally run the post-node handler.
709*61d06d6bSBaptiste Daroussin 	 */
710*61d06d6bSBaptiste Daroussin 	if (NODE_ENDED & n->flags)
711*61d06d6bSBaptiste Daroussin 		return;
712*61d06d6bSBaptiste Daroussin 
713*61d06d6bSBaptiste Daroussin 	if (cond && act->post)
714*61d06d6bSBaptiste Daroussin 		(*act->post)(meta, n);
715*61d06d6bSBaptiste Daroussin 
716*61d06d6bSBaptiste Daroussin 	if (ENDBODY_NOT != n->end)
717*61d06d6bSBaptiste Daroussin 		n->body->flags |= NODE_ENDED;
718*61d06d6bSBaptiste Daroussin }
719*61d06d6bSBaptiste Daroussin 
720*61d06d6bSBaptiste Daroussin static int
721*61d06d6bSBaptiste Daroussin cond_head(DECL_ARGS)
722*61d06d6bSBaptiste Daroussin {
723*61d06d6bSBaptiste Daroussin 
724*61d06d6bSBaptiste Daroussin 	return n->type == ROFFT_HEAD;
725*61d06d6bSBaptiste Daroussin }
726*61d06d6bSBaptiste Daroussin 
727*61d06d6bSBaptiste Daroussin static int
728*61d06d6bSBaptiste Daroussin cond_body(DECL_ARGS)
729*61d06d6bSBaptiste Daroussin {
730*61d06d6bSBaptiste Daroussin 
731*61d06d6bSBaptiste Daroussin 	return n->type == ROFFT_BODY;
732*61d06d6bSBaptiste Daroussin }
733*61d06d6bSBaptiste Daroussin 
734*61d06d6bSBaptiste Daroussin static int
735*61d06d6bSBaptiste Daroussin pre_enc(DECL_ARGS)
736*61d06d6bSBaptiste Daroussin {
737*61d06d6bSBaptiste Daroussin 	const char	*prefix;
738*61d06d6bSBaptiste Daroussin 
739*61d06d6bSBaptiste Daroussin 	prefix = manacts[n->tok].prefix;
740*61d06d6bSBaptiste Daroussin 	if (NULL == prefix)
741*61d06d6bSBaptiste Daroussin 		return 1;
742*61d06d6bSBaptiste Daroussin 	print_word(prefix);
743*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
744*61d06d6bSBaptiste Daroussin 	return 1;
745*61d06d6bSBaptiste Daroussin }
746*61d06d6bSBaptiste Daroussin 
747*61d06d6bSBaptiste Daroussin static void
748*61d06d6bSBaptiste Daroussin post_enc(DECL_ARGS)
749*61d06d6bSBaptiste Daroussin {
750*61d06d6bSBaptiste Daroussin 	const char *suffix;
751*61d06d6bSBaptiste Daroussin 
752*61d06d6bSBaptiste Daroussin 	suffix = manacts[n->tok].suffix;
753*61d06d6bSBaptiste Daroussin 	if (NULL == suffix)
754*61d06d6bSBaptiste Daroussin 		return;
755*61d06d6bSBaptiste Daroussin 	outflags &= ~(MMAN_spc | MMAN_nl);
756*61d06d6bSBaptiste Daroussin 	print_word(suffix);
757*61d06d6bSBaptiste Daroussin }
758*61d06d6bSBaptiste Daroussin 
759*61d06d6bSBaptiste Daroussin static int
760*61d06d6bSBaptiste Daroussin pre_ex(DECL_ARGS)
761*61d06d6bSBaptiste Daroussin {
762*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_br | MMAN_nl;
763*61d06d6bSBaptiste Daroussin 	return 1;
764*61d06d6bSBaptiste Daroussin }
765*61d06d6bSBaptiste Daroussin 
766*61d06d6bSBaptiste Daroussin static void
767*61d06d6bSBaptiste Daroussin post_font(DECL_ARGS)
768*61d06d6bSBaptiste Daroussin {
769*61d06d6bSBaptiste Daroussin 
770*61d06d6bSBaptiste Daroussin 	font_pop();
771*61d06d6bSBaptiste Daroussin }
772*61d06d6bSBaptiste Daroussin 
773*61d06d6bSBaptiste Daroussin static void
774*61d06d6bSBaptiste Daroussin post_percent(DECL_ARGS)
775*61d06d6bSBaptiste Daroussin {
776*61d06d6bSBaptiste Daroussin 
777*61d06d6bSBaptiste Daroussin 	if (pre_em == manacts[n->tok].pre)
778*61d06d6bSBaptiste Daroussin 		font_pop();
779*61d06d6bSBaptiste Daroussin 	if (n->next) {
780*61d06d6bSBaptiste Daroussin 		print_word(",");
781*61d06d6bSBaptiste Daroussin 		if (n->prev &&	n->prev->tok == n->tok &&
782*61d06d6bSBaptiste Daroussin 				n->next->tok == n->tok)
783*61d06d6bSBaptiste Daroussin 			print_word("and");
784*61d06d6bSBaptiste Daroussin 	} else {
785*61d06d6bSBaptiste Daroussin 		print_word(".");
786*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_nl;
787*61d06d6bSBaptiste Daroussin 	}
788*61d06d6bSBaptiste Daroussin }
789*61d06d6bSBaptiste Daroussin 
790*61d06d6bSBaptiste Daroussin static int
791*61d06d6bSBaptiste Daroussin pre__t(DECL_ARGS)
792*61d06d6bSBaptiste Daroussin {
793*61d06d6bSBaptiste Daroussin 
794*61d06d6bSBaptiste Daroussin 	if (n->parent->tok == MDOC_Rs && n->parent->norm->Rs.quote_T) {
795*61d06d6bSBaptiste Daroussin 		print_word("\\(lq");
796*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
797*61d06d6bSBaptiste Daroussin 	} else
798*61d06d6bSBaptiste Daroussin 		font_push('I');
799*61d06d6bSBaptiste Daroussin 	return 1;
800*61d06d6bSBaptiste Daroussin }
801*61d06d6bSBaptiste Daroussin 
802*61d06d6bSBaptiste Daroussin static void
803*61d06d6bSBaptiste Daroussin post__t(DECL_ARGS)
804*61d06d6bSBaptiste Daroussin {
805*61d06d6bSBaptiste Daroussin 
806*61d06d6bSBaptiste Daroussin 	if (n->parent->tok  == MDOC_Rs && n->parent->norm->Rs.quote_T) {
807*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
808*61d06d6bSBaptiste Daroussin 		print_word("\\(rq");
809*61d06d6bSBaptiste Daroussin 	} else
810*61d06d6bSBaptiste Daroussin 		font_pop();
811*61d06d6bSBaptiste Daroussin 	post_percent(meta, n);
812*61d06d6bSBaptiste Daroussin }
813*61d06d6bSBaptiste Daroussin 
814*61d06d6bSBaptiste Daroussin /*
815*61d06d6bSBaptiste Daroussin  * Print before a section header.
816*61d06d6bSBaptiste Daroussin  */
817*61d06d6bSBaptiste Daroussin static int
818*61d06d6bSBaptiste Daroussin pre_sect(DECL_ARGS)
819*61d06d6bSBaptiste Daroussin {
820*61d06d6bSBaptiste Daroussin 
821*61d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_HEAD) {
822*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_sp;
823*61d06d6bSBaptiste Daroussin 		print_block(manacts[n->tok].prefix, 0);
824*61d06d6bSBaptiste Daroussin 		print_word("");
825*61d06d6bSBaptiste Daroussin 		putchar('\"');
826*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
827*61d06d6bSBaptiste Daroussin 	}
828*61d06d6bSBaptiste Daroussin 	return 1;
829*61d06d6bSBaptiste Daroussin }
830*61d06d6bSBaptiste Daroussin 
831*61d06d6bSBaptiste Daroussin /*
832*61d06d6bSBaptiste Daroussin  * Print subsequent a section header.
833*61d06d6bSBaptiste Daroussin  */
834*61d06d6bSBaptiste Daroussin static void
835*61d06d6bSBaptiste Daroussin post_sect(DECL_ARGS)
836*61d06d6bSBaptiste Daroussin {
837*61d06d6bSBaptiste Daroussin 
838*61d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_HEAD)
839*61d06d6bSBaptiste Daroussin 		return;
840*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
841*61d06d6bSBaptiste Daroussin 	print_word("");
842*61d06d6bSBaptiste Daroussin 	putchar('\"');
843*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
844*61d06d6bSBaptiste Daroussin 	if (MDOC_Sh == n->tok && SEC_AUTHORS == n->sec)
845*61d06d6bSBaptiste Daroussin 		outflags &= ~(MMAN_An_split | MMAN_An_nosplit);
846*61d06d6bSBaptiste Daroussin }
847*61d06d6bSBaptiste Daroussin 
848*61d06d6bSBaptiste Daroussin /* See mdoc_term.c, synopsis_pre() for comments. */
849*61d06d6bSBaptiste Daroussin static void
850*61d06d6bSBaptiste Daroussin pre_syn(const struct roff_node *n)
851*61d06d6bSBaptiste Daroussin {
852*61d06d6bSBaptiste Daroussin 
853*61d06d6bSBaptiste Daroussin 	if (NULL == n->prev || ! (NODE_SYNPRETTY & n->flags))
854*61d06d6bSBaptiste Daroussin 		return;
855*61d06d6bSBaptiste Daroussin 
856*61d06d6bSBaptiste Daroussin 	if (n->prev->tok == n->tok &&
857*61d06d6bSBaptiste Daroussin 	    MDOC_Ft != n->tok &&
858*61d06d6bSBaptiste Daroussin 	    MDOC_Fo != n->tok &&
859*61d06d6bSBaptiste Daroussin 	    MDOC_Fn != n->tok) {
860*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_br;
861*61d06d6bSBaptiste Daroussin 		return;
862*61d06d6bSBaptiste Daroussin 	}
863*61d06d6bSBaptiste Daroussin 
864*61d06d6bSBaptiste Daroussin 	switch (n->prev->tok) {
865*61d06d6bSBaptiste Daroussin 	case MDOC_Fd:
866*61d06d6bSBaptiste Daroussin 	case MDOC_Fn:
867*61d06d6bSBaptiste Daroussin 	case MDOC_Fo:
868*61d06d6bSBaptiste Daroussin 	case MDOC_In:
869*61d06d6bSBaptiste Daroussin 	case MDOC_Vt:
870*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_sp;
871*61d06d6bSBaptiste Daroussin 		break;
872*61d06d6bSBaptiste Daroussin 	case MDOC_Ft:
873*61d06d6bSBaptiste Daroussin 		if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
874*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_sp;
875*61d06d6bSBaptiste Daroussin 			break;
876*61d06d6bSBaptiste Daroussin 		}
877*61d06d6bSBaptiste Daroussin 		/* FALLTHROUGH */
878*61d06d6bSBaptiste Daroussin 	default:
879*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_br;
880*61d06d6bSBaptiste Daroussin 		break;
881*61d06d6bSBaptiste Daroussin 	}
882*61d06d6bSBaptiste Daroussin }
883*61d06d6bSBaptiste Daroussin 
884*61d06d6bSBaptiste Daroussin static int
885*61d06d6bSBaptiste Daroussin pre_an(DECL_ARGS)
886*61d06d6bSBaptiste Daroussin {
887*61d06d6bSBaptiste Daroussin 
888*61d06d6bSBaptiste Daroussin 	switch (n->norm->An.auth) {
889*61d06d6bSBaptiste Daroussin 	case AUTH_split:
890*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_An_nosplit;
891*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_An_split;
892*61d06d6bSBaptiste Daroussin 		return 0;
893*61d06d6bSBaptiste Daroussin 	case AUTH_nosplit:
894*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_An_split;
895*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_An_nosplit;
896*61d06d6bSBaptiste Daroussin 		return 0;
897*61d06d6bSBaptiste Daroussin 	default:
898*61d06d6bSBaptiste Daroussin 		if (MMAN_An_split & outflags)
899*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_br;
900*61d06d6bSBaptiste Daroussin 		else if (SEC_AUTHORS == n->sec &&
901*61d06d6bSBaptiste Daroussin 		    ! (MMAN_An_nosplit & outflags))
902*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_An_split;
903*61d06d6bSBaptiste Daroussin 		return 1;
904*61d06d6bSBaptiste Daroussin 	}
905*61d06d6bSBaptiste Daroussin }
906*61d06d6bSBaptiste Daroussin 
907*61d06d6bSBaptiste Daroussin static int
908*61d06d6bSBaptiste Daroussin pre_ap(DECL_ARGS)
909*61d06d6bSBaptiste Daroussin {
910*61d06d6bSBaptiste Daroussin 
911*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
912*61d06d6bSBaptiste Daroussin 	print_word("'");
913*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
914*61d06d6bSBaptiste Daroussin 	return 0;
915*61d06d6bSBaptiste Daroussin }
916*61d06d6bSBaptiste Daroussin 
917*61d06d6bSBaptiste Daroussin static int
918*61d06d6bSBaptiste Daroussin pre_aq(DECL_ARGS)
919*61d06d6bSBaptiste Daroussin {
920*61d06d6bSBaptiste Daroussin 
921*61d06d6bSBaptiste Daroussin 	print_word(n->child != NULL && n->child->next == NULL &&
922*61d06d6bSBaptiste Daroussin 	    n->child->tok == MDOC_Mt ?  "<" : "\\(la");
923*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
924*61d06d6bSBaptiste Daroussin 	return 1;
925*61d06d6bSBaptiste Daroussin }
926*61d06d6bSBaptiste Daroussin 
927*61d06d6bSBaptiste Daroussin static void
928*61d06d6bSBaptiste Daroussin post_aq(DECL_ARGS)
929*61d06d6bSBaptiste Daroussin {
930*61d06d6bSBaptiste Daroussin 
931*61d06d6bSBaptiste Daroussin 	outflags &= ~(MMAN_spc | MMAN_nl);
932*61d06d6bSBaptiste Daroussin 	print_word(n->child != NULL && n->child->next == NULL &&
933*61d06d6bSBaptiste Daroussin 	    n->child->tok == MDOC_Mt ?  ">" : "\\(ra");
934*61d06d6bSBaptiste Daroussin }
935*61d06d6bSBaptiste Daroussin 
936*61d06d6bSBaptiste Daroussin static int
937*61d06d6bSBaptiste Daroussin pre_bd(DECL_ARGS)
938*61d06d6bSBaptiste Daroussin {
939*61d06d6bSBaptiste Daroussin 
940*61d06d6bSBaptiste Daroussin 	outflags &= ~(MMAN_PP | MMAN_sp | MMAN_br);
941*61d06d6bSBaptiste Daroussin 
942*61d06d6bSBaptiste Daroussin 	if (DISP_unfilled == n->norm->Bd.type ||
943*61d06d6bSBaptiste Daroussin 	    DISP_literal  == n->norm->Bd.type)
944*61d06d6bSBaptiste Daroussin 		print_line(".nf", 0);
945*61d06d6bSBaptiste Daroussin 	if (0 == n->norm->Bd.comp && NULL != n->parent->prev)
946*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_sp;
947*61d06d6bSBaptiste Daroussin 	print_offs(n->norm->Bd.offs, 1);
948*61d06d6bSBaptiste Daroussin 	return 1;
949*61d06d6bSBaptiste Daroussin }
950*61d06d6bSBaptiste Daroussin 
951*61d06d6bSBaptiste Daroussin static void
952*61d06d6bSBaptiste Daroussin post_bd(DECL_ARGS)
953*61d06d6bSBaptiste Daroussin {
954*61d06d6bSBaptiste Daroussin 
955*61d06d6bSBaptiste Daroussin 	/* Close out this display. */
956*61d06d6bSBaptiste Daroussin 	print_line(".RE", MMAN_nl);
957*61d06d6bSBaptiste Daroussin 	if (DISP_unfilled == n->norm->Bd.type ||
958*61d06d6bSBaptiste Daroussin 	    DISP_literal  == n->norm->Bd.type)
959*61d06d6bSBaptiste Daroussin 		print_line(".fi", MMAN_nl);
960*61d06d6bSBaptiste Daroussin 
961*61d06d6bSBaptiste Daroussin 	/* Maybe we are inside an enclosing list? */
962*61d06d6bSBaptiste Daroussin 	if (NULL != n->parent->next)
963*61d06d6bSBaptiste Daroussin 		mid_it();
964*61d06d6bSBaptiste Daroussin }
965*61d06d6bSBaptiste Daroussin 
966*61d06d6bSBaptiste Daroussin static int
967*61d06d6bSBaptiste Daroussin pre_bf(DECL_ARGS)
968*61d06d6bSBaptiste Daroussin {
969*61d06d6bSBaptiste Daroussin 
970*61d06d6bSBaptiste Daroussin 	switch (n->type) {
971*61d06d6bSBaptiste Daroussin 	case ROFFT_BLOCK:
972*61d06d6bSBaptiste Daroussin 		return 1;
973*61d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
974*61d06d6bSBaptiste Daroussin 		break;
975*61d06d6bSBaptiste Daroussin 	default:
976*61d06d6bSBaptiste Daroussin 		return 0;
977*61d06d6bSBaptiste Daroussin 	}
978*61d06d6bSBaptiste Daroussin 	switch (n->norm->Bf.font) {
979*61d06d6bSBaptiste Daroussin 	case FONT_Em:
980*61d06d6bSBaptiste Daroussin 		font_push('I');
981*61d06d6bSBaptiste Daroussin 		break;
982*61d06d6bSBaptiste Daroussin 	case FONT_Sy:
983*61d06d6bSBaptiste Daroussin 		font_push('B');
984*61d06d6bSBaptiste Daroussin 		break;
985*61d06d6bSBaptiste Daroussin 	default:
986*61d06d6bSBaptiste Daroussin 		font_push('R');
987*61d06d6bSBaptiste Daroussin 		break;
988*61d06d6bSBaptiste Daroussin 	}
989*61d06d6bSBaptiste Daroussin 	return 1;
990*61d06d6bSBaptiste Daroussin }
991*61d06d6bSBaptiste Daroussin 
992*61d06d6bSBaptiste Daroussin static void
993*61d06d6bSBaptiste Daroussin post_bf(DECL_ARGS)
994*61d06d6bSBaptiste Daroussin {
995*61d06d6bSBaptiste Daroussin 
996*61d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_BODY)
997*61d06d6bSBaptiste Daroussin 		font_pop();
998*61d06d6bSBaptiste Daroussin }
999*61d06d6bSBaptiste Daroussin 
1000*61d06d6bSBaptiste Daroussin static int
1001*61d06d6bSBaptiste Daroussin pre_bk(DECL_ARGS)
1002*61d06d6bSBaptiste Daroussin {
1003*61d06d6bSBaptiste Daroussin 	switch (n->type) {
1004*61d06d6bSBaptiste Daroussin 	case ROFFT_BLOCK:
1005*61d06d6bSBaptiste Daroussin 		return 1;
1006*61d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
1007*61d06d6bSBaptiste Daroussin 	case ROFFT_ELEM:
1008*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_Bk;
1009*61d06d6bSBaptiste Daroussin 		return 1;
1010*61d06d6bSBaptiste Daroussin 	default:
1011*61d06d6bSBaptiste Daroussin 		return 0;
1012*61d06d6bSBaptiste Daroussin 	}
1013*61d06d6bSBaptiste Daroussin }
1014*61d06d6bSBaptiste Daroussin 
1015*61d06d6bSBaptiste Daroussin static void
1016*61d06d6bSBaptiste Daroussin post_bk(DECL_ARGS)
1017*61d06d6bSBaptiste Daroussin {
1018*61d06d6bSBaptiste Daroussin 	switch (n->type) {
1019*61d06d6bSBaptiste Daroussin 	case ROFFT_ELEM:
1020*61d06d6bSBaptiste Daroussin 		while ((n = n->parent) != NULL)
1021*61d06d6bSBaptiste Daroussin 			 if (n->tok == MDOC_Bk)
1022*61d06d6bSBaptiste Daroussin 				return;
1023*61d06d6bSBaptiste Daroussin 		/* FALLTHROUGH */
1024*61d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
1025*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_Bk;
1026*61d06d6bSBaptiste Daroussin 		break;
1027*61d06d6bSBaptiste Daroussin 	default:
1028*61d06d6bSBaptiste Daroussin 		break;
1029*61d06d6bSBaptiste Daroussin 	}
1030*61d06d6bSBaptiste Daroussin }
1031*61d06d6bSBaptiste Daroussin 
1032*61d06d6bSBaptiste Daroussin static int
1033*61d06d6bSBaptiste Daroussin pre_bl(DECL_ARGS)
1034*61d06d6bSBaptiste Daroussin {
1035*61d06d6bSBaptiste Daroussin 	size_t		 icol;
1036*61d06d6bSBaptiste Daroussin 
1037*61d06d6bSBaptiste Daroussin 	/*
1038*61d06d6bSBaptiste Daroussin 	 * print_offs() will increase the -offset to account for
1039*61d06d6bSBaptiste Daroussin 	 * a possible enclosing .It, but any enclosed .It blocks
1040*61d06d6bSBaptiste Daroussin 	 * just nest and do not add up their indentation.
1041*61d06d6bSBaptiste Daroussin 	 */
1042*61d06d6bSBaptiste Daroussin 	if (n->norm->Bl.offs) {
1043*61d06d6bSBaptiste Daroussin 		print_offs(n->norm->Bl.offs, 0);
1044*61d06d6bSBaptiste Daroussin 		Bl_stack[Bl_stack_len++] = 0;
1045*61d06d6bSBaptiste Daroussin 	}
1046*61d06d6bSBaptiste Daroussin 
1047*61d06d6bSBaptiste Daroussin 	switch (n->norm->Bl.type) {
1048*61d06d6bSBaptiste Daroussin 	case LIST_enum:
1049*61d06d6bSBaptiste Daroussin 		n->norm->Bl.count = 0;
1050*61d06d6bSBaptiste Daroussin 		return 1;
1051*61d06d6bSBaptiste Daroussin 	case LIST_column:
1052*61d06d6bSBaptiste Daroussin 		break;
1053*61d06d6bSBaptiste Daroussin 	default:
1054*61d06d6bSBaptiste Daroussin 		return 1;
1055*61d06d6bSBaptiste Daroussin 	}
1056*61d06d6bSBaptiste Daroussin 
1057*61d06d6bSBaptiste Daroussin 	if (n->child != NULL) {
1058*61d06d6bSBaptiste Daroussin 		print_line(".TS", MMAN_nl);
1059*61d06d6bSBaptiste Daroussin 		for (icol = 0; icol < n->norm->Bl.ncols; icol++)
1060*61d06d6bSBaptiste Daroussin 			print_word("l");
1061*61d06d6bSBaptiste Daroussin 		print_word(".");
1062*61d06d6bSBaptiste Daroussin 	}
1063*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
1064*61d06d6bSBaptiste Daroussin 	return 1;
1065*61d06d6bSBaptiste Daroussin }
1066*61d06d6bSBaptiste Daroussin 
1067*61d06d6bSBaptiste Daroussin static void
1068*61d06d6bSBaptiste Daroussin post_bl(DECL_ARGS)
1069*61d06d6bSBaptiste Daroussin {
1070*61d06d6bSBaptiste Daroussin 
1071*61d06d6bSBaptiste Daroussin 	switch (n->norm->Bl.type) {
1072*61d06d6bSBaptiste Daroussin 	case LIST_column:
1073*61d06d6bSBaptiste Daroussin 		if (n->child != NULL)
1074*61d06d6bSBaptiste Daroussin 			print_line(".TE", 0);
1075*61d06d6bSBaptiste Daroussin 		break;
1076*61d06d6bSBaptiste Daroussin 	case LIST_enum:
1077*61d06d6bSBaptiste Daroussin 		n->norm->Bl.count = 0;
1078*61d06d6bSBaptiste Daroussin 		break;
1079*61d06d6bSBaptiste Daroussin 	default:
1080*61d06d6bSBaptiste Daroussin 		break;
1081*61d06d6bSBaptiste Daroussin 	}
1082*61d06d6bSBaptiste Daroussin 
1083*61d06d6bSBaptiste Daroussin 	if (n->norm->Bl.offs) {
1084*61d06d6bSBaptiste Daroussin 		print_line(".RE", MMAN_nl);
1085*61d06d6bSBaptiste Daroussin 		assert(Bl_stack_len);
1086*61d06d6bSBaptiste Daroussin 		Bl_stack_len--;
1087*61d06d6bSBaptiste Daroussin 		assert(0 == Bl_stack[Bl_stack_len]);
1088*61d06d6bSBaptiste Daroussin 	} else {
1089*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_PP | MMAN_nl;
1090*61d06d6bSBaptiste Daroussin 		outflags &= ~(MMAN_sp | MMAN_br);
1091*61d06d6bSBaptiste Daroussin 	}
1092*61d06d6bSBaptiste Daroussin 
1093*61d06d6bSBaptiste Daroussin 	/* Maybe we are inside an enclosing list? */
1094*61d06d6bSBaptiste Daroussin 	if (NULL != n->parent->next)
1095*61d06d6bSBaptiste Daroussin 		mid_it();
1096*61d06d6bSBaptiste Daroussin 
1097*61d06d6bSBaptiste Daroussin }
1098*61d06d6bSBaptiste Daroussin 
1099*61d06d6bSBaptiste Daroussin static void
1100*61d06d6bSBaptiste Daroussin pre_br(DECL_ARGS)
1101*61d06d6bSBaptiste Daroussin {
1102*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_br;
1103*61d06d6bSBaptiste Daroussin }
1104*61d06d6bSBaptiste Daroussin 
1105*61d06d6bSBaptiste Daroussin static int
1106*61d06d6bSBaptiste Daroussin pre_dl(DECL_ARGS)
1107*61d06d6bSBaptiste Daroussin {
1108*61d06d6bSBaptiste Daroussin 
1109*61d06d6bSBaptiste Daroussin 	print_offs("6n", 0);
1110*61d06d6bSBaptiste Daroussin 	return 1;
1111*61d06d6bSBaptiste Daroussin }
1112*61d06d6bSBaptiste Daroussin 
1113*61d06d6bSBaptiste Daroussin static void
1114*61d06d6bSBaptiste Daroussin post_dl(DECL_ARGS)
1115*61d06d6bSBaptiste Daroussin {
1116*61d06d6bSBaptiste Daroussin 
1117*61d06d6bSBaptiste Daroussin 	print_line(".RE", MMAN_nl);
1118*61d06d6bSBaptiste Daroussin 
1119*61d06d6bSBaptiste Daroussin 	/* Maybe we are inside an enclosing list? */
1120*61d06d6bSBaptiste Daroussin 	if (NULL != n->parent->next)
1121*61d06d6bSBaptiste Daroussin 		mid_it();
1122*61d06d6bSBaptiste Daroussin }
1123*61d06d6bSBaptiste Daroussin 
1124*61d06d6bSBaptiste Daroussin static int
1125*61d06d6bSBaptiste Daroussin pre_em(DECL_ARGS)
1126*61d06d6bSBaptiste Daroussin {
1127*61d06d6bSBaptiste Daroussin 
1128*61d06d6bSBaptiste Daroussin 	font_push('I');
1129*61d06d6bSBaptiste Daroussin 	return 1;
1130*61d06d6bSBaptiste Daroussin }
1131*61d06d6bSBaptiste Daroussin 
1132*61d06d6bSBaptiste Daroussin static int
1133*61d06d6bSBaptiste Daroussin pre_en(DECL_ARGS)
1134*61d06d6bSBaptiste Daroussin {
1135*61d06d6bSBaptiste Daroussin 
1136*61d06d6bSBaptiste Daroussin 	if (NULL == n->norm->Es ||
1137*61d06d6bSBaptiste Daroussin 	    NULL == n->norm->Es->child)
1138*61d06d6bSBaptiste Daroussin 		return 1;
1139*61d06d6bSBaptiste Daroussin 
1140*61d06d6bSBaptiste Daroussin 	print_word(n->norm->Es->child->string);
1141*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
1142*61d06d6bSBaptiste Daroussin 	return 1;
1143*61d06d6bSBaptiste Daroussin }
1144*61d06d6bSBaptiste Daroussin 
1145*61d06d6bSBaptiste Daroussin static void
1146*61d06d6bSBaptiste Daroussin post_en(DECL_ARGS)
1147*61d06d6bSBaptiste Daroussin {
1148*61d06d6bSBaptiste Daroussin 
1149*61d06d6bSBaptiste Daroussin 	if (NULL == n->norm->Es ||
1150*61d06d6bSBaptiste Daroussin 	    NULL == n->norm->Es->child ||
1151*61d06d6bSBaptiste Daroussin 	    NULL == n->norm->Es->child->next)
1152*61d06d6bSBaptiste Daroussin 		return;
1153*61d06d6bSBaptiste Daroussin 
1154*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
1155*61d06d6bSBaptiste Daroussin 	print_word(n->norm->Es->child->next->string);
1156*61d06d6bSBaptiste Daroussin 	return;
1157*61d06d6bSBaptiste Daroussin }
1158*61d06d6bSBaptiste Daroussin 
1159*61d06d6bSBaptiste Daroussin static int
1160*61d06d6bSBaptiste Daroussin pre_eo(DECL_ARGS)
1161*61d06d6bSBaptiste Daroussin {
1162*61d06d6bSBaptiste Daroussin 
1163*61d06d6bSBaptiste Daroussin 	if (n->end == ENDBODY_NOT &&
1164*61d06d6bSBaptiste Daroussin 	    n->parent->head->child == NULL &&
1165*61d06d6bSBaptiste Daroussin 	    n->child != NULL &&
1166*61d06d6bSBaptiste Daroussin 	    n->child->end != ENDBODY_NOT)
1167*61d06d6bSBaptiste Daroussin 		print_word("\\&");
1168*61d06d6bSBaptiste Daroussin 	else if (n->end != ENDBODY_NOT ? n->child != NULL :
1169*61d06d6bSBaptiste Daroussin 	    n->parent->head->child != NULL && (n->child != NULL ||
1170*61d06d6bSBaptiste Daroussin 	    (n->parent->tail != NULL && n->parent->tail->child != NULL)))
1171*61d06d6bSBaptiste Daroussin 		outflags &= ~(MMAN_spc | MMAN_nl);
1172*61d06d6bSBaptiste Daroussin 	return 1;
1173*61d06d6bSBaptiste Daroussin }
1174*61d06d6bSBaptiste Daroussin 
1175*61d06d6bSBaptiste Daroussin static void
1176*61d06d6bSBaptiste Daroussin post_eo(DECL_ARGS)
1177*61d06d6bSBaptiste Daroussin {
1178*61d06d6bSBaptiste Daroussin 	int	 body, tail;
1179*61d06d6bSBaptiste Daroussin 
1180*61d06d6bSBaptiste Daroussin 	if (n->end != ENDBODY_NOT) {
1181*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_spc;
1182*61d06d6bSBaptiste Daroussin 		return;
1183*61d06d6bSBaptiste Daroussin 	}
1184*61d06d6bSBaptiste Daroussin 
1185*61d06d6bSBaptiste Daroussin 	body = n->child != NULL || n->parent->head->child != NULL;
1186*61d06d6bSBaptiste Daroussin 	tail = n->parent->tail != NULL && n->parent->tail->child != NULL;
1187*61d06d6bSBaptiste Daroussin 
1188*61d06d6bSBaptiste Daroussin 	if (body && tail)
1189*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
1190*61d06d6bSBaptiste Daroussin 	else if ( ! (body || tail))
1191*61d06d6bSBaptiste Daroussin 		print_word("\\&");
1192*61d06d6bSBaptiste Daroussin 	else if ( ! tail)
1193*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_spc;
1194*61d06d6bSBaptiste Daroussin }
1195*61d06d6bSBaptiste Daroussin 
1196*61d06d6bSBaptiste Daroussin static int
1197*61d06d6bSBaptiste Daroussin pre_fa(DECL_ARGS)
1198*61d06d6bSBaptiste Daroussin {
1199*61d06d6bSBaptiste Daroussin 	int	 am_Fa;
1200*61d06d6bSBaptiste Daroussin 
1201*61d06d6bSBaptiste Daroussin 	am_Fa = MDOC_Fa == n->tok;
1202*61d06d6bSBaptiste Daroussin 
1203*61d06d6bSBaptiste Daroussin 	if (am_Fa)
1204*61d06d6bSBaptiste Daroussin 		n = n->child;
1205*61d06d6bSBaptiste Daroussin 
1206*61d06d6bSBaptiste Daroussin 	while (NULL != n) {
1207*61d06d6bSBaptiste Daroussin 		font_push('I');
1208*61d06d6bSBaptiste Daroussin 		if (am_Fa || NODE_SYNPRETTY & n->flags)
1209*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_nbrword;
1210*61d06d6bSBaptiste Daroussin 		print_node(meta, n);
1211*61d06d6bSBaptiste Daroussin 		font_pop();
1212*61d06d6bSBaptiste Daroussin 		if (NULL != (n = n->next))
1213*61d06d6bSBaptiste Daroussin 			print_word(",");
1214*61d06d6bSBaptiste Daroussin 	}
1215*61d06d6bSBaptiste Daroussin 	return 0;
1216*61d06d6bSBaptiste Daroussin }
1217*61d06d6bSBaptiste Daroussin 
1218*61d06d6bSBaptiste Daroussin static void
1219*61d06d6bSBaptiste Daroussin post_fa(DECL_ARGS)
1220*61d06d6bSBaptiste Daroussin {
1221*61d06d6bSBaptiste Daroussin 
1222*61d06d6bSBaptiste Daroussin 	if (NULL != n->next && MDOC_Fa == n->next->tok)
1223*61d06d6bSBaptiste Daroussin 		print_word(",");
1224*61d06d6bSBaptiste Daroussin }
1225*61d06d6bSBaptiste Daroussin 
1226*61d06d6bSBaptiste Daroussin static int
1227*61d06d6bSBaptiste Daroussin pre_fd(DECL_ARGS)
1228*61d06d6bSBaptiste Daroussin {
1229*61d06d6bSBaptiste Daroussin 
1230*61d06d6bSBaptiste Daroussin 	pre_syn(n);
1231*61d06d6bSBaptiste Daroussin 	font_push('B');
1232*61d06d6bSBaptiste Daroussin 	return 1;
1233*61d06d6bSBaptiste Daroussin }
1234*61d06d6bSBaptiste Daroussin 
1235*61d06d6bSBaptiste Daroussin static void
1236*61d06d6bSBaptiste Daroussin post_fd(DECL_ARGS)
1237*61d06d6bSBaptiste Daroussin {
1238*61d06d6bSBaptiste Daroussin 
1239*61d06d6bSBaptiste Daroussin 	font_pop();
1240*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_br;
1241*61d06d6bSBaptiste Daroussin }
1242*61d06d6bSBaptiste Daroussin 
1243*61d06d6bSBaptiste Daroussin static int
1244*61d06d6bSBaptiste Daroussin pre_fl(DECL_ARGS)
1245*61d06d6bSBaptiste Daroussin {
1246*61d06d6bSBaptiste Daroussin 
1247*61d06d6bSBaptiste Daroussin 	font_push('B');
1248*61d06d6bSBaptiste Daroussin 	print_word("\\-");
1249*61d06d6bSBaptiste Daroussin 	if (n->child != NULL)
1250*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
1251*61d06d6bSBaptiste Daroussin 	return 1;
1252*61d06d6bSBaptiste Daroussin }
1253*61d06d6bSBaptiste Daroussin 
1254*61d06d6bSBaptiste Daroussin static void
1255*61d06d6bSBaptiste Daroussin post_fl(DECL_ARGS)
1256*61d06d6bSBaptiste Daroussin {
1257*61d06d6bSBaptiste Daroussin 
1258*61d06d6bSBaptiste Daroussin 	font_pop();
1259*61d06d6bSBaptiste Daroussin 	if (!(n->child != NULL ||
1260*61d06d6bSBaptiste Daroussin 	    n->next == NULL ||
1261*61d06d6bSBaptiste Daroussin 	    n->next->type == ROFFT_TEXT ||
1262*61d06d6bSBaptiste Daroussin 	    n->next->flags & NODE_LINE))
1263*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
1264*61d06d6bSBaptiste Daroussin }
1265*61d06d6bSBaptiste Daroussin 
1266*61d06d6bSBaptiste Daroussin static int
1267*61d06d6bSBaptiste Daroussin pre_fn(DECL_ARGS)
1268*61d06d6bSBaptiste Daroussin {
1269*61d06d6bSBaptiste Daroussin 
1270*61d06d6bSBaptiste Daroussin 	pre_syn(n);
1271*61d06d6bSBaptiste Daroussin 
1272*61d06d6bSBaptiste Daroussin 	n = n->child;
1273*61d06d6bSBaptiste Daroussin 	if (NULL == n)
1274*61d06d6bSBaptiste Daroussin 		return 0;
1275*61d06d6bSBaptiste Daroussin 
1276*61d06d6bSBaptiste Daroussin 	if (NODE_SYNPRETTY & n->flags)
1277*61d06d6bSBaptiste Daroussin 		print_block(".HP 4n", MMAN_nl);
1278*61d06d6bSBaptiste Daroussin 
1279*61d06d6bSBaptiste Daroussin 	font_push('B');
1280*61d06d6bSBaptiste Daroussin 	print_node(meta, n);
1281*61d06d6bSBaptiste Daroussin 	font_pop();
1282*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
1283*61d06d6bSBaptiste Daroussin 	print_word("(");
1284*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
1285*61d06d6bSBaptiste Daroussin 
1286*61d06d6bSBaptiste Daroussin 	n = n->next;
1287*61d06d6bSBaptiste Daroussin 	if (NULL != n)
1288*61d06d6bSBaptiste Daroussin 		pre_fa(meta, n);
1289*61d06d6bSBaptiste Daroussin 	return 0;
1290*61d06d6bSBaptiste Daroussin }
1291*61d06d6bSBaptiste Daroussin 
1292*61d06d6bSBaptiste Daroussin static void
1293*61d06d6bSBaptiste Daroussin post_fn(DECL_ARGS)
1294*61d06d6bSBaptiste Daroussin {
1295*61d06d6bSBaptiste Daroussin 
1296*61d06d6bSBaptiste Daroussin 	print_word(")");
1297*61d06d6bSBaptiste Daroussin 	if (NODE_SYNPRETTY & n->flags) {
1298*61d06d6bSBaptiste Daroussin 		print_word(";");
1299*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_PP;
1300*61d06d6bSBaptiste Daroussin 	}
1301*61d06d6bSBaptiste Daroussin }
1302*61d06d6bSBaptiste Daroussin 
1303*61d06d6bSBaptiste Daroussin static int
1304*61d06d6bSBaptiste Daroussin pre_fo(DECL_ARGS)
1305*61d06d6bSBaptiste Daroussin {
1306*61d06d6bSBaptiste Daroussin 
1307*61d06d6bSBaptiste Daroussin 	switch (n->type) {
1308*61d06d6bSBaptiste Daroussin 	case ROFFT_BLOCK:
1309*61d06d6bSBaptiste Daroussin 		pre_syn(n);
1310*61d06d6bSBaptiste Daroussin 		break;
1311*61d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
1312*61d06d6bSBaptiste Daroussin 		if (n->child == NULL)
1313*61d06d6bSBaptiste Daroussin 			return 0;
1314*61d06d6bSBaptiste Daroussin 		if (NODE_SYNPRETTY & n->flags)
1315*61d06d6bSBaptiste Daroussin 			print_block(".HP 4n", MMAN_nl);
1316*61d06d6bSBaptiste Daroussin 		font_push('B');
1317*61d06d6bSBaptiste Daroussin 		break;
1318*61d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
1319*61d06d6bSBaptiste Daroussin 		outflags &= ~(MMAN_spc | MMAN_nl);
1320*61d06d6bSBaptiste Daroussin 		print_word("(");
1321*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
1322*61d06d6bSBaptiste Daroussin 		break;
1323*61d06d6bSBaptiste Daroussin 	default:
1324*61d06d6bSBaptiste Daroussin 		break;
1325*61d06d6bSBaptiste Daroussin 	}
1326*61d06d6bSBaptiste Daroussin 	return 1;
1327*61d06d6bSBaptiste Daroussin }
1328*61d06d6bSBaptiste Daroussin 
1329*61d06d6bSBaptiste Daroussin static void
1330*61d06d6bSBaptiste Daroussin post_fo(DECL_ARGS)
1331*61d06d6bSBaptiste Daroussin {
1332*61d06d6bSBaptiste Daroussin 
1333*61d06d6bSBaptiste Daroussin 	switch (n->type) {
1334*61d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
1335*61d06d6bSBaptiste Daroussin 		if (n->child != NULL)
1336*61d06d6bSBaptiste Daroussin 			font_pop();
1337*61d06d6bSBaptiste Daroussin 		break;
1338*61d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
1339*61d06d6bSBaptiste Daroussin 		post_fn(meta, n);
1340*61d06d6bSBaptiste Daroussin 		break;
1341*61d06d6bSBaptiste Daroussin 	default:
1342*61d06d6bSBaptiste Daroussin 		break;
1343*61d06d6bSBaptiste Daroussin 	}
1344*61d06d6bSBaptiste Daroussin }
1345*61d06d6bSBaptiste Daroussin 
1346*61d06d6bSBaptiste Daroussin static int
1347*61d06d6bSBaptiste Daroussin pre_Ft(DECL_ARGS)
1348*61d06d6bSBaptiste Daroussin {
1349*61d06d6bSBaptiste Daroussin 
1350*61d06d6bSBaptiste Daroussin 	pre_syn(n);
1351*61d06d6bSBaptiste Daroussin 	font_push('I');
1352*61d06d6bSBaptiste Daroussin 	return 1;
1353*61d06d6bSBaptiste Daroussin }
1354*61d06d6bSBaptiste Daroussin 
1355*61d06d6bSBaptiste Daroussin static void
1356*61d06d6bSBaptiste Daroussin pre_ft(DECL_ARGS)
1357*61d06d6bSBaptiste Daroussin {
1358*61d06d6bSBaptiste Daroussin 	print_line(".ft", 0);
1359*61d06d6bSBaptiste Daroussin 	print_word(n->child->string);
1360*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
1361*61d06d6bSBaptiste Daroussin }
1362*61d06d6bSBaptiste Daroussin 
1363*61d06d6bSBaptiste Daroussin static int
1364*61d06d6bSBaptiste Daroussin pre_in(DECL_ARGS)
1365*61d06d6bSBaptiste Daroussin {
1366*61d06d6bSBaptiste Daroussin 
1367*61d06d6bSBaptiste Daroussin 	if (NODE_SYNPRETTY & n->flags) {
1368*61d06d6bSBaptiste Daroussin 		pre_syn(n);
1369*61d06d6bSBaptiste Daroussin 		font_push('B');
1370*61d06d6bSBaptiste Daroussin 		print_word("#include <");
1371*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
1372*61d06d6bSBaptiste Daroussin 	} else {
1373*61d06d6bSBaptiste Daroussin 		print_word("<");
1374*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
1375*61d06d6bSBaptiste Daroussin 		font_push('I');
1376*61d06d6bSBaptiste Daroussin 	}
1377*61d06d6bSBaptiste Daroussin 	return 1;
1378*61d06d6bSBaptiste Daroussin }
1379*61d06d6bSBaptiste Daroussin 
1380*61d06d6bSBaptiste Daroussin static void
1381*61d06d6bSBaptiste Daroussin post_in(DECL_ARGS)
1382*61d06d6bSBaptiste Daroussin {
1383*61d06d6bSBaptiste Daroussin 
1384*61d06d6bSBaptiste Daroussin 	if (NODE_SYNPRETTY & n->flags) {
1385*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
1386*61d06d6bSBaptiste Daroussin 		print_word(">");
1387*61d06d6bSBaptiste Daroussin 		font_pop();
1388*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_br;
1389*61d06d6bSBaptiste Daroussin 	} else {
1390*61d06d6bSBaptiste Daroussin 		font_pop();
1391*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
1392*61d06d6bSBaptiste Daroussin 		print_word(">");
1393*61d06d6bSBaptiste Daroussin 	}
1394*61d06d6bSBaptiste Daroussin }
1395*61d06d6bSBaptiste Daroussin 
1396*61d06d6bSBaptiste Daroussin static int
1397*61d06d6bSBaptiste Daroussin pre_it(DECL_ARGS)
1398*61d06d6bSBaptiste Daroussin {
1399*61d06d6bSBaptiste Daroussin 	const struct roff_node *bln;
1400*61d06d6bSBaptiste Daroussin 
1401*61d06d6bSBaptiste Daroussin 	switch (n->type) {
1402*61d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
1403*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_PP | MMAN_nl;
1404*61d06d6bSBaptiste Daroussin 		bln = n->parent->parent;
1405*61d06d6bSBaptiste Daroussin 		if (0 == bln->norm->Bl.comp ||
1406*61d06d6bSBaptiste Daroussin 		    (NULL == n->parent->prev &&
1407*61d06d6bSBaptiste Daroussin 		     NULL == bln->parent->prev))
1408*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_sp;
1409*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_br;
1410*61d06d6bSBaptiste Daroussin 		switch (bln->norm->Bl.type) {
1411*61d06d6bSBaptiste Daroussin 		case LIST_item:
1412*61d06d6bSBaptiste Daroussin 			return 0;
1413*61d06d6bSBaptiste Daroussin 		case LIST_inset:
1414*61d06d6bSBaptiste Daroussin 		case LIST_diag:
1415*61d06d6bSBaptiste Daroussin 		case LIST_ohang:
1416*61d06d6bSBaptiste Daroussin 			if (bln->norm->Bl.type == LIST_diag)
1417*61d06d6bSBaptiste Daroussin 				print_line(".B \"", 0);
1418*61d06d6bSBaptiste Daroussin 			else
1419*61d06d6bSBaptiste Daroussin 				print_line(".BR \\& \"", 0);
1420*61d06d6bSBaptiste Daroussin 			outflags &= ~MMAN_spc;
1421*61d06d6bSBaptiste Daroussin 			return 1;
1422*61d06d6bSBaptiste Daroussin 		case LIST_bullet:
1423*61d06d6bSBaptiste Daroussin 		case LIST_dash:
1424*61d06d6bSBaptiste Daroussin 		case LIST_hyphen:
1425*61d06d6bSBaptiste Daroussin 			print_width(&bln->norm->Bl, NULL);
1426*61d06d6bSBaptiste Daroussin 			TPremain = 0;
1427*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_nl;
1428*61d06d6bSBaptiste Daroussin 			font_push('B');
1429*61d06d6bSBaptiste Daroussin 			if (LIST_bullet == bln->norm->Bl.type)
1430*61d06d6bSBaptiste Daroussin 				print_word("\\(bu");
1431*61d06d6bSBaptiste Daroussin 			else
1432*61d06d6bSBaptiste Daroussin 				print_word("-");
1433*61d06d6bSBaptiste Daroussin 			font_pop();
1434*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_nl;
1435*61d06d6bSBaptiste Daroussin 			return 0;
1436*61d06d6bSBaptiste Daroussin 		case LIST_enum:
1437*61d06d6bSBaptiste Daroussin 			print_width(&bln->norm->Bl, NULL);
1438*61d06d6bSBaptiste Daroussin 			TPremain = 0;
1439*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_nl;
1440*61d06d6bSBaptiste Daroussin 			print_count(&bln->norm->Bl.count);
1441*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_nl;
1442*61d06d6bSBaptiste Daroussin 			return 0;
1443*61d06d6bSBaptiste Daroussin 		case LIST_hang:
1444*61d06d6bSBaptiste Daroussin 			print_width(&bln->norm->Bl, n->child);
1445*61d06d6bSBaptiste Daroussin 			TPremain = 0;
1446*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_nl;
1447*61d06d6bSBaptiste Daroussin 			return 1;
1448*61d06d6bSBaptiste Daroussin 		case LIST_tag:
1449*61d06d6bSBaptiste Daroussin 			print_width(&bln->norm->Bl, n->child);
1450*61d06d6bSBaptiste Daroussin 			putchar('\n');
1451*61d06d6bSBaptiste Daroussin 			outflags &= ~MMAN_spc;
1452*61d06d6bSBaptiste Daroussin 			return 1;
1453*61d06d6bSBaptiste Daroussin 		default:
1454*61d06d6bSBaptiste Daroussin 			return 1;
1455*61d06d6bSBaptiste Daroussin 		}
1456*61d06d6bSBaptiste Daroussin 	default:
1457*61d06d6bSBaptiste Daroussin 		break;
1458*61d06d6bSBaptiste Daroussin 	}
1459*61d06d6bSBaptiste Daroussin 	return 1;
1460*61d06d6bSBaptiste Daroussin }
1461*61d06d6bSBaptiste Daroussin 
1462*61d06d6bSBaptiste Daroussin /*
1463*61d06d6bSBaptiste Daroussin  * This function is called after closing out an indented block.
1464*61d06d6bSBaptiste Daroussin  * If we are inside an enclosing list, restore its indentation.
1465*61d06d6bSBaptiste Daroussin  */
1466*61d06d6bSBaptiste Daroussin static void
1467*61d06d6bSBaptiste Daroussin mid_it(void)
1468*61d06d6bSBaptiste Daroussin {
1469*61d06d6bSBaptiste Daroussin 	char		 buf[24];
1470*61d06d6bSBaptiste Daroussin 
1471*61d06d6bSBaptiste Daroussin 	/* Nothing to do outside a list. */
1472*61d06d6bSBaptiste Daroussin 	if (0 == Bl_stack_len || 0 == Bl_stack[Bl_stack_len - 1])
1473*61d06d6bSBaptiste Daroussin 		return;
1474*61d06d6bSBaptiste Daroussin 
1475*61d06d6bSBaptiste Daroussin 	/* The indentation has already been set up. */
1476*61d06d6bSBaptiste Daroussin 	if (Bl_stack_post[Bl_stack_len - 1])
1477*61d06d6bSBaptiste Daroussin 		return;
1478*61d06d6bSBaptiste Daroussin 
1479*61d06d6bSBaptiste Daroussin 	/* Restore the indentation of the enclosing list. */
1480*61d06d6bSBaptiste Daroussin 	print_line(".RS", MMAN_Bk_susp);
1481*61d06d6bSBaptiste Daroussin 	(void)snprintf(buf, sizeof(buf), "%dn",
1482*61d06d6bSBaptiste Daroussin 	    Bl_stack[Bl_stack_len - 1]);
1483*61d06d6bSBaptiste Daroussin 	print_word(buf);
1484*61d06d6bSBaptiste Daroussin 
1485*61d06d6bSBaptiste Daroussin 	/* Remeber to close out this .RS block later. */
1486*61d06d6bSBaptiste Daroussin 	Bl_stack_post[Bl_stack_len - 1] = 1;
1487*61d06d6bSBaptiste Daroussin }
1488*61d06d6bSBaptiste Daroussin 
1489*61d06d6bSBaptiste Daroussin static void
1490*61d06d6bSBaptiste Daroussin post_it(DECL_ARGS)
1491*61d06d6bSBaptiste Daroussin {
1492*61d06d6bSBaptiste Daroussin 	const struct roff_node *bln;
1493*61d06d6bSBaptiste Daroussin 
1494*61d06d6bSBaptiste Daroussin 	bln = n->parent->parent;
1495*61d06d6bSBaptiste Daroussin 
1496*61d06d6bSBaptiste Daroussin 	switch (n->type) {
1497*61d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
1498*61d06d6bSBaptiste Daroussin 		switch (bln->norm->Bl.type) {
1499*61d06d6bSBaptiste Daroussin 		case LIST_diag:
1500*61d06d6bSBaptiste Daroussin 			outflags &= ~MMAN_spc;
1501*61d06d6bSBaptiste Daroussin 			print_word("\\ ");
1502*61d06d6bSBaptiste Daroussin 			break;
1503*61d06d6bSBaptiste Daroussin 		case LIST_ohang:
1504*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_br;
1505*61d06d6bSBaptiste Daroussin 			break;
1506*61d06d6bSBaptiste Daroussin 		default:
1507*61d06d6bSBaptiste Daroussin 			break;
1508*61d06d6bSBaptiste Daroussin 		}
1509*61d06d6bSBaptiste Daroussin 		break;
1510*61d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
1511*61d06d6bSBaptiste Daroussin 		switch (bln->norm->Bl.type) {
1512*61d06d6bSBaptiste Daroussin 		case LIST_bullet:
1513*61d06d6bSBaptiste Daroussin 		case LIST_dash:
1514*61d06d6bSBaptiste Daroussin 		case LIST_hyphen:
1515*61d06d6bSBaptiste Daroussin 		case LIST_enum:
1516*61d06d6bSBaptiste Daroussin 		case LIST_hang:
1517*61d06d6bSBaptiste Daroussin 		case LIST_tag:
1518*61d06d6bSBaptiste Daroussin 			assert(Bl_stack_len);
1519*61d06d6bSBaptiste Daroussin 			Bl_stack[--Bl_stack_len] = 0;
1520*61d06d6bSBaptiste Daroussin 
1521*61d06d6bSBaptiste Daroussin 			/*
1522*61d06d6bSBaptiste Daroussin 			 * Our indentation had to be restored
1523*61d06d6bSBaptiste Daroussin 			 * after a child display or child list.
1524*61d06d6bSBaptiste Daroussin 			 * Close out that indentation block now.
1525*61d06d6bSBaptiste Daroussin 			 */
1526*61d06d6bSBaptiste Daroussin 			if (Bl_stack_post[Bl_stack_len]) {
1527*61d06d6bSBaptiste Daroussin 				print_line(".RE", MMAN_nl);
1528*61d06d6bSBaptiste Daroussin 				Bl_stack_post[Bl_stack_len] = 0;
1529*61d06d6bSBaptiste Daroussin 			}
1530*61d06d6bSBaptiste Daroussin 			break;
1531*61d06d6bSBaptiste Daroussin 		case LIST_column:
1532*61d06d6bSBaptiste Daroussin 			if (NULL != n->next) {
1533*61d06d6bSBaptiste Daroussin 				putchar('\t');
1534*61d06d6bSBaptiste Daroussin 				outflags &= ~MMAN_spc;
1535*61d06d6bSBaptiste Daroussin 			}
1536*61d06d6bSBaptiste Daroussin 			break;
1537*61d06d6bSBaptiste Daroussin 		default:
1538*61d06d6bSBaptiste Daroussin 			break;
1539*61d06d6bSBaptiste Daroussin 		}
1540*61d06d6bSBaptiste Daroussin 		break;
1541*61d06d6bSBaptiste Daroussin 	default:
1542*61d06d6bSBaptiste Daroussin 		break;
1543*61d06d6bSBaptiste Daroussin 	}
1544*61d06d6bSBaptiste Daroussin }
1545*61d06d6bSBaptiste Daroussin 
1546*61d06d6bSBaptiste Daroussin static void
1547*61d06d6bSBaptiste Daroussin post_lb(DECL_ARGS)
1548*61d06d6bSBaptiste Daroussin {
1549*61d06d6bSBaptiste Daroussin 
1550*61d06d6bSBaptiste Daroussin 	if (SEC_LIBRARY == n->sec)
1551*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_br;
1552*61d06d6bSBaptiste Daroussin }
1553*61d06d6bSBaptiste Daroussin 
1554*61d06d6bSBaptiste Daroussin static int
1555*61d06d6bSBaptiste Daroussin pre_lk(DECL_ARGS)
1556*61d06d6bSBaptiste Daroussin {
1557*61d06d6bSBaptiste Daroussin 	const struct roff_node *link, *descr, *punct;
1558*61d06d6bSBaptiste Daroussin 
1559*61d06d6bSBaptiste Daroussin 	if ((link = n->child) == NULL)
1560*61d06d6bSBaptiste Daroussin 		return 0;
1561*61d06d6bSBaptiste Daroussin 
1562*61d06d6bSBaptiste Daroussin 	/* Find beginning of trailing punctuation. */
1563*61d06d6bSBaptiste Daroussin 	punct = n->last;
1564*61d06d6bSBaptiste Daroussin 	while (punct != link && punct->flags & NODE_DELIMC)
1565*61d06d6bSBaptiste Daroussin 		punct = punct->prev;
1566*61d06d6bSBaptiste Daroussin 	punct = punct->next;
1567*61d06d6bSBaptiste Daroussin 
1568*61d06d6bSBaptiste Daroussin 	/* Link text. */
1569*61d06d6bSBaptiste Daroussin 	if ((descr = link->next) != NULL && descr != punct) {
1570*61d06d6bSBaptiste Daroussin 		font_push('I');
1571*61d06d6bSBaptiste Daroussin 		while (descr != punct) {
1572*61d06d6bSBaptiste Daroussin 			print_word(descr->string);
1573*61d06d6bSBaptiste Daroussin 			descr = descr->next;
1574*61d06d6bSBaptiste Daroussin 		}
1575*61d06d6bSBaptiste Daroussin 		font_pop();
1576*61d06d6bSBaptiste Daroussin 		print_word(":");
1577*61d06d6bSBaptiste Daroussin 	}
1578*61d06d6bSBaptiste Daroussin 
1579*61d06d6bSBaptiste Daroussin 	/* Link target. */
1580*61d06d6bSBaptiste Daroussin 	font_push('B');
1581*61d06d6bSBaptiste Daroussin 	print_word(link->string);
1582*61d06d6bSBaptiste Daroussin 	font_pop();
1583*61d06d6bSBaptiste Daroussin 
1584*61d06d6bSBaptiste Daroussin 	/* Trailing punctuation. */
1585*61d06d6bSBaptiste Daroussin 	while (punct != NULL) {
1586*61d06d6bSBaptiste Daroussin 		print_word(punct->string);
1587*61d06d6bSBaptiste Daroussin 		punct = punct->next;
1588*61d06d6bSBaptiste Daroussin 	}
1589*61d06d6bSBaptiste Daroussin 	return 0;
1590*61d06d6bSBaptiste Daroussin }
1591*61d06d6bSBaptiste Daroussin 
1592*61d06d6bSBaptiste Daroussin static void
1593*61d06d6bSBaptiste Daroussin pre_onearg(DECL_ARGS)
1594*61d06d6bSBaptiste Daroussin {
1595*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
1596*61d06d6bSBaptiste Daroussin 	print_word(".");
1597*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
1598*61d06d6bSBaptiste Daroussin 	print_word(roff_name[n->tok]);
1599*61d06d6bSBaptiste Daroussin 	if (n->child != NULL)
1600*61d06d6bSBaptiste Daroussin 		print_word(n->child->string);
1601*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
1602*61d06d6bSBaptiste Daroussin 	if (n->tok == ROFF_ce)
1603*61d06d6bSBaptiste Daroussin 		for (n = n->child->next; n != NULL; n = n->next)
1604*61d06d6bSBaptiste Daroussin 			print_node(meta, n);
1605*61d06d6bSBaptiste Daroussin }
1606*61d06d6bSBaptiste Daroussin 
1607*61d06d6bSBaptiste Daroussin static int
1608*61d06d6bSBaptiste Daroussin pre_li(DECL_ARGS)
1609*61d06d6bSBaptiste Daroussin {
1610*61d06d6bSBaptiste Daroussin 
1611*61d06d6bSBaptiste Daroussin 	font_push('R');
1612*61d06d6bSBaptiste Daroussin 	return 1;
1613*61d06d6bSBaptiste Daroussin }
1614*61d06d6bSBaptiste Daroussin 
1615*61d06d6bSBaptiste Daroussin static int
1616*61d06d6bSBaptiste Daroussin pre_nm(DECL_ARGS)
1617*61d06d6bSBaptiste Daroussin {
1618*61d06d6bSBaptiste Daroussin 	char	*name;
1619*61d06d6bSBaptiste Daroussin 
1620*61d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_BLOCK) {
1621*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_Bk;
1622*61d06d6bSBaptiste Daroussin 		pre_syn(n);
1623*61d06d6bSBaptiste Daroussin 	}
1624*61d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_ELEM && n->type != ROFFT_HEAD)
1625*61d06d6bSBaptiste Daroussin 		return 1;
1626*61d06d6bSBaptiste Daroussin 	name = n->child == NULL ? NULL : n->child->string;
1627*61d06d6bSBaptiste Daroussin 	if (NULL == name)
1628*61d06d6bSBaptiste Daroussin 		return 0;
1629*61d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_HEAD) {
1630*61d06d6bSBaptiste Daroussin 		if (NULL == n->parent->prev)
1631*61d06d6bSBaptiste Daroussin 			outflags |= MMAN_sp;
1632*61d06d6bSBaptiste Daroussin 		print_block(".HP", 0);
1633*61d06d6bSBaptiste Daroussin 		printf(" %dn", man_strlen(name) + 1);
1634*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_nl;
1635*61d06d6bSBaptiste Daroussin 	}
1636*61d06d6bSBaptiste Daroussin 	font_push('B');
1637*61d06d6bSBaptiste Daroussin 	return 1;
1638*61d06d6bSBaptiste Daroussin }
1639*61d06d6bSBaptiste Daroussin 
1640*61d06d6bSBaptiste Daroussin static void
1641*61d06d6bSBaptiste Daroussin post_nm(DECL_ARGS)
1642*61d06d6bSBaptiste Daroussin {
1643*61d06d6bSBaptiste Daroussin 
1644*61d06d6bSBaptiste Daroussin 	switch (n->type) {
1645*61d06d6bSBaptiste Daroussin 	case ROFFT_BLOCK:
1646*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_Bk;
1647*61d06d6bSBaptiste Daroussin 		break;
1648*61d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
1649*61d06d6bSBaptiste Daroussin 	case ROFFT_ELEM:
1650*61d06d6bSBaptiste Daroussin 		if (n->child != NULL && n->child->string != NULL)
1651*61d06d6bSBaptiste Daroussin 			font_pop();
1652*61d06d6bSBaptiste Daroussin 		break;
1653*61d06d6bSBaptiste Daroussin 	default:
1654*61d06d6bSBaptiste Daroussin 		break;
1655*61d06d6bSBaptiste Daroussin 	}
1656*61d06d6bSBaptiste Daroussin }
1657*61d06d6bSBaptiste Daroussin 
1658*61d06d6bSBaptiste Daroussin static int
1659*61d06d6bSBaptiste Daroussin pre_no(DECL_ARGS)
1660*61d06d6bSBaptiste Daroussin {
1661*61d06d6bSBaptiste Daroussin 
1662*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_spc_force;
1663*61d06d6bSBaptiste Daroussin 	return 1;
1664*61d06d6bSBaptiste Daroussin }
1665*61d06d6bSBaptiste Daroussin 
1666*61d06d6bSBaptiste Daroussin static int
1667*61d06d6bSBaptiste Daroussin pre_ns(DECL_ARGS)
1668*61d06d6bSBaptiste Daroussin {
1669*61d06d6bSBaptiste Daroussin 
1670*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
1671*61d06d6bSBaptiste Daroussin 	return 0;
1672*61d06d6bSBaptiste Daroussin }
1673*61d06d6bSBaptiste Daroussin 
1674*61d06d6bSBaptiste Daroussin static void
1675*61d06d6bSBaptiste Daroussin post_pf(DECL_ARGS)
1676*61d06d6bSBaptiste Daroussin {
1677*61d06d6bSBaptiste Daroussin 
1678*61d06d6bSBaptiste Daroussin 	if ( ! (n->next == NULL || n->next->flags & NODE_LINE))
1679*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
1680*61d06d6bSBaptiste Daroussin }
1681*61d06d6bSBaptiste Daroussin 
1682*61d06d6bSBaptiste Daroussin static int
1683*61d06d6bSBaptiste Daroussin pre_pp(DECL_ARGS)
1684*61d06d6bSBaptiste Daroussin {
1685*61d06d6bSBaptiste Daroussin 
1686*61d06d6bSBaptiste Daroussin 	if (MDOC_It != n->parent->tok)
1687*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_PP;
1688*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_sp | MMAN_nl;
1689*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_br;
1690*61d06d6bSBaptiste Daroussin 	return 0;
1691*61d06d6bSBaptiste Daroussin }
1692*61d06d6bSBaptiste Daroussin 
1693*61d06d6bSBaptiste Daroussin static int
1694*61d06d6bSBaptiste Daroussin pre_rs(DECL_ARGS)
1695*61d06d6bSBaptiste Daroussin {
1696*61d06d6bSBaptiste Daroussin 
1697*61d06d6bSBaptiste Daroussin 	if (SEC_SEE_ALSO == n->sec) {
1698*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_PP | MMAN_sp | MMAN_nl;
1699*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_br;
1700*61d06d6bSBaptiste Daroussin 	}
1701*61d06d6bSBaptiste Daroussin 	return 1;
1702*61d06d6bSBaptiste Daroussin }
1703*61d06d6bSBaptiste Daroussin 
1704*61d06d6bSBaptiste Daroussin static int
1705*61d06d6bSBaptiste Daroussin pre_skip(DECL_ARGS)
1706*61d06d6bSBaptiste Daroussin {
1707*61d06d6bSBaptiste Daroussin 
1708*61d06d6bSBaptiste Daroussin 	return 0;
1709*61d06d6bSBaptiste Daroussin }
1710*61d06d6bSBaptiste Daroussin 
1711*61d06d6bSBaptiste Daroussin static int
1712*61d06d6bSBaptiste Daroussin pre_sm(DECL_ARGS)
1713*61d06d6bSBaptiste Daroussin {
1714*61d06d6bSBaptiste Daroussin 
1715*61d06d6bSBaptiste Daroussin 	if (NULL == n->child)
1716*61d06d6bSBaptiste Daroussin 		outflags ^= MMAN_Sm;
1717*61d06d6bSBaptiste Daroussin 	else if (0 == strcmp("on", n->child->string))
1718*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_Sm;
1719*61d06d6bSBaptiste Daroussin 	else
1720*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_Sm;
1721*61d06d6bSBaptiste Daroussin 
1722*61d06d6bSBaptiste Daroussin 	if (MMAN_Sm & outflags)
1723*61d06d6bSBaptiste Daroussin 		outflags |= MMAN_spc;
1724*61d06d6bSBaptiste Daroussin 
1725*61d06d6bSBaptiste Daroussin 	return 0;
1726*61d06d6bSBaptiste Daroussin }
1727*61d06d6bSBaptiste Daroussin 
1728*61d06d6bSBaptiste Daroussin static void
1729*61d06d6bSBaptiste Daroussin pre_sp(DECL_ARGS)
1730*61d06d6bSBaptiste Daroussin {
1731*61d06d6bSBaptiste Daroussin 	if (outflags & MMAN_PP) {
1732*61d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_PP;
1733*61d06d6bSBaptiste Daroussin 		print_line(".PP", 0);
1734*61d06d6bSBaptiste Daroussin 	} else {
1735*61d06d6bSBaptiste Daroussin 		print_line(".sp", 0);
1736*61d06d6bSBaptiste Daroussin 		if (n->child != NULL)
1737*61d06d6bSBaptiste Daroussin 			print_word(n->child->string);
1738*61d06d6bSBaptiste Daroussin 	}
1739*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
1740*61d06d6bSBaptiste Daroussin }
1741*61d06d6bSBaptiste Daroussin 
1742*61d06d6bSBaptiste Daroussin static int
1743*61d06d6bSBaptiste Daroussin pre_sy(DECL_ARGS)
1744*61d06d6bSBaptiste Daroussin {
1745*61d06d6bSBaptiste Daroussin 
1746*61d06d6bSBaptiste Daroussin 	font_push('B');
1747*61d06d6bSBaptiste Daroussin 	return 1;
1748*61d06d6bSBaptiste Daroussin }
1749*61d06d6bSBaptiste Daroussin 
1750*61d06d6bSBaptiste Daroussin static void
1751*61d06d6bSBaptiste Daroussin pre_ta(DECL_ARGS)
1752*61d06d6bSBaptiste Daroussin {
1753*61d06d6bSBaptiste Daroussin 	print_line(".ta", 0);
1754*61d06d6bSBaptiste Daroussin 	for (n = n->child; n != NULL; n = n->next)
1755*61d06d6bSBaptiste Daroussin 		print_word(n->string);
1756*61d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
1757*61d06d6bSBaptiste Daroussin }
1758*61d06d6bSBaptiste Daroussin 
1759*61d06d6bSBaptiste Daroussin static int
1760*61d06d6bSBaptiste Daroussin pre_vt(DECL_ARGS)
1761*61d06d6bSBaptiste Daroussin {
1762*61d06d6bSBaptiste Daroussin 
1763*61d06d6bSBaptiste Daroussin 	if (NODE_SYNPRETTY & n->flags) {
1764*61d06d6bSBaptiste Daroussin 		switch (n->type) {
1765*61d06d6bSBaptiste Daroussin 		case ROFFT_BLOCK:
1766*61d06d6bSBaptiste Daroussin 			pre_syn(n);
1767*61d06d6bSBaptiste Daroussin 			return 1;
1768*61d06d6bSBaptiste Daroussin 		case ROFFT_BODY:
1769*61d06d6bSBaptiste Daroussin 			break;
1770*61d06d6bSBaptiste Daroussin 		default:
1771*61d06d6bSBaptiste Daroussin 			return 0;
1772*61d06d6bSBaptiste Daroussin 		}
1773*61d06d6bSBaptiste Daroussin 	}
1774*61d06d6bSBaptiste Daroussin 	font_push('I');
1775*61d06d6bSBaptiste Daroussin 	return 1;
1776*61d06d6bSBaptiste Daroussin }
1777*61d06d6bSBaptiste Daroussin 
1778*61d06d6bSBaptiste Daroussin static void
1779*61d06d6bSBaptiste Daroussin post_vt(DECL_ARGS)
1780*61d06d6bSBaptiste Daroussin {
1781*61d06d6bSBaptiste Daroussin 
1782*61d06d6bSBaptiste Daroussin 	if (n->flags & NODE_SYNPRETTY && n->type != ROFFT_BODY)
1783*61d06d6bSBaptiste Daroussin 		return;
1784*61d06d6bSBaptiste Daroussin 	font_pop();
1785*61d06d6bSBaptiste Daroussin }
1786*61d06d6bSBaptiste Daroussin 
1787*61d06d6bSBaptiste Daroussin static int
1788*61d06d6bSBaptiste Daroussin pre_xr(DECL_ARGS)
1789*61d06d6bSBaptiste Daroussin {
1790*61d06d6bSBaptiste Daroussin 
1791*61d06d6bSBaptiste Daroussin 	n = n->child;
1792*61d06d6bSBaptiste Daroussin 	if (NULL == n)
1793*61d06d6bSBaptiste Daroussin 		return 0;
1794*61d06d6bSBaptiste Daroussin 	print_node(meta, n);
1795*61d06d6bSBaptiste Daroussin 	n = n->next;
1796*61d06d6bSBaptiste Daroussin 	if (NULL == n)
1797*61d06d6bSBaptiste Daroussin 		return 0;
1798*61d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
1799*61d06d6bSBaptiste Daroussin 	print_word("(");
1800*61d06d6bSBaptiste Daroussin 	print_node(meta, n);
1801*61d06d6bSBaptiste Daroussin 	print_word(")");
1802*61d06d6bSBaptiste Daroussin 	return 0;
1803*61d06d6bSBaptiste Daroussin }
1804