xref: /freebsd/contrib/mandoc/mdoc_man.c (revision c1c95add8c80843ba15d784f95c361d795b1f593)
1*c1c95addSBrooks Davis /* $Id: mdoc_man.c,v 1.138 2023/04/28 19:11:04 schwarze Exp $ */
261d06d6bSBaptiste Daroussin /*
36d38604fSBaptiste Daroussin  * Copyright (c) 2011-2021 Ingo Schwarze <schwarze@openbsd.org>
461d06d6bSBaptiste Daroussin  *
561d06d6bSBaptiste Daroussin  * Permission to use, copy, modify, and distribute this software for any
661d06d6bSBaptiste Daroussin  * purpose with or without fee is hereby granted, provided that the above
761d06d6bSBaptiste Daroussin  * copyright notice and this permission notice appear in all copies.
861d06d6bSBaptiste Daroussin  *
961d06d6bSBaptiste Daroussin  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1061d06d6bSBaptiste Daroussin  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1161d06d6bSBaptiste Daroussin  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1261d06d6bSBaptiste Daroussin  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1361d06d6bSBaptiste Daroussin  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1461d06d6bSBaptiste Daroussin  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1561d06d6bSBaptiste Daroussin  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1661d06d6bSBaptiste Daroussin  */
1761d06d6bSBaptiste Daroussin #include "config.h"
1861d06d6bSBaptiste Daroussin 
1961d06d6bSBaptiste Daroussin #include <sys/types.h>
2061d06d6bSBaptiste Daroussin 
2161d06d6bSBaptiste Daroussin #include <assert.h>
2261d06d6bSBaptiste Daroussin #include <stdio.h>
2361d06d6bSBaptiste Daroussin #include <stdlib.h>
2461d06d6bSBaptiste Daroussin #include <string.h>
2561d06d6bSBaptiste Daroussin 
2661d06d6bSBaptiste Daroussin #include "mandoc_aux.h"
2761d06d6bSBaptiste Daroussin #include "mandoc.h"
2861d06d6bSBaptiste Daroussin #include "roff.h"
2961d06d6bSBaptiste Daroussin #include "mdoc.h"
3061d06d6bSBaptiste Daroussin #include "man.h"
3161d06d6bSBaptiste Daroussin #include "out.h"
3261d06d6bSBaptiste Daroussin #include "main.h"
3361d06d6bSBaptiste Daroussin 
3461d06d6bSBaptiste Daroussin #define	DECL_ARGS const struct roff_meta *meta, struct roff_node *n
3561d06d6bSBaptiste Daroussin 
3661d06d6bSBaptiste Daroussin typedef	int	(*int_fp)(DECL_ARGS);
3761d06d6bSBaptiste Daroussin typedef	void	(*void_fp)(DECL_ARGS);
3861d06d6bSBaptiste Daroussin 
397295610fSBaptiste Daroussin struct	mdoc_man_act {
4061d06d6bSBaptiste Daroussin 	int_fp		  cond; /* DON'T run actions */
4161d06d6bSBaptiste Daroussin 	int_fp		  pre; /* pre-node action */
4261d06d6bSBaptiste Daroussin 	void_fp		  post; /* post-node action */
4361d06d6bSBaptiste Daroussin 	const char	 *prefix; /* pre-node string constant */
4461d06d6bSBaptiste Daroussin 	const char	 *suffix; /* post-node string constant */
4561d06d6bSBaptiste Daroussin };
4661d06d6bSBaptiste Daroussin 
4761d06d6bSBaptiste Daroussin static	int	  cond_body(DECL_ARGS);
4861d06d6bSBaptiste Daroussin static	int	  cond_head(DECL_ARGS);
4961d06d6bSBaptiste Daroussin static  void	  font_push(char);
5061d06d6bSBaptiste Daroussin static	void	  font_pop(void);
5161d06d6bSBaptiste Daroussin static	int	  man_strlen(const char *);
5261d06d6bSBaptiste Daroussin static	void	  mid_it(void);
5361d06d6bSBaptiste Daroussin static	void	  post__t(DECL_ARGS);
5461d06d6bSBaptiste Daroussin static	void	  post_aq(DECL_ARGS);
5561d06d6bSBaptiste Daroussin static	void	  post_bd(DECL_ARGS);
5661d06d6bSBaptiste Daroussin static	void	  post_bf(DECL_ARGS);
5761d06d6bSBaptiste Daroussin static	void	  post_bk(DECL_ARGS);
5861d06d6bSBaptiste Daroussin static	void	  post_bl(DECL_ARGS);
5961d06d6bSBaptiste Daroussin static	void	  post_dl(DECL_ARGS);
6061d06d6bSBaptiste Daroussin static	void	  post_en(DECL_ARGS);
6161d06d6bSBaptiste Daroussin static	void	  post_enc(DECL_ARGS);
6261d06d6bSBaptiste Daroussin static	void	  post_eo(DECL_ARGS);
6361d06d6bSBaptiste Daroussin static	void	  post_fa(DECL_ARGS);
6461d06d6bSBaptiste Daroussin static	void	  post_fd(DECL_ARGS);
6561d06d6bSBaptiste Daroussin static	void	  post_fl(DECL_ARGS);
6661d06d6bSBaptiste Daroussin static	void	  post_fn(DECL_ARGS);
6761d06d6bSBaptiste Daroussin static	void	  post_fo(DECL_ARGS);
6861d06d6bSBaptiste Daroussin static	void	  post_font(DECL_ARGS);
6961d06d6bSBaptiste Daroussin static	void	  post_in(DECL_ARGS);
7061d06d6bSBaptiste Daroussin static	void	  post_it(DECL_ARGS);
7161d06d6bSBaptiste Daroussin static	void	  post_lb(DECL_ARGS);
7261d06d6bSBaptiste Daroussin static	void	  post_nm(DECL_ARGS);
7361d06d6bSBaptiste Daroussin static	void	  post_percent(DECL_ARGS);
7461d06d6bSBaptiste Daroussin static	void	  post_pf(DECL_ARGS);
7561d06d6bSBaptiste Daroussin static	void	  post_sect(DECL_ARGS);
7661d06d6bSBaptiste Daroussin static	void	  post_vt(DECL_ARGS);
7761d06d6bSBaptiste Daroussin static	int	  pre__t(DECL_ARGS);
787295610fSBaptiste Daroussin static	int	  pre_abort(DECL_ARGS);
7961d06d6bSBaptiste Daroussin static	int	  pre_an(DECL_ARGS);
8061d06d6bSBaptiste Daroussin static	int	  pre_ap(DECL_ARGS);
8161d06d6bSBaptiste Daroussin static	int	  pre_aq(DECL_ARGS);
8261d06d6bSBaptiste Daroussin static	int	  pre_bd(DECL_ARGS);
8361d06d6bSBaptiste Daroussin static	int	  pre_bf(DECL_ARGS);
8461d06d6bSBaptiste Daroussin static	int	  pre_bk(DECL_ARGS);
8561d06d6bSBaptiste Daroussin static	int	  pre_bl(DECL_ARGS);
8661d06d6bSBaptiste Daroussin static	void	  pre_br(DECL_ARGS);
8761d06d6bSBaptiste Daroussin static	int	  pre_dl(DECL_ARGS);
8861d06d6bSBaptiste Daroussin static	int	  pre_en(DECL_ARGS);
8961d06d6bSBaptiste Daroussin static	int	  pre_enc(DECL_ARGS);
9061d06d6bSBaptiste Daroussin static	int	  pre_em(DECL_ARGS);
9161d06d6bSBaptiste Daroussin static	int	  pre_skip(DECL_ARGS);
9261d06d6bSBaptiste Daroussin static	int	  pre_eo(DECL_ARGS);
9361d06d6bSBaptiste Daroussin static	int	  pre_ex(DECL_ARGS);
9461d06d6bSBaptiste Daroussin static	int	  pre_fa(DECL_ARGS);
9561d06d6bSBaptiste Daroussin static	int	  pre_fd(DECL_ARGS);
9661d06d6bSBaptiste Daroussin static	int	  pre_fl(DECL_ARGS);
9761d06d6bSBaptiste Daroussin static	int	  pre_fn(DECL_ARGS);
9861d06d6bSBaptiste Daroussin static	int	  pre_fo(DECL_ARGS);
9961d06d6bSBaptiste Daroussin static	void	  pre_ft(DECL_ARGS);
10061d06d6bSBaptiste Daroussin static	int	  pre_Ft(DECL_ARGS);
10161d06d6bSBaptiste Daroussin static	int	  pre_in(DECL_ARGS);
10261d06d6bSBaptiste Daroussin static	int	  pre_it(DECL_ARGS);
10361d06d6bSBaptiste Daroussin static	int	  pre_lk(DECL_ARGS);
10461d06d6bSBaptiste Daroussin static	int	  pre_li(DECL_ARGS);
10561d06d6bSBaptiste Daroussin static	int	  pre_nm(DECL_ARGS);
10661d06d6bSBaptiste Daroussin static	int	  pre_no(DECL_ARGS);
1077295610fSBaptiste Daroussin static	void	  pre_noarg(DECL_ARGS);
10861d06d6bSBaptiste Daroussin static	int	  pre_ns(DECL_ARGS);
10961d06d6bSBaptiste Daroussin static	void	  pre_onearg(DECL_ARGS);
11061d06d6bSBaptiste Daroussin static	int	  pre_pp(DECL_ARGS);
11161d06d6bSBaptiste Daroussin static	int	  pre_rs(DECL_ARGS);
11261d06d6bSBaptiste Daroussin static	int	  pre_sm(DECL_ARGS);
11361d06d6bSBaptiste Daroussin static	void	  pre_sp(DECL_ARGS);
11461d06d6bSBaptiste Daroussin static	int	  pre_sect(DECL_ARGS);
11561d06d6bSBaptiste Daroussin static	int	  pre_sy(DECL_ARGS);
1166d38604fSBaptiste Daroussin static	void	  pre_syn(struct roff_node *);
11761d06d6bSBaptiste Daroussin static	void	  pre_ta(DECL_ARGS);
11861d06d6bSBaptiste Daroussin static	int	  pre_vt(DECL_ARGS);
11961d06d6bSBaptiste Daroussin static	int	  pre_xr(DECL_ARGS);
12061d06d6bSBaptiste Daroussin static	void	  print_word(const char *);
12161d06d6bSBaptiste Daroussin static	void	  print_line(const char *, int);
12261d06d6bSBaptiste Daroussin static	void	  print_block(const char *, int);
12361d06d6bSBaptiste Daroussin static	void	  print_offs(const char *, int);
12461d06d6bSBaptiste Daroussin static	void	  print_width(const struct mdoc_bl *,
12561d06d6bSBaptiste Daroussin 			const struct roff_node *);
12661d06d6bSBaptiste Daroussin static	void	  print_count(int *);
12761d06d6bSBaptiste Daroussin static	void	  print_node(DECL_ARGS);
12861d06d6bSBaptiste Daroussin 
1297295610fSBaptiste Daroussin static const void_fp roff_man_acts[ROFF_MAX] = {
13061d06d6bSBaptiste Daroussin 	pre_br,		/* br */
13161d06d6bSBaptiste Daroussin 	pre_onearg,	/* ce */
1327295610fSBaptiste Daroussin 	pre_noarg,	/* fi */
13361d06d6bSBaptiste Daroussin 	pre_ft,		/* ft */
13461d06d6bSBaptiste Daroussin 	pre_onearg,	/* ll */
13561d06d6bSBaptiste Daroussin 	pre_onearg,	/* mc */
1367295610fSBaptiste Daroussin 	pre_noarg,	/* nf */
13761d06d6bSBaptiste Daroussin 	pre_onearg,	/* po */
13861d06d6bSBaptiste Daroussin 	pre_onearg,	/* rj */
13961d06d6bSBaptiste Daroussin 	pre_sp,		/* sp */
14061d06d6bSBaptiste Daroussin 	pre_ta,		/* ta */
14161d06d6bSBaptiste Daroussin 	pre_onearg,	/* ti */
14261d06d6bSBaptiste Daroussin };
14361d06d6bSBaptiste Daroussin 
1447295610fSBaptiste Daroussin static const struct mdoc_man_act mdoc_man_acts[MDOC_MAX - MDOC_Dd] = {
14561d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Dd */
14661d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Dt */
14761d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Os */
14861d06d6bSBaptiste Daroussin 	{ NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */
14961d06d6bSBaptiste Daroussin 	{ NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */
15061d06d6bSBaptiste Daroussin 	{ NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
15161d06d6bSBaptiste Daroussin 	{ cond_body, pre_dl, post_dl, NULL, NULL }, /* D1 */
15261d06d6bSBaptiste Daroussin 	{ cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
15361d06d6bSBaptiste Daroussin 	{ cond_body, pre_bd, post_bd, NULL, NULL }, /* Bd */
15461d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ed */
15561d06d6bSBaptiste Daroussin 	{ cond_body, pre_bl, post_bl, NULL, NULL }, /* Bl */
15661d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* El */
15761d06d6bSBaptiste Daroussin 	{ NULL, pre_it, post_it, NULL, NULL }, /* It */
15861d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Ad */
15961d06d6bSBaptiste Daroussin 	{ NULL, pre_an, NULL, NULL, NULL }, /* An */
16061d06d6bSBaptiste Daroussin 	{ NULL, pre_ap, NULL, NULL, NULL }, /* Ap */
16161d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Ar */
16261d06d6bSBaptiste Daroussin 	{ NULL, pre_sy, post_font, NULL, NULL }, /* Cd */
16361d06d6bSBaptiste Daroussin 	{ NULL, pre_sy, post_font, NULL, NULL }, /* Cm */
16461d06d6bSBaptiste Daroussin 	{ NULL, pre_li, post_font, NULL, NULL }, /* Dv */
16561d06d6bSBaptiste Daroussin 	{ NULL, pre_li, post_font, NULL, NULL }, /* Er */
16661d06d6bSBaptiste Daroussin 	{ NULL, pre_li, post_font, NULL, NULL }, /* Ev */
16761d06d6bSBaptiste Daroussin 	{ NULL, pre_ex, NULL, NULL, NULL }, /* Ex */
16861d06d6bSBaptiste Daroussin 	{ NULL, pre_fa, post_fa, NULL, NULL }, /* Fa */
16961d06d6bSBaptiste Daroussin 	{ NULL, pre_fd, post_fd, NULL, NULL }, /* Fd */
17061d06d6bSBaptiste Daroussin 	{ NULL, pre_fl, post_fl, NULL, NULL }, /* Fl */
17161d06d6bSBaptiste Daroussin 	{ NULL, pre_fn, post_fn, NULL, NULL }, /* Fn */
17261d06d6bSBaptiste Daroussin 	{ NULL, pre_Ft, post_font, NULL, NULL }, /* Ft */
17361d06d6bSBaptiste Daroussin 	{ NULL, pre_sy, post_font, NULL, NULL }, /* Ic */
17461d06d6bSBaptiste Daroussin 	{ NULL, pre_in, post_in, NULL, NULL }, /* In */
17561d06d6bSBaptiste Daroussin 	{ NULL, pre_li, post_font, NULL, NULL }, /* Li */
17661d06d6bSBaptiste Daroussin 	{ cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
17761d06d6bSBaptiste Daroussin 	{ NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
17861d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
1797295610fSBaptiste Daroussin 	{ NULL, pre_abort, NULL, NULL, NULL }, /* Ot */
18061d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Pa */
18161d06d6bSBaptiste Daroussin 	{ NULL, pre_ex, NULL, NULL, NULL }, /* Rv */
18261d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* St */
18361d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Va */
18461d06d6bSBaptiste Daroussin 	{ NULL, pre_vt, post_vt, NULL, NULL }, /* Vt */
18561d06d6bSBaptiste Daroussin 	{ NULL, pre_xr, NULL, NULL, NULL }, /* Xr */
18661d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %A */
18761d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_percent, NULL, NULL }, /* %B */
18861d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %D */
18961d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_percent, NULL, NULL }, /* %I */
19061d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_percent, NULL, NULL }, /* %J */
19161d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %N */
19261d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %O */
19361d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %P */
19461d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %R */
19561d06d6bSBaptiste Daroussin 	{ NULL, pre__t, post__t, NULL, NULL }, /* %T */
19661d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %V */
19761d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ac */
19861d06d6bSBaptiste Daroussin 	{ cond_body, pre_aq, post_aq, NULL, NULL }, /* Ao */
19961d06d6bSBaptiste Daroussin 	{ cond_body, pre_aq, post_aq, NULL, NULL }, /* Aq */
20061d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* At */
20161d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Bc */
20261d06d6bSBaptiste Daroussin 	{ NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */
20361d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
20461d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
20561d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Bsx */
20661d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Bx */
20761d06d6bSBaptiste Daroussin 	{ NULL, pre_skip, NULL, NULL, NULL }, /* Db */
20861d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Dc */
20961d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Do */
21061d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Dq */
21161d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ec */
21261d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ef */
21361d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Em */
21461d06d6bSBaptiste Daroussin 	{ cond_body, pre_eo, post_eo, NULL, NULL }, /* Eo */
21561d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Fx */
21661d06d6bSBaptiste Daroussin 	{ NULL, pre_sy, post_font, NULL, NULL }, /* Ms */
21761d06d6bSBaptiste Daroussin 	{ NULL, pre_no, NULL, NULL, NULL }, /* No */
21861d06d6bSBaptiste Daroussin 	{ NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
21961d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Nx */
22061d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Ox */
22161d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Pc */
22261d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_pf, NULL, NULL }, /* Pf */
22361d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
22461d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */
22561d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Qc */
22661d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Ql */
22761d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */
22861d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */
22961d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Re */
23061d06d6bSBaptiste Daroussin 	{ cond_body, pre_rs, NULL, NULL, NULL }, /* Rs */
23161d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Sc */
23261d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* So */
23361d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Sq */
23461d06d6bSBaptiste Daroussin 	{ NULL, pre_sm, NULL, NULL, NULL }, /* Sm */
23561d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Sx */
23661d06d6bSBaptiste Daroussin 	{ NULL, pre_sy, post_font, NULL, NULL }, /* Sy */
23761d06d6bSBaptiste Daroussin 	{ NULL, pre_li, post_font, NULL, NULL }, /* Tn */
23861d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ux */
23961d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Xc */
24061d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Xo */
24161d06d6bSBaptiste Daroussin 	{ NULL, pre_fo, post_fo, NULL, NULL }, /* Fo */
24261d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Fc */
24361d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */
24461d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Oc */
24561d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Bk */
24661d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ek */
24761d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Bt */
24861d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Hf */
24961d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Fr */
25061d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ud */
25161d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_lb, NULL, NULL }, /* Lb */
2527295610fSBaptiste Daroussin 	{ NULL, pre_abort, NULL, NULL, NULL }, /* Lp */
25361d06d6bSBaptiste Daroussin 	{ NULL, pre_lk, NULL, NULL, NULL }, /* Lk */
25461d06d6bSBaptiste Daroussin 	{ NULL, pre_em, post_font, NULL, NULL }, /* Mt */
25561d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */
25661d06d6bSBaptiste Daroussin 	{ cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */
25761d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Brc */
25861d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %C */
25961d06d6bSBaptiste Daroussin 	{ NULL, pre_skip, NULL, NULL, NULL }, /* Es */
26061d06d6bSBaptiste Daroussin 	{ cond_body, pre_en, post_en, NULL, NULL }, /* En */
26161d06d6bSBaptiste Daroussin 	{ NULL, pre_bk, post_bk, NULL, NULL }, /* Dx */
26261d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %Q */
26361d06d6bSBaptiste Daroussin 	{ NULL, NULL, post_percent, NULL, NULL }, /* %U */
26461d06d6bSBaptiste Daroussin 	{ NULL, NULL, NULL, NULL, NULL }, /* Ta */
2656d38604fSBaptiste Daroussin 	{ NULL, pre_skip, NULL, NULL, NULL }, /* Tg */
26661d06d6bSBaptiste Daroussin };
2677295610fSBaptiste Daroussin static const struct mdoc_man_act *mdoc_man_act(enum roff_tok);
26861d06d6bSBaptiste Daroussin 
26961d06d6bSBaptiste Daroussin static	int		outflags;
27061d06d6bSBaptiste Daroussin #define	MMAN_spc	(1 << 0)  /* blank character before next word */
27161d06d6bSBaptiste Daroussin #define	MMAN_spc_force	(1 << 1)  /* even before trailing punctuation */
27261d06d6bSBaptiste Daroussin #define	MMAN_nl		(1 << 2)  /* break man(7) code line */
27361d06d6bSBaptiste Daroussin #define	MMAN_br		(1 << 3)  /* break output line */
27461d06d6bSBaptiste Daroussin #define	MMAN_sp		(1 << 4)  /* insert a blank output line */
27561d06d6bSBaptiste Daroussin #define	MMAN_PP		(1 << 5)  /* reset indentation etc. */
27661d06d6bSBaptiste Daroussin #define	MMAN_Sm		(1 << 6)  /* horizontal spacing mode */
27761d06d6bSBaptiste Daroussin #define	MMAN_Bk		(1 << 7)  /* word keep mode */
27861d06d6bSBaptiste Daroussin #define	MMAN_Bk_susp	(1 << 8)  /* suspend this (after a macro) */
27961d06d6bSBaptiste Daroussin #define	MMAN_An_split	(1 << 9)  /* author mode is "split" */
28061d06d6bSBaptiste Daroussin #define	MMAN_An_nosplit	(1 << 10) /* author mode is "nosplit" */
28161d06d6bSBaptiste Daroussin #define	MMAN_PD		(1 << 11) /* inter-paragraph spacing disabled */
28261d06d6bSBaptiste Daroussin #define	MMAN_nbrword	(1 << 12) /* do not break the next word */
28361d06d6bSBaptiste Daroussin 
28461d06d6bSBaptiste Daroussin #define	BL_STACK_MAX	32
28561d06d6bSBaptiste Daroussin 
28661d06d6bSBaptiste Daroussin static	int		Bl_stack[BL_STACK_MAX];  /* offsets [chars] */
28761d06d6bSBaptiste Daroussin static	int		Bl_stack_post[BL_STACK_MAX];  /* add final .RE */
28861d06d6bSBaptiste Daroussin static	int		Bl_stack_len;  /* number of nested Bl blocks */
28961d06d6bSBaptiste Daroussin static	int		TPremain;  /* characters before tag is full */
29061d06d6bSBaptiste Daroussin 
29161d06d6bSBaptiste Daroussin static	struct {
29261d06d6bSBaptiste Daroussin 	char	*head;
29361d06d6bSBaptiste Daroussin 	char	*tail;
29461d06d6bSBaptiste Daroussin 	size_t	 size;
29561d06d6bSBaptiste Daroussin }	fontqueue;
29661d06d6bSBaptiste Daroussin 
29761d06d6bSBaptiste Daroussin 
2987295610fSBaptiste Daroussin static const struct mdoc_man_act *
mdoc_man_act(enum roff_tok tok)2997295610fSBaptiste Daroussin mdoc_man_act(enum roff_tok tok)
3007295610fSBaptiste Daroussin {
3017295610fSBaptiste Daroussin 	assert(tok >= MDOC_Dd && tok <= MDOC_MAX);
3027295610fSBaptiste Daroussin 	return mdoc_man_acts + (tok - MDOC_Dd);
3037295610fSBaptiste Daroussin }
3047295610fSBaptiste Daroussin 
30561d06d6bSBaptiste Daroussin static int
man_strlen(const char * cp)30661d06d6bSBaptiste Daroussin man_strlen(const char *cp)
30761d06d6bSBaptiste Daroussin {
30861d06d6bSBaptiste Daroussin 	size_t	 rsz;
30961d06d6bSBaptiste Daroussin 	int	 skip, sz;
31061d06d6bSBaptiste Daroussin 
31161d06d6bSBaptiste Daroussin 	sz = 0;
31261d06d6bSBaptiste Daroussin 	skip = 0;
31361d06d6bSBaptiste Daroussin 	for (;;) {
31461d06d6bSBaptiste Daroussin 		rsz = strcspn(cp, "\\");
31561d06d6bSBaptiste Daroussin 		if (rsz) {
31661d06d6bSBaptiste Daroussin 			cp += rsz;
31761d06d6bSBaptiste Daroussin 			if (skip) {
31861d06d6bSBaptiste Daroussin 				skip = 0;
31961d06d6bSBaptiste Daroussin 				rsz--;
32061d06d6bSBaptiste Daroussin 			}
32161d06d6bSBaptiste Daroussin 			sz += rsz;
32261d06d6bSBaptiste Daroussin 		}
32361d06d6bSBaptiste Daroussin 		if ('\0' == *cp)
32461d06d6bSBaptiste Daroussin 			break;
32561d06d6bSBaptiste Daroussin 		cp++;
32661d06d6bSBaptiste Daroussin 		switch (mandoc_escape(&cp, NULL, NULL)) {
32761d06d6bSBaptiste Daroussin 		case ESCAPE_ERROR:
32861d06d6bSBaptiste Daroussin 			return sz;
32961d06d6bSBaptiste Daroussin 		case ESCAPE_UNICODE:
33061d06d6bSBaptiste Daroussin 		case ESCAPE_NUMBERED:
33161d06d6bSBaptiste Daroussin 		case ESCAPE_SPECIAL:
3327295610fSBaptiste Daroussin 		case ESCAPE_UNDEF:
33361d06d6bSBaptiste Daroussin 		case ESCAPE_OVERSTRIKE:
33461d06d6bSBaptiste Daroussin 			if (skip)
33561d06d6bSBaptiste Daroussin 				skip = 0;
33661d06d6bSBaptiste Daroussin 			else
33761d06d6bSBaptiste Daroussin 				sz++;
33861d06d6bSBaptiste Daroussin 			break;
33961d06d6bSBaptiste Daroussin 		case ESCAPE_SKIPCHAR:
34061d06d6bSBaptiste Daroussin 			skip = 1;
34161d06d6bSBaptiste Daroussin 			break;
34261d06d6bSBaptiste Daroussin 		default:
34361d06d6bSBaptiste Daroussin 			break;
34461d06d6bSBaptiste Daroussin 		}
34561d06d6bSBaptiste Daroussin 	}
34661d06d6bSBaptiste Daroussin 	return sz;
34761d06d6bSBaptiste Daroussin }
34861d06d6bSBaptiste Daroussin 
34961d06d6bSBaptiste Daroussin static void
font_push(char newfont)35061d06d6bSBaptiste Daroussin font_push(char newfont)
35161d06d6bSBaptiste Daroussin {
35261d06d6bSBaptiste Daroussin 
35361d06d6bSBaptiste Daroussin 	if (fontqueue.head + fontqueue.size <= ++fontqueue.tail) {
35461d06d6bSBaptiste Daroussin 		fontqueue.size += 8;
35561d06d6bSBaptiste Daroussin 		fontqueue.head = mandoc_realloc(fontqueue.head,
35661d06d6bSBaptiste Daroussin 		    fontqueue.size);
35761d06d6bSBaptiste Daroussin 	}
35861d06d6bSBaptiste Daroussin 	*fontqueue.tail = newfont;
35961d06d6bSBaptiste Daroussin 	print_word("");
36061d06d6bSBaptiste Daroussin 	printf("\\f");
36161d06d6bSBaptiste Daroussin 	putchar(newfont);
36261d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
36361d06d6bSBaptiste Daroussin }
36461d06d6bSBaptiste Daroussin 
36561d06d6bSBaptiste Daroussin static void
font_pop(void)36661d06d6bSBaptiste Daroussin font_pop(void)
36761d06d6bSBaptiste Daroussin {
36861d06d6bSBaptiste Daroussin 
36961d06d6bSBaptiste Daroussin 	if (fontqueue.tail > fontqueue.head)
37061d06d6bSBaptiste Daroussin 		fontqueue.tail--;
37161d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
37261d06d6bSBaptiste Daroussin 	print_word("");
37361d06d6bSBaptiste Daroussin 	printf("\\f");
37461d06d6bSBaptiste Daroussin 	putchar(*fontqueue.tail);
37561d06d6bSBaptiste Daroussin }
37661d06d6bSBaptiste Daroussin 
37761d06d6bSBaptiste Daroussin static void
print_word(const char * s)37861d06d6bSBaptiste Daroussin print_word(const char *s)
37961d06d6bSBaptiste Daroussin {
38061d06d6bSBaptiste Daroussin 
38161d06d6bSBaptiste Daroussin 	if ((MMAN_PP | MMAN_sp | MMAN_br | MMAN_nl) & outflags) {
38261d06d6bSBaptiste Daroussin 		/*
38361d06d6bSBaptiste Daroussin 		 * If we need a newline, print it now and start afresh.
38461d06d6bSBaptiste Daroussin 		 */
38561d06d6bSBaptiste Daroussin 		if (MMAN_PP & outflags) {
38661d06d6bSBaptiste Daroussin 			if (MMAN_sp & outflags) {
38761d06d6bSBaptiste Daroussin 				if (MMAN_PD & outflags) {
38861d06d6bSBaptiste Daroussin 					printf("\n.PD");
38961d06d6bSBaptiste Daroussin 					outflags &= ~MMAN_PD;
39061d06d6bSBaptiste Daroussin 				}
39161d06d6bSBaptiste Daroussin 			} else if ( ! (MMAN_PD & outflags)) {
39261d06d6bSBaptiste Daroussin 				printf("\n.PD 0");
39361d06d6bSBaptiste Daroussin 				outflags |= MMAN_PD;
39461d06d6bSBaptiste Daroussin 			}
39561d06d6bSBaptiste Daroussin 			printf("\n.PP\n");
39661d06d6bSBaptiste Daroussin 		} else if (MMAN_sp & outflags)
39761d06d6bSBaptiste Daroussin 			printf("\n.sp\n");
39861d06d6bSBaptiste Daroussin 		else if (MMAN_br & outflags)
39961d06d6bSBaptiste Daroussin 			printf("\n.br\n");
40061d06d6bSBaptiste Daroussin 		else if (MMAN_nl & outflags)
40161d06d6bSBaptiste Daroussin 			putchar('\n');
40261d06d6bSBaptiste Daroussin 		outflags &= ~(MMAN_PP|MMAN_sp|MMAN_br|MMAN_nl|MMAN_spc);
40361d06d6bSBaptiste Daroussin 		if (1 == TPremain)
40461d06d6bSBaptiste Daroussin 			printf(".br\n");
40561d06d6bSBaptiste Daroussin 		TPremain = 0;
40661d06d6bSBaptiste Daroussin 	} else if (MMAN_spc & outflags) {
40761d06d6bSBaptiste Daroussin 		/*
40861d06d6bSBaptiste Daroussin 		 * If we need a space, only print it if
40961d06d6bSBaptiste Daroussin 		 * (1) it is forced by `No' or
41061d06d6bSBaptiste Daroussin 		 * (2) what follows is not terminating punctuation or
41161d06d6bSBaptiste Daroussin 		 * (3) what follows is longer than one character.
41261d06d6bSBaptiste Daroussin 		 */
41361d06d6bSBaptiste Daroussin 		if (MMAN_spc_force & outflags || '\0' == s[0] ||
41461d06d6bSBaptiste Daroussin 		    NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) {
41561d06d6bSBaptiste Daroussin 			if (MMAN_Bk & outflags &&
41661d06d6bSBaptiste Daroussin 			    ! (MMAN_Bk_susp & outflags))
41761d06d6bSBaptiste Daroussin 				putchar('\\');
41861d06d6bSBaptiste Daroussin 			putchar(' ');
41961d06d6bSBaptiste Daroussin 			if (TPremain)
42061d06d6bSBaptiste Daroussin 				TPremain--;
42161d06d6bSBaptiste Daroussin 		}
42261d06d6bSBaptiste Daroussin 	}
42361d06d6bSBaptiste Daroussin 
42461d06d6bSBaptiste Daroussin 	/*
42561d06d6bSBaptiste Daroussin 	 * Reassign needing space if we're not following opening
42661d06d6bSBaptiste Daroussin 	 * punctuation.
42761d06d6bSBaptiste Daroussin 	 */
42861d06d6bSBaptiste Daroussin 	if (MMAN_Sm & outflags && ('\0' == s[0] ||
42961d06d6bSBaptiste Daroussin 	    (('(' != s[0] && '[' != s[0]) || '\0' != s[1])))
43061d06d6bSBaptiste Daroussin 		outflags |= MMAN_spc;
43161d06d6bSBaptiste Daroussin 	else
43261d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
43361d06d6bSBaptiste Daroussin 	outflags &= ~(MMAN_spc_force | MMAN_Bk_susp);
43461d06d6bSBaptiste Daroussin 
43561d06d6bSBaptiste Daroussin 	for ( ; *s; s++) {
43661d06d6bSBaptiste Daroussin 		switch (*s) {
43761d06d6bSBaptiste Daroussin 		case ASCII_NBRSP:
43861d06d6bSBaptiste Daroussin 			printf("\\ ");
43961d06d6bSBaptiste Daroussin 			break;
44061d06d6bSBaptiste Daroussin 		case ASCII_HYPH:
44161d06d6bSBaptiste Daroussin 			putchar('-');
44261d06d6bSBaptiste Daroussin 			break;
44361d06d6bSBaptiste Daroussin 		case ASCII_BREAK:
44461d06d6bSBaptiste Daroussin 			printf("\\:");
44561d06d6bSBaptiste Daroussin 			break;
44661d06d6bSBaptiste Daroussin 		case ' ':
44761d06d6bSBaptiste Daroussin 			if (MMAN_nbrword & outflags) {
44861d06d6bSBaptiste Daroussin 				printf("\\ ");
44961d06d6bSBaptiste Daroussin 				break;
45061d06d6bSBaptiste Daroussin 			}
45161d06d6bSBaptiste Daroussin 			/* FALLTHROUGH */
45261d06d6bSBaptiste Daroussin 		default:
45361d06d6bSBaptiste Daroussin 			putchar((unsigned char)*s);
45461d06d6bSBaptiste Daroussin 			break;
45561d06d6bSBaptiste Daroussin 		}
45661d06d6bSBaptiste Daroussin 		if (TPremain)
45761d06d6bSBaptiste Daroussin 			TPremain--;
45861d06d6bSBaptiste Daroussin 	}
45961d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_nbrword;
46061d06d6bSBaptiste Daroussin }
46161d06d6bSBaptiste Daroussin 
46261d06d6bSBaptiste Daroussin static void
print_line(const char * s,int newflags)46361d06d6bSBaptiste Daroussin print_line(const char *s, int newflags)
46461d06d6bSBaptiste Daroussin {
46561d06d6bSBaptiste Daroussin 
46661d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
46761d06d6bSBaptiste Daroussin 	print_word(s);
46861d06d6bSBaptiste Daroussin 	outflags |= newflags;
46961d06d6bSBaptiste Daroussin }
47061d06d6bSBaptiste Daroussin 
47161d06d6bSBaptiste Daroussin static void
print_block(const char * s,int newflags)47261d06d6bSBaptiste Daroussin print_block(const char *s, int newflags)
47361d06d6bSBaptiste Daroussin {
47461d06d6bSBaptiste Daroussin 
47561d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_PP;
47661d06d6bSBaptiste Daroussin 	if (MMAN_sp & outflags) {
47761d06d6bSBaptiste Daroussin 		outflags &= ~(MMAN_sp | MMAN_br);
47861d06d6bSBaptiste Daroussin 		if (MMAN_PD & outflags) {
47961d06d6bSBaptiste Daroussin 			print_line(".PD", 0);
48061d06d6bSBaptiste Daroussin 			outflags &= ~MMAN_PD;
48161d06d6bSBaptiste Daroussin 		}
48261d06d6bSBaptiste Daroussin 	} else if (! (MMAN_PD & outflags))
48361d06d6bSBaptiste Daroussin 		print_line(".PD 0", MMAN_PD);
48461d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
48561d06d6bSBaptiste Daroussin 	print_word(s);
48661d06d6bSBaptiste Daroussin 	outflags |= MMAN_Bk_susp | newflags;
48761d06d6bSBaptiste Daroussin }
48861d06d6bSBaptiste Daroussin 
48961d06d6bSBaptiste Daroussin static void
print_offs(const char * v,int keywords)49061d06d6bSBaptiste Daroussin print_offs(const char *v, int keywords)
49161d06d6bSBaptiste Daroussin {
49261d06d6bSBaptiste Daroussin 	char		  buf[24];
49361d06d6bSBaptiste Daroussin 	struct roffsu	  su;
49461d06d6bSBaptiste Daroussin 	const char	 *end;
49561d06d6bSBaptiste Daroussin 	int		  sz;
49661d06d6bSBaptiste Daroussin 
49761d06d6bSBaptiste Daroussin 	print_line(".RS", MMAN_Bk_susp);
49861d06d6bSBaptiste Daroussin 
49961d06d6bSBaptiste Daroussin 	/* Convert v into a number (of characters). */
50061d06d6bSBaptiste Daroussin 	if (NULL == v || '\0' == *v || (keywords && !strcmp(v, "left")))
50161d06d6bSBaptiste Daroussin 		sz = 0;
50261d06d6bSBaptiste Daroussin 	else if (keywords && !strcmp(v, "indent"))
50361d06d6bSBaptiste Daroussin 		sz = 6;
50461d06d6bSBaptiste Daroussin 	else if (keywords && !strcmp(v, "indent-two"))
50561d06d6bSBaptiste Daroussin 		sz = 12;
50661d06d6bSBaptiste Daroussin 	else {
50761d06d6bSBaptiste Daroussin 		end = a2roffsu(v, &su, SCALE_EN);
50861d06d6bSBaptiste Daroussin 		if (end == NULL || *end != '\0')
50961d06d6bSBaptiste Daroussin 			sz = man_strlen(v);
51061d06d6bSBaptiste Daroussin 		else if (SCALE_EN == su.unit)
51161d06d6bSBaptiste Daroussin 			sz = su.scale;
51261d06d6bSBaptiste Daroussin 		else {
51361d06d6bSBaptiste Daroussin 			/*
51461d06d6bSBaptiste Daroussin 			 * XXX
51561d06d6bSBaptiste Daroussin 			 * If we are inside an enclosing list,
51661d06d6bSBaptiste Daroussin 			 * there is no easy way to add the two
51761d06d6bSBaptiste Daroussin 			 * indentations because they are provided
51861d06d6bSBaptiste Daroussin 			 * in terms of different units.
51961d06d6bSBaptiste Daroussin 			 */
52061d06d6bSBaptiste Daroussin 			print_word(v);
52161d06d6bSBaptiste Daroussin 			outflags |= MMAN_nl;
52261d06d6bSBaptiste Daroussin 			return;
52361d06d6bSBaptiste Daroussin 		}
52461d06d6bSBaptiste Daroussin 	}
52561d06d6bSBaptiste Daroussin 
52661d06d6bSBaptiste Daroussin 	/*
52761d06d6bSBaptiste Daroussin 	 * We are inside an enclosing list.
52861d06d6bSBaptiste Daroussin 	 * Add the two indentations.
52961d06d6bSBaptiste Daroussin 	 */
53061d06d6bSBaptiste Daroussin 	if (Bl_stack_len)
53161d06d6bSBaptiste Daroussin 		sz += Bl_stack[Bl_stack_len - 1];
53261d06d6bSBaptiste Daroussin 
53361d06d6bSBaptiste Daroussin 	(void)snprintf(buf, sizeof(buf), "%dn", sz);
53461d06d6bSBaptiste Daroussin 	print_word(buf);
53561d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
53661d06d6bSBaptiste Daroussin }
53761d06d6bSBaptiste Daroussin 
53861d06d6bSBaptiste Daroussin /*
53961d06d6bSBaptiste Daroussin  * Set up the indentation for a list item; used from pre_it().
54061d06d6bSBaptiste Daroussin  */
54161d06d6bSBaptiste Daroussin static void
print_width(const struct mdoc_bl * bl,const struct roff_node * child)54261d06d6bSBaptiste Daroussin print_width(const struct mdoc_bl *bl, const struct roff_node *child)
54361d06d6bSBaptiste Daroussin {
54461d06d6bSBaptiste Daroussin 	char		  buf[24];
54561d06d6bSBaptiste Daroussin 	struct roffsu	  su;
54661d06d6bSBaptiste Daroussin 	const char	 *end;
54761d06d6bSBaptiste Daroussin 	int		  numeric, remain, sz, chsz;
54861d06d6bSBaptiste Daroussin 
54961d06d6bSBaptiste Daroussin 	numeric = 1;
55061d06d6bSBaptiste Daroussin 	remain = 0;
55161d06d6bSBaptiste Daroussin 
55261d06d6bSBaptiste Daroussin 	/* Convert the width into a number (of characters). */
55361d06d6bSBaptiste Daroussin 	if (bl->width == NULL)
55461d06d6bSBaptiste Daroussin 		sz = (bl->type == LIST_hang) ? 6 : 0;
55561d06d6bSBaptiste Daroussin 	else {
55661d06d6bSBaptiste Daroussin 		end = a2roffsu(bl->width, &su, SCALE_MAX);
55761d06d6bSBaptiste Daroussin 		if (end == NULL || *end != '\0')
55861d06d6bSBaptiste Daroussin 			sz = man_strlen(bl->width);
55961d06d6bSBaptiste Daroussin 		else if (SCALE_EN == su.unit)
56061d06d6bSBaptiste Daroussin 			sz = su.scale;
56161d06d6bSBaptiste Daroussin 		else {
56261d06d6bSBaptiste Daroussin 			sz = 0;
56361d06d6bSBaptiste Daroussin 			numeric = 0;
56461d06d6bSBaptiste Daroussin 		}
56561d06d6bSBaptiste Daroussin 	}
56661d06d6bSBaptiste Daroussin 
56761d06d6bSBaptiste Daroussin 	/* XXX Rough estimation, might have multiple parts. */
56861d06d6bSBaptiste Daroussin 	if (bl->type == LIST_enum)
56961d06d6bSBaptiste Daroussin 		chsz = (bl->count > 8) + 1;
57061d06d6bSBaptiste Daroussin 	else if (child != NULL && child->type == ROFFT_TEXT)
57161d06d6bSBaptiste Daroussin 		chsz = man_strlen(child->string);
57261d06d6bSBaptiste Daroussin 	else
57361d06d6bSBaptiste Daroussin 		chsz = 0;
57461d06d6bSBaptiste Daroussin 
57561d06d6bSBaptiste Daroussin 	/* Maybe we are inside an enclosing list? */
57661d06d6bSBaptiste Daroussin 	mid_it();
57761d06d6bSBaptiste Daroussin 
57861d06d6bSBaptiste Daroussin 	/*
57961d06d6bSBaptiste Daroussin 	 * Save our own indentation,
58061d06d6bSBaptiste Daroussin 	 * such that child lists can use it.
58161d06d6bSBaptiste Daroussin 	 */
58261d06d6bSBaptiste Daroussin 	Bl_stack[Bl_stack_len++] = sz + 2;
58361d06d6bSBaptiste Daroussin 
58461d06d6bSBaptiste Daroussin 	/* Set up the current list. */
58561d06d6bSBaptiste Daroussin 	if (chsz > sz && bl->type != LIST_tag)
5866d38604fSBaptiste Daroussin 		print_block(".HP", MMAN_spc);
58761d06d6bSBaptiste Daroussin 	else {
5886d38604fSBaptiste Daroussin 		print_block(".TP", MMAN_spc);
58961d06d6bSBaptiste Daroussin 		remain = sz + 2;
59061d06d6bSBaptiste Daroussin 	}
59161d06d6bSBaptiste Daroussin 	if (numeric) {
59261d06d6bSBaptiste Daroussin 		(void)snprintf(buf, sizeof(buf), "%dn", sz + 2);
59361d06d6bSBaptiste Daroussin 		print_word(buf);
59461d06d6bSBaptiste Daroussin 	} else
59561d06d6bSBaptiste Daroussin 		print_word(bl->width);
59661d06d6bSBaptiste Daroussin 	TPremain = remain;
59761d06d6bSBaptiste Daroussin }
59861d06d6bSBaptiste Daroussin 
59961d06d6bSBaptiste Daroussin static void
print_count(int * count)60061d06d6bSBaptiste Daroussin print_count(int *count)
60161d06d6bSBaptiste Daroussin {
60261d06d6bSBaptiste Daroussin 	char		  buf[24];
60361d06d6bSBaptiste Daroussin 
60461d06d6bSBaptiste Daroussin 	(void)snprintf(buf, sizeof(buf), "%d.\\&", ++*count);
60561d06d6bSBaptiste Daroussin 	print_word(buf);
60661d06d6bSBaptiste Daroussin }
60761d06d6bSBaptiste Daroussin 
60861d06d6bSBaptiste Daroussin void
man_mdoc(void * arg,const struct roff_meta * mdoc)6097295610fSBaptiste Daroussin man_mdoc(void *arg, const struct roff_meta *mdoc)
61061d06d6bSBaptiste Daroussin {
61161d06d6bSBaptiste Daroussin 	struct roff_node *n;
61261d06d6bSBaptiste Daroussin 
61361d06d6bSBaptiste Daroussin 	printf(".\\\" Automatically generated from an mdoc input file."
61461d06d6bSBaptiste Daroussin 	    "  Do not edit.\n");
61561d06d6bSBaptiste Daroussin 	for (n = mdoc->first->child; n != NULL; n = n->next) {
61661d06d6bSBaptiste Daroussin 		if (n->type != ROFFT_COMMENT)
61761d06d6bSBaptiste Daroussin 			break;
61861d06d6bSBaptiste Daroussin 		printf(".\\\"%s\n", n->string);
61961d06d6bSBaptiste Daroussin 	}
62061d06d6bSBaptiste Daroussin 
62161d06d6bSBaptiste Daroussin 	printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
6227295610fSBaptiste Daroussin 	    mdoc->title, (mdoc->msec == NULL ? "" : mdoc->msec),
6237295610fSBaptiste Daroussin 	    mdoc->date, mdoc->os, mdoc->vol);
62461d06d6bSBaptiste Daroussin 
62561d06d6bSBaptiste Daroussin 	/* Disable hyphenation and if nroff, disable justification. */
62661d06d6bSBaptiste Daroussin 	printf(".nh\n.if n .ad l");
62761d06d6bSBaptiste Daroussin 
62861d06d6bSBaptiste Daroussin 	outflags = MMAN_nl | MMAN_Sm;
62961d06d6bSBaptiste Daroussin 	if (0 == fontqueue.size) {
63061d06d6bSBaptiste Daroussin 		fontqueue.size = 8;
63161d06d6bSBaptiste Daroussin 		fontqueue.head = fontqueue.tail = mandoc_malloc(8);
63261d06d6bSBaptiste Daroussin 		*fontqueue.tail = 'R';
63361d06d6bSBaptiste Daroussin 	}
63461d06d6bSBaptiste Daroussin 	for (; n != NULL; n = n->next)
6357295610fSBaptiste Daroussin 		print_node(mdoc, n);
63661d06d6bSBaptiste Daroussin 	putchar('\n');
63761d06d6bSBaptiste Daroussin }
63861d06d6bSBaptiste Daroussin 
63961d06d6bSBaptiste Daroussin static void
print_node(DECL_ARGS)64061d06d6bSBaptiste Daroussin print_node(DECL_ARGS)
64161d06d6bSBaptiste Daroussin {
6427295610fSBaptiste Daroussin 	const struct mdoc_man_act	*act;
64361d06d6bSBaptiste Daroussin 	struct roff_node		*sub;
64461d06d6bSBaptiste Daroussin 	int				 cond, do_sub;
64561d06d6bSBaptiste Daroussin 
64661d06d6bSBaptiste Daroussin 	if (n->flags & NODE_NOPRT)
64761d06d6bSBaptiste Daroussin 		return;
64861d06d6bSBaptiste Daroussin 
64961d06d6bSBaptiste Daroussin 	/*
65061d06d6bSBaptiste Daroussin 	 * Break the line if we were parsed subsequent the current node.
65161d06d6bSBaptiste Daroussin 	 * This makes the page structure be more consistent.
65261d06d6bSBaptiste Daroussin 	 */
6536d38604fSBaptiste Daroussin 	if (outflags & MMAN_spc &&
6546d38604fSBaptiste Daroussin 	    n->flags & NODE_LINE &&
6556d38604fSBaptiste Daroussin 	    !roff_node_transparent(n))
65661d06d6bSBaptiste Daroussin 		outflags |= MMAN_nl;
65761d06d6bSBaptiste Daroussin 
65861d06d6bSBaptiste Daroussin 	act = NULL;
65961d06d6bSBaptiste Daroussin 	cond = 0;
66061d06d6bSBaptiste Daroussin 	do_sub = 1;
66161d06d6bSBaptiste Daroussin 	n->flags &= ~NODE_ENDED;
66261d06d6bSBaptiste Daroussin 
6636d38604fSBaptiste Daroussin 	switch (n->type) {
6646d38604fSBaptiste Daroussin 	case ROFFT_EQN:
6656d38604fSBaptiste Daroussin 	case ROFFT_TBL:
6666d38604fSBaptiste Daroussin 		mandoc_msg(n->type == ROFFT_EQN ? MANDOCERR_EQN_TMAN :
6676d38604fSBaptiste Daroussin 		    MANDOCERR_TBL_TMAN, n->line, n->pos, NULL);
6686d38604fSBaptiste Daroussin 		outflags |= MMAN_PP | MMAN_sp | MMAN_nl;
6696d38604fSBaptiste Daroussin 		print_word("The");
6706d38604fSBaptiste Daroussin 		print_line(".B \\-T man", MMAN_nl);
6716d38604fSBaptiste Daroussin 		print_word("output mode does not support");
6726d38604fSBaptiste Daroussin 		print_word(n->type == ROFFT_EQN ? "eqn(7)" : "tbl(7)");
6736d38604fSBaptiste Daroussin 		print_word("input.");
6746d38604fSBaptiste Daroussin 		outflags |= MMAN_PP | MMAN_sp | MMAN_nl;
6756d38604fSBaptiste Daroussin 		return;
6766d38604fSBaptiste Daroussin 	case ROFFT_TEXT:
67761d06d6bSBaptiste Daroussin 		/*
67861d06d6bSBaptiste Daroussin 		 * Make sure that we don't happen to start with a
67961d06d6bSBaptiste Daroussin 		 * control character at the start of a line.
68061d06d6bSBaptiste Daroussin 		 */
68161d06d6bSBaptiste Daroussin 		if (MMAN_nl & outflags &&
68261d06d6bSBaptiste Daroussin 		    ('.' == *n->string || '\'' == *n->string)) {
68361d06d6bSBaptiste Daroussin 			print_word("");
68461d06d6bSBaptiste Daroussin 			printf("\\&");
68561d06d6bSBaptiste Daroussin 			outflags &= ~MMAN_spc;
68661d06d6bSBaptiste Daroussin 		}
68761d06d6bSBaptiste Daroussin 		if (n->flags & NODE_DELIMC)
68861d06d6bSBaptiste Daroussin 			outflags &= ~(MMAN_spc | MMAN_spc_force);
68961d06d6bSBaptiste Daroussin 		else if (outflags & MMAN_Sm)
69061d06d6bSBaptiste Daroussin 			outflags |= MMAN_spc_force;
69161d06d6bSBaptiste Daroussin 		print_word(n->string);
69261d06d6bSBaptiste Daroussin 		if (n->flags & NODE_DELIMO)
69361d06d6bSBaptiste Daroussin 			outflags &= ~(MMAN_spc | MMAN_spc_force);
69461d06d6bSBaptiste Daroussin 		else if (outflags & MMAN_Sm)
69561d06d6bSBaptiste Daroussin 			outflags |= MMAN_spc;
6966d38604fSBaptiste Daroussin 		break;
6976d38604fSBaptiste Daroussin 	default:
6986d38604fSBaptiste Daroussin 		if (n->tok < ROFF_MAX) {
6997295610fSBaptiste Daroussin 			(*roff_man_acts[n->tok])(meta, n);
70061d06d6bSBaptiste Daroussin 			return;
7016d38604fSBaptiste Daroussin 		}
7027295610fSBaptiste Daroussin 		act = mdoc_man_act(n->tok);
70361d06d6bSBaptiste Daroussin 		cond = act->cond == NULL || (*act->cond)(meta, n);
70461d06d6bSBaptiste Daroussin 		if (cond && act->pre != NULL &&
70561d06d6bSBaptiste Daroussin 		    (n->end == ENDBODY_NOT || n->child != NULL))
70661d06d6bSBaptiste Daroussin 			do_sub = (*act->pre)(meta, n);
7076d38604fSBaptiste Daroussin 		break;
70861d06d6bSBaptiste Daroussin 	}
70961d06d6bSBaptiste Daroussin 
71061d06d6bSBaptiste Daroussin 	/*
71161d06d6bSBaptiste Daroussin 	 * Conditionally run all child nodes.
71261d06d6bSBaptiste Daroussin 	 * Note that this iterates over children instead of using
71361d06d6bSBaptiste Daroussin 	 * recursion.  This prevents unnecessary depth in the stack.
71461d06d6bSBaptiste Daroussin 	 */
71561d06d6bSBaptiste Daroussin 	if (do_sub)
71661d06d6bSBaptiste Daroussin 		for (sub = n->child; sub; sub = sub->next)
71761d06d6bSBaptiste Daroussin 			print_node(meta, sub);
71861d06d6bSBaptiste Daroussin 
71961d06d6bSBaptiste Daroussin 	/*
72061d06d6bSBaptiste Daroussin 	 * Lastly, conditionally run the post-node handler.
72161d06d6bSBaptiste Daroussin 	 */
72261d06d6bSBaptiste Daroussin 	if (NODE_ENDED & n->flags)
72361d06d6bSBaptiste Daroussin 		return;
72461d06d6bSBaptiste Daroussin 
72561d06d6bSBaptiste Daroussin 	if (cond && act->post)
72661d06d6bSBaptiste Daroussin 		(*act->post)(meta, n);
72761d06d6bSBaptiste Daroussin 
72861d06d6bSBaptiste Daroussin 	if (ENDBODY_NOT != n->end)
72961d06d6bSBaptiste Daroussin 		n->body->flags |= NODE_ENDED;
73061d06d6bSBaptiste Daroussin }
73161d06d6bSBaptiste Daroussin 
73261d06d6bSBaptiste Daroussin static int
cond_head(DECL_ARGS)73361d06d6bSBaptiste Daroussin cond_head(DECL_ARGS)
73461d06d6bSBaptiste Daroussin {
73561d06d6bSBaptiste Daroussin 
73661d06d6bSBaptiste Daroussin 	return n->type == ROFFT_HEAD;
73761d06d6bSBaptiste Daroussin }
73861d06d6bSBaptiste Daroussin 
73961d06d6bSBaptiste Daroussin static int
cond_body(DECL_ARGS)74061d06d6bSBaptiste Daroussin cond_body(DECL_ARGS)
74161d06d6bSBaptiste Daroussin {
74261d06d6bSBaptiste Daroussin 
74361d06d6bSBaptiste Daroussin 	return n->type == ROFFT_BODY;
74461d06d6bSBaptiste Daroussin }
74561d06d6bSBaptiste Daroussin 
74661d06d6bSBaptiste Daroussin static int
pre_abort(DECL_ARGS)7477295610fSBaptiste Daroussin pre_abort(DECL_ARGS)
7487295610fSBaptiste Daroussin {
7497295610fSBaptiste Daroussin 	abort();
7507295610fSBaptiste Daroussin }
7517295610fSBaptiste Daroussin 
7527295610fSBaptiste Daroussin static int
pre_enc(DECL_ARGS)75361d06d6bSBaptiste Daroussin pre_enc(DECL_ARGS)
75461d06d6bSBaptiste Daroussin {
75561d06d6bSBaptiste Daroussin 	const char	*prefix;
75661d06d6bSBaptiste Daroussin 
7577295610fSBaptiste Daroussin 	prefix = mdoc_man_act(n->tok)->prefix;
75861d06d6bSBaptiste Daroussin 	if (NULL == prefix)
75961d06d6bSBaptiste Daroussin 		return 1;
76061d06d6bSBaptiste Daroussin 	print_word(prefix);
76161d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
76261d06d6bSBaptiste Daroussin 	return 1;
76361d06d6bSBaptiste Daroussin }
76461d06d6bSBaptiste Daroussin 
76561d06d6bSBaptiste Daroussin static void
post_enc(DECL_ARGS)76661d06d6bSBaptiste Daroussin post_enc(DECL_ARGS)
76761d06d6bSBaptiste Daroussin {
76861d06d6bSBaptiste Daroussin 	const char *suffix;
76961d06d6bSBaptiste Daroussin 
7707295610fSBaptiste Daroussin 	suffix = mdoc_man_act(n->tok)->suffix;
77161d06d6bSBaptiste Daroussin 	if (NULL == suffix)
77261d06d6bSBaptiste Daroussin 		return;
77361d06d6bSBaptiste Daroussin 	outflags &= ~(MMAN_spc | MMAN_nl);
77461d06d6bSBaptiste Daroussin 	print_word(suffix);
77561d06d6bSBaptiste Daroussin }
77661d06d6bSBaptiste Daroussin 
77761d06d6bSBaptiste Daroussin static int
pre_ex(DECL_ARGS)77861d06d6bSBaptiste Daroussin pre_ex(DECL_ARGS)
77961d06d6bSBaptiste Daroussin {
78061d06d6bSBaptiste Daroussin 	outflags |= MMAN_br | MMAN_nl;
78161d06d6bSBaptiste Daroussin 	return 1;
78261d06d6bSBaptiste Daroussin }
78361d06d6bSBaptiste Daroussin 
78461d06d6bSBaptiste Daroussin static void
post_font(DECL_ARGS)78561d06d6bSBaptiste Daroussin post_font(DECL_ARGS)
78661d06d6bSBaptiste Daroussin {
78761d06d6bSBaptiste Daroussin 
78861d06d6bSBaptiste Daroussin 	font_pop();
78961d06d6bSBaptiste Daroussin }
79061d06d6bSBaptiste Daroussin 
79161d06d6bSBaptiste Daroussin static void
post_percent(DECL_ARGS)79261d06d6bSBaptiste Daroussin post_percent(DECL_ARGS)
79361d06d6bSBaptiste Daroussin {
7946d38604fSBaptiste Daroussin 	struct roff_node *np, *nn, *nnn;
79561d06d6bSBaptiste Daroussin 
7967295610fSBaptiste Daroussin 	if (mdoc_man_act(n->tok)->pre == pre_em)
79761d06d6bSBaptiste Daroussin 		font_pop();
7986d38604fSBaptiste Daroussin 
7996d38604fSBaptiste Daroussin 	if ((nn = roff_node_next(n)) != NULL) {
8006d38604fSBaptiste Daroussin 		np = roff_node_prev(n);
8016d38604fSBaptiste Daroussin 		nnn = nn == NULL ? NULL : roff_node_next(nn);
8026d38604fSBaptiste Daroussin 		if (nn->tok != n->tok ||
8036d38604fSBaptiste Daroussin 		    (np != NULL && np->tok == n->tok) ||
8046d38604fSBaptiste Daroussin 		    (nnn != NULL && nnn->tok == n->tok))
80561d06d6bSBaptiste Daroussin 			print_word(",");
8066d38604fSBaptiste Daroussin 		if (nn->tok == n->tok &&
8076d38604fSBaptiste Daroussin 		    (nnn == NULL || nnn->tok != n->tok))
80861d06d6bSBaptiste Daroussin 			print_word("and");
80961d06d6bSBaptiste Daroussin 	} else {
81061d06d6bSBaptiste Daroussin 		print_word(".");
81161d06d6bSBaptiste Daroussin 		outflags |= MMAN_nl;
81261d06d6bSBaptiste Daroussin 	}
81361d06d6bSBaptiste Daroussin }
81461d06d6bSBaptiste Daroussin 
81561d06d6bSBaptiste Daroussin static int
pre__t(DECL_ARGS)81661d06d6bSBaptiste Daroussin pre__t(DECL_ARGS)
81761d06d6bSBaptiste Daroussin {
81861d06d6bSBaptiste Daroussin 
81961d06d6bSBaptiste Daroussin 	if (n->parent->tok == MDOC_Rs && n->parent->norm->Rs.quote_T) {
82061d06d6bSBaptiste Daroussin 		print_word("\\(lq");
82161d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
82261d06d6bSBaptiste Daroussin 	} else
82361d06d6bSBaptiste Daroussin 		font_push('I');
82461d06d6bSBaptiste Daroussin 	return 1;
82561d06d6bSBaptiste Daroussin }
82661d06d6bSBaptiste Daroussin 
82761d06d6bSBaptiste Daroussin static void
post__t(DECL_ARGS)82861d06d6bSBaptiste Daroussin post__t(DECL_ARGS)
82961d06d6bSBaptiste Daroussin {
83061d06d6bSBaptiste Daroussin 
83161d06d6bSBaptiste Daroussin 	if (n->parent->tok  == MDOC_Rs && n->parent->norm->Rs.quote_T) {
83261d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
83361d06d6bSBaptiste Daroussin 		print_word("\\(rq");
83461d06d6bSBaptiste Daroussin 	} else
83561d06d6bSBaptiste Daroussin 		font_pop();
83661d06d6bSBaptiste Daroussin 	post_percent(meta, n);
83761d06d6bSBaptiste Daroussin }
83861d06d6bSBaptiste Daroussin 
83961d06d6bSBaptiste Daroussin /*
84061d06d6bSBaptiste Daroussin  * Print before a section header.
84161d06d6bSBaptiste Daroussin  */
84261d06d6bSBaptiste Daroussin static int
pre_sect(DECL_ARGS)84361d06d6bSBaptiste Daroussin pre_sect(DECL_ARGS)
84461d06d6bSBaptiste Daroussin {
84561d06d6bSBaptiste Daroussin 
84661d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_HEAD) {
84761d06d6bSBaptiste Daroussin 		outflags |= MMAN_sp;
8487295610fSBaptiste Daroussin 		print_block(mdoc_man_act(n->tok)->prefix, 0);
84961d06d6bSBaptiste Daroussin 		print_word("");
85061d06d6bSBaptiste Daroussin 		putchar('\"');
85161d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
85261d06d6bSBaptiste Daroussin 	}
85361d06d6bSBaptiste Daroussin 	return 1;
85461d06d6bSBaptiste Daroussin }
85561d06d6bSBaptiste Daroussin 
85661d06d6bSBaptiste Daroussin /*
85761d06d6bSBaptiste Daroussin  * Print subsequent a section header.
85861d06d6bSBaptiste Daroussin  */
85961d06d6bSBaptiste Daroussin static void
post_sect(DECL_ARGS)86061d06d6bSBaptiste Daroussin post_sect(DECL_ARGS)
86161d06d6bSBaptiste Daroussin {
86261d06d6bSBaptiste Daroussin 
86361d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_HEAD)
86461d06d6bSBaptiste Daroussin 		return;
86561d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
86661d06d6bSBaptiste Daroussin 	print_word("");
86761d06d6bSBaptiste Daroussin 	putchar('\"');
86861d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
86961d06d6bSBaptiste Daroussin 	if (MDOC_Sh == n->tok && SEC_AUTHORS == n->sec)
87061d06d6bSBaptiste Daroussin 		outflags &= ~(MMAN_An_split | MMAN_An_nosplit);
87161d06d6bSBaptiste Daroussin }
87261d06d6bSBaptiste Daroussin 
87361d06d6bSBaptiste Daroussin /* See mdoc_term.c, synopsis_pre() for comments. */
87461d06d6bSBaptiste Daroussin static void
pre_syn(struct roff_node * n)8756d38604fSBaptiste Daroussin pre_syn(struct roff_node *n)
87661d06d6bSBaptiste Daroussin {
8776d38604fSBaptiste Daroussin 	struct roff_node *np;
87861d06d6bSBaptiste Daroussin 
8796d38604fSBaptiste Daroussin 	if ((n->flags & NODE_SYNPRETTY) == 0 ||
8806d38604fSBaptiste Daroussin 	    (np = roff_node_prev(n)) == NULL)
88161d06d6bSBaptiste Daroussin 		return;
88261d06d6bSBaptiste Daroussin 
8836d38604fSBaptiste Daroussin 	if (np->tok == n->tok &&
88461d06d6bSBaptiste Daroussin 	    MDOC_Ft != n->tok &&
88561d06d6bSBaptiste Daroussin 	    MDOC_Fo != n->tok &&
88661d06d6bSBaptiste Daroussin 	    MDOC_Fn != n->tok) {
88761d06d6bSBaptiste Daroussin 		outflags |= MMAN_br;
88861d06d6bSBaptiste Daroussin 		return;
88961d06d6bSBaptiste Daroussin 	}
89061d06d6bSBaptiste Daroussin 
8916d38604fSBaptiste Daroussin 	switch (np->tok) {
89261d06d6bSBaptiste Daroussin 	case MDOC_Fd:
89361d06d6bSBaptiste Daroussin 	case MDOC_Fn:
89461d06d6bSBaptiste Daroussin 	case MDOC_Fo:
89561d06d6bSBaptiste Daroussin 	case MDOC_In:
89661d06d6bSBaptiste Daroussin 	case MDOC_Vt:
89761d06d6bSBaptiste Daroussin 		outflags |= MMAN_sp;
89861d06d6bSBaptiste Daroussin 		break;
89961d06d6bSBaptiste Daroussin 	case MDOC_Ft:
90061d06d6bSBaptiste Daroussin 		if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
90161d06d6bSBaptiste Daroussin 			outflags |= MMAN_sp;
90261d06d6bSBaptiste Daroussin 			break;
90361d06d6bSBaptiste Daroussin 		}
90461d06d6bSBaptiste Daroussin 		/* FALLTHROUGH */
90561d06d6bSBaptiste Daroussin 	default:
90661d06d6bSBaptiste Daroussin 		outflags |= MMAN_br;
90761d06d6bSBaptiste Daroussin 		break;
90861d06d6bSBaptiste Daroussin 	}
90961d06d6bSBaptiste Daroussin }
91061d06d6bSBaptiste Daroussin 
91161d06d6bSBaptiste Daroussin static int
pre_an(DECL_ARGS)91261d06d6bSBaptiste Daroussin pre_an(DECL_ARGS)
91361d06d6bSBaptiste Daroussin {
91461d06d6bSBaptiste Daroussin 
91561d06d6bSBaptiste Daroussin 	switch (n->norm->An.auth) {
91661d06d6bSBaptiste Daroussin 	case AUTH_split:
91761d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_An_nosplit;
91861d06d6bSBaptiste Daroussin 		outflags |= MMAN_An_split;
91961d06d6bSBaptiste Daroussin 		return 0;
92061d06d6bSBaptiste Daroussin 	case AUTH_nosplit:
92161d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_An_split;
92261d06d6bSBaptiste Daroussin 		outflags |= MMAN_An_nosplit;
92361d06d6bSBaptiste Daroussin 		return 0;
92461d06d6bSBaptiste Daroussin 	default:
92561d06d6bSBaptiste Daroussin 		if (MMAN_An_split & outflags)
92661d06d6bSBaptiste Daroussin 			outflags |= MMAN_br;
92761d06d6bSBaptiste Daroussin 		else if (SEC_AUTHORS == n->sec &&
92861d06d6bSBaptiste Daroussin 		    ! (MMAN_An_nosplit & outflags))
92961d06d6bSBaptiste Daroussin 			outflags |= MMAN_An_split;
93061d06d6bSBaptiste Daroussin 		return 1;
93161d06d6bSBaptiste Daroussin 	}
93261d06d6bSBaptiste Daroussin }
93361d06d6bSBaptiste Daroussin 
93461d06d6bSBaptiste Daroussin static int
pre_ap(DECL_ARGS)93561d06d6bSBaptiste Daroussin pre_ap(DECL_ARGS)
93661d06d6bSBaptiste Daroussin {
93761d06d6bSBaptiste Daroussin 
93861d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
93961d06d6bSBaptiste Daroussin 	print_word("'");
94061d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
94161d06d6bSBaptiste Daroussin 	return 0;
94261d06d6bSBaptiste Daroussin }
94361d06d6bSBaptiste Daroussin 
94461d06d6bSBaptiste Daroussin static int
pre_aq(DECL_ARGS)94561d06d6bSBaptiste Daroussin pre_aq(DECL_ARGS)
94661d06d6bSBaptiste Daroussin {
94761d06d6bSBaptiste Daroussin 
94861d06d6bSBaptiste Daroussin 	print_word(n->child != NULL && n->child->next == NULL &&
94961d06d6bSBaptiste Daroussin 	    n->child->tok == MDOC_Mt ?  "<" : "\\(la");
95061d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
95161d06d6bSBaptiste Daroussin 	return 1;
95261d06d6bSBaptiste Daroussin }
95361d06d6bSBaptiste Daroussin 
95461d06d6bSBaptiste Daroussin static void
post_aq(DECL_ARGS)95561d06d6bSBaptiste Daroussin post_aq(DECL_ARGS)
95661d06d6bSBaptiste Daroussin {
95761d06d6bSBaptiste Daroussin 
95861d06d6bSBaptiste Daroussin 	outflags &= ~(MMAN_spc | MMAN_nl);
95961d06d6bSBaptiste Daroussin 	print_word(n->child != NULL && n->child->next == NULL &&
96061d06d6bSBaptiste Daroussin 	    n->child->tok == MDOC_Mt ?  ">" : "\\(ra");
96161d06d6bSBaptiste Daroussin }
96261d06d6bSBaptiste Daroussin 
96361d06d6bSBaptiste Daroussin static int
pre_bd(DECL_ARGS)96461d06d6bSBaptiste Daroussin pre_bd(DECL_ARGS)
96561d06d6bSBaptiste Daroussin {
96661d06d6bSBaptiste Daroussin 	outflags &= ~(MMAN_PP | MMAN_sp | MMAN_br);
9676d38604fSBaptiste Daroussin 	if (n->norm->Bd.type == DISP_unfilled ||
9686d38604fSBaptiste Daroussin 	    n->norm->Bd.type == DISP_literal)
96961d06d6bSBaptiste Daroussin 		print_line(".nf", 0);
9706d38604fSBaptiste Daroussin 	if (n->norm->Bd.comp == 0 && roff_node_prev(n->parent) != NULL)
97161d06d6bSBaptiste Daroussin 		outflags |= MMAN_sp;
97261d06d6bSBaptiste Daroussin 	print_offs(n->norm->Bd.offs, 1);
97361d06d6bSBaptiste Daroussin 	return 1;
97461d06d6bSBaptiste Daroussin }
97561d06d6bSBaptiste Daroussin 
97661d06d6bSBaptiste Daroussin static void
post_bd(DECL_ARGS)97761d06d6bSBaptiste Daroussin post_bd(DECL_ARGS)
97861d06d6bSBaptiste Daroussin {
9797295610fSBaptiste Daroussin 	enum roff_tok	 bef, now;
98061d06d6bSBaptiste Daroussin 
98161d06d6bSBaptiste Daroussin 	/* Close out this display. */
98261d06d6bSBaptiste Daroussin 	print_line(".RE", MMAN_nl);
9837295610fSBaptiste Daroussin 	bef = n->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi;
9847295610fSBaptiste Daroussin 	if (n->last == NULL)
9857295610fSBaptiste Daroussin 		now = n->norm->Bd.type == DISP_unfilled ||
9867295610fSBaptiste Daroussin 		    n->norm->Bd.type == DISP_literal ? ROFF_nf : ROFF_fi;
9877295610fSBaptiste Daroussin 	else if (n->last->tok == ROFF_nf)
9887295610fSBaptiste Daroussin 		now = ROFF_nf;
9897295610fSBaptiste Daroussin 	else if (n->last->tok == ROFF_fi)
9907295610fSBaptiste Daroussin 		now = ROFF_fi;
9917295610fSBaptiste Daroussin 	else
9927295610fSBaptiste Daroussin 		now = n->last->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi;
9937295610fSBaptiste Daroussin 	if (bef != now) {
9947295610fSBaptiste Daroussin 		outflags |= MMAN_nl;
9957295610fSBaptiste Daroussin 		print_word(".");
9967295610fSBaptiste Daroussin 		outflags &= ~MMAN_spc;
9977295610fSBaptiste Daroussin 		print_word(roff_name[bef]);
9987295610fSBaptiste Daroussin 		outflags |= MMAN_nl;
9997295610fSBaptiste Daroussin 	}
100061d06d6bSBaptiste Daroussin 
100161d06d6bSBaptiste Daroussin 	/* Maybe we are inside an enclosing list? */
10026d38604fSBaptiste Daroussin 	if (roff_node_next(n->parent) != NULL)
100361d06d6bSBaptiste Daroussin 		mid_it();
100461d06d6bSBaptiste Daroussin }
100561d06d6bSBaptiste Daroussin 
100661d06d6bSBaptiste Daroussin static int
pre_bf(DECL_ARGS)100761d06d6bSBaptiste Daroussin pre_bf(DECL_ARGS)
100861d06d6bSBaptiste Daroussin {
100961d06d6bSBaptiste Daroussin 
101061d06d6bSBaptiste Daroussin 	switch (n->type) {
101161d06d6bSBaptiste Daroussin 	case ROFFT_BLOCK:
101261d06d6bSBaptiste Daroussin 		return 1;
101361d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
101461d06d6bSBaptiste Daroussin 		break;
101561d06d6bSBaptiste Daroussin 	default:
101661d06d6bSBaptiste Daroussin 		return 0;
101761d06d6bSBaptiste Daroussin 	}
101861d06d6bSBaptiste Daroussin 	switch (n->norm->Bf.font) {
101961d06d6bSBaptiste Daroussin 	case FONT_Em:
102061d06d6bSBaptiste Daroussin 		font_push('I');
102161d06d6bSBaptiste Daroussin 		break;
102261d06d6bSBaptiste Daroussin 	case FONT_Sy:
102361d06d6bSBaptiste Daroussin 		font_push('B');
102461d06d6bSBaptiste Daroussin 		break;
102561d06d6bSBaptiste Daroussin 	default:
102661d06d6bSBaptiste Daroussin 		font_push('R');
102761d06d6bSBaptiste Daroussin 		break;
102861d06d6bSBaptiste Daroussin 	}
102961d06d6bSBaptiste Daroussin 	return 1;
103061d06d6bSBaptiste Daroussin }
103161d06d6bSBaptiste Daroussin 
103261d06d6bSBaptiste Daroussin static void
post_bf(DECL_ARGS)103361d06d6bSBaptiste Daroussin post_bf(DECL_ARGS)
103461d06d6bSBaptiste Daroussin {
103561d06d6bSBaptiste Daroussin 
103661d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_BODY)
103761d06d6bSBaptiste Daroussin 		font_pop();
103861d06d6bSBaptiste Daroussin }
103961d06d6bSBaptiste Daroussin 
104061d06d6bSBaptiste Daroussin static int
pre_bk(DECL_ARGS)104161d06d6bSBaptiste Daroussin pre_bk(DECL_ARGS)
104261d06d6bSBaptiste Daroussin {
104361d06d6bSBaptiste Daroussin 	switch (n->type) {
104461d06d6bSBaptiste Daroussin 	case ROFFT_BLOCK:
104561d06d6bSBaptiste Daroussin 		return 1;
104661d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
104761d06d6bSBaptiste Daroussin 	case ROFFT_ELEM:
104861d06d6bSBaptiste Daroussin 		outflags |= MMAN_Bk;
104961d06d6bSBaptiste Daroussin 		return 1;
105061d06d6bSBaptiste Daroussin 	default:
105161d06d6bSBaptiste Daroussin 		return 0;
105261d06d6bSBaptiste Daroussin 	}
105361d06d6bSBaptiste Daroussin }
105461d06d6bSBaptiste Daroussin 
105561d06d6bSBaptiste Daroussin static void
post_bk(DECL_ARGS)105661d06d6bSBaptiste Daroussin post_bk(DECL_ARGS)
105761d06d6bSBaptiste Daroussin {
105861d06d6bSBaptiste Daroussin 	switch (n->type) {
105961d06d6bSBaptiste Daroussin 	case ROFFT_ELEM:
106061d06d6bSBaptiste Daroussin 		while ((n = n->parent) != NULL)
106161d06d6bSBaptiste Daroussin 			 if (n->tok == MDOC_Bk)
106261d06d6bSBaptiste Daroussin 				return;
106361d06d6bSBaptiste Daroussin 		/* FALLTHROUGH */
106461d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
106561d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_Bk;
106661d06d6bSBaptiste Daroussin 		break;
106761d06d6bSBaptiste Daroussin 	default:
106861d06d6bSBaptiste Daroussin 		break;
106961d06d6bSBaptiste Daroussin 	}
107061d06d6bSBaptiste Daroussin }
107161d06d6bSBaptiste Daroussin 
107261d06d6bSBaptiste Daroussin static int
pre_bl(DECL_ARGS)107361d06d6bSBaptiste Daroussin pre_bl(DECL_ARGS)
107461d06d6bSBaptiste Daroussin {
107561d06d6bSBaptiste Daroussin 	size_t		 icol;
107661d06d6bSBaptiste Daroussin 
107761d06d6bSBaptiste Daroussin 	/*
107861d06d6bSBaptiste Daroussin 	 * print_offs() will increase the -offset to account for
107961d06d6bSBaptiste Daroussin 	 * a possible enclosing .It, but any enclosed .It blocks
108061d06d6bSBaptiste Daroussin 	 * just nest and do not add up their indentation.
108161d06d6bSBaptiste Daroussin 	 */
108261d06d6bSBaptiste Daroussin 	if (n->norm->Bl.offs) {
108361d06d6bSBaptiste Daroussin 		print_offs(n->norm->Bl.offs, 0);
108461d06d6bSBaptiste Daroussin 		Bl_stack[Bl_stack_len++] = 0;
108561d06d6bSBaptiste Daroussin 	}
108661d06d6bSBaptiste Daroussin 
108761d06d6bSBaptiste Daroussin 	switch (n->norm->Bl.type) {
108861d06d6bSBaptiste Daroussin 	case LIST_enum:
108961d06d6bSBaptiste Daroussin 		n->norm->Bl.count = 0;
109061d06d6bSBaptiste Daroussin 		return 1;
109161d06d6bSBaptiste Daroussin 	case LIST_column:
109261d06d6bSBaptiste Daroussin 		break;
109361d06d6bSBaptiste Daroussin 	default:
109461d06d6bSBaptiste Daroussin 		return 1;
109561d06d6bSBaptiste Daroussin 	}
109661d06d6bSBaptiste Daroussin 
109761d06d6bSBaptiste Daroussin 	if (n->child != NULL) {
109861d06d6bSBaptiste Daroussin 		print_line(".TS", MMAN_nl);
109961d06d6bSBaptiste Daroussin 		for (icol = 0; icol < n->norm->Bl.ncols; icol++)
110061d06d6bSBaptiste Daroussin 			print_word("l");
110161d06d6bSBaptiste Daroussin 		print_word(".");
110261d06d6bSBaptiste Daroussin 	}
110361d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
110461d06d6bSBaptiste Daroussin 	return 1;
110561d06d6bSBaptiste Daroussin }
110661d06d6bSBaptiste Daroussin 
110761d06d6bSBaptiste Daroussin static void
post_bl(DECL_ARGS)110861d06d6bSBaptiste Daroussin post_bl(DECL_ARGS)
110961d06d6bSBaptiste Daroussin {
111061d06d6bSBaptiste Daroussin 
111161d06d6bSBaptiste Daroussin 	switch (n->norm->Bl.type) {
111261d06d6bSBaptiste Daroussin 	case LIST_column:
111361d06d6bSBaptiste Daroussin 		if (n->child != NULL)
111461d06d6bSBaptiste Daroussin 			print_line(".TE", 0);
111561d06d6bSBaptiste Daroussin 		break;
111661d06d6bSBaptiste Daroussin 	case LIST_enum:
111761d06d6bSBaptiste Daroussin 		n->norm->Bl.count = 0;
111861d06d6bSBaptiste Daroussin 		break;
111961d06d6bSBaptiste Daroussin 	default:
112061d06d6bSBaptiste Daroussin 		break;
112161d06d6bSBaptiste Daroussin 	}
112261d06d6bSBaptiste Daroussin 
112361d06d6bSBaptiste Daroussin 	if (n->norm->Bl.offs) {
112461d06d6bSBaptiste Daroussin 		print_line(".RE", MMAN_nl);
112561d06d6bSBaptiste Daroussin 		assert(Bl_stack_len);
112661d06d6bSBaptiste Daroussin 		Bl_stack_len--;
11276d38604fSBaptiste Daroussin 		assert(Bl_stack[Bl_stack_len] == 0);
112861d06d6bSBaptiste Daroussin 	} else {
112961d06d6bSBaptiste Daroussin 		outflags |= MMAN_PP | MMAN_nl;
113061d06d6bSBaptiste Daroussin 		outflags &= ~(MMAN_sp | MMAN_br);
113161d06d6bSBaptiste Daroussin 	}
113261d06d6bSBaptiste Daroussin 
113361d06d6bSBaptiste Daroussin 	/* Maybe we are inside an enclosing list? */
11346d38604fSBaptiste Daroussin 	if (roff_node_next(n->parent) != NULL)
113561d06d6bSBaptiste Daroussin 		mid_it();
113661d06d6bSBaptiste Daroussin }
113761d06d6bSBaptiste Daroussin 
113861d06d6bSBaptiste Daroussin static void
pre_br(DECL_ARGS)113961d06d6bSBaptiste Daroussin pre_br(DECL_ARGS)
114061d06d6bSBaptiste Daroussin {
114161d06d6bSBaptiste Daroussin 	outflags |= MMAN_br;
114261d06d6bSBaptiste Daroussin }
114361d06d6bSBaptiste Daroussin 
114461d06d6bSBaptiste Daroussin static int
pre_dl(DECL_ARGS)114561d06d6bSBaptiste Daroussin pre_dl(DECL_ARGS)
114661d06d6bSBaptiste Daroussin {
114761d06d6bSBaptiste Daroussin 	print_offs("6n", 0);
114861d06d6bSBaptiste Daroussin 	return 1;
114961d06d6bSBaptiste Daroussin }
115061d06d6bSBaptiste Daroussin 
115161d06d6bSBaptiste Daroussin static void
post_dl(DECL_ARGS)115261d06d6bSBaptiste Daroussin post_dl(DECL_ARGS)
115361d06d6bSBaptiste Daroussin {
115461d06d6bSBaptiste Daroussin 	print_line(".RE", MMAN_nl);
115561d06d6bSBaptiste Daroussin 
115661d06d6bSBaptiste Daroussin 	/* Maybe we are inside an enclosing list? */
11576d38604fSBaptiste Daroussin 	if (roff_node_next(n->parent) != NULL)
115861d06d6bSBaptiste Daroussin 		mid_it();
115961d06d6bSBaptiste Daroussin }
116061d06d6bSBaptiste Daroussin 
116161d06d6bSBaptiste Daroussin static int
pre_em(DECL_ARGS)116261d06d6bSBaptiste Daroussin pre_em(DECL_ARGS)
116361d06d6bSBaptiste Daroussin {
116461d06d6bSBaptiste Daroussin 
116561d06d6bSBaptiste Daroussin 	font_push('I');
116661d06d6bSBaptiste Daroussin 	return 1;
116761d06d6bSBaptiste Daroussin }
116861d06d6bSBaptiste Daroussin 
116961d06d6bSBaptiste Daroussin static int
pre_en(DECL_ARGS)117061d06d6bSBaptiste Daroussin pre_en(DECL_ARGS)
117161d06d6bSBaptiste Daroussin {
117261d06d6bSBaptiste Daroussin 
117361d06d6bSBaptiste Daroussin 	if (NULL == n->norm->Es ||
117461d06d6bSBaptiste Daroussin 	    NULL == n->norm->Es->child)
117561d06d6bSBaptiste Daroussin 		return 1;
117661d06d6bSBaptiste Daroussin 
117761d06d6bSBaptiste Daroussin 	print_word(n->norm->Es->child->string);
117861d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
117961d06d6bSBaptiste Daroussin 	return 1;
118061d06d6bSBaptiste Daroussin }
118161d06d6bSBaptiste Daroussin 
118261d06d6bSBaptiste Daroussin static void
post_en(DECL_ARGS)118361d06d6bSBaptiste Daroussin post_en(DECL_ARGS)
118461d06d6bSBaptiste Daroussin {
118561d06d6bSBaptiste Daroussin 
118661d06d6bSBaptiste Daroussin 	if (NULL == n->norm->Es ||
118761d06d6bSBaptiste Daroussin 	    NULL == n->norm->Es->child ||
118861d06d6bSBaptiste Daroussin 	    NULL == n->norm->Es->child->next)
118961d06d6bSBaptiste Daroussin 		return;
119061d06d6bSBaptiste Daroussin 
119161d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
119261d06d6bSBaptiste Daroussin 	print_word(n->norm->Es->child->next->string);
119361d06d6bSBaptiste Daroussin 	return;
119461d06d6bSBaptiste Daroussin }
119561d06d6bSBaptiste Daroussin 
119661d06d6bSBaptiste Daroussin static int
pre_eo(DECL_ARGS)119761d06d6bSBaptiste Daroussin pre_eo(DECL_ARGS)
119861d06d6bSBaptiste Daroussin {
119961d06d6bSBaptiste Daroussin 
120061d06d6bSBaptiste Daroussin 	if (n->end == ENDBODY_NOT &&
120161d06d6bSBaptiste Daroussin 	    n->parent->head->child == NULL &&
120261d06d6bSBaptiste Daroussin 	    n->child != NULL &&
120361d06d6bSBaptiste Daroussin 	    n->child->end != ENDBODY_NOT)
120461d06d6bSBaptiste Daroussin 		print_word("\\&");
120561d06d6bSBaptiste Daroussin 	else if (n->end != ENDBODY_NOT ? n->child != NULL :
120661d06d6bSBaptiste Daroussin 	    n->parent->head->child != NULL && (n->child != NULL ||
120761d06d6bSBaptiste Daroussin 	    (n->parent->tail != NULL && n->parent->tail->child != NULL)))
120861d06d6bSBaptiste Daroussin 		outflags &= ~(MMAN_spc | MMAN_nl);
120961d06d6bSBaptiste Daroussin 	return 1;
121061d06d6bSBaptiste Daroussin }
121161d06d6bSBaptiste Daroussin 
121261d06d6bSBaptiste Daroussin static void
post_eo(DECL_ARGS)121361d06d6bSBaptiste Daroussin post_eo(DECL_ARGS)
121461d06d6bSBaptiste Daroussin {
121561d06d6bSBaptiste Daroussin 	int	 body, tail;
121661d06d6bSBaptiste Daroussin 
121761d06d6bSBaptiste Daroussin 	if (n->end != ENDBODY_NOT) {
121861d06d6bSBaptiste Daroussin 		outflags |= MMAN_spc;
121961d06d6bSBaptiste Daroussin 		return;
122061d06d6bSBaptiste Daroussin 	}
122161d06d6bSBaptiste Daroussin 
122261d06d6bSBaptiste Daroussin 	body = n->child != NULL || n->parent->head->child != NULL;
122361d06d6bSBaptiste Daroussin 	tail = n->parent->tail != NULL && n->parent->tail->child != NULL;
122461d06d6bSBaptiste Daroussin 
122561d06d6bSBaptiste Daroussin 	if (body && tail)
122661d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
122761d06d6bSBaptiste Daroussin 	else if ( ! (body || tail))
122861d06d6bSBaptiste Daroussin 		print_word("\\&");
122961d06d6bSBaptiste Daroussin 	else if ( ! tail)
123061d06d6bSBaptiste Daroussin 		outflags |= MMAN_spc;
123161d06d6bSBaptiste Daroussin }
123261d06d6bSBaptiste Daroussin 
123361d06d6bSBaptiste Daroussin static int
pre_fa(DECL_ARGS)123461d06d6bSBaptiste Daroussin pre_fa(DECL_ARGS)
123561d06d6bSBaptiste Daroussin {
123661d06d6bSBaptiste Daroussin 	int	 am_Fa;
123761d06d6bSBaptiste Daroussin 
123861d06d6bSBaptiste Daroussin 	am_Fa = MDOC_Fa == n->tok;
123961d06d6bSBaptiste Daroussin 
124061d06d6bSBaptiste Daroussin 	if (am_Fa)
124161d06d6bSBaptiste Daroussin 		n = n->child;
124261d06d6bSBaptiste Daroussin 
124361d06d6bSBaptiste Daroussin 	while (NULL != n) {
124461d06d6bSBaptiste Daroussin 		font_push('I');
124561d06d6bSBaptiste Daroussin 		if (am_Fa || NODE_SYNPRETTY & n->flags)
124661d06d6bSBaptiste Daroussin 			outflags |= MMAN_nbrword;
124761d06d6bSBaptiste Daroussin 		print_node(meta, n);
124861d06d6bSBaptiste Daroussin 		font_pop();
124961d06d6bSBaptiste Daroussin 		if (NULL != (n = n->next))
125061d06d6bSBaptiste Daroussin 			print_word(",");
125161d06d6bSBaptiste Daroussin 	}
125261d06d6bSBaptiste Daroussin 	return 0;
125361d06d6bSBaptiste Daroussin }
125461d06d6bSBaptiste Daroussin 
125561d06d6bSBaptiste Daroussin static void
post_fa(DECL_ARGS)125661d06d6bSBaptiste Daroussin post_fa(DECL_ARGS)
125761d06d6bSBaptiste Daroussin {
12586d38604fSBaptiste Daroussin 	struct roff_node *nn;
125961d06d6bSBaptiste Daroussin 
12606d38604fSBaptiste Daroussin 	if ((nn = roff_node_next(n)) != NULL && nn->tok == MDOC_Fa)
126161d06d6bSBaptiste Daroussin 		print_word(",");
126261d06d6bSBaptiste Daroussin }
126361d06d6bSBaptiste Daroussin 
126461d06d6bSBaptiste Daroussin static int
pre_fd(DECL_ARGS)126561d06d6bSBaptiste Daroussin pre_fd(DECL_ARGS)
126661d06d6bSBaptiste Daroussin {
126761d06d6bSBaptiste Daroussin 	pre_syn(n);
126861d06d6bSBaptiste Daroussin 	font_push('B');
126961d06d6bSBaptiste Daroussin 	return 1;
127061d06d6bSBaptiste Daroussin }
127161d06d6bSBaptiste Daroussin 
127261d06d6bSBaptiste Daroussin static void
post_fd(DECL_ARGS)127361d06d6bSBaptiste Daroussin post_fd(DECL_ARGS)
127461d06d6bSBaptiste Daroussin {
127561d06d6bSBaptiste Daroussin 	font_pop();
127661d06d6bSBaptiste Daroussin 	outflags |= MMAN_br;
127761d06d6bSBaptiste Daroussin }
127861d06d6bSBaptiste Daroussin 
127961d06d6bSBaptiste Daroussin static int
pre_fl(DECL_ARGS)128061d06d6bSBaptiste Daroussin pre_fl(DECL_ARGS)
128161d06d6bSBaptiste Daroussin {
128261d06d6bSBaptiste Daroussin 	font_push('B');
128361d06d6bSBaptiste Daroussin 	print_word("\\-");
128461d06d6bSBaptiste Daroussin 	if (n->child != NULL)
128561d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
128661d06d6bSBaptiste Daroussin 	return 1;
128761d06d6bSBaptiste Daroussin }
128861d06d6bSBaptiste Daroussin 
128961d06d6bSBaptiste Daroussin static void
post_fl(DECL_ARGS)129061d06d6bSBaptiste Daroussin post_fl(DECL_ARGS)
129161d06d6bSBaptiste Daroussin {
12926d38604fSBaptiste Daroussin 	struct roff_node *nn;
129361d06d6bSBaptiste Daroussin 
129461d06d6bSBaptiste Daroussin 	font_pop();
12956d38604fSBaptiste Daroussin 	if (n->child == NULL &&
12966d38604fSBaptiste Daroussin 	    ((nn = roff_node_next(n)) != NULL &&
12976d38604fSBaptiste Daroussin 	    nn->type != ROFFT_TEXT &&
12986d38604fSBaptiste Daroussin 	    (nn->flags & NODE_LINE) == 0))
129961d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
130061d06d6bSBaptiste Daroussin }
130161d06d6bSBaptiste Daroussin 
130261d06d6bSBaptiste Daroussin static int
pre_fn(DECL_ARGS)130361d06d6bSBaptiste Daroussin pre_fn(DECL_ARGS)
130461d06d6bSBaptiste Daroussin {
130561d06d6bSBaptiste Daroussin 
130661d06d6bSBaptiste Daroussin 	pre_syn(n);
130761d06d6bSBaptiste Daroussin 
130861d06d6bSBaptiste Daroussin 	n = n->child;
130961d06d6bSBaptiste Daroussin 	if (NULL == n)
131061d06d6bSBaptiste Daroussin 		return 0;
131161d06d6bSBaptiste Daroussin 
131261d06d6bSBaptiste Daroussin 	if (NODE_SYNPRETTY & n->flags)
131361d06d6bSBaptiste Daroussin 		print_block(".HP 4n", MMAN_nl);
131461d06d6bSBaptiste Daroussin 
131561d06d6bSBaptiste Daroussin 	font_push('B');
131661d06d6bSBaptiste Daroussin 	print_node(meta, n);
131761d06d6bSBaptiste Daroussin 	font_pop();
131861d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
131961d06d6bSBaptiste Daroussin 	print_word("(");
132061d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
132161d06d6bSBaptiste Daroussin 
132261d06d6bSBaptiste Daroussin 	n = n->next;
132361d06d6bSBaptiste Daroussin 	if (NULL != n)
132461d06d6bSBaptiste Daroussin 		pre_fa(meta, n);
132561d06d6bSBaptiste Daroussin 	return 0;
132661d06d6bSBaptiste Daroussin }
132761d06d6bSBaptiste Daroussin 
132861d06d6bSBaptiste Daroussin static void
post_fn(DECL_ARGS)132961d06d6bSBaptiste Daroussin post_fn(DECL_ARGS)
133061d06d6bSBaptiste Daroussin {
133161d06d6bSBaptiste Daroussin 
133261d06d6bSBaptiste Daroussin 	print_word(")");
133361d06d6bSBaptiste Daroussin 	if (NODE_SYNPRETTY & n->flags) {
133461d06d6bSBaptiste Daroussin 		print_word(";");
133561d06d6bSBaptiste Daroussin 		outflags |= MMAN_PP;
133661d06d6bSBaptiste Daroussin 	}
133761d06d6bSBaptiste Daroussin }
133861d06d6bSBaptiste Daroussin 
133961d06d6bSBaptiste Daroussin static int
pre_fo(DECL_ARGS)134061d06d6bSBaptiste Daroussin pre_fo(DECL_ARGS)
134161d06d6bSBaptiste Daroussin {
134261d06d6bSBaptiste Daroussin 
134361d06d6bSBaptiste Daroussin 	switch (n->type) {
134461d06d6bSBaptiste Daroussin 	case ROFFT_BLOCK:
134561d06d6bSBaptiste Daroussin 		pre_syn(n);
134661d06d6bSBaptiste Daroussin 		break;
134761d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
134861d06d6bSBaptiste Daroussin 		if (n->child == NULL)
134961d06d6bSBaptiste Daroussin 			return 0;
135061d06d6bSBaptiste Daroussin 		if (NODE_SYNPRETTY & n->flags)
135161d06d6bSBaptiste Daroussin 			print_block(".HP 4n", MMAN_nl);
135261d06d6bSBaptiste Daroussin 		font_push('B');
135361d06d6bSBaptiste Daroussin 		break;
135461d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
135561d06d6bSBaptiste Daroussin 		outflags &= ~(MMAN_spc | MMAN_nl);
135661d06d6bSBaptiste Daroussin 		print_word("(");
135761d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
135861d06d6bSBaptiste Daroussin 		break;
135961d06d6bSBaptiste Daroussin 	default:
136061d06d6bSBaptiste Daroussin 		break;
136161d06d6bSBaptiste Daroussin 	}
136261d06d6bSBaptiste Daroussin 	return 1;
136361d06d6bSBaptiste Daroussin }
136461d06d6bSBaptiste Daroussin 
136561d06d6bSBaptiste Daroussin static void
post_fo(DECL_ARGS)136661d06d6bSBaptiste Daroussin post_fo(DECL_ARGS)
136761d06d6bSBaptiste Daroussin {
136861d06d6bSBaptiste Daroussin 
136961d06d6bSBaptiste Daroussin 	switch (n->type) {
137061d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
137161d06d6bSBaptiste Daroussin 		if (n->child != NULL)
137261d06d6bSBaptiste Daroussin 			font_pop();
137361d06d6bSBaptiste Daroussin 		break;
137461d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
137561d06d6bSBaptiste Daroussin 		post_fn(meta, n);
137661d06d6bSBaptiste Daroussin 		break;
137761d06d6bSBaptiste Daroussin 	default:
137861d06d6bSBaptiste Daroussin 		break;
137961d06d6bSBaptiste Daroussin 	}
138061d06d6bSBaptiste Daroussin }
138161d06d6bSBaptiste Daroussin 
138261d06d6bSBaptiste Daroussin static int
pre_Ft(DECL_ARGS)138361d06d6bSBaptiste Daroussin pre_Ft(DECL_ARGS)
138461d06d6bSBaptiste Daroussin {
138561d06d6bSBaptiste Daroussin 
138661d06d6bSBaptiste Daroussin 	pre_syn(n);
138761d06d6bSBaptiste Daroussin 	font_push('I');
138861d06d6bSBaptiste Daroussin 	return 1;
138961d06d6bSBaptiste Daroussin }
139061d06d6bSBaptiste Daroussin 
139161d06d6bSBaptiste Daroussin static void
pre_ft(DECL_ARGS)139261d06d6bSBaptiste Daroussin pre_ft(DECL_ARGS)
139361d06d6bSBaptiste Daroussin {
139461d06d6bSBaptiste Daroussin 	print_line(".ft", 0);
139561d06d6bSBaptiste Daroussin 	print_word(n->child->string);
139661d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
139761d06d6bSBaptiste Daroussin }
139861d06d6bSBaptiste Daroussin 
139961d06d6bSBaptiste Daroussin static int
pre_in(DECL_ARGS)140061d06d6bSBaptiste Daroussin pre_in(DECL_ARGS)
140161d06d6bSBaptiste Daroussin {
140261d06d6bSBaptiste Daroussin 
140361d06d6bSBaptiste Daroussin 	if (NODE_SYNPRETTY & n->flags) {
140461d06d6bSBaptiste Daroussin 		pre_syn(n);
140561d06d6bSBaptiste Daroussin 		font_push('B');
140661d06d6bSBaptiste Daroussin 		print_word("#include <");
140761d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
140861d06d6bSBaptiste Daroussin 	} else {
140961d06d6bSBaptiste Daroussin 		print_word("<");
141061d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
141161d06d6bSBaptiste Daroussin 		font_push('I');
141261d06d6bSBaptiste Daroussin 	}
141361d06d6bSBaptiste Daroussin 	return 1;
141461d06d6bSBaptiste Daroussin }
141561d06d6bSBaptiste Daroussin 
141661d06d6bSBaptiste Daroussin static void
post_in(DECL_ARGS)141761d06d6bSBaptiste Daroussin post_in(DECL_ARGS)
141861d06d6bSBaptiste Daroussin {
141961d06d6bSBaptiste Daroussin 
142061d06d6bSBaptiste Daroussin 	if (NODE_SYNPRETTY & n->flags) {
142161d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
142261d06d6bSBaptiste Daroussin 		print_word(">");
142361d06d6bSBaptiste Daroussin 		font_pop();
142461d06d6bSBaptiste Daroussin 		outflags |= MMAN_br;
142561d06d6bSBaptiste Daroussin 	} else {
142661d06d6bSBaptiste Daroussin 		font_pop();
142761d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
142861d06d6bSBaptiste Daroussin 		print_word(">");
142961d06d6bSBaptiste Daroussin 	}
143061d06d6bSBaptiste Daroussin }
143161d06d6bSBaptiste Daroussin 
143261d06d6bSBaptiste Daroussin static int
pre_it(DECL_ARGS)143361d06d6bSBaptiste Daroussin pre_it(DECL_ARGS)
143461d06d6bSBaptiste Daroussin {
143561d06d6bSBaptiste Daroussin 	const struct roff_node *bln;
143661d06d6bSBaptiste Daroussin 
143761d06d6bSBaptiste Daroussin 	switch (n->type) {
143861d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
143961d06d6bSBaptiste Daroussin 		outflags |= MMAN_PP | MMAN_nl;
144061d06d6bSBaptiste Daroussin 		bln = n->parent->parent;
14416d38604fSBaptiste Daroussin 		if (bln->norm->Bl.comp == 0 ||
14426d38604fSBaptiste Daroussin 		    (n->parent->prev == NULL &&
14436d38604fSBaptiste Daroussin 		     roff_node_prev(bln->parent) == NULL))
144461d06d6bSBaptiste Daroussin 			outflags |= MMAN_sp;
144561d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_br;
144661d06d6bSBaptiste Daroussin 		switch (bln->norm->Bl.type) {
144761d06d6bSBaptiste Daroussin 		case LIST_item:
144861d06d6bSBaptiste Daroussin 			return 0;
144961d06d6bSBaptiste Daroussin 		case LIST_inset:
145061d06d6bSBaptiste Daroussin 		case LIST_diag:
145161d06d6bSBaptiste Daroussin 		case LIST_ohang:
145261d06d6bSBaptiste Daroussin 			if (bln->norm->Bl.type == LIST_diag)
145361d06d6bSBaptiste Daroussin 				print_line(".B \"", 0);
145461d06d6bSBaptiste Daroussin 			else
145561d06d6bSBaptiste Daroussin 				print_line(".BR \\& \"", 0);
145661d06d6bSBaptiste Daroussin 			outflags &= ~MMAN_spc;
145761d06d6bSBaptiste Daroussin 			return 1;
145861d06d6bSBaptiste Daroussin 		case LIST_bullet:
145961d06d6bSBaptiste Daroussin 		case LIST_dash:
146061d06d6bSBaptiste Daroussin 		case LIST_hyphen:
146161d06d6bSBaptiste Daroussin 			print_width(&bln->norm->Bl, NULL);
146261d06d6bSBaptiste Daroussin 			TPremain = 0;
146361d06d6bSBaptiste Daroussin 			outflags |= MMAN_nl;
146461d06d6bSBaptiste Daroussin 			font_push('B');
146561d06d6bSBaptiste Daroussin 			if (LIST_bullet == bln->norm->Bl.type)
146661d06d6bSBaptiste Daroussin 				print_word("\\(bu");
146761d06d6bSBaptiste Daroussin 			else
146861d06d6bSBaptiste Daroussin 				print_word("-");
146961d06d6bSBaptiste Daroussin 			font_pop();
147061d06d6bSBaptiste Daroussin 			outflags |= MMAN_nl;
147161d06d6bSBaptiste Daroussin 			return 0;
147261d06d6bSBaptiste Daroussin 		case LIST_enum:
147361d06d6bSBaptiste Daroussin 			print_width(&bln->norm->Bl, NULL);
147461d06d6bSBaptiste Daroussin 			TPremain = 0;
147561d06d6bSBaptiste Daroussin 			outflags |= MMAN_nl;
147661d06d6bSBaptiste Daroussin 			print_count(&bln->norm->Bl.count);
147761d06d6bSBaptiste Daroussin 			outflags |= MMAN_nl;
147861d06d6bSBaptiste Daroussin 			return 0;
147961d06d6bSBaptiste Daroussin 		case LIST_hang:
148061d06d6bSBaptiste Daroussin 			print_width(&bln->norm->Bl, n->child);
148161d06d6bSBaptiste Daroussin 			TPremain = 0;
148261d06d6bSBaptiste Daroussin 			outflags |= MMAN_nl;
148361d06d6bSBaptiste Daroussin 			return 1;
148461d06d6bSBaptiste Daroussin 		case LIST_tag:
148561d06d6bSBaptiste Daroussin 			print_width(&bln->norm->Bl, n->child);
148661d06d6bSBaptiste Daroussin 			putchar('\n');
148761d06d6bSBaptiste Daroussin 			outflags &= ~MMAN_spc;
148861d06d6bSBaptiste Daroussin 			return 1;
148961d06d6bSBaptiste Daroussin 		default:
149061d06d6bSBaptiste Daroussin 			return 1;
149161d06d6bSBaptiste Daroussin 		}
149261d06d6bSBaptiste Daroussin 	default:
149361d06d6bSBaptiste Daroussin 		break;
149461d06d6bSBaptiste Daroussin 	}
149561d06d6bSBaptiste Daroussin 	return 1;
149661d06d6bSBaptiste Daroussin }
149761d06d6bSBaptiste Daroussin 
149861d06d6bSBaptiste Daroussin /*
149961d06d6bSBaptiste Daroussin  * This function is called after closing out an indented block.
150061d06d6bSBaptiste Daroussin  * If we are inside an enclosing list, restore its indentation.
150161d06d6bSBaptiste Daroussin  */
150261d06d6bSBaptiste Daroussin static void
mid_it(void)150361d06d6bSBaptiste Daroussin mid_it(void)
150461d06d6bSBaptiste Daroussin {
150561d06d6bSBaptiste Daroussin 	char		 buf[24];
150661d06d6bSBaptiste Daroussin 
150761d06d6bSBaptiste Daroussin 	/* Nothing to do outside a list. */
150861d06d6bSBaptiste Daroussin 	if (0 == Bl_stack_len || 0 == Bl_stack[Bl_stack_len - 1])
150961d06d6bSBaptiste Daroussin 		return;
151061d06d6bSBaptiste Daroussin 
151161d06d6bSBaptiste Daroussin 	/* The indentation has already been set up. */
151261d06d6bSBaptiste Daroussin 	if (Bl_stack_post[Bl_stack_len - 1])
151361d06d6bSBaptiste Daroussin 		return;
151461d06d6bSBaptiste Daroussin 
151561d06d6bSBaptiste Daroussin 	/* Restore the indentation of the enclosing list. */
151661d06d6bSBaptiste Daroussin 	print_line(".RS", MMAN_Bk_susp);
151761d06d6bSBaptiste Daroussin 	(void)snprintf(buf, sizeof(buf), "%dn",
151861d06d6bSBaptiste Daroussin 	    Bl_stack[Bl_stack_len - 1]);
151961d06d6bSBaptiste Daroussin 	print_word(buf);
152061d06d6bSBaptiste Daroussin 
1521*c1c95addSBrooks Davis 	/* Remember to close out this .RS block later. */
152261d06d6bSBaptiste Daroussin 	Bl_stack_post[Bl_stack_len - 1] = 1;
152361d06d6bSBaptiste Daroussin }
152461d06d6bSBaptiste Daroussin 
152561d06d6bSBaptiste Daroussin static void
post_it(DECL_ARGS)152661d06d6bSBaptiste Daroussin post_it(DECL_ARGS)
152761d06d6bSBaptiste Daroussin {
152861d06d6bSBaptiste Daroussin 	const struct roff_node *bln;
152961d06d6bSBaptiste Daroussin 
153061d06d6bSBaptiste Daroussin 	bln = n->parent->parent;
153161d06d6bSBaptiste Daroussin 
153261d06d6bSBaptiste Daroussin 	switch (n->type) {
153361d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
153461d06d6bSBaptiste Daroussin 		switch (bln->norm->Bl.type) {
153561d06d6bSBaptiste Daroussin 		case LIST_diag:
153661d06d6bSBaptiste Daroussin 			outflags &= ~MMAN_spc;
153761d06d6bSBaptiste Daroussin 			print_word("\\ ");
153861d06d6bSBaptiste Daroussin 			break;
153961d06d6bSBaptiste Daroussin 		case LIST_ohang:
154061d06d6bSBaptiste Daroussin 			outflags |= MMAN_br;
154161d06d6bSBaptiste Daroussin 			break;
154261d06d6bSBaptiste Daroussin 		default:
154361d06d6bSBaptiste Daroussin 			break;
154461d06d6bSBaptiste Daroussin 		}
154561d06d6bSBaptiste Daroussin 		break;
154661d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
154761d06d6bSBaptiste Daroussin 		switch (bln->norm->Bl.type) {
154861d06d6bSBaptiste Daroussin 		case LIST_bullet:
154961d06d6bSBaptiste Daroussin 		case LIST_dash:
155061d06d6bSBaptiste Daroussin 		case LIST_hyphen:
155161d06d6bSBaptiste Daroussin 		case LIST_enum:
155261d06d6bSBaptiste Daroussin 		case LIST_hang:
155361d06d6bSBaptiste Daroussin 		case LIST_tag:
155461d06d6bSBaptiste Daroussin 			assert(Bl_stack_len);
155561d06d6bSBaptiste Daroussin 			Bl_stack[--Bl_stack_len] = 0;
155661d06d6bSBaptiste Daroussin 
155761d06d6bSBaptiste Daroussin 			/*
155861d06d6bSBaptiste Daroussin 			 * Our indentation had to be restored
155961d06d6bSBaptiste Daroussin 			 * after a child display or child list.
156061d06d6bSBaptiste Daroussin 			 * Close out that indentation block now.
156161d06d6bSBaptiste Daroussin 			 */
156261d06d6bSBaptiste Daroussin 			if (Bl_stack_post[Bl_stack_len]) {
156361d06d6bSBaptiste Daroussin 				print_line(".RE", MMAN_nl);
156461d06d6bSBaptiste Daroussin 				Bl_stack_post[Bl_stack_len] = 0;
156561d06d6bSBaptiste Daroussin 			}
156661d06d6bSBaptiste Daroussin 			break;
156761d06d6bSBaptiste Daroussin 		case LIST_column:
156861d06d6bSBaptiste Daroussin 			if (NULL != n->next) {
156961d06d6bSBaptiste Daroussin 				putchar('\t');
157061d06d6bSBaptiste Daroussin 				outflags &= ~MMAN_spc;
157161d06d6bSBaptiste Daroussin 			}
157261d06d6bSBaptiste Daroussin 			break;
157361d06d6bSBaptiste Daroussin 		default:
157461d06d6bSBaptiste Daroussin 			break;
157561d06d6bSBaptiste Daroussin 		}
157661d06d6bSBaptiste Daroussin 		break;
157761d06d6bSBaptiste Daroussin 	default:
157861d06d6bSBaptiste Daroussin 		break;
157961d06d6bSBaptiste Daroussin 	}
158061d06d6bSBaptiste Daroussin }
158161d06d6bSBaptiste Daroussin 
158261d06d6bSBaptiste Daroussin static void
post_lb(DECL_ARGS)158361d06d6bSBaptiste Daroussin post_lb(DECL_ARGS)
158461d06d6bSBaptiste Daroussin {
158561d06d6bSBaptiste Daroussin 
158661d06d6bSBaptiste Daroussin 	if (SEC_LIBRARY == n->sec)
158761d06d6bSBaptiste Daroussin 		outflags |= MMAN_br;
158861d06d6bSBaptiste Daroussin }
158961d06d6bSBaptiste Daroussin 
159061d06d6bSBaptiste Daroussin static int
pre_lk(DECL_ARGS)159161d06d6bSBaptiste Daroussin pre_lk(DECL_ARGS)
159261d06d6bSBaptiste Daroussin {
159361d06d6bSBaptiste Daroussin 	const struct roff_node *link, *descr, *punct;
159461d06d6bSBaptiste Daroussin 
159561d06d6bSBaptiste Daroussin 	if ((link = n->child) == NULL)
159661d06d6bSBaptiste Daroussin 		return 0;
159761d06d6bSBaptiste Daroussin 
159861d06d6bSBaptiste Daroussin 	/* Find beginning of trailing punctuation. */
159961d06d6bSBaptiste Daroussin 	punct = n->last;
160061d06d6bSBaptiste Daroussin 	while (punct != link && punct->flags & NODE_DELIMC)
160161d06d6bSBaptiste Daroussin 		punct = punct->prev;
160261d06d6bSBaptiste Daroussin 	punct = punct->next;
160361d06d6bSBaptiste Daroussin 
160461d06d6bSBaptiste Daroussin 	/* Link text. */
160561d06d6bSBaptiste Daroussin 	if ((descr = link->next) != NULL && descr != punct) {
160661d06d6bSBaptiste Daroussin 		font_push('I');
160761d06d6bSBaptiste Daroussin 		while (descr != punct) {
160861d06d6bSBaptiste Daroussin 			print_word(descr->string);
160961d06d6bSBaptiste Daroussin 			descr = descr->next;
161061d06d6bSBaptiste Daroussin 		}
161161d06d6bSBaptiste Daroussin 		font_pop();
161261d06d6bSBaptiste Daroussin 		print_word(":");
161361d06d6bSBaptiste Daroussin 	}
161461d06d6bSBaptiste Daroussin 
161561d06d6bSBaptiste Daroussin 	/* Link target. */
161661d06d6bSBaptiste Daroussin 	font_push('B');
161761d06d6bSBaptiste Daroussin 	print_word(link->string);
161861d06d6bSBaptiste Daroussin 	font_pop();
161961d06d6bSBaptiste Daroussin 
162061d06d6bSBaptiste Daroussin 	/* Trailing punctuation. */
162161d06d6bSBaptiste Daroussin 	while (punct != NULL) {
162261d06d6bSBaptiste Daroussin 		print_word(punct->string);
162361d06d6bSBaptiste Daroussin 		punct = punct->next;
162461d06d6bSBaptiste Daroussin 	}
162561d06d6bSBaptiste Daroussin 	return 0;
162661d06d6bSBaptiste Daroussin }
162761d06d6bSBaptiste Daroussin 
162861d06d6bSBaptiste Daroussin static void
pre_onearg(DECL_ARGS)162961d06d6bSBaptiste Daroussin pre_onearg(DECL_ARGS)
163061d06d6bSBaptiste Daroussin {
163161d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
163261d06d6bSBaptiste Daroussin 	print_word(".");
163361d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
163461d06d6bSBaptiste Daroussin 	print_word(roff_name[n->tok]);
163561d06d6bSBaptiste Daroussin 	if (n->child != NULL)
163661d06d6bSBaptiste Daroussin 		print_word(n->child->string);
163761d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
163861d06d6bSBaptiste Daroussin 	if (n->tok == ROFF_ce)
163961d06d6bSBaptiste Daroussin 		for (n = n->child->next; n != NULL; n = n->next)
164061d06d6bSBaptiste Daroussin 			print_node(meta, n);
164161d06d6bSBaptiste Daroussin }
164261d06d6bSBaptiste Daroussin 
164361d06d6bSBaptiste Daroussin static int
pre_li(DECL_ARGS)164461d06d6bSBaptiste Daroussin pre_li(DECL_ARGS)
164561d06d6bSBaptiste Daroussin {
164661d06d6bSBaptiste Daroussin 	font_push('R');
164761d06d6bSBaptiste Daroussin 	return 1;
164861d06d6bSBaptiste Daroussin }
164961d06d6bSBaptiste Daroussin 
165061d06d6bSBaptiste Daroussin static int
pre_nm(DECL_ARGS)165161d06d6bSBaptiste Daroussin pre_nm(DECL_ARGS)
165261d06d6bSBaptiste Daroussin {
165361d06d6bSBaptiste Daroussin 	char	*name;
165461d06d6bSBaptiste Daroussin 
16556d38604fSBaptiste Daroussin 	switch (n->type) {
16566d38604fSBaptiste Daroussin 	case ROFFT_BLOCK:
165761d06d6bSBaptiste Daroussin 		outflags |= MMAN_Bk;
165861d06d6bSBaptiste Daroussin 		pre_syn(n);
165961d06d6bSBaptiste Daroussin 		return 1;
16606d38604fSBaptiste Daroussin 	case ROFFT_HEAD:
16616d38604fSBaptiste Daroussin 	case ROFFT_ELEM:
16626d38604fSBaptiste Daroussin 		break;
16636d38604fSBaptiste Daroussin 	default:
16646d38604fSBaptiste Daroussin 		return 1;
16656d38604fSBaptiste Daroussin 	}
166661d06d6bSBaptiste Daroussin 	name = n->child == NULL ? NULL : n->child->string;
16676d38604fSBaptiste Daroussin 	if (name == NULL)
166861d06d6bSBaptiste Daroussin 		return 0;
166961d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_HEAD) {
16706d38604fSBaptiste Daroussin 		if (roff_node_prev(n->parent) == NULL)
167161d06d6bSBaptiste Daroussin 			outflags |= MMAN_sp;
167261d06d6bSBaptiste Daroussin 		print_block(".HP", 0);
167361d06d6bSBaptiste Daroussin 		printf(" %dn", man_strlen(name) + 1);
167461d06d6bSBaptiste Daroussin 		outflags |= MMAN_nl;
167561d06d6bSBaptiste Daroussin 	}
167661d06d6bSBaptiste Daroussin 	font_push('B');
167761d06d6bSBaptiste Daroussin 	return 1;
167861d06d6bSBaptiste Daroussin }
167961d06d6bSBaptiste Daroussin 
168061d06d6bSBaptiste Daroussin static void
post_nm(DECL_ARGS)168161d06d6bSBaptiste Daroussin post_nm(DECL_ARGS)
168261d06d6bSBaptiste Daroussin {
168361d06d6bSBaptiste Daroussin 	switch (n->type) {
168461d06d6bSBaptiste Daroussin 	case ROFFT_BLOCK:
168561d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_Bk;
168661d06d6bSBaptiste Daroussin 		break;
168761d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
168861d06d6bSBaptiste Daroussin 	case ROFFT_ELEM:
168961d06d6bSBaptiste Daroussin 		if (n->child != NULL && n->child->string != NULL)
169061d06d6bSBaptiste Daroussin 			font_pop();
169161d06d6bSBaptiste Daroussin 		break;
169261d06d6bSBaptiste Daroussin 	default:
169361d06d6bSBaptiste Daroussin 		break;
169461d06d6bSBaptiste Daroussin 	}
169561d06d6bSBaptiste Daroussin }
169661d06d6bSBaptiste Daroussin 
169761d06d6bSBaptiste Daroussin static int
pre_no(DECL_ARGS)169861d06d6bSBaptiste Daroussin pre_no(DECL_ARGS)
169961d06d6bSBaptiste Daroussin {
170061d06d6bSBaptiste Daroussin 	outflags |= MMAN_spc_force;
170161d06d6bSBaptiste Daroussin 	return 1;
170261d06d6bSBaptiste Daroussin }
170361d06d6bSBaptiste Daroussin 
17047295610fSBaptiste Daroussin static void
pre_noarg(DECL_ARGS)17057295610fSBaptiste Daroussin pre_noarg(DECL_ARGS)
17067295610fSBaptiste Daroussin {
17077295610fSBaptiste Daroussin 	outflags |= MMAN_nl;
17087295610fSBaptiste Daroussin 	print_word(".");
17097295610fSBaptiste Daroussin 	outflags &= ~MMAN_spc;
17107295610fSBaptiste Daroussin 	print_word(roff_name[n->tok]);
17117295610fSBaptiste Daroussin 	outflags |= MMAN_nl;
17127295610fSBaptiste Daroussin }
17137295610fSBaptiste Daroussin 
171461d06d6bSBaptiste Daroussin static int
pre_ns(DECL_ARGS)171561d06d6bSBaptiste Daroussin pre_ns(DECL_ARGS)
171661d06d6bSBaptiste Daroussin {
171761d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
171861d06d6bSBaptiste Daroussin 	return 0;
171961d06d6bSBaptiste Daroussin }
172061d06d6bSBaptiste Daroussin 
172161d06d6bSBaptiste Daroussin static void
post_pf(DECL_ARGS)172261d06d6bSBaptiste Daroussin post_pf(DECL_ARGS)
172361d06d6bSBaptiste Daroussin {
172461d06d6bSBaptiste Daroussin 
172561d06d6bSBaptiste Daroussin 	if ( ! (n->next == NULL || n->next->flags & NODE_LINE))
172661d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_spc;
172761d06d6bSBaptiste Daroussin }
172861d06d6bSBaptiste Daroussin 
172961d06d6bSBaptiste Daroussin static int
pre_pp(DECL_ARGS)173061d06d6bSBaptiste Daroussin pre_pp(DECL_ARGS)
173161d06d6bSBaptiste Daroussin {
173261d06d6bSBaptiste Daroussin 
173361d06d6bSBaptiste Daroussin 	if (MDOC_It != n->parent->tok)
173461d06d6bSBaptiste Daroussin 		outflags |= MMAN_PP;
173561d06d6bSBaptiste Daroussin 	outflags |= MMAN_sp | MMAN_nl;
173661d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_br;
173761d06d6bSBaptiste Daroussin 	return 0;
173861d06d6bSBaptiste Daroussin }
173961d06d6bSBaptiste Daroussin 
174061d06d6bSBaptiste Daroussin static int
pre_rs(DECL_ARGS)174161d06d6bSBaptiste Daroussin pre_rs(DECL_ARGS)
174261d06d6bSBaptiste Daroussin {
174361d06d6bSBaptiste Daroussin 
174461d06d6bSBaptiste Daroussin 	if (SEC_SEE_ALSO == n->sec) {
174561d06d6bSBaptiste Daroussin 		outflags |= MMAN_PP | MMAN_sp | MMAN_nl;
174661d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_br;
174761d06d6bSBaptiste Daroussin 	}
174861d06d6bSBaptiste Daroussin 	return 1;
174961d06d6bSBaptiste Daroussin }
175061d06d6bSBaptiste Daroussin 
175161d06d6bSBaptiste Daroussin static int
pre_skip(DECL_ARGS)175261d06d6bSBaptiste Daroussin pre_skip(DECL_ARGS)
175361d06d6bSBaptiste Daroussin {
175461d06d6bSBaptiste Daroussin 
175561d06d6bSBaptiste Daroussin 	return 0;
175661d06d6bSBaptiste Daroussin }
175761d06d6bSBaptiste Daroussin 
175861d06d6bSBaptiste Daroussin static int
pre_sm(DECL_ARGS)175961d06d6bSBaptiste Daroussin pre_sm(DECL_ARGS)
176061d06d6bSBaptiste Daroussin {
176161d06d6bSBaptiste Daroussin 
176261d06d6bSBaptiste Daroussin 	if (NULL == n->child)
176361d06d6bSBaptiste Daroussin 		outflags ^= MMAN_Sm;
176461d06d6bSBaptiste Daroussin 	else if (0 == strcmp("on", n->child->string))
176561d06d6bSBaptiste Daroussin 		outflags |= MMAN_Sm;
176661d06d6bSBaptiste Daroussin 	else
176761d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_Sm;
176861d06d6bSBaptiste Daroussin 
176961d06d6bSBaptiste Daroussin 	if (MMAN_Sm & outflags)
177061d06d6bSBaptiste Daroussin 		outflags |= MMAN_spc;
177161d06d6bSBaptiste Daroussin 
177261d06d6bSBaptiste Daroussin 	return 0;
177361d06d6bSBaptiste Daroussin }
177461d06d6bSBaptiste Daroussin 
177561d06d6bSBaptiste Daroussin static void
pre_sp(DECL_ARGS)177661d06d6bSBaptiste Daroussin pre_sp(DECL_ARGS)
177761d06d6bSBaptiste Daroussin {
177861d06d6bSBaptiste Daroussin 	if (outflags & MMAN_PP) {
177961d06d6bSBaptiste Daroussin 		outflags &= ~MMAN_PP;
178061d06d6bSBaptiste Daroussin 		print_line(".PP", 0);
178161d06d6bSBaptiste Daroussin 	} else {
178261d06d6bSBaptiste Daroussin 		print_line(".sp", 0);
178361d06d6bSBaptiste Daroussin 		if (n->child != NULL)
178461d06d6bSBaptiste Daroussin 			print_word(n->child->string);
178561d06d6bSBaptiste Daroussin 	}
178661d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
178761d06d6bSBaptiste Daroussin }
178861d06d6bSBaptiste Daroussin 
178961d06d6bSBaptiste Daroussin static int
pre_sy(DECL_ARGS)179061d06d6bSBaptiste Daroussin pre_sy(DECL_ARGS)
179161d06d6bSBaptiste Daroussin {
179261d06d6bSBaptiste Daroussin 
179361d06d6bSBaptiste Daroussin 	font_push('B');
179461d06d6bSBaptiste Daroussin 	return 1;
179561d06d6bSBaptiste Daroussin }
179661d06d6bSBaptiste Daroussin 
179761d06d6bSBaptiste Daroussin static void
pre_ta(DECL_ARGS)179861d06d6bSBaptiste Daroussin pre_ta(DECL_ARGS)
179961d06d6bSBaptiste Daroussin {
180061d06d6bSBaptiste Daroussin 	print_line(".ta", 0);
180161d06d6bSBaptiste Daroussin 	for (n = n->child; n != NULL; n = n->next)
180261d06d6bSBaptiste Daroussin 		print_word(n->string);
180361d06d6bSBaptiste Daroussin 	outflags |= MMAN_nl;
180461d06d6bSBaptiste Daroussin }
180561d06d6bSBaptiste Daroussin 
180661d06d6bSBaptiste Daroussin static int
pre_vt(DECL_ARGS)180761d06d6bSBaptiste Daroussin pre_vt(DECL_ARGS)
180861d06d6bSBaptiste Daroussin {
180961d06d6bSBaptiste Daroussin 
181061d06d6bSBaptiste Daroussin 	if (NODE_SYNPRETTY & n->flags) {
181161d06d6bSBaptiste Daroussin 		switch (n->type) {
181261d06d6bSBaptiste Daroussin 		case ROFFT_BLOCK:
181361d06d6bSBaptiste Daroussin 			pre_syn(n);
181461d06d6bSBaptiste Daroussin 			return 1;
181561d06d6bSBaptiste Daroussin 		case ROFFT_BODY:
181661d06d6bSBaptiste Daroussin 			break;
181761d06d6bSBaptiste Daroussin 		default:
181861d06d6bSBaptiste Daroussin 			return 0;
181961d06d6bSBaptiste Daroussin 		}
182061d06d6bSBaptiste Daroussin 	}
182161d06d6bSBaptiste Daroussin 	font_push('I');
182261d06d6bSBaptiste Daroussin 	return 1;
182361d06d6bSBaptiste Daroussin }
182461d06d6bSBaptiste Daroussin 
182561d06d6bSBaptiste Daroussin static void
post_vt(DECL_ARGS)182661d06d6bSBaptiste Daroussin post_vt(DECL_ARGS)
182761d06d6bSBaptiste Daroussin {
182861d06d6bSBaptiste Daroussin 
182961d06d6bSBaptiste Daroussin 	if (n->flags & NODE_SYNPRETTY && n->type != ROFFT_BODY)
183061d06d6bSBaptiste Daroussin 		return;
183161d06d6bSBaptiste Daroussin 	font_pop();
183261d06d6bSBaptiste Daroussin }
183361d06d6bSBaptiste Daroussin 
183461d06d6bSBaptiste Daroussin static int
pre_xr(DECL_ARGS)183561d06d6bSBaptiste Daroussin pre_xr(DECL_ARGS)
183661d06d6bSBaptiste Daroussin {
183761d06d6bSBaptiste Daroussin 
183861d06d6bSBaptiste Daroussin 	n = n->child;
183961d06d6bSBaptiste Daroussin 	if (NULL == n)
184061d06d6bSBaptiste Daroussin 		return 0;
184161d06d6bSBaptiste Daroussin 	print_node(meta, n);
184261d06d6bSBaptiste Daroussin 	n = n->next;
184361d06d6bSBaptiste Daroussin 	if (NULL == n)
184461d06d6bSBaptiste Daroussin 		return 0;
184561d06d6bSBaptiste Daroussin 	outflags &= ~MMAN_spc;
184661d06d6bSBaptiste Daroussin 	print_word("(");
184761d06d6bSBaptiste Daroussin 	print_node(meta, n);
184861d06d6bSBaptiste Daroussin 	print_word(")");
184961d06d6bSBaptiste Daroussin 	return 0;
185061d06d6bSBaptiste Daroussin }
1851