1*723822f6Sschwarze /* $OpenBSD: mdoc_man.c,v 1.137 2025/01/24 22:36:51 schwarze Exp $ */ 275d4d0e5Sschwarze /* 3*723822f6Sschwarze * Copyright (c) 2011-2021, 2025 Ingo Schwarze <schwarze@openbsd.org> 475d4d0e5Sschwarze * 575d4d0e5Sschwarze * Permission to use, copy, modify, and distribute this software for any 675d4d0e5Sschwarze * purpose with or without fee is hereby granted, provided that the above 775d4d0e5Sschwarze * copyright notice and this permission notice appear in all copies. 875d4d0e5Sschwarze * 975d4d0e5Sschwarze * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1075d4d0e5Sschwarze * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1175d4d0e5Sschwarze * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1275d4d0e5Sschwarze * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1375d4d0e5Sschwarze * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1475d4d0e5Sschwarze * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1575d4d0e5Sschwarze * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1675d4d0e5Sschwarze */ 1790d52a15Sschwarze #include <sys/types.h> 1890d52a15Sschwarze 19c8addc6fSschwarze #include <assert.h> 2075d4d0e5Sschwarze #include <stdio.h> 2129478532Sschwarze #include <stdlib.h> 2275d4d0e5Sschwarze #include <string.h> 2375d4d0e5Sschwarze 244f4f7972Sschwarze #include "mandoc_aux.h" 25d1982c71Sschwarze #include "mandoc.h" 26d1982c71Sschwarze #include "roff.h" 2775d4d0e5Sschwarze #include "mdoc.h" 28d1982c71Sschwarze #include "man.h" 29d1982c71Sschwarze #include "out.h" 3075d4d0e5Sschwarze #include "main.h" 3175d4d0e5Sschwarze 322a238f45Sschwarze #define DECL_ARGS const struct roff_meta *meta, struct roff_node *n 3375d4d0e5Sschwarze 34644b390bSschwarze typedef int (*int_fp)(DECL_ARGS); 35644b390bSschwarze typedef void (*void_fp)(DECL_ARGS); 36644b390bSschwarze 3716fe0cfcSschwarze struct mdoc_man_act { 38644b390bSschwarze int_fp cond; /* DON'T run actions */ 39644b390bSschwarze int_fp pre; /* pre-node action */ 40644b390bSschwarze void_fp post; /* post-node action */ 41ca0ce676Sschwarze const char *prefix; /* pre-node string constant */ 42ca0ce676Sschwarze const char *suffix; /* post-node string constant */ 43ca0ce676Sschwarze }; 4475d4d0e5Sschwarze 4575d4d0e5Sschwarze static int cond_body(DECL_ARGS); 46ca0ce676Sschwarze static int cond_head(DECL_ARGS); 47388939aeSschwarze static void font_push(char); 48388939aeSschwarze static void font_pop(void); 499f97fb19Sschwarze static int man_strlen(const char *); 50a14e0b20Sschwarze static void mid_it(void); 51e3ceda8aSschwarze static void post__t(DECL_ARGS); 5227d19a00Sschwarze static void post_aq(DECL_ARGS); 53ca0ce676Sschwarze static void post_bd(DECL_ARGS); 540129f95fSschwarze static void post_bf(DECL_ARGS); 558b4da3beSschwarze static void post_bk(DECL_ARGS); 565eced068Sschwarze static void post_bl(DECL_ARGS); 57ca0ce676Sschwarze static void post_dl(DECL_ARGS); 58551cd4a8Sschwarze static void post_en(DECL_ARGS); 5975d4d0e5Sschwarze static void post_enc(DECL_ARGS); 60c19c703eSschwarze static void post_eo(DECL_ARGS); 61e2ee3b43Sschwarze static void post_fa(DECL_ARGS); 62d97bd30dSschwarze static void post_fd(DECL_ARGS); 63388939aeSschwarze static void post_fl(DECL_ARGS); 640df06370Sschwarze static void post_fn(DECL_ARGS); 65e2ee3b43Sschwarze static void post_fo(DECL_ARGS); 66388939aeSschwarze static void post_font(DECL_ARGS); 670e0aff12Sschwarze static void post_in(DECL_ARGS); 685eced068Sschwarze static void post_it(DECL_ARGS); 69835b952bSschwarze static void post_lb(DECL_ARGS); 70ca0ce676Sschwarze static void post_nm(DECL_ARGS); 7175d4d0e5Sschwarze static void post_percent(DECL_ARGS); 72ca0ce676Sschwarze static void post_pf(DECL_ARGS); 73e6ab379cSschwarze static void post_sect(DECL_ARGS); 74bce51a71Sschwarze static void post_vt(DECL_ARGS); 75e3ceda8aSschwarze static int pre__t(DECL_ARGS); 767c539ecbSschwarze static int pre_abort(DECL_ARGS); 778ba5d246Sschwarze static int pre_an(DECL_ARGS); 78e6ab379cSschwarze static int pre_ap(DECL_ARGS); 7927d19a00Sschwarze static int pre_aq(DECL_ARGS); 80e6ab379cSschwarze static int pre_bd(DECL_ARGS); 810129f95fSschwarze static int pre_bf(DECL_ARGS); 828b4da3beSschwarze static int pre_bk(DECL_ARGS); 835eced068Sschwarze static int pre_bl(DECL_ARGS); 84644b390bSschwarze static void pre_br(DECL_ARGS); 8575d4d0e5Sschwarze static int pre_dl(DECL_ARGS); 86551cd4a8Sschwarze static int pre_en(DECL_ARGS); 87ca0ce676Sschwarze static int pre_enc(DECL_ARGS); 88388939aeSschwarze static int pre_em(DECL_ARGS); 8978bbbab4Sschwarze static int pre_skip(DECL_ARGS); 907d18a139Sschwarze static int pre_eo(DECL_ARGS); 91e214f641Sschwarze static int pre_ex(DECL_ARGS); 92e2ee3b43Sschwarze static int pre_fa(DECL_ARGS); 93d97bd30dSschwarze static int pre_fd(DECL_ARGS); 94388939aeSschwarze static int pre_fl(DECL_ARGS); 950df06370Sschwarze static int pre_fn(DECL_ARGS); 96e2ee3b43Sschwarze static int pre_fo(DECL_ARGS); 97644b390bSschwarze static void pre_ft(DECL_ARGS); 98c4d3fa85Sschwarze static int pre_Ft(DECL_ARGS); 990e0aff12Sschwarze static int pre_in(DECL_ARGS); 10075d4d0e5Sschwarze static int pre_it(DECL_ARGS); 101cfd12f23Sschwarze static int pre_lk(DECL_ARGS); 102388939aeSschwarze static int pre_li(DECL_ARGS); 10375d4d0e5Sschwarze static int pre_nm(DECL_ARGS); 104d4adcee8Sschwarze static int pre_no(DECL_ARGS); 105b7fc66beSschwarze static void pre_noarg(DECL_ARGS); 10675d4d0e5Sschwarze static int pre_ns(DECL_ARGS); 10711d70615Sschwarze static void pre_onearg(DECL_ARGS); 10875d4d0e5Sschwarze static int pre_pp(DECL_ARGS); 109e3ceda8aSschwarze static int pre_rs(DECL_ARGS); 110c8addc6fSschwarze static int pre_sm(DECL_ARGS); 1116561cb23Sschwarze static void pre_sp(DECL_ARGS); 112ca0ce676Sschwarze static int pre_sect(DECL_ARGS); 113388939aeSschwarze static int pre_sy(DECL_ARGS); 1147ebbefbeSschwarze static void pre_syn(struct roff_node *); 115f7242c43Sschwarze static void pre_ta(DECL_ARGS); 116bce51a71Sschwarze static int pre_vt(DECL_ARGS); 11775d4d0e5Sschwarze static int pre_xr(DECL_ARGS); 11851c88ffdSschwarze static void print_word(const char *); 11954cad943Sschwarze static void print_line(const char *, int); 12054cad943Sschwarze static void print_block(const char *, int); 12190d52a15Sschwarze static void print_offs(const char *, int); 12225da2733Sschwarze static void print_width(const struct mdoc_bl *, 1233a0d07afSschwarze const struct roff_node *); 1245eced068Sschwarze static void print_count(int *); 125ca0ce676Sschwarze static void print_node(DECL_ARGS); 12675d4d0e5Sschwarze 12716fe0cfcSschwarze static const void_fp roff_man_acts[ROFF_MAX] = { 1286de096f4Sschwarze pre_br, /* br */ 1296de096f4Sschwarze pre_onearg, /* ce */ 130b7fc66beSschwarze pre_noarg, /* fi */ 1316de096f4Sschwarze pre_ft, /* ft */ 1326de096f4Sschwarze pre_onearg, /* ll */ 1336de096f4Sschwarze pre_onearg, /* mc */ 134b7fc66beSschwarze pre_noarg, /* nf */ 135af1e8f15Sschwarze pre_onearg, /* po */ 1366de096f4Sschwarze pre_onearg, /* rj */ 1376de096f4Sschwarze pre_sp, /* sp */ 1386de096f4Sschwarze pre_ta, /* ta */ 1396de096f4Sschwarze pre_onearg, /* ti */ 140644b390bSschwarze }; 141644b390bSschwarze 14216fe0cfcSschwarze static const struct mdoc_man_act mdoc_man_acts[MDOC_MAX - MDOC_Dd] = { 143e6ab379cSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Dd */ 144e6ab379cSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Dt */ 145a0c8580aSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Os */ 146e6ab379cSschwarze { NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */ 147e6ab379cSschwarze { NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */ 14875d4d0e5Sschwarze { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */ 149e6ab379cSschwarze { cond_body, pre_dl, post_dl, NULL, NULL }, /* D1 */ 15075d4d0e5Sschwarze { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */ 151e6ab379cSschwarze { cond_body, pre_bd, post_bd, NULL, NULL }, /* Bd */ 152e6ab379cSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Ed */ 1535eced068Sschwarze { cond_body, pre_bl, post_bl, NULL, NULL }, /* Bl */ 154e6ab379cSschwarze { NULL, NULL, NULL, NULL, NULL }, /* El */ 1555eced068Sschwarze { NULL, pre_it, post_it, NULL, NULL }, /* It */ 156388939aeSschwarze { NULL, pre_em, post_font, NULL, NULL }, /* Ad */ 1578ba5d246Sschwarze { NULL, pre_an, NULL, NULL, NULL }, /* An */ 15814a309e3Sschwarze { NULL, pre_ap, NULL, NULL, NULL }, /* Ap */ 159388939aeSschwarze { NULL, pre_em, post_font, NULL, NULL }, /* Ar */ 160388939aeSschwarze { NULL, pre_sy, post_font, NULL, NULL }, /* Cd */ 161388939aeSschwarze { NULL, pre_sy, post_font, NULL, NULL }, /* Cm */ 162388939aeSschwarze { NULL, pre_li, post_font, NULL, NULL }, /* Dv */ 163388939aeSschwarze { NULL, pre_li, post_font, NULL, NULL }, /* Er */ 164388939aeSschwarze { NULL, pre_li, post_font, NULL, NULL }, /* Ev */ 165e214f641Sschwarze { NULL, pre_ex, NULL, NULL, NULL }, /* Ex */ 166e2ee3b43Sschwarze { NULL, pre_fa, post_fa, NULL, NULL }, /* Fa */ 167d97bd30dSschwarze { NULL, pre_fd, post_fd, NULL, NULL }, /* Fd */ 168388939aeSschwarze { NULL, pre_fl, post_fl, NULL, NULL }, /* Fl */ 1690df06370Sschwarze { NULL, pre_fn, post_fn, NULL, NULL }, /* Fn */ 170c4d3fa85Sschwarze { NULL, pre_Ft, post_font, NULL, NULL }, /* Ft */ 171388939aeSschwarze { NULL, pre_sy, post_font, NULL, NULL }, /* Ic */ 1720e0aff12Sschwarze { NULL, pre_in, post_in, NULL, NULL }, /* In */ 173388939aeSschwarze { NULL, pre_li, post_font, NULL, NULL }, /* Li */ 17475d4d0e5Sschwarze { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */ 17575d4d0e5Sschwarze { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */ 17675d4d0e5Sschwarze { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */ 1777c539ecbSschwarze { NULL, pre_abort, NULL, NULL, NULL }, /* Ot */ 178388939aeSschwarze { NULL, pre_em, post_font, NULL, NULL }, /* Pa */ 1798ccddcd3Sschwarze { NULL, pre_ex, NULL, NULL, NULL }, /* Rv */ 180a0c8580aSschwarze { NULL, NULL, NULL, NULL, NULL }, /* St */ 181388939aeSschwarze { NULL, pre_em, post_font, NULL, NULL }, /* Va */ 182bce51a71Sschwarze { NULL, pre_vt, post_vt, NULL, NULL }, /* Vt */ 183a0c8580aSschwarze { NULL, pre_xr, NULL, NULL, NULL }, /* Xr */ 184e3ceda8aSschwarze { NULL, NULL, post_percent, NULL, NULL }, /* %A */ 185e3ceda8aSschwarze { NULL, pre_em, post_percent, NULL, NULL }, /* %B */ 186e3ceda8aSschwarze { NULL, NULL, post_percent, NULL, NULL }, /* %D */ 187e3ceda8aSschwarze { NULL, pre_em, post_percent, NULL, NULL }, /* %I */ 188e3ceda8aSschwarze { NULL, pre_em, post_percent, NULL, NULL }, /* %J */ 189e3ceda8aSschwarze { NULL, NULL, post_percent, NULL, NULL }, /* %N */ 190e3ceda8aSschwarze { NULL, NULL, post_percent, NULL, NULL }, /* %O */ 191e3ceda8aSschwarze { NULL, NULL, post_percent, NULL, NULL }, /* %P */ 192e3ceda8aSschwarze { NULL, NULL, post_percent, NULL, NULL }, /* %R */ 193e3ceda8aSschwarze { NULL, pre__t, post__t, NULL, NULL }, /* %T */ 194e3ceda8aSschwarze { NULL, NULL, post_percent, NULL, NULL }, /* %V */ 195f3042e3bSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Ac */ 19627d19a00Sschwarze { cond_body, pre_aq, post_aq, NULL, NULL }, /* Ao */ 19727d19a00Sschwarze { cond_body, pre_aq, post_aq, NULL, NULL }, /* Aq */ 198a0c8580aSschwarze { NULL, NULL, NULL, NULL, NULL }, /* At */ 199e6ab379cSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Bc */ 2000129f95fSschwarze { NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */ 201e6ab379cSschwarze { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */ 202e6ab379cSschwarze { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */ 203f54c3aafSschwarze { NULL, pre_bk, post_bk, NULL, NULL }, /* Bsx */ 204f54c3aafSschwarze { NULL, pre_bk, post_bk, NULL, NULL }, /* Bx */ 20578bbbab4Sschwarze { NULL, pre_skip, NULL, NULL, NULL }, /* Db */ 206f3042e3bSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Dc */ 20777f49befSschwarze { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Do */ 20877f49befSschwarze { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Dq */ 209c19c703eSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Ec */ 210c19c703eSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Ef */ 211388939aeSschwarze { NULL, pre_em, post_font, NULL, NULL }, /* Em */ 2127d18a139Sschwarze { cond_body, pre_eo, post_eo, NULL, NULL }, /* Eo */ 213f54c3aafSschwarze { NULL, pre_bk, post_bk, NULL, NULL }, /* Fx */ 214388939aeSschwarze { NULL, pre_sy, post_font, NULL, NULL }, /* Ms */ 215d4adcee8Sschwarze { NULL, pre_no, NULL, NULL, NULL }, /* No */ 21675d4d0e5Sschwarze { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */ 217f54c3aafSschwarze { NULL, pre_bk, post_bk, NULL, NULL }, /* Nx */ 218f54c3aafSschwarze { NULL, pre_bk, post_bk, NULL, NULL }, /* Ox */ 219e6ab379cSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Pc */ 220e6ab379cSschwarze { NULL, NULL, post_pf, NULL, NULL }, /* Pf */ 221e6ab379cSschwarze { cond_body, pre_enc, post_enc, "(", ")" }, /* Po */ 222e6ab379cSschwarze { cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */ 223f3042e3bSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Qc */ 2243987ac13Sschwarze { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Ql */ 225f3042e3bSschwarze { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */ 226f3042e3bSschwarze { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */ 227f3042e3bSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Re */ 228e3ceda8aSschwarze { cond_body, pre_rs, NULL, NULL, NULL }, /* Rs */ 229f3042e3bSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Sc */ 2303987ac13Sschwarze { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* So */ 2313987ac13Sschwarze { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Sq */ 232c8addc6fSschwarze { NULL, pre_sm, NULL, NULL, NULL }, /* Sm */ 233388939aeSschwarze { NULL, pre_em, post_font, NULL, NULL }, /* Sx */ 234388939aeSschwarze { NULL, pre_sy, post_font, NULL, NULL }, /* Sy */ 235388939aeSschwarze { NULL, pre_li, post_font, NULL, NULL }, /* Tn */ 236816c3c54Sschwarze { NULL, NULL, NULL, NULL, NULL }, /* Ux */ 237e3ceda8aSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Xc */ 238e3ceda8aSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Xo */ 239e2ee3b43Sschwarze { NULL, pre_fo, post_fo, NULL, NULL }, /* Fo */ 240e2ee3b43Sschwarze { NULL, NULL, NULL, NULL, NULL }, /* Fc */ 241e6ab379cSschwarze { cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */ 242f3042e3bSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Oc */ 2438b4da3beSschwarze { NULL, pre_bk, post_bk, NULL, NULL }, /* Bk */ 2448b4da3beSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Ek */ 2458ccddcd3Sschwarze { NULL, NULL, NULL, NULL, NULL }, /* Bt */ 246a0c8580aSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Hf */ 247551cd4a8Sschwarze { NULL, pre_em, post_font, NULL, NULL }, /* Fr */ 2488ccddcd3Sschwarze { NULL, NULL, NULL, NULL, NULL }, /* Ud */ 249835b952bSschwarze { NULL, NULL, post_lb, NULL, NULL }, /* Lb */ 2507c539ecbSschwarze { NULL, pre_abort, NULL, NULL, NULL }, /* Lp */ 251cfd12f23Sschwarze { NULL, pre_lk, NULL, NULL, NULL }, /* Lk */ 252388939aeSschwarze { NULL, pre_em, post_font, NULL, NULL }, /* Mt */ 253f3042e3bSschwarze { cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */ 254f3042e3bSschwarze { cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */ 255f3042e3bSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Brc */ 256e3ceda8aSschwarze { NULL, NULL, post_percent, NULL, NULL }, /* %C */ 25778bbbab4Sschwarze { NULL, pre_skip, NULL, NULL, NULL }, /* Es */ 258551cd4a8Sschwarze { cond_body, pre_en, post_en, NULL, NULL }, /* En */ 259f54c3aafSschwarze { NULL, pre_bk, post_bk, NULL, NULL }, /* Dx */ 260e3ceda8aSschwarze { NULL, NULL, post_percent, NULL, NULL }, /* %Q */ 261e3ceda8aSschwarze { NULL, NULL, post_percent, NULL, NULL }, /* %U */ 262e3ceda8aSschwarze { NULL, NULL, NULL, NULL, NULL }, /* Ta */ 2638b1bef1aSschwarze { NULL, pre_skip, NULL, NULL, NULL }, /* Tg */ 26475d4d0e5Sschwarze }; 26516fe0cfcSschwarze static const struct mdoc_man_act *mdoc_man_act(enum roff_tok); 26675d4d0e5Sschwarze 26751c88ffdSschwarze static int outflags; 26854cad943Sschwarze #define MMAN_spc (1 << 0) /* blank character before next word */ 26954cad943Sschwarze #define MMAN_spc_force (1 << 1) /* even before trailing punctuation */ 27054cad943Sschwarze #define MMAN_nl (1 << 2) /* break man(7) code line */ 27154cad943Sschwarze #define MMAN_br (1 << 3) /* break output line */ 27254cad943Sschwarze #define MMAN_sp (1 << 4) /* insert a blank output line */ 27354cad943Sschwarze #define MMAN_PP (1 << 5) /* reset indentation etc. */ 27454cad943Sschwarze #define MMAN_Sm (1 << 6) /* horizontal spacing mode */ 27554cad943Sschwarze #define MMAN_Bk (1 << 7) /* word keep mode */ 276f54686a1Sschwarze #define MMAN_Bk_susp (1 << 8) /* suspend this (after a macro) */ 277f54686a1Sschwarze #define MMAN_An_split (1 << 9) /* author mode is "split" */ 278f54686a1Sschwarze #define MMAN_An_nosplit (1 << 10) /* author mode is "nosplit" */ 279f54686a1Sschwarze #define MMAN_PD (1 << 11) /* inter-paragraph spacing disabled */ 2801192b926Sschwarze #define MMAN_nbrword (1 << 12) /* do not break the next word */ 28151c88ffdSschwarze 2825ee03fc6Sschwarze #define BL_STACK_MAX 32 2835ee03fc6Sschwarze 28425da2733Sschwarze static int Bl_stack[BL_STACK_MAX]; /* offsets [chars] */ 2855ee03fc6Sschwarze static int Bl_stack_post[BL_STACK_MAX]; /* add final .RE */ 2865ee03fc6Sschwarze static int Bl_stack_len; /* number of nested Bl blocks */ 28780a412c7Sschwarze static int TPremain; /* characters before tag is full */ 28880a412c7Sschwarze 289388939aeSschwarze static struct { 290388939aeSschwarze char *head; 291388939aeSschwarze char *tail; 292388939aeSschwarze size_t size; 293388939aeSschwarze } fontqueue; 294388939aeSschwarze 29549aff9f8Sschwarze 29616fe0cfcSschwarze static const struct mdoc_man_act * 29716fe0cfcSschwarze mdoc_man_act(enum roff_tok tok) 29816fe0cfcSschwarze { 29916fe0cfcSschwarze assert(tok >= MDOC_Dd && tok <= MDOC_MAX); 30016fe0cfcSschwarze return mdoc_man_acts + (tok - MDOC_Dd); 30116fe0cfcSschwarze } 30216fe0cfcSschwarze 3039f97fb19Sschwarze static int 3049f97fb19Sschwarze man_strlen(const char *cp) 3059f97fb19Sschwarze { 3069f97fb19Sschwarze size_t rsz; 3079f97fb19Sschwarze int skip, sz; 3089f97fb19Sschwarze 3099f97fb19Sschwarze sz = 0; 3109f97fb19Sschwarze skip = 0; 3119f97fb19Sschwarze for (;;) { 3129f97fb19Sschwarze rsz = strcspn(cp, "\\"); 3139f97fb19Sschwarze if (rsz) { 3149f97fb19Sschwarze cp += rsz; 3159f97fb19Sschwarze if (skip) { 3169f97fb19Sschwarze skip = 0; 3179f97fb19Sschwarze rsz--; 3189f97fb19Sschwarze } 3199f97fb19Sschwarze sz += rsz; 3209f97fb19Sschwarze } 3219f97fb19Sschwarze if ('\0' == *cp) 3229f97fb19Sschwarze break; 3239f97fb19Sschwarze cp++; 3249f97fb19Sschwarze switch (mandoc_escape(&cp, NULL, NULL)) { 3259f97fb19Sschwarze case ESCAPE_ERROR: 3269f97fb19Sschwarze return sz; 3279f97fb19Sschwarze case ESCAPE_UNICODE: 3289f97fb19Sschwarze case ESCAPE_NUMBERED: 3299f97fb19Sschwarze case ESCAPE_SPECIAL: 3306f6722cbSschwarze case ESCAPE_UNDEF: 3319f97fb19Sschwarze case ESCAPE_OVERSTRIKE: 3329f97fb19Sschwarze if (skip) 3339f97fb19Sschwarze skip = 0; 3349f97fb19Sschwarze else 3359f97fb19Sschwarze sz++; 3369f97fb19Sschwarze break; 3379f97fb19Sschwarze case ESCAPE_SKIPCHAR: 3389f97fb19Sschwarze skip = 1; 3399f97fb19Sschwarze break; 3409f97fb19Sschwarze default: 3419f97fb19Sschwarze break; 3429f97fb19Sschwarze } 3439f97fb19Sschwarze } 3449f97fb19Sschwarze return sz; 3459f97fb19Sschwarze } 3469f97fb19Sschwarze 347388939aeSschwarze static void 348388939aeSschwarze font_push(char newfont) 349388939aeSschwarze { 350388939aeSschwarze 351388939aeSschwarze if (fontqueue.head + fontqueue.size <= ++fontqueue.tail) { 352388939aeSschwarze fontqueue.size += 8; 353388939aeSschwarze fontqueue.head = mandoc_realloc(fontqueue.head, 354388939aeSschwarze fontqueue.size); 355388939aeSschwarze } 356388939aeSschwarze *fontqueue.tail = newfont; 35780a412c7Sschwarze print_word(""); 35880a412c7Sschwarze printf("\\f"); 359388939aeSschwarze putchar(newfont); 360388939aeSschwarze outflags &= ~MMAN_spc; 361388939aeSschwarze } 362388939aeSschwarze 363388939aeSschwarze static void 364388939aeSschwarze font_pop(void) 365388939aeSschwarze { 366388939aeSschwarze 367388939aeSschwarze if (fontqueue.tail > fontqueue.head) 368388939aeSschwarze fontqueue.tail--; 369388939aeSschwarze outflags &= ~MMAN_spc; 37080a412c7Sschwarze print_word(""); 37180a412c7Sschwarze printf("\\f"); 372388939aeSschwarze putchar(*fontqueue.tail); 373388939aeSschwarze } 374388939aeSschwarze 37575d4d0e5Sschwarze static void 37651c88ffdSschwarze print_word(const char *s) 37775d4d0e5Sschwarze { 378ca0ce676Sschwarze 37954cad943Sschwarze if ((MMAN_PP | MMAN_sp | MMAN_br | MMAN_nl) & outflags) { 380ca0ce676Sschwarze /* 381ca0ce676Sschwarze * If we need a newline, print it now and start afresh. 382ca0ce676Sschwarze */ 38354cad943Sschwarze if (MMAN_PP & outflags) { 3849c576c3dSschwarze if (MMAN_sp & outflags) { 3859c576c3dSschwarze if (MMAN_PD & outflags) { 3869c576c3dSschwarze printf("\n.PD"); 3879c576c3dSschwarze outflags &= ~MMAN_PD; 3889c576c3dSschwarze } 3899c576c3dSschwarze } else if ( ! (MMAN_PD & outflags)) { 3909c576c3dSschwarze printf("\n.PD 0"); 3919c576c3dSschwarze outflags |= MMAN_PD; 3929c576c3dSschwarze } 39354cad943Sschwarze printf("\n.PP\n"); 39454cad943Sschwarze } else if (MMAN_sp & outflags) 39528ee9174Sschwarze printf("\n.sp\n"); 39628ee9174Sschwarze else if (MMAN_br & outflags) 39728ee9174Sschwarze printf("\n.br\n"); 39828ee9174Sschwarze else if (MMAN_nl & outflags) 39975d4d0e5Sschwarze putchar('\n'); 40054cad943Sschwarze outflags &= ~(MMAN_PP|MMAN_sp|MMAN_br|MMAN_nl|MMAN_spc); 40180a412c7Sschwarze if (1 == TPremain) 40280a412c7Sschwarze printf(".br\n"); 40380a412c7Sschwarze TPremain = 0; 40480a412c7Sschwarze } else if (MMAN_spc & outflags) { 405ca0ce676Sschwarze /* 406d4adcee8Sschwarze * If we need a space, only print it if 407d4adcee8Sschwarze * (1) it is forced by `No' or 408d4adcee8Sschwarze * (2) what follows is not terminating punctuation or 409d4adcee8Sschwarze * (3) what follows is longer than one character. 410ca0ce676Sschwarze */ 41180a412c7Sschwarze if (MMAN_spc_force & outflags || '\0' == s[0] || 412d4adcee8Sschwarze NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) { 413f54686a1Sschwarze if (MMAN_Bk & outflags && 414f54686a1Sschwarze ! (MMAN_Bk_susp & outflags)) 4158b4da3beSschwarze putchar('\\'); 41675d4d0e5Sschwarze putchar(' '); 41780a412c7Sschwarze if (TPremain) 41880a412c7Sschwarze TPremain--; 41980a412c7Sschwarze } 4208b4da3beSschwarze } 421ca0ce676Sschwarze 422ca0ce676Sschwarze /* 423ca0ce676Sschwarze * Reassign needing space if we're not following opening 424ca0ce676Sschwarze * punctuation. 425ca0ce676Sschwarze */ 42680a412c7Sschwarze if (MMAN_Sm & outflags && ('\0' == s[0] || 42780a412c7Sschwarze (('(' != s[0] && '[' != s[0]) || '\0' != s[1]))) 42851c88ffdSschwarze outflags |= MMAN_spc; 42951c88ffdSschwarze else 43051c88ffdSschwarze outflags &= ~MMAN_spc; 431f54686a1Sschwarze outflags &= ~(MMAN_spc_force | MMAN_Bk_susp); 432ca0ce676Sschwarze 43375d4d0e5Sschwarze for ( ; *s; s++) { 43475d4d0e5Sschwarze switch (*s) { 43549aff9f8Sschwarze case ASCII_NBRSP: 4360fc7a91fSmillert printf("\\ "); 43775d4d0e5Sschwarze break; 43849aff9f8Sschwarze case ASCII_HYPH: 43975d4d0e5Sschwarze putchar('-'); 44075d4d0e5Sschwarze break; 44149aff9f8Sschwarze case ASCII_BREAK: 4421281a50cSschwarze printf("\\:"); 4431281a50cSschwarze break; 44449aff9f8Sschwarze case ' ': 4451192b926Sschwarze if (MMAN_nbrword & outflags) { 4461192b926Sschwarze printf("\\ "); 4471192b926Sschwarze break; 4481192b926Sschwarze } 4491192b926Sschwarze /* FALLTHROUGH */ 45075d4d0e5Sschwarze default: 451ca0ce676Sschwarze putchar((unsigned char)*s); 45275d4d0e5Sschwarze break; 45375d4d0e5Sschwarze } 45480a412c7Sschwarze if (TPremain) 45580a412c7Sschwarze TPremain--; 45675d4d0e5Sschwarze } 4571192b926Sschwarze outflags &= ~MMAN_nbrword; 45875d4d0e5Sschwarze } 45975d4d0e5Sschwarze 46087accd8cSschwarze static void 46154cad943Sschwarze print_line(const char *s, int newflags) 46254cad943Sschwarze { 46354cad943Sschwarze 46454cad943Sschwarze outflags |= MMAN_nl; 46554cad943Sschwarze print_word(s); 46654cad943Sschwarze outflags |= newflags; 46754cad943Sschwarze } 46854cad943Sschwarze 46954cad943Sschwarze static void 47054cad943Sschwarze print_block(const char *s, int newflags) 47154cad943Sschwarze { 47254cad943Sschwarze 47354cad943Sschwarze outflags &= ~MMAN_PP; 4749c576c3dSschwarze if (MMAN_sp & outflags) { 47554cad943Sschwarze outflags &= ~(MMAN_sp | MMAN_br); 4769c576c3dSschwarze if (MMAN_PD & outflags) { 4779c576c3dSschwarze print_line(".PD", 0); 4789c576c3dSschwarze outflags &= ~MMAN_PD; 4799c576c3dSschwarze } 480f54686a1Sschwarze } else if (! (MMAN_PD & outflags)) 481f54686a1Sschwarze print_line(".PD 0", MMAN_PD); 48254cad943Sschwarze outflags |= MMAN_nl; 48354cad943Sschwarze print_word(s); 484f54686a1Sschwarze outflags |= MMAN_Bk_susp | newflags; 48554cad943Sschwarze } 48654cad943Sschwarze 48754cad943Sschwarze static void 48890d52a15Sschwarze print_offs(const char *v, int keywords) 48987accd8cSschwarze { 49087accd8cSschwarze char buf[24]; 49187accd8cSschwarze struct roffsu su; 492ecd22486Sschwarze const char *end; 49325da2733Sschwarze int sz; 49487accd8cSschwarze 495f7135bb7Sschwarze print_line(".RS", MMAN_Bk_susp); 496f7135bb7Sschwarze 4975ee03fc6Sschwarze /* Convert v into a number (of characters). */ 49890d52a15Sschwarze if (NULL == v || '\0' == *v || (keywords && !strcmp(v, "left"))) 49987accd8cSschwarze sz = 0; 50090d52a15Sschwarze else if (keywords && !strcmp(v, "indent")) 50187accd8cSschwarze sz = 6; 50290d52a15Sschwarze else if (keywords && !strcmp(v, "indent-two")) 50387accd8cSschwarze sz = 12; 504ecd22486Sschwarze else { 505ecd22486Sschwarze end = a2roffsu(v, &su, SCALE_EN); 506ecd22486Sschwarze if (end == NULL || *end != '\0') 507ecd22486Sschwarze sz = man_strlen(v); 508ecd22486Sschwarze else if (SCALE_EN == su.unit) 5095ee03fc6Sschwarze sz = su.scale; 5105ee03fc6Sschwarze else { 5115ee03fc6Sschwarze /* 5125ee03fc6Sschwarze * XXX 5135ee03fc6Sschwarze * If we are inside an enclosing list, 5145ee03fc6Sschwarze * there is no easy way to add the two 5155ee03fc6Sschwarze * indentations because they are provided 5165ee03fc6Sschwarze * in terms of different units. 5175ee03fc6Sschwarze */ 51851c88ffdSschwarze print_word(v); 519f7135bb7Sschwarze outflags |= MMAN_nl; 52087accd8cSschwarze return; 5215ee03fc6Sschwarze } 522ecd22486Sschwarze } 52387accd8cSschwarze 5245ee03fc6Sschwarze /* 5255ee03fc6Sschwarze * We are inside an enclosing list. 5265ee03fc6Sschwarze * Add the two indentations. 5275ee03fc6Sschwarze */ 5285ee03fc6Sschwarze if (Bl_stack_len) 5295ee03fc6Sschwarze sz += Bl_stack[Bl_stack_len - 1]; 5305ee03fc6Sschwarze 53125da2733Sschwarze (void)snprintf(buf, sizeof(buf), "%dn", sz); 53251c88ffdSschwarze print_word(buf); 533f7135bb7Sschwarze outflags |= MMAN_nl; 53487accd8cSschwarze } 53587accd8cSschwarze 536a14e0b20Sschwarze /* 537a14e0b20Sschwarze * Set up the indentation for a list item; used from pre_it(). 538a14e0b20Sschwarze */ 5394f4f7972Sschwarze static void 5403a0d07afSschwarze print_width(const struct mdoc_bl *bl, const struct roff_node *child) 5415eced068Sschwarze { 5425eced068Sschwarze char buf[24]; 5435eced068Sschwarze struct roffsu su; 544ecd22486Sschwarze const char *end; 54525da2733Sschwarze int numeric, remain, sz, chsz; 54608765786Sschwarze 54780a412c7Sschwarze numeric = 1; 54880a412c7Sschwarze remain = 0; 5495ee03fc6Sschwarze 55025da2733Sschwarze /* Convert the width into a number (of characters). */ 55125da2733Sschwarze if (bl->width == NULL) 55225da2733Sschwarze sz = (bl->type == LIST_hang) ? 6 : 0; 553ecd22486Sschwarze else { 554ecd22486Sschwarze end = a2roffsu(bl->width, &su, SCALE_MAX); 555ecd22486Sschwarze if (end == NULL || *end != '\0') 556ecd22486Sschwarze sz = man_strlen(bl->width); 557ecd22486Sschwarze else if (SCALE_EN == su.unit) 5585eced068Sschwarze sz = su.scale; 5595eced068Sschwarze else { 56080a412c7Sschwarze sz = 0; 56180a412c7Sschwarze numeric = 0; 5625eced068Sschwarze } 563ecd22486Sschwarze } 5645eced068Sschwarze 56580a412c7Sschwarze /* XXX Rough estimation, might have multiple parts. */ 56625da2733Sschwarze if (bl->type == LIST_enum) 56725da2733Sschwarze chsz = (bl->count > 8) + 1; 568d1982c71Sschwarze else if (child != NULL && child->type == ROFFT_TEXT) 5699f97fb19Sschwarze chsz = man_strlen(child->string); 57025da2733Sschwarze else 57125da2733Sschwarze chsz = 0; 57280a412c7Sschwarze 573a14e0b20Sschwarze /* Maybe we are inside an enclosing list? */ 574a14e0b20Sschwarze mid_it(); 5755ee03fc6Sschwarze 5765ee03fc6Sschwarze /* 5775ee03fc6Sschwarze * Save our own indentation, 5785ee03fc6Sschwarze * such that child lists can use it. 5795ee03fc6Sschwarze */ 5805ee03fc6Sschwarze Bl_stack[Bl_stack_len++] = sz + 2; 5815ee03fc6Sschwarze 5825ee03fc6Sschwarze /* Set up the current list. */ 58325da2733Sschwarze if (chsz > sz && bl->type != LIST_tag) 58428ac7daaSschwarze print_block(".HP", MMAN_spc); 58580a412c7Sschwarze else { 58628ac7daaSschwarze print_block(".TP", MMAN_spc); 58780a412c7Sschwarze remain = sz + 2; 58880a412c7Sschwarze } 58980a412c7Sschwarze if (numeric) { 59025da2733Sschwarze (void)snprintf(buf, sizeof(buf), "%dn", sz + 2); 5915eced068Sschwarze print_word(buf); 59280a412c7Sschwarze } else 59325da2733Sschwarze print_word(bl->width); 59480a412c7Sschwarze TPremain = remain; 5955eced068Sschwarze } 5965eced068Sschwarze 5974f4f7972Sschwarze static void 5985eced068Sschwarze print_count(int *count) 5995eced068Sschwarze { 60047813146Sschwarze char buf[24]; 6015eced068Sschwarze 60225da2733Sschwarze (void)snprintf(buf, sizeof(buf), "%d.\\&", ++*count); 6035eced068Sschwarze print_word(buf); 6045eced068Sschwarze } 6055eced068Sschwarze 6065eced068Sschwarze void 6076b86842eSschwarze man_mdoc(void *arg, const struct roff_meta *mdoc) 60875d4d0e5Sschwarze { 6093a0d07afSschwarze struct roff_node *n; 61075d4d0e5Sschwarze 6114c293873Sschwarze printf(".\\\" Automatically generated from an mdoc input file." 6124c293873Sschwarze " Do not edit.\n"); 6134c293873Sschwarze for (n = mdoc->first->child; n != NULL; n = n->next) { 6144c293873Sschwarze if (n->type != ROFFT_COMMENT) 6154c293873Sschwarze break; 6164c293873Sschwarze printf(".\\\"%s\n", n->string); 6174c293873Sschwarze } 6184c293873Sschwarze 619ac65dd21Smillert printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", 6206b86842eSschwarze mdoc->title, (mdoc->msec == NULL ? "" : mdoc->msec), 6216b86842eSschwarze mdoc->date, mdoc->os, mdoc->vol); 62275d4d0e5Sschwarze 623ac65dd21Smillert /* Disable hyphenation and if nroff, disable justification. */ 624ac65dd21Smillert printf(".nh\n.if n .ad l"); 625ac65dd21Smillert 62651c88ffdSschwarze outflags = MMAN_nl | MMAN_Sm; 627388939aeSschwarze if (0 == fontqueue.size) { 628388939aeSschwarze fontqueue.size = 8; 629388939aeSschwarze fontqueue.head = fontqueue.tail = mandoc_malloc(8); 630388939aeSschwarze *fontqueue.tail = 'R'; 631388939aeSschwarze } 6324c293873Sschwarze for (; n != NULL; n = n->next) 6336b86842eSschwarze print_node(mdoc, n); 634e6ab379cSschwarze putchar('\n'); 63575d4d0e5Sschwarze } 63675d4d0e5Sschwarze 63775d4d0e5Sschwarze static void 63875d4d0e5Sschwarze print_node(DECL_ARGS) 63975d4d0e5Sschwarze { 64016fe0cfcSschwarze const struct mdoc_man_act *act; 6413a0d07afSschwarze struct roff_node *sub; 64275d4d0e5Sschwarze int cond, do_sub; 64375d4d0e5Sschwarze 64443808411Sschwarze if (n->flags & NODE_NOPRT) 64543808411Sschwarze return; 64643808411Sschwarze 647ca0ce676Sschwarze /* 648ca0ce676Sschwarze * Break the line if we were parsed subsequent the current node. 649ca0ce676Sschwarze * This makes the page structure be more consistent. 650ca0ce676Sschwarze */ 6517ebbefbeSschwarze if (outflags & MMAN_spc && 6527ebbefbeSschwarze n->flags & NODE_LINE && 6537ebbefbeSschwarze !roff_node_transparent(n)) 65451c88ffdSschwarze outflags |= MMAN_nl; 65575d4d0e5Sschwarze 656ca0ce676Sschwarze act = NULL; 65775d4d0e5Sschwarze cond = 0; 65875d4d0e5Sschwarze do_sub = 1; 659c4b0939cSschwarze n->flags &= ~NODE_ENDED; 660ca0ce676Sschwarze 661c96b4f2bSschwarze switch (n->type) { 662c96b4f2bSschwarze case ROFFT_EQN: 663c96b4f2bSschwarze case ROFFT_TBL: 664c96b4f2bSschwarze mandoc_msg(n->type == ROFFT_EQN ? MANDOCERR_EQN_TMAN : 665c96b4f2bSschwarze MANDOCERR_TBL_TMAN, n->line, n->pos, NULL); 666c96b4f2bSschwarze outflags |= MMAN_PP | MMAN_sp | MMAN_nl; 667c96b4f2bSschwarze print_word("The"); 668c96b4f2bSschwarze print_line(".B \\-T man", MMAN_nl); 669c96b4f2bSschwarze print_word("output mode does not support"); 670c96b4f2bSschwarze print_word(n->type == ROFFT_EQN ? "eqn(7)" : "tbl(7)"); 671c96b4f2bSschwarze print_word("input."); 672c96b4f2bSschwarze outflags |= MMAN_PP | MMAN_sp | MMAN_nl; 673c96b4f2bSschwarze return; 674c96b4f2bSschwarze case ROFFT_TEXT: 675ca0ce676Sschwarze /* 676ca0ce676Sschwarze * Make sure that we don't happen to start with a 677ca0ce676Sschwarze * control character at the start of a line. 678ca0ce676Sschwarze */ 67949aff9f8Sschwarze if (MMAN_nl & outflags && 68049aff9f8Sschwarze ('.' == *n->string || '\'' == *n->string)) { 68180a412c7Sschwarze print_word(""); 68280a412c7Sschwarze printf("\\&"); 68351c88ffdSschwarze outflags &= ~MMAN_spc; 684e6ab379cSschwarze } 6858ccddcd3Sschwarze if (n->flags & NODE_DELIMC) 6868ccddcd3Sschwarze outflags &= ~(MMAN_spc | MMAN_spc_force); 6878ccddcd3Sschwarze else if (outflags & MMAN_Sm) 6886f9818f6Sschwarze outflags |= MMAN_spc_force; 68951c88ffdSschwarze print_word(n->string); 6908ccddcd3Sschwarze if (n->flags & NODE_DELIMO) 6918ccddcd3Sschwarze outflags &= ~(MMAN_spc | MMAN_spc_force); 6928ccddcd3Sschwarze else if (outflags & MMAN_Sm) 6936f9818f6Sschwarze outflags |= MMAN_spc; 694c96b4f2bSschwarze break; 695c96b4f2bSschwarze default: 696c96b4f2bSschwarze if (n->tok < ROFF_MAX) { 69716fe0cfcSschwarze (*roff_man_acts[n->tok])(meta, n); 698644b390bSschwarze return; 699c96b4f2bSschwarze } 70016fe0cfcSschwarze act = mdoc_man_act(n->tok); 7017d18a139Sschwarze cond = act->cond == NULL || (*act->cond)(meta, n); 70230e5ee06Sschwarze if (cond && act->pre != NULL && 70330e5ee06Sschwarze (n->end == ENDBODY_NOT || n->child != NULL)) 7047ead8a4eSschwarze do_sub = (*act->pre)(meta, n); 705c96b4f2bSschwarze break; 70675d4d0e5Sschwarze } 70775d4d0e5Sschwarze 708ca0ce676Sschwarze /* 709ca0ce676Sschwarze * Conditionally run all child nodes. 710ca0ce676Sschwarze * Note that this iterates over children instead of using 711ca0ce676Sschwarze * recursion. This prevents unnecessary depth in the stack. 712ca0ce676Sschwarze */ 71375d4d0e5Sschwarze if (do_sub) 71475d4d0e5Sschwarze for (sub = n->child; sub; sub = sub->next) 7157ead8a4eSschwarze print_node(meta, sub); 71675d4d0e5Sschwarze 717ca0ce676Sschwarze /* 718ca0ce676Sschwarze * Lastly, conditionally run the post-node handler. 719ca0ce676Sschwarze */ 720c4b0939cSschwarze if (NODE_ENDED & n->flags) 721e63c2667Sschwarze return; 722e63c2667Sschwarze 72375d4d0e5Sschwarze if (cond && act->post) 7247ead8a4eSschwarze (*act->post)(meta, n); 725e63c2667Sschwarze 726e63c2667Sschwarze if (ENDBODY_NOT != n->end) 727c4b0939cSschwarze n->body->flags |= NODE_ENDED; 72875d4d0e5Sschwarze } 72975d4d0e5Sschwarze 73075d4d0e5Sschwarze static int 73175d4d0e5Sschwarze cond_head(DECL_ARGS) 73275d4d0e5Sschwarze { 733ca0ce676Sschwarze 734526e306bSschwarze return n->type == ROFFT_HEAD; 73575d4d0e5Sschwarze } 73675d4d0e5Sschwarze 73775d4d0e5Sschwarze static int 73875d4d0e5Sschwarze cond_body(DECL_ARGS) 73975d4d0e5Sschwarze { 740ca0ce676Sschwarze 741526e306bSschwarze return n->type == ROFFT_BODY; 74275d4d0e5Sschwarze } 74375d4d0e5Sschwarze 74475d4d0e5Sschwarze static int 7457c539ecbSschwarze pre_abort(DECL_ARGS) 7467c539ecbSschwarze { 7477c539ecbSschwarze abort(); 7487c539ecbSschwarze } 7497c539ecbSschwarze 7507c539ecbSschwarze static int 75175d4d0e5Sschwarze pre_enc(DECL_ARGS) 75275d4d0e5Sschwarze { 75375d4d0e5Sschwarze const char *prefix; 75475d4d0e5Sschwarze 75516fe0cfcSschwarze prefix = mdoc_man_act(n->tok)->prefix; 75675d4d0e5Sschwarze if (NULL == prefix) 757526e306bSschwarze return 1; 75851c88ffdSschwarze print_word(prefix); 75951c88ffdSschwarze outflags &= ~MMAN_spc; 760526e306bSschwarze return 1; 76175d4d0e5Sschwarze } 76275d4d0e5Sschwarze 76375d4d0e5Sschwarze static void 76475d4d0e5Sschwarze post_enc(DECL_ARGS) 76575d4d0e5Sschwarze { 76675d4d0e5Sschwarze const char *suffix; 76775d4d0e5Sschwarze 76816fe0cfcSschwarze suffix = mdoc_man_act(n->tok)->suffix; 76975d4d0e5Sschwarze if (NULL == suffix) 77075d4d0e5Sschwarze return; 771e63c2667Sschwarze outflags &= ~(MMAN_spc | MMAN_nl); 77251c88ffdSschwarze print_word(suffix); 773388939aeSschwarze } 774388939aeSschwarze 775e214f641Sschwarze static int 776e214f641Sschwarze pre_ex(DECL_ARGS) 777e214f641Sschwarze { 778e214f641Sschwarze outflags |= MMAN_br | MMAN_nl; 7798ccddcd3Sschwarze return 1; 780e214f641Sschwarze } 781e214f641Sschwarze 782388939aeSschwarze static void 783388939aeSschwarze post_font(DECL_ARGS) 784388939aeSschwarze { 785388939aeSschwarze 786388939aeSschwarze font_pop(); 78775d4d0e5Sschwarze } 78875d4d0e5Sschwarze 78975d4d0e5Sschwarze static void 79075d4d0e5Sschwarze post_percent(DECL_ARGS) 79175d4d0e5Sschwarze { 7927ebbefbeSschwarze struct roff_node *np, *nn, *nnn; 79375d4d0e5Sschwarze 79416fe0cfcSschwarze if (mdoc_man_act(n->tok)->pre == pre_em) 795e3ceda8aSschwarze font_pop(); 7967ebbefbeSschwarze 797*723822f6Sschwarze if (n->parent == NULL || n->parent->tok != MDOC_Rs) 798*723822f6Sschwarze return; 799*723822f6Sschwarze 8007ebbefbeSschwarze if ((nn = roff_node_next(n)) != NULL) { 8017ebbefbeSschwarze np = roff_node_prev(n); 8027ebbefbeSschwarze nnn = nn == NULL ? NULL : roff_node_next(nn); 8037ebbefbeSschwarze if (nn->tok != n->tok || 8047ebbefbeSschwarze (np != NULL && np->tok == n->tok) || 8057ebbefbeSschwarze (nnn != NULL && nnn->tok == n->tok)) 80651c88ffdSschwarze print_word(","); 8077ebbefbeSschwarze if (nn->tok == n->tok && 8087ebbefbeSschwarze (nnn == NULL || nnn->tok != n->tok)) 809e3ceda8aSschwarze print_word("and"); 810e3ceda8aSschwarze } else { 81151c88ffdSschwarze print_word("."); 81251c88ffdSschwarze outflags |= MMAN_nl; 81375d4d0e5Sschwarze } 81475d4d0e5Sschwarze } 81575d4d0e5Sschwarze 816e3ceda8aSschwarze static int 817e3ceda8aSschwarze pre__t(DECL_ARGS) 818e3ceda8aSschwarze { 819e3ceda8aSschwarze 8206b7d675aSschwarze if (n->parent->tok == MDOC_Rs && n->parent->norm->Rs.quote_T) { 8211aeba4ffSschwarze print_word("\\(lq"); 822e3ceda8aSschwarze outflags &= ~MMAN_spc; 823e3ceda8aSschwarze } else 824e3ceda8aSschwarze font_push('I'); 825526e306bSschwarze return 1; 826e3ceda8aSschwarze } 827e3ceda8aSschwarze 828e3ceda8aSschwarze static void 829e3ceda8aSschwarze post__t(DECL_ARGS) 830e3ceda8aSschwarze { 831e3ceda8aSschwarze 8326b7d675aSschwarze if (n->parent->tok == MDOC_Rs && n->parent->norm->Rs.quote_T) { 833e3ceda8aSschwarze outflags &= ~MMAN_spc; 8341aeba4ffSschwarze print_word("\\(rq"); 835e3ceda8aSschwarze } else 836e3ceda8aSschwarze font_pop(); 8377ead8a4eSschwarze post_percent(meta, n); 838e3ceda8aSschwarze } 839e3ceda8aSschwarze 840ca0ce676Sschwarze /* 841ca0ce676Sschwarze * Print before a section header. 842ca0ce676Sschwarze */ 84375d4d0e5Sschwarze static int 844e6ab379cSschwarze pre_sect(DECL_ARGS) 845e6ab379cSschwarze { 846e6ab379cSschwarze 847d1982c71Sschwarze if (n->type == ROFFT_HEAD) { 84854cad943Sschwarze outflags |= MMAN_sp; 84916fe0cfcSschwarze print_block(mdoc_man_act(n->tok)->prefix, 0); 85080a412c7Sschwarze print_word(""); 85180a412c7Sschwarze putchar('\"'); 85251c88ffdSschwarze outflags &= ~MMAN_spc; 853f54686a1Sschwarze } 854526e306bSschwarze return 1; 855e6ab379cSschwarze } 856e6ab379cSschwarze 857ca0ce676Sschwarze /* 858ca0ce676Sschwarze * Print subsequent a section header. 859ca0ce676Sschwarze */ 860e6ab379cSschwarze static void 861e6ab379cSschwarze post_sect(DECL_ARGS) 862e6ab379cSschwarze { 863e6ab379cSschwarze 864d1982c71Sschwarze if (n->type != ROFFT_HEAD) 865e6ab379cSschwarze return; 86651c88ffdSschwarze outflags &= ~MMAN_spc; 86780a412c7Sschwarze print_word(""); 86880a412c7Sschwarze putchar('\"'); 86951c88ffdSschwarze outflags |= MMAN_nl; 8708ba5d246Sschwarze if (MDOC_Sh == n->tok && SEC_AUTHORS == n->sec) 8718ba5d246Sschwarze outflags &= ~(MMAN_An_split | MMAN_An_nosplit); 8728ba5d246Sschwarze } 8738ba5d246Sschwarze 874fb6b7277Sschwarze /* See mdoc_term.c, synopsis_pre() for comments. */ 875fb6b7277Sschwarze static void 8767ebbefbeSschwarze pre_syn(struct roff_node *n) 877fb6b7277Sschwarze { 8787ebbefbeSschwarze struct roff_node *np; 879fb6b7277Sschwarze 8807ebbefbeSschwarze if ((n->flags & NODE_SYNPRETTY) == 0 || 8817ebbefbeSschwarze (np = roff_node_prev(n)) == NULL) 882fb6b7277Sschwarze return; 883fb6b7277Sschwarze 8847ebbefbeSschwarze if (np->tok == n->tok && 885fb6b7277Sschwarze MDOC_Ft != n->tok && 886fb6b7277Sschwarze MDOC_Fo != n->tok && 887fb6b7277Sschwarze MDOC_Fn != n->tok) { 888fb6b7277Sschwarze outflags |= MMAN_br; 889fb6b7277Sschwarze return; 890fb6b7277Sschwarze } 891fb6b7277Sschwarze 8927ebbefbeSschwarze switch (np->tok) { 89349aff9f8Sschwarze case MDOC_Fd: 89449aff9f8Sschwarze case MDOC_Fn: 89549aff9f8Sschwarze case MDOC_Fo: 89649aff9f8Sschwarze case MDOC_In: 89749aff9f8Sschwarze case MDOC_Vt: 898fb6b7277Sschwarze outflags |= MMAN_sp; 899fb6b7277Sschwarze break; 90049aff9f8Sschwarze case MDOC_Ft: 901fb6b7277Sschwarze if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) { 902fb6b7277Sschwarze outflags |= MMAN_sp; 903fb6b7277Sschwarze break; 904fb6b7277Sschwarze } 905fb6b7277Sschwarze /* FALLTHROUGH */ 906fb6b7277Sschwarze default: 907fb6b7277Sschwarze outflags |= MMAN_br; 908fb6b7277Sschwarze break; 909fb6b7277Sschwarze } 910fb6b7277Sschwarze } 911fb6b7277Sschwarze 9128ba5d246Sschwarze static int 9138ba5d246Sschwarze pre_an(DECL_ARGS) 9148ba5d246Sschwarze { 9158ba5d246Sschwarze 9168ba5d246Sschwarze switch (n->norm->An.auth) { 91749aff9f8Sschwarze case AUTH_split: 9188ba5d246Sschwarze outflags &= ~MMAN_An_nosplit; 9198ba5d246Sschwarze outflags |= MMAN_An_split; 920526e306bSschwarze return 0; 92149aff9f8Sschwarze case AUTH_nosplit: 9228ba5d246Sschwarze outflags &= ~MMAN_An_split; 9238ba5d246Sschwarze outflags |= MMAN_An_nosplit; 924526e306bSschwarze return 0; 9258ba5d246Sschwarze default: 9268ba5d246Sschwarze if (MMAN_An_split & outflags) 9278ba5d246Sschwarze outflags |= MMAN_br; 9288ba5d246Sschwarze else if (SEC_AUTHORS == n->sec && 9298ba5d246Sschwarze ! (MMAN_An_nosplit & outflags)) 9308ba5d246Sschwarze outflags |= MMAN_An_split; 931526e306bSschwarze return 1; 9328ba5d246Sschwarze } 933e6ab379cSschwarze } 934e6ab379cSschwarze 935e6ab379cSschwarze static int 936e6ab379cSschwarze pre_ap(DECL_ARGS) 937e6ab379cSschwarze { 938e6ab379cSschwarze 93951c88ffdSschwarze outflags &= ~MMAN_spc; 94051c88ffdSschwarze print_word("'"); 94151c88ffdSschwarze outflags &= ~MMAN_spc; 942526e306bSschwarze return 0; 943e6ab379cSschwarze } 944e6ab379cSschwarze 945e6ab379cSschwarze static int 94627d19a00Sschwarze pre_aq(DECL_ARGS) 94727d19a00Sschwarze { 94827d19a00Sschwarze 94930e5ee06Sschwarze print_word(n->child != NULL && n->child->next == NULL && 950ba61527cSschwarze n->child->tok == MDOC_Mt ? "<" : "\\(la"); 95127d19a00Sschwarze outflags &= ~MMAN_spc; 952526e306bSschwarze return 1; 95327d19a00Sschwarze } 95427d19a00Sschwarze 95527d19a00Sschwarze static void 95627d19a00Sschwarze post_aq(DECL_ARGS) 95727d19a00Sschwarze { 95827d19a00Sschwarze 95927d19a00Sschwarze outflags &= ~(MMAN_spc | MMAN_nl); 96030e5ee06Sschwarze print_word(n->child != NULL && n->child->next == NULL && 961ba61527cSschwarze n->child->tok == MDOC_Mt ? ">" : "\\(ra"); 96227d19a00Sschwarze } 96327d19a00Sschwarze 96427d19a00Sschwarze static int 965e6ab379cSschwarze pre_bd(DECL_ARGS) 966e6ab379cSschwarze { 96754cad943Sschwarze outflags &= ~(MMAN_PP | MMAN_sp | MMAN_br); 9687ebbefbeSschwarze if (n->norm->Bd.type == DISP_unfilled || 9697ebbefbeSschwarze n->norm->Bd.type == DISP_literal) 97054cad943Sschwarze print_line(".nf", 0); 9717ebbefbeSschwarze if (n->norm->Bd.comp == 0 && roff_node_prev(n->parent) != NULL) 97254cad943Sschwarze outflags |= MMAN_sp; 97390d52a15Sschwarze print_offs(n->norm->Bd.offs, 1); 974526e306bSschwarze return 1; 975e6ab379cSschwarze } 976e6ab379cSschwarze 977e6ab379cSschwarze static void 978e6ab379cSschwarze post_bd(DECL_ARGS) 979e6ab379cSschwarze { 980b7fc66beSschwarze enum roff_tok bef, now; 981e6ab379cSschwarze 9825ee03fc6Sschwarze /* Close out this display. */ 98354cad943Sschwarze print_line(".RE", MMAN_nl); 984b7fc66beSschwarze bef = n->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi; 985b7fc66beSschwarze if (n->last == NULL) 986b7fc66beSschwarze now = n->norm->Bd.type == DISP_unfilled || 987b7fc66beSschwarze n->norm->Bd.type == DISP_literal ? ROFF_nf : ROFF_fi; 988b7fc66beSschwarze else if (n->last->tok == ROFF_nf) 989b7fc66beSschwarze now = ROFF_nf; 990b7fc66beSschwarze else if (n->last->tok == ROFF_fi) 991b7fc66beSschwarze now = ROFF_fi; 992b7fc66beSschwarze else 993b7fc66beSschwarze now = n->last->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi; 994b7fc66beSschwarze if (bef != now) { 995b7fc66beSschwarze outflags |= MMAN_nl; 996b7fc66beSschwarze print_word("."); 997b7fc66beSschwarze outflags &= ~MMAN_spc; 998b7fc66beSschwarze print_word(roff_name[bef]); 999b7fc66beSschwarze outflags |= MMAN_nl; 1000b7fc66beSschwarze } 10015ee03fc6Sschwarze 1002a14e0b20Sschwarze /* Maybe we are inside an enclosing list? */ 10037ebbefbeSschwarze if (roff_node_next(n->parent) != NULL) 1004a14e0b20Sschwarze mid_it(); 1005e6ab379cSschwarze } 1006e6ab379cSschwarze 1007e6ab379cSschwarze static int 10080129f95fSschwarze pre_bf(DECL_ARGS) 10090129f95fSschwarze { 10100129f95fSschwarze 10110129f95fSschwarze switch (n->type) { 1012d1982c71Sschwarze case ROFFT_BLOCK: 1013526e306bSschwarze return 1; 1014d1982c71Sschwarze case ROFFT_BODY: 10150129f95fSschwarze break; 10160129f95fSschwarze default: 1017526e306bSschwarze return 0; 10180129f95fSschwarze } 10190129f95fSschwarze switch (n->norm->Bf.font) { 102049aff9f8Sschwarze case FONT_Em: 10210129f95fSschwarze font_push('I'); 10220129f95fSschwarze break; 102349aff9f8Sschwarze case FONT_Sy: 10240129f95fSschwarze font_push('B'); 10250129f95fSschwarze break; 10260129f95fSschwarze default: 10270129f95fSschwarze font_push('R'); 10280129f95fSschwarze break; 10290129f95fSschwarze } 1030526e306bSschwarze return 1; 10310129f95fSschwarze } 10320129f95fSschwarze 10330129f95fSschwarze static void 10340129f95fSschwarze post_bf(DECL_ARGS) 10350129f95fSschwarze { 10360129f95fSschwarze 1037d1982c71Sschwarze if (n->type == ROFFT_BODY) 10380129f95fSschwarze font_pop(); 10390129f95fSschwarze } 10400129f95fSschwarze 10410129f95fSschwarze static int 10428b4da3beSschwarze pre_bk(DECL_ARGS) 10438b4da3beSschwarze { 10448b4da3beSschwarze switch (n->type) { 1045d1982c71Sschwarze case ROFFT_BLOCK: 1046526e306bSschwarze return 1; 1047d1982c71Sschwarze case ROFFT_BODY: 1048f54c3aafSschwarze case ROFFT_ELEM: 104951c88ffdSschwarze outflags |= MMAN_Bk; 1050526e306bSschwarze return 1; 10518b4da3beSschwarze default: 1052526e306bSschwarze return 0; 10538b4da3beSschwarze } 10548b4da3beSschwarze } 10558b4da3beSschwarze 10568b4da3beSschwarze static void 10578b4da3beSschwarze post_bk(DECL_ARGS) 10588b4da3beSschwarze { 1059f54c3aafSschwarze switch (n->type) { 1060f54c3aafSschwarze case ROFFT_ELEM: 1061f54c3aafSschwarze while ((n = n->parent) != NULL) 1062f54c3aafSschwarze if (n->tok == MDOC_Bk) 1063f54c3aafSschwarze return; 1064f54c3aafSschwarze /* FALLTHROUGH */ 1065f54c3aafSschwarze case ROFFT_BODY: 106651c88ffdSschwarze outflags &= ~MMAN_Bk; 1067f54c3aafSschwarze break; 1068f54c3aafSschwarze default: 1069f54c3aafSschwarze break; 1070f54c3aafSschwarze } 10718b4da3beSschwarze } 10728b4da3beSschwarze 10738b4da3beSschwarze static int 10745eced068Sschwarze pre_bl(DECL_ARGS) 10755eced068Sschwarze { 10769ea7155cSschwarze size_t icol; 10775eced068Sschwarze 10781b12f2b2Sschwarze /* 10791b12f2b2Sschwarze * print_offs() will increase the -offset to account for 10801b12f2b2Sschwarze * a possible enclosing .It, but any enclosed .It blocks 10811b12f2b2Sschwarze * just nest and do not add up their indentation. 10821b12f2b2Sschwarze */ 10831b12f2b2Sschwarze if (n->norm->Bl.offs) { 108490d52a15Sschwarze print_offs(n->norm->Bl.offs, 0); 10851b12f2b2Sschwarze Bl_stack[Bl_stack_len++] = 0; 10861b12f2b2Sschwarze } 10871b12f2b2Sschwarze 10889ea7155cSschwarze switch (n->norm->Bl.type) { 108949aff9f8Sschwarze case LIST_enum: 10905eced068Sschwarze n->norm->Bl.count = 0; 1091526e306bSschwarze return 1; 109249aff9f8Sschwarze case LIST_column: 10939ea7155cSschwarze break; 10949ea7155cSschwarze default: 1095526e306bSschwarze return 1; 10969ea7155cSschwarze } 10979ea7155cSschwarze 109830e5ee06Sschwarze if (n->child != NULL) { 109954cad943Sschwarze print_line(".TS", MMAN_nl); 11009ea7155cSschwarze for (icol = 0; icol < n->norm->Bl.ncols; icol++) 11019ea7155cSschwarze print_word("l"); 11029ea7155cSschwarze print_word("."); 110392ff8da6Sschwarze } 110454cad943Sschwarze outflags |= MMAN_nl; 1105526e306bSschwarze return 1; 11065eced068Sschwarze } 11075eced068Sschwarze 11085eced068Sschwarze static void 11095eced068Sschwarze post_bl(DECL_ARGS) 11105eced068Sschwarze { 11115eced068Sschwarze 11129ea7155cSschwarze switch (n->norm->Bl.type) { 111349aff9f8Sschwarze case LIST_column: 111430e5ee06Sschwarze if (n->child != NULL) 111554cad943Sschwarze print_line(".TE", 0); 111654cad943Sschwarze break; 111749aff9f8Sschwarze case LIST_enum: 11185eced068Sschwarze n->norm->Bl.count = 0; 11199ea7155cSschwarze break; 11209ea7155cSschwarze default: 11219ea7155cSschwarze break; 11229ea7155cSschwarze } 11231b12f2b2Sschwarze 11241b12f2b2Sschwarze if (n->norm->Bl.offs) { 11251b12f2b2Sschwarze print_line(".RE", MMAN_nl); 11261b12f2b2Sschwarze assert(Bl_stack_len); 11271b12f2b2Sschwarze Bl_stack_len--; 11287ebbefbeSschwarze assert(Bl_stack[Bl_stack_len] == 0); 11291b12f2b2Sschwarze } else { 113054cad943Sschwarze outflags |= MMAN_PP | MMAN_nl; 113154cad943Sschwarze outflags &= ~(MMAN_sp | MMAN_br); 11321b12f2b2Sschwarze } 1133a14e0b20Sschwarze 1134a14e0b20Sschwarze /* Maybe we are inside an enclosing list? */ 11357ebbefbeSschwarze if (roff_node_next(n->parent) != NULL) 1136a14e0b20Sschwarze mid_it(); 11375eced068Sschwarze } 11385eced068Sschwarze 1139644b390bSschwarze static void 1140e6ab379cSschwarze pre_br(DECL_ARGS) 1141e6ab379cSschwarze { 114228ee9174Sschwarze outflags |= MMAN_br; 1143e6ab379cSschwarze } 1144e6ab379cSschwarze 1145e6ab379cSschwarze static int 114675d4d0e5Sschwarze pre_dl(DECL_ARGS) 114775d4d0e5Sschwarze { 114890d52a15Sschwarze print_offs("6n", 0); 1149526e306bSschwarze return 1; 115075d4d0e5Sschwarze } 115175d4d0e5Sschwarze 115275d4d0e5Sschwarze static void 115375d4d0e5Sschwarze post_dl(DECL_ARGS) 115475d4d0e5Sschwarze { 115554cad943Sschwarze print_line(".RE", MMAN_nl); 1156a14e0b20Sschwarze 1157a14e0b20Sschwarze /* Maybe we are inside an enclosing list? */ 11587ebbefbeSschwarze if (roff_node_next(n->parent) != NULL) 1159a14e0b20Sschwarze mid_it(); 116075d4d0e5Sschwarze } 116175d4d0e5Sschwarze 116275d4d0e5Sschwarze static int 1163388939aeSschwarze pre_em(DECL_ARGS) 1164388939aeSschwarze { 1165388939aeSschwarze 1166388939aeSschwarze font_push('I'); 1167526e306bSschwarze return 1; 1168388939aeSschwarze } 1169388939aeSschwarze 1170551cd4a8Sschwarze static int 1171551cd4a8Sschwarze pre_en(DECL_ARGS) 1172551cd4a8Sschwarze { 1173551cd4a8Sschwarze 1174551cd4a8Sschwarze if (NULL == n->norm->Es || 1175551cd4a8Sschwarze NULL == n->norm->Es->child) 1176526e306bSschwarze return 1; 1177551cd4a8Sschwarze 1178551cd4a8Sschwarze print_word(n->norm->Es->child->string); 1179551cd4a8Sschwarze outflags &= ~MMAN_spc; 1180526e306bSschwarze return 1; 1181551cd4a8Sschwarze } 1182551cd4a8Sschwarze 1183551cd4a8Sschwarze static void 1184551cd4a8Sschwarze post_en(DECL_ARGS) 1185551cd4a8Sschwarze { 1186551cd4a8Sschwarze 1187551cd4a8Sschwarze if (NULL == n->norm->Es || 1188551cd4a8Sschwarze NULL == n->norm->Es->child || 1189551cd4a8Sschwarze NULL == n->norm->Es->child->next) 1190551cd4a8Sschwarze return; 1191551cd4a8Sschwarze 1192551cd4a8Sschwarze outflags &= ~MMAN_spc; 1193551cd4a8Sschwarze print_word(n->norm->Es->child->next->string); 1194551cd4a8Sschwarze return; 1195551cd4a8Sschwarze } 1196551cd4a8Sschwarze 11977d18a139Sschwarze static int 11987d18a139Sschwarze pre_eo(DECL_ARGS) 11997d18a139Sschwarze { 12007d18a139Sschwarze 120103ed6ec9Sschwarze if (n->end == ENDBODY_NOT && 120203ed6ec9Sschwarze n->parent->head->child == NULL && 120303ed6ec9Sschwarze n->child != NULL && 120403ed6ec9Sschwarze n->child->end != ENDBODY_NOT) 120503ed6ec9Sschwarze print_word("\\&"); 120603ed6ec9Sschwarze else if (n->end != ENDBODY_NOT ? n->child != NULL : 1207c69b5c37Sschwarze n->parent->head->child != NULL && (n->child != NULL || 1208c69b5c37Sschwarze (n->parent->tail != NULL && n->parent->tail->child != NULL))) 12097d18a139Sschwarze outflags &= ~(MMAN_spc | MMAN_nl); 1210526e306bSschwarze return 1; 12117d18a139Sschwarze } 12127d18a139Sschwarze 1213c19c703eSschwarze static void 1214c19c703eSschwarze post_eo(DECL_ARGS) 1215c19c703eSschwarze { 121603ed6ec9Sschwarze int body, tail; 1217c19c703eSschwarze 121803ed6ec9Sschwarze if (n->end != ENDBODY_NOT) { 121903ed6ec9Sschwarze outflags |= MMAN_spc; 122003ed6ec9Sschwarze return; 122103ed6ec9Sschwarze } 122203ed6ec9Sschwarze 122303ed6ec9Sschwarze body = n->child != NULL || n->parent->head->child != NULL; 122403ed6ec9Sschwarze tail = n->parent->tail != NULL && n->parent->tail->child != NULL; 122503ed6ec9Sschwarze 122603ed6ec9Sschwarze if (body && tail) 1227c19c703eSschwarze outflags &= ~MMAN_spc; 122803ed6ec9Sschwarze else if ( ! (body || tail)) 122903ed6ec9Sschwarze print_word("\\&"); 123003ed6ec9Sschwarze else if ( ! tail) 123103ed6ec9Sschwarze outflags |= MMAN_spc; 1232c19c703eSschwarze } 1233c19c703eSschwarze 1234388939aeSschwarze static int 1235e2ee3b43Sschwarze pre_fa(DECL_ARGS) 1236e2ee3b43Sschwarze { 12371074fc8aSschwarze int am_Fa; 1238e2ee3b43Sschwarze 12391074fc8aSschwarze am_Fa = MDOC_Fa == n->tok; 12401074fc8aSschwarze 12411074fc8aSschwarze if (am_Fa) 1242e2ee3b43Sschwarze n = n->child; 1243e2ee3b43Sschwarze 1244e2ee3b43Sschwarze while (NULL != n) { 1245388939aeSschwarze font_push('I'); 1246c4b0939cSschwarze if (am_Fa || NODE_SYNPRETTY & n->flags) 12471192b926Sschwarze outflags |= MMAN_nbrword; 12487ead8a4eSschwarze print_node(meta, n); 1249388939aeSschwarze font_pop(); 1250e2ee3b43Sschwarze if (NULL != (n = n->next)) 125151c88ffdSschwarze print_word(","); 1252e2ee3b43Sschwarze } 1253526e306bSschwarze return 0; 1254e2ee3b43Sschwarze } 1255e2ee3b43Sschwarze 1256e2ee3b43Sschwarze static void 1257e2ee3b43Sschwarze post_fa(DECL_ARGS) 1258e2ee3b43Sschwarze { 12597ebbefbeSschwarze struct roff_node *nn; 1260e2ee3b43Sschwarze 12617ebbefbeSschwarze if ((nn = roff_node_next(n)) != NULL && nn->tok == MDOC_Fa) 126251c88ffdSschwarze print_word(","); 1263e2ee3b43Sschwarze } 1264e2ee3b43Sschwarze 1265e2ee3b43Sschwarze static int 1266d97bd30dSschwarze pre_fd(DECL_ARGS) 1267d97bd30dSschwarze { 1268d97bd30dSschwarze pre_syn(n); 1269d97bd30dSschwarze font_push('B'); 1270526e306bSschwarze return 1; 1271d97bd30dSschwarze } 1272d97bd30dSschwarze 1273d97bd30dSschwarze static void 1274d97bd30dSschwarze post_fd(DECL_ARGS) 1275d97bd30dSschwarze { 1276d97bd30dSschwarze font_pop(); 1277d97bd30dSschwarze outflags |= MMAN_br; 1278d97bd30dSschwarze } 1279d97bd30dSschwarze 1280d97bd30dSschwarze static int 1281388939aeSschwarze pre_fl(DECL_ARGS) 1282388939aeSschwarze { 1283388939aeSschwarze font_push('B'); 12840e67873aSmillert print_word("\\-"); 128530e5ee06Sschwarze if (n->child != NULL) 1286388939aeSschwarze outflags &= ~MMAN_spc; 1287526e306bSschwarze return 1; 1288388939aeSschwarze } 1289388939aeSschwarze 1290388939aeSschwarze static void 1291388939aeSschwarze post_fl(DECL_ARGS) 1292388939aeSschwarze { 12937ebbefbeSschwarze struct roff_node *nn; 1294388939aeSschwarze 1295388939aeSschwarze font_pop(); 12967ebbefbeSschwarze if (n->child == NULL && 12977ebbefbeSschwarze ((nn = roff_node_next(n)) != NULL && 12987ebbefbeSschwarze nn->type != ROFFT_TEXT && 12997ebbefbeSschwarze (nn->flags & NODE_LINE) == 0)) 1300388939aeSschwarze outflags &= ~MMAN_spc; 1301388939aeSschwarze } 1302388939aeSschwarze 1303388939aeSschwarze static int 13040df06370Sschwarze pre_fn(DECL_ARGS) 13050df06370Sschwarze { 13060df06370Sschwarze 1307fb6b7277Sschwarze pre_syn(n); 1308fb6b7277Sschwarze 13090df06370Sschwarze n = n->child; 13100df06370Sschwarze if (NULL == n) 1311526e306bSschwarze return 0; 13120df06370Sschwarze 1313c4b0939cSschwarze if (NODE_SYNPRETTY & n->flags) 13148018f0c4Sschwarze print_block(".HP 4n", MMAN_nl); 13158018f0c4Sschwarze 1316388939aeSschwarze font_push('B'); 13177ead8a4eSschwarze print_node(meta, n); 1318388939aeSschwarze font_pop(); 131951c88ffdSschwarze outflags &= ~MMAN_spc; 1320388939aeSschwarze print_word("("); 132151c88ffdSschwarze outflags &= ~MMAN_spc; 132220649b49Sschwarze 132320649b49Sschwarze n = n->next; 132420649b49Sschwarze if (NULL != n) 13257ead8a4eSschwarze pre_fa(meta, n); 1326526e306bSschwarze return 0; 13270df06370Sschwarze } 13280df06370Sschwarze 13290df06370Sschwarze static void 13300df06370Sschwarze post_fn(DECL_ARGS) 13310df06370Sschwarze { 13320df06370Sschwarze 133351c88ffdSschwarze print_word(")"); 1334c4b0939cSschwarze if (NODE_SYNPRETTY & n->flags) { 133551c88ffdSschwarze print_word(";"); 13368018f0c4Sschwarze outflags |= MMAN_PP; 1337e2ee3b43Sschwarze } 1338e2ee3b43Sschwarze } 1339e2ee3b43Sschwarze 1340e2ee3b43Sschwarze static int 1341e2ee3b43Sschwarze pre_fo(DECL_ARGS) 1342e2ee3b43Sschwarze { 1343e2ee3b43Sschwarze 1344e2ee3b43Sschwarze switch (n->type) { 1345d1982c71Sschwarze case ROFFT_BLOCK: 1346fb6b7277Sschwarze pre_syn(n); 1347fb6b7277Sschwarze break; 1348d1982c71Sschwarze case ROFFT_HEAD: 1349afcd1f03Sschwarze if (n->child == NULL) 1350526e306bSschwarze return 0; 1351c4b0939cSschwarze if (NODE_SYNPRETTY & n->flags) 13521074fc8aSschwarze print_block(".HP 4n", MMAN_nl); 1353388939aeSschwarze font_push('B'); 1354e2ee3b43Sschwarze break; 1355d1982c71Sschwarze case ROFFT_BODY: 1356afcd1f03Sschwarze outflags &= ~(MMAN_spc | MMAN_nl); 135751c88ffdSschwarze print_word("("); 135851c88ffdSschwarze outflags &= ~MMAN_spc; 1359e2ee3b43Sschwarze break; 1360e2ee3b43Sschwarze default: 1361e2ee3b43Sschwarze break; 1362e2ee3b43Sschwarze } 1363526e306bSschwarze return 1; 1364e2ee3b43Sschwarze } 1365e2ee3b43Sschwarze 1366e2ee3b43Sschwarze static void 1367e2ee3b43Sschwarze post_fo(DECL_ARGS) 1368e2ee3b43Sschwarze { 1369e2ee3b43Sschwarze 1370e2ee3b43Sschwarze switch (n->type) { 1371d1982c71Sschwarze case ROFFT_HEAD: 1372afcd1f03Sschwarze if (n->child != NULL) 1373388939aeSschwarze font_pop(); 1374e2ee3b43Sschwarze break; 1375d1982c71Sschwarze case ROFFT_BODY: 13767ead8a4eSschwarze post_fn(meta, n); 1377e2ee3b43Sschwarze break; 1378e2ee3b43Sschwarze default: 1379e2ee3b43Sschwarze break; 1380e2ee3b43Sschwarze } 13810df06370Sschwarze } 13820df06370Sschwarze 13830df06370Sschwarze static int 1384c4d3fa85Sschwarze pre_Ft(DECL_ARGS) 1385fb6b7277Sschwarze { 1386fb6b7277Sschwarze 1387fb6b7277Sschwarze pre_syn(n); 1388388939aeSschwarze font_push('I'); 1389526e306bSschwarze return 1; 1390fb6b7277Sschwarze } 1391fb6b7277Sschwarze 1392644b390bSschwarze static void 1393c4d3fa85Sschwarze pre_ft(DECL_ARGS) 1394c4d3fa85Sschwarze { 1395c4d3fa85Sschwarze print_line(".ft", 0); 1396c4d3fa85Sschwarze print_word(n->child->string); 1397c4d3fa85Sschwarze outflags |= MMAN_nl; 1398c4d3fa85Sschwarze } 1399c4d3fa85Sschwarze 1400c4d3fa85Sschwarze static int 14010e0aff12Sschwarze pre_in(DECL_ARGS) 14020e0aff12Sschwarze { 14030e0aff12Sschwarze 1404c4b0939cSschwarze if (NODE_SYNPRETTY & n->flags) { 1405fb6b7277Sschwarze pre_syn(n); 1406388939aeSschwarze font_push('B'); 1407388939aeSschwarze print_word("#include <"); 140851c88ffdSschwarze outflags &= ~MMAN_spc; 1409388939aeSschwarze } else { 1410388939aeSschwarze print_word("<"); 1411388939aeSschwarze outflags &= ~MMAN_spc; 1412388939aeSschwarze font_push('I'); 1413388939aeSschwarze } 1414526e306bSschwarze return 1; 14150e0aff12Sschwarze } 14160e0aff12Sschwarze 14170e0aff12Sschwarze static void 14180e0aff12Sschwarze post_in(DECL_ARGS) 14190e0aff12Sschwarze { 14200e0aff12Sschwarze 1421c4b0939cSschwarze if (NODE_SYNPRETTY & n->flags) { 1422388939aeSschwarze outflags &= ~MMAN_spc; 1423388939aeSschwarze print_word(">"); 1424388939aeSschwarze font_pop(); 142528ee9174Sschwarze outflags |= MMAN_br; 1426388939aeSschwarze } else { 1427388939aeSschwarze font_pop(); 1428388939aeSschwarze outflags &= ~MMAN_spc; 1429388939aeSschwarze print_word(">"); 1430388939aeSschwarze } 14310e0aff12Sschwarze } 14320e0aff12Sschwarze 14330e0aff12Sschwarze static int 143475d4d0e5Sschwarze pre_it(DECL_ARGS) 143575d4d0e5Sschwarze { 14363a0d07afSschwarze const struct roff_node *bln; 143775d4d0e5Sschwarze 14385eced068Sschwarze switch (n->type) { 1439d1982c71Sschwarze case ROFFT_HEAD: 144054cad943Sschwarze outflags |= MMAN_PP | MMAN_nl; 14415eced068Sschwarze bln = n->parent->parent; 14427ebbefbeSschwarze if (bln->norm->Bl.comp == 0 || 14437ebbefbeSschwarze (n->parent->prev == NULL && 14447ebbefbeSschwarze roff_node_prev(bln->parent) == NULL)) 144554cad943Sschwarze outflags |= MMAN_sp; 144654cad943Sschwarze outflags &= ~MMAN_br; 1447e6ab379cSschwarze switch (bln->norm->Bl.type) { 144849aff9f8Sschwarze case LIST_item: 1449526e306bSschwarze return 0; 145049aff9f8Sschwarze case LIST_inset: 145149aff9f8Sschwarze case LIST_diag: 145249aff9f8Sschwarze case LIST_ohang: 14535eced068Sschwarze if (bln->norm->Bl.type == LIST_diag) 145454cad943Sschwarze print_line(".B \"", 0); 14555eced068Sschwarze else 145672ee7308Sschwarze print_line(".BR \\& \"", 0); 14575eced068Sschwarze outflags &= ~MMAN_spc; 1458526e306bSschwarze return 1; 145949aff9f8Sschwarze case LIST_bullet: 146049aff9f8Sschwarze case LIST_dash: 146149aff9f8Sschwarze case LIST_hyphen: 146225da2733Sschwarze print_width(&bln->norm->Bl, NULL); 146380a412c7Sschwarze TPremain = 0; 146451c88ffdSschwarze outflags |= MMAN_nl; 14655eced068Sschwarze font_push('B'); 14665eced068Sschwarze if (LIST_bullet == bln->norm->Bl.type) 14677c64ba2fSschwarze print_word("\\(bu"); 14685eced068Sschwarze else 14695eced068Sschwarze print_word("-"); 14705eced068Sschwarze font_pop(); 1471ecb10c32Sschwarze outflags |= MMAN_nl; 1472526e306bSschwarze return 0; 147349aff9f8Sschwarze case LIST_enum: 147425da2733Sschwarze print_width(&bln->norm->Bl, NULL); 147580a412c7Sschwarze TPremain = 0; 14765eced068Sschwarze outflags |= MMAN_nl; 14775eced068Sschwarze print_count(&bln->norm->Bl.count); 1478ecb10c32Sschwarze outflags |= MMAN_nl; 1479526e306bSschwarze return 0; 148049aff9f8Sschwarze case LIST_hang: 148125da2733Sschwarze print_width(&bln->norm->Bl, n->child); 148280a412c7Sschwarze TPremain = 0; 1483ecb10c32Sschwarze outflags |= MMAN_nl; 1484526e306bSschwarze return 1; 148549aff9f8Sschwarze case LIST_tag: 148625da2733Sschwarze print_width(&bln->norm->Bl, n->child); 148780a412c7Sschwarze putchar('\n'); 148880a412c7Sschwarze outflags &= ~MMAN_spc; 1489526e306bSschwarze return 1; 1490e6ab379cSschwarze default: 1491526e306bSschwarze return 1; 1492e6ab379cSschwarze } 14935eced068Sschwarze default: 14945eced068Sschwarze break; 149575d4d0e5Sschwarze } 1496526e306bSschwarze return 1; 149775d4d0e5Sschwarze } 149875d4d0e5Sschwarze 1499a14e0b20Sschwarze /* 1500a14e0b20Sschwarze * This function is called after closing out an indented block. 1501a14e0b20Sschwarze * If we are inside an enclosing list, restore its indentation. 1502a14e0b20Sschwarze */ 1503a14e0b20Sschwarze static void 1504a14e0b20Sschwarze mid_it(void) 1505a14e0b20Sschwarze { 1506a14e0b20Sschwarze char buf[24]; 1507a14e0b20Sschwarze 1508a14e0b20Sschwarze /* Nothing to do outside a list. */ 1509a14e0b20Sschwarze if (0 == Bl_stack_len || 0 == Bl_stack[Bl_stack_len - 1]) 1510a14e0b20Sschwarze return; 1511a14e0b20Sschwarze 1512a14e0b20Sschwarze /* The indentation has already been set up. */ 1513a14e0b20Sschwarze if (Bl_stack_post[Bl_stack_len - 1]) 1514a14e0b20Sschwarze return; 1515a14e0b20Sschwarze 1516a14e0b20Sschwarze /* Restore the indentation of the enclosing list. */ 1517a14e0b20Sschwarze print_line(".RS", MMAN_Bk_susp); 151825da2733Sschwarze (void)snprintf(buf, sizeof(buf), "%dn", 151947813146Sschwarze Bl_stack[Bl_stack_len - 1]); 1520a14e0b20Sschwarze print_word(buf); 1521a14e0b20Sschwarze 1522d9a51c35Sjmc /* Remember to close out this .RS block later. */ 1523a14e0b20Sschwarze Bl_stack_post[Bl_stack_len - 1] = 1; 1524a14e0b20Sschwarze } 1525a14e0b20Sschwarze 1526835b952bSschwarze static void 15275eced068Sschwarze post_it(DECL_ARGS) 15285eced068Sschwarze { 15293a0d07afSschwarze const struct roff_node *bln; 15305eced068Sschwarze 15315eced068Sschwarze bln = n->parent->parent; 15329ea7155cSschwarze 15339ea7155cSschwarze switch (n->type) { 1534d1982c71Sschwarze case ROFFT_HEAD: 15355eced068Sschwarze switch (bln->norm->Bl.type) { 153649aff9f8Sschwarze case LIST_diag: 15375eced068Sschwarze outflags &= ~MMAN_spc; 15385eced068Sschwarze print_word("\\ "); 15395eced068Sschwarze break; 154049aff9f8Sschwarze case LIST_ohang: 15415eced068Sschwarze outflags |= MMAN_br; 15425eced068Sschwarze break; 15435eced068Sschwarze default: 15445eced068Sschwarze break; 15455eced068Sschwarze } 15469ea7155cSschwarze break; 1547d1982c71Sschwarze case ROFFT_BODY: 15485ee03fc6Sschwarze switch (bln->norm->Bl.type) { 154949aff9f8Sschwarze case LIST_bullet: 155049aff9f8Sschwarze case LIST_dash: 155149aff9f8Sschwarze case LIST_hyphen: 155249aff9f8Sschwarze case LIST_enum: 155349aff9f8Sschwarze case LIST_hang: 155449aff9f8Sschwarze case LIST_tag: 15555ee03fc6Sschwarze assert(Bl_stack_len); 15565ee03fc6Sschwarze Bl_stack[--Bl_stack_len] = 0; 15575ee03fc6Sschwarze 15585ee03fc6Sschwarze /* 15595ee03fc6Sschwarze * Our indentation had to be restored 1560a14e0b20Sschwarze * after a child display or child list. 15615ee03fc6Sschwarze * Close out that indentation block now. 15625ee03fc6Sschwarze */ 15635ee03fc6Sschwarze if (Bl_stack_post[Bl_stack_len]) { 15645ee03fc6Sschwarze print_line(".RE", MMAN_nl); 15655ee03fc6Sschwarze Bl_stack_post[Bl_stack_len] = 0; 15665ee03fc6Sschwarze } 15675ee03fc6Sschwarze break; 156849aff9f8Sschwarze case LIST_column: 15695ee03fc6Sschwarze if (NULL != n->next) { 15709ea7155cSschwarze putchar('\t'); 15719ea7155cSschwarze outflags &= ~MMAN_spc; 15729ea7155cSschwarze } 15739ea7155cSschwarze break; 15749ea7155cSschwarze default: 15759ea7155cSschwarze break; 15765eced068Sschwarze } 15775ee03fc6Sschwarze break; 15785ee03fc6Sschwarze default: 15795ee03fc6Sschwarze break; 15805ee03fc6Sschwarze } 15815eced068Sschwarze } 15825eced068Sschwarze 15835eced068Sschwarze static void 1584835b952bSschwarze post_lb(DECL_ARGS) 1585835b952bSschwarze { 1586835b952bSschwarze 158728ee9174Sschwarze if (SEC_LIBRARY == n->sec) 158828ee9174Sschwarze outflags |= MMAN_br; 1589835b952bSschwarze } 1590835b952bSschwarze 159175d4d0e5Sschwarze static int 1592cfd12f23Sschwarze pre_lk(DECL_ARGS) 1593cfd12f23Sschwarze { 1594eb4d0f30Sschwarze const struct roff_node *link, *descr, *punct; 1595cfd12f23Sschwarze 159696aebfb3Sschwarze if ((link = n->child) == NULL) 1597526e306bSschwarze return 0; 1598cfd12f23Sschwarze 1599eb4d0f30Sschwarze /* Find beginning of trailing punctuation. */ 1600eb4d0f30Sschwarze punct = n->last; 1601eb4d0f30Sschwarze while (punct != link && punct->flags & NODE_DELIMC) 1602eb4d0f30Sschwarze punct = punct->prev; 1603eb4d0f30Sschwarze punct = punct->next; 1604eb4d0f30Sschwarze 160596aebfb3Sschwarze /* Link text. */ 1606eb4d0f30Sschwarze if ((descr = link->next) != NULL && descr != punct) { 1607388939aeSschwarze font_push('I'); 1608eb4d0f30Sschwarze while (descr != punct) { 1609cfd12f23Sschwarze print_word(descr->string); 1610cfd12f23Sschwarze descr = descr->next; 1611cfd12f23Sschwarze } 1612388939aeSschwarze font_pop(); 1613f6fe732fSschwarze print_word(":"); 1614cfd12f23Sschwarze } 1615cfd12f23Sschwarze 161696aebfb3Sschwarze /* Link target. */ 1617388939aeSschwarze font_push('B'); 1618cfd12f23Sschwarze print_word(link->string); 1619388939aeSschwarze font_pop(); 162096aebfb3Sschwarze 162196aebfb3Sschwarze /* Trailing punctuation. */ 1622eb4d0f30Sschwarze while (punct != NULL) { 1623eb4d0f30Sschwarze print_word(punct->string); 1624eb4d0f30Sschwarze punct = punct->next; 162596aebfb3Sschwarze } 1626526e306bSschwarze return 0; 1627cfd12f23Sschwarze } 1628cfd12f23Sschwarze 1629644b390bSschwarze static void 163011d70615Sschwarze pre_onearg(DECL_ARGS) 16315281506aSschwarze { 163211d70615Sschwarze outflags |= MMAN_nl; 163311d70615Sschwarze print_word("."); 163411d70615Sschwarze outflags &= ~MMAN_spc; 163511d70615Sschwarze print_word(roff_name[n->tok]); 1636644b390bSschwarze if (n->child != NULL) 1637644b390bSschwarze print_word(n->child->string); 1638644b390bSschwarze outflags |= MMAN_nl; 1639e13b4195Sschwarze if (n->tok == ROFF_ce) 1640e13b4195Sschwarze for (n = n->child->next; n != NULL; n = n->next) 1641e13b4195Sschwarze print_node(meta, n); 16425281506aSschwarze } 16435281506aSschwarze 16445281506aSschwarze static int 1645388939aeSschwarze pre_li(DECL_ARGS) 1646388939aeSschwarze { 1647388939aeSschwarze font_push('R'); 1648526e306bSschwarze return 1; 1649388939aeSschwarze } 1650388939aeSschwarze 1651388939aeSschwarze static int 165275d4d0e5Sschwarze pre_nm(DECL_ARGS) 165375d4d0e5Sschwarze { 1654e0ceaf97Sschwarze char *name; 165575d4d0e5Sschwarze 16567ebbefbeSschwarze switch (n->type) { 16577ebbefbeSschwarze case ROFFT_BLOCK: 16584b1aedf8Sschwarze outflags |= MMAN_Bk; 1659fb6b7277Sschwarze pre_syn(n); 1660526e306bSschwarze return 1; 16617ebbefbeSschwarze case ROFFT_HEAD: 16627ebbefbeSschwarze case ROFFT_ELEM: 16637ebbefbeSschwarze break; 16647ebbefbeSschwarze default: 16657ebbefbeSschwarze return 1; 16667ebbefbeSschwarze } 166790957cf5Sschwarze name = n->child == NULL ? NULL : n->child->string; 16687ebbefbeSschwarze if (name == NULL) 1669526e306bSschwarze return 0; 1670d1982c71Sschwarze if (n->type == ROFFT_HEAD) { 16717ebbefbeSschwarze if (roff_node_prev(n->parent) == NULL) 1672e0ceaf97Sschwarze outflags |= MMAN_sp; 1673e0ceaf97Sschwarze print_block(".HP", 0); 16749f97fb19Sschwarze printf(" %dn", man_strlen(name) + 1); 1675e0ceaf97Sschwarze outflags |= MMAN_nl; 1676e0ceaf97Sschwarze } 1677388939aeSschwarze font_push('B'); 1678526e306bSschwarze return 1; 167975d4d0e5Sschwarze } 168075d4d0e5Sschwarze 168175d4d0e5Sschwarze static void 168275d4d0e5Sschwarze post_nm(DECL_ARGS) 168375d4d0e5Sschwarze { 16844b1aedf8Sschwarze switch (n->type) { 1685d1982c71Sschwarze case ROFFT_BLOCK: 16864b1aedf8Sschwarze outflags &= ~MMAN_Bk; 16874b1aedf8Sschwarze break; 1688d1982c71Sschwarze case ROFFT_HEAD: 1689d1982c71Sschwarze case ROFFT_ELEM: 169090957cf5Sschwarze if (n->child != NULL && n->child->string != NULL) 1691388939aeSschwarze font_pop(); 16924b1aedf8Sschwarze break; 16934b1aedf8Sschwarze default: 16944b1aedf8Sschwarze break; 16954b1aedf8Sschwarze } 169675d4d0e5Sschwarze } 169775d4d0e5Sschwarze 169875d4d0e5Sschwarze static int 1699d4adcee8Sschwarze pre_no(DECL_ARGS) 1700d4adcee8Sschwarze { 1701d4adcee8Sschwarze outflags |= MMAN_spc_force; 1702526e306bSschwarze return 1; 1703d4adcee8Sschwarze } 1704d4adcee8Sschwarze 1705b7fc66beSschwarze static void 1706b7fc66beSschwarze pre_noarg(DECL_ARGS) 1707b7fc66beSschwarze { 1708b7fc66beSschwarze outflags |= MMAN_nl; 1709b7fc66beSschwarze print_word("."); 1710b7fc66beSschwarze outflags &= ~MMAN_spc; 1711b7fc66beSschwarze print_word(roff_name[n->tok]); 1712b7fc66beSschwarze outflags |= MMAN_nl; 1713b7fc66beSschwarze } 1714b7fc66beSschwarze 1715d4adcee8Sschwarze static int 171675d4d0e5Sschwarze pre_ns(DECL_ARGS) 171775d4d0e5Sschwarze { 171851c88ffdSschwarze outflags &= ~MMAN_spc; 1719526e306bSschwarze return 0; 172075d4d0e5Sschwarze } 172175d4d0e5Sschwarze 1722e6ab379cSschwarze static void 1723e6ab379cSschwarze post_pf(DECL_ARGS) 1724e6ab379cSschwarze { 1725e6ab379cSschwarze 1726c4b0939cSschwarze if ( ! (n->next == NULL || n->next->flags & NODE_LINE)) 172751c88ffdSschwarze outflags &= ~MMAN_spc; 1728e6ab379cSschwarze } 1729e6ab379cSschwarze 173075d4d0e5Sschwarze static int 173175d4d0e5Sschwarze pre_pp(DECL_ARGS) 173275d4d0e5Sschwarze { 173375d4d0e5Sschwarze 173454cad943Sschwarze if (MDOC_It != n->parent->tok) 173554cad943Sschwarze outflags |= MMAN_PP; 173654cad943Sschwarze outflags |= MMAN_sp | MMAN_nl; 173754cad943Sschwarze outflags &= ~MMAN_br; 1738526e306bSschwarze return 0; 1739e3ceda8aSschwarze } 1740e3ceda8aSschwarze 1741e3ceda8aSschwarze static int 1742e3ceda8aSschwarze pre_rs(DECL_ARGS) 1743e3ceda8aSschwarze { 1744e3ceda8aSschwarze 1745e3ceda8aSschwarze if (SEC_SEE_ALSO == n->sec) { 174654cad943Sschwarze outflags |= MMAN_PP | MMAN_sp | MMAN_nl; 174754cad943Sschwarze outflags &= ~MMAN_br; 1748e3ceda8aSschwarze } 1749526e306bSschwarze return 1; 175075d4d0e5Sschwarze } 175175d4d0e5Sschwarze 175275d4d0e5Sschwarze static int 175378bbbab4Sschwarze pre_skip(DECL_ARGS) 175478bbbab4Sschwarze { 175578bbbab4Sschwarze 1756526e306bSschwarze return 0; 175778bbbab4Sschwarze } 175878bbbab4Sschwarze 175978bbbab4Sschwarze static int 1760c8addc6fSschwarze pre_sm(DECL_ARGS) 1761c8addc6fSschwarze { 1762c8addc6fSschwarze 1763f9e7bf99Sschwarze if (NULL == n->child) 1764f9e7bf99Sschwarze outflags ^= MMAN_Sm; 1765f9e7bf99Sschwarze else if (0 == strcmp("on", n->child->string)) 1766f9e7bf99Sschwarze outflags |= MMAN_Sm; 1767c8addc6fSschwarze else 176851c88ffdSschwarze outflags &= ~MMAN_Sm; 1769f9e7bf99Sschwarze 1770f9e7bf99Sschwarze if (MMAN_Sm & outflags) 1771f9e7bf99Sschwarze outflags |= MMAN_spc; 1772f9e7bf99Sschwarze 1773526e306bSschwarze return 0; 1774c8addc6fSschwarze } 1775c8addc6fSschwarze 17766561cb23Sschwarze static void 1777e6ab379cSschwarze pre_sp(DECL_ARGS) 177875d4d0e5Sschwarze { 17796561cb23Sschwarze if (outflags & MMAN_PP) { 1780da5e360cSschwarze outflags &= ~MMAN_PP; 1781da5e360cSschwarze print_line(".PP", 0); 17826561cb23Sschwarze } else { 1783da5e360cSschwarze print_line(".sp", 0); 17846561cb23Sschwarze if (n->child != NULL) 17856561cb23Sschwarze print_word(n->child->string); 178675d4d0e5Sschwarze } 178751c88ffdSschwarze outflags |= MMAN_nl; 178875d4d0e5Sschwarze } 178975d4d0e5Sschwarze 179075d4d0e5Sschwarze static int 1791388939aeSschwarze pre_sy(DECL_ARGS) 1792388939aeSschwarze { 1793388939aeSschwarze 1794388939aeSschwarze font_push('B'); 1795526e306bSschwarze return 1; 1796388939aeSschwarze } 1797388939aeSschwarze 1798f7242c43Sschwarze static void 1799f7242c43Sschwarze pre_ta(DECL_ARGS) 1800f7242c43Sschwarze { 1801f7242c43Sschwarze print_line(".ta", 0); 1802f7242c43Sschwarze for (n = n->child; n != NULL; n = n->next) 1803f7242c43Sschwarze print_word(n->string); 1804f7242c43Sschwarze outflags |= MMAN_nl; 1805f7242c43Sschwarze } 1806f7242c43Sschwarze 1807388939aeSschwarze static int 1808bce51a71Sschwarze pre_vt(DECL_ARGS) 1809bce51a71Sschwarze { 1810bce51a71Sschwarze 1811c4b0939cSschwarze if (NODE_SYNPRETTY & n->flags) { 1812e4315607Sschwarze switch (n->type) { 1813d1982c71Sschwarze case ROFFT_BLOCK: 1814fb6b7277Sschwarze pre_syn(n); 1815526e306bSschwarze return 1; 1816d1982c71Sschwarze case ROFFT_BODY: 1817e4315607Sschwarze break; 1818e4315607Sschwarze default: 1819526e306bSschwarze return 0; 1820e4315607Sschwarze } 1821bce51a71Sschwarze } 1822388939aeSschwarze font_push('I'); 1823526e306bSschwarze return 1; 1824bce51a71Sschwarze } 1825bce51a71Sschwarze 1826bce51a71Sschwarze static void 1827bce51a71Sschwarze post_vt(DECL_ARGS) 1828bce51a71Sschwarze { 1829bce51a71Sschwarze 1830c4b0939cSschwarze if (n->flags & NODE_SYNPRETTY && n->type != ROFFT_BODY) 1831e4315607Sschwarze return; 1832388939aeSschwarze font_pop(); 1833bce51a71Sschwarze } 1834bce51a71Sschwarze 1835bce51a71Sschwarze static int 183675d4d0e5Sschwarze pre_xr(DECL_ARGS) 183775d4d0e5Sschwarze { 183875d4d0e5Sschwarze 183975d4d0e5Sschwarze n = n->child; 184075d4d0e5Sschwarze if (NULL == n) 1841526e306bSschwarze return 0; 18427ead8a4eSschwarze print_node(meta, n); 184375d4d0e5Sschwarze n = n->next; 184475d4d0e5Sschwarze if (NULL == n) 1845526e306bSschwarze return 0; 184651c88ffdSschwarze outflags &= ~MMAN_spc; 184751c88ffdSschwarze print_word("("); 18487ead8a4eSschwarze print_node(meta, n); 184951c88ffdSschwarze print_word(")"); 1850526e306bSschwarze return 0; 185175d4d0e5Sschwarze } 1852