1*95c635efSGarrett D'Amore /* $Id: mdoc_man.c,v 1.9 2011/10/24 21:47:59 schwarze Exp $ */ 2*95c635efSGarrett D'Amore /* 3*95c635efSGarrett D'Amore * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org> 4*95c635efSGarrett D'Amore * 5*95c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any 6*95c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above 7*95c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies. 8*95c635efSGarrett D'Amore * 9*95c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10*95c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*95c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12*95c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*95c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*95c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15*95c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16*95c635efSGarrett D'Amore */ 17*95c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H 18*95c635efSGarrett D'Amore #include "config.h" 19*95c635efSGarrett D'Amore #endif 20*95c635efSGarrett D'Amore 21*95c635efSGarrett D'Amore #include <stdio.h> 22*95c635efSGarrett D'Amore #include <string.h> 23*95c635efSGarrett D'Amore 24*95c635efSGarrett D'Amore #include "mandoc.h" 25*95c635efSGarrett D'Amore #include "man.h" 26*95c635efSGarrett D'Amore #include "mdoc.h" 27*95c635efSGarrett D'Amore #include "main.h" 28*95c635efSGarrett D'Amore 29*95c635efSGarrett D'Amore #define DECL_ARGS const struct mdoc_meta *m, \ 30*95c635efSGarrett D'Amore const struct mdoc_node *n, \ 31*95c635efSGarrett D'Amore struct mman *mm 32*95c635efSGarrett D'Amore 33*95c635efSGarrett D'Amore struct mman { 34*95c635efSGarrett D'Amore int need_space; /* next word needs prior ws */ 35*95c635efSGarrett D'Amore int need_nl; /* next word needs prior nl */ 36*95c635efSGarrett D'Amore }; 37*95c635efSGarrett D'Amore 38*95c635efSGarrett D'Amore struct manact { 39*95c635efSGarrett D'Amore int (*cond)(DECL_ARGS); /* DON'T run actions */ 40*95c635efSGarrett D'Amore int (*pre)(DECL_ARGS); /* pre-node action */ 41*95c635efSGarrett D'Amore void (*post)(DECL_ARGS); /* post-node action */ 42*95c635efSGarrett D'Amore const char *prefix; /* pre-node string constant */ 43*95c635efSGarrett D'Amore const char *suffix; /* post-node string constant */ 44*95c635efSGarrett D'Amore }; 45*95c635efSGarrett D'Amore 46*95c635efSGarrett D'Amore static int cond_body(DECL_ARGS); 47*95c635efSGarrett D'Amore static int cond_head(DECL_ARGS); 48*95c635efSGarrett D'Amore static void post_bd(DECL_ARGS); 49*95c635efSGarrett D'Amore static void post_dl(DECL_ARGS); 50*95c635efSGarrett D'Amore static void post_enc(DECL_ARGS); 51*95c635efSGarrett D'Amore static void post_nm(DECL_ARGS); 52*95c635efSGarrett D'Amore static void post_percent(DECL_ARGS); 53*95c635efSGarrett D'Amore static void post_pf(DECL_ARGS); 54*95c635efSGarrett D'Amore static void post_sect(DECL_ARGS); 55*95c635efSGarrett D'Amore static void post_sp(DECL_ARGS); 56*95c635efSGarrett D'Amore static int pre_ap(DECL_ARGS); 57*95c635efSGarrett D'Amore static int pre_bd(DECL_ARGS); 58*95c635efSGarrett D'Amore static int pre_br(DECL_ARGS); 59*95c635efSGarrett D'Amore static int pre_bx(DECL_ARGS); 60*95c635efSGarrett D'Amore static int pre_dl(DECL_ARGS); 61*95c635efSGarrett D'Amore static int pre_enc(DECL_ARGS); 62*95c635efSGarrett D'Amore static int pre_it(DECL_ARGS); 63*95c635efSGarrett D'Amore static int pre_nm(DECL_ARGS); 64*95c635efSGarrett D'Amore static int pre_ns(DECL_ARGS); 65*95c635efSGarrett D'Amore static int pre_pp(DECL_ARGS); 66*95c635efSGarrett D'Amore static int pre_sp(DECL_ARGS); 67*95c635efSGarrett D'Amore static int pre_sect(DECL_ARGS); 68*95c635efSGarrett D'Amore static int pre_ux(DECL_ARGS); 69*95c635efSGarrett D'Amore static int pre_xr(DECL_ARGS); 70*95c635efSGarrett D'Amore static void print_word(struct mman *, const char *); 71*95c635efSGarrett D'Amore static void print_node(DECL_ARGS); 72*95c635efSGarrett D'Amore 73*95c635efSGarrett D'Amore static const struct manact manacts[MDOC_MAX + 1] = { 74*95c635efSGarrett D'Amore { NULL, pre_ap, NULL, NULL, NULL }, /* Ap */ 75*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Dd */ 76*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Dt */ 77*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Os */ 78*95c635efSGarrett D'Amore { NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */ 79*95c635efSGarrett D'Amore { NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */ 80*95c635efSGarrett D'Amore { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */ 81*95c635efSGarrett D'Amore { cond_body, pre_dl, post_dl, NULL, NULL }, /* D1 */ 82*95c635efSGarrett D'Amore { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */ 83*95c635efSGarrett D'Amore { cond_body, pre_bd, post_bd, NULL, NULL }, /* Bd */ 84*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Ed */ 85*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Bl */ 86*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* El */ 87*95c635efSGarrett D'Amore { NULL, pre_it, NULL, NULL, NULL }, /* _It */ 88*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ad */ 89*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _An */ 90*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ar */ 91*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cd */ 92*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cm */ 93*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Dv */ 94*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Er */ 95*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Ev */ 96*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "The \\fB", 97*95c635efSGarrett D'Amore "\\fP\nutility exits 0 on success, and >0 if an error occurs." 98*95c635efSGarrett D'Amore }, /* Ex */ 99*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Fa */ 100*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Fd */ 101*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fB-", "\\fP" }, /* Fl */ 102*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Fn */ 103*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Ft */ 104*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ic */ 105*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _In */ 106*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Li */ 107*95c635efSGarrett D'Amore { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */ 108*95c635efSGarrett D'Amore { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */ 109*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */ 110*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Ot */ 111*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Pa */ 112*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "The \\fB", 113*95c635efSGarrett D'Amore "\\fP\nfunction returns the value 0 if successful;\n" 114*95c635efSGarrett D'Amore "otherwise the value -1 is returned and the global\n" 115*95c635efSGarrett D'Amore "variable \\fIerrno\\fP is set to indicate the error." 116*95c635efSGarrett D'Amore }, /* Rv */ 117*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* St */ 118*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Va */ 119*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Vt */ 120*95c635efSGarrett D'Amore { NULL, pre_xr, NULL, NULL, NULL }, /* Xr */ 121*95c635efSGarrett D'Amore { NULL, NULL, post_percent, NULL, NULL }, /* _%A */ 122*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _%B */ 123*95c635efSGarrett D'Amore { NULL, NULL, post_percent, NULL, NULL }, /* _%D */ 124*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _%I */ 125*95c635efSGarrett D'Amore { NULL, pre_enc, post_percent, "\\fI", "\\fP" }, /* %J */ 126*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _%N */ 127*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _%O */ 128*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _%P */ 129*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _%R */ 130*95c635efSGarrett D'Amore { NULL, pre_enc, post_percent, "\"", "\"" }, /* %T */ 131*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _%V */ 132*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Ac */ 133*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "<", ">" }, /* Ao */ 134*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */ 135*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* At */ 136*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Bc */ 137*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Bf */ 138*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */ 139*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */ 140*95c635efSGarrett D'Amore { NULL, pre_ux, NULL, "BSD/OS", NULL }, /* Bsx */ 141*95c635efSGarrett D'Amore { NULL, pre_bx, NULL, NULL, NULL }, /* Bx */ 142*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Db */ 143*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Dc */ 144*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "``", "''" }, /* Do */ 145*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */ 146*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Ec */ 147*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Ef */ 148*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Em */ 149*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Eo */ 150*95c635efSGarrett D'Amore { NULL, pre_ux, NULL, "FreeBSD", NULL }, /* Fx */ 151*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ms */ 152*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* No */ 153*95c635efSGarrett D'Amore { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */ 154*95c635efSGarrett D'Amore { NULL, pre_ux, NULL, "NetBSD", NULL }, /* Nx */ 155*95c635efSGarrett D'Amore { NULL, pre_ux, NULL, "OpenBSD", NULL }, /* Ox */ 156*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Pc */ 157*95c635efSGarrett D'Amore { NULL, NULL, post_pf, NULL, NULL }, /* Pf */ 158*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "(", ")" }, /* Po */ 159*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */ 160*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Qc */ 161*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */ 162*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */ 163*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */ 164*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Re */ 165*95c635efSGarrett D'Amore { cond_body, pre_pp, NULL, NULL, NULL }, /* Rs */ 166*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Sc */ 167*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "`", "'" }, /* So */ 168*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */ 169*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Sm */ 170*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Sx */ 171*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Sy */ 172*95c635efSGarrett D'Amore { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Tn */ 173*95c635efSGarrett D'Amore { NULL, pre_ux, NULL, "UNIX", NULL }, /* Ux */ 174*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Xc */ 175*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Xo */ 176*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Fo */ 177*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Fc */ 178*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */ 179*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Oc */ 180*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Bk */ 181*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Ek */ 182*95c635efSGarrett D'Amore { NULL, pre_ux, NULL, "is currently in beta test.", NULL }, /* Bt */ 183*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Hf */ 184*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Fr */ 185*95c635efSGarrett D'Amore { NULL, pre_ux, NULL, "currently under development.", NULL }, /* Ud */ 186*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Lb */ 187*95c635efSGarrett D'Amore { NULL, pre_pp, NULL, NULL, NULL }, /* Lp */ 188*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Lk */ 189*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Mt */ 190*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */ 191*95c635efSGarrett D'Amore { cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */ 192*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* Brc */ 193*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _%C */ 194*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Es */ 195*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _En */ 196*95c635efSGarrett D'Amore { NULL, pre_ux, NULL, "DragonFly", NULL }, /* Dx */ 197*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _%Q */ 198*95c635efSGarrett D'Amore { NULL, pre_br, NULL, NULL, NULL }, /* br */ 199*95c635efSGarrett D'Amore { NULL, pre_sp, post_sp, NULL, NULL }, /* sp */ 200*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _%U */ 201*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* _Ta */ 202*95c635efSGarrett D'Amore { NULL, NULL, NULL, NULL, NULL }, /* ROOT */ 203*95c635efSGarrett D'Amore }; 204*95c635efSGarrett D'Amore 205*95c635efSGarrett D'Amore static void 206*95c635efSGarrett D'Amore print_word(struct mman *mm, const char *s) 207*95c635efSGarrett D'Amore { 208*95c635efSGarrett D'Amore 209*95c635efSGarrett D'Amore if (mm->need_nl) { 210*95c635efSGarrett D'Amore /* 211*95c635efSGarrett D'Amore * If we need a newline, print it now and start afresh. 212*95c635efSGarrett D'Amore */ 213*95c635efSGarrett D'Amore putchar('\n'); 214*95c635efSGarrett D'Amore mm->need_space = 0; 215*95c635efSGarrett D'Amore mm->need_nl = 0; 216*95c635efSGarrett D'Amore } else if (mm->need_space && '\0' != s[0]) 217*95c635efSGarrett D'Amore /* 218*95c635efSGarrett D'Amore * If we need a space, only print it before 219*95c635efSGarrett D'Amore * (1) a nonzero length word; 220*95c635efSGarrett D'Amore * (2) a word that is non-punctuation; and 221*95c635efSGarrett D'Amore * (3) if punctuation, non-terminating puncutation. 222*95c635efSGarrett D'Amore */ 223*95c635efSGarrett D'Amore if (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) 224*95c635efSGarrett D'Amore putchar(' '); 225*95c635efSGarrett D'Amore 226*95c635efSGarrett D'Amore /* 227*95c635efSGarrett D'Amore * Reassign needing space if we're not following opening 228*95c635efSGarrett D'Amore * punctuation. 229*95c635efSGarrett D'Amore */ 230*95c635efSGarrett D'Amore mm->need_space = 231*95c635efSGarrett D'Amore ('(' != s[0] && '[' != s[0]) || '\0' != s[1]; 232*95c635efSGarrett D'Amore 233*95c635efSGarrett D'Amore for ( ; *s; s++) { 234*95c635efSGarrett D'Amore switch (*s) { 235*95c635efSGarrett D'Amore case (ASCII_NBRSP): 236*95c635efSGarrett D'Amore printf("\\~"); 237*95c635efSGarrett D'Amore break; 238*95c635efSGarrett D'Amore case (ASCII_HYPH): 239*95c635efSGarrett D'Amore putchar('-'); 240*95c635efSGarrett D'Amore break; 241*95c635efSGarrett D'Amore default: 242*95c635efSGarrett D'Amore putchar((unsigned char)*s); 243*95c635efSGarrett D'Amore break; 244*95c635efSGarrett D'Amore } 245*95c635efSGarrett D'Amore } 246*95c635efSGarrett D'Amore } 247*95c635efSGarrett D'Amore 248*95c635efSGarrett D'Amore void 249*95c635efSGarrett D'Amore man_man(void *arg, const struct man *man) 250*95c635efSGarrett D'Amore { 251*95c635efSGarrett D'Amore 252*95c635efSGarrett D'Amore /* 253*95c635efSGarrett D'Amore * Dump the keep buffer. 254*95c635efSGarrett D'Amore * We're guaranteed by now that this exists (is non-NULL). 255*95c635efSGarrett D'Amore * Flush stdout afterward, just in case. 256*95c635efSGarrett D'Amore */ 257*95c635efSGarrett D'Amore fputs(mparse_getkeep(man_mparse(man)), stdout); 258*95c635efSGarrett D'Amore fflush(stdout); 259*95c635efSGarrett D'Amore } 260*95c635efSGarrett D'Amore 261*95c635efSGarrett D'Amore void 262*95c635efSGarrett D'Amore man_mdoc(void *arg, const struct mdoc *mdoc) 263*95c635efSGarrett D'Amore { 264*95c635efSGarrett D'Amore const struct mdoc_meta *m; 265*95c635efSGarrett D'Amore const struct mdoc_node *n; 266*95c635efSGarrett D'Amore struct mman mm; 267*95c635efSGarrett D'Amore 268*95c635efSGarrett D'Amore m = mdoc_meta(mdoc); 269*95c635efSGarrett D'Amore n = mdoc_node(mdoc); 270*95c635efSGarrett D'Amore 271*95c635efSGarrett D'Amore printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"", 272*95c635efSGarrett D'Amore m->title, m->msec, m->date, m->os, m->vol); 273*95c635efSGarrett D'Amore 274*95c635efSGarrett D'Amore memset(&mm, 0, sizeof(struct mman)); 275*95c635efSGarrett D'Amore 276*95c635efSGarrett D'Amore mm.need_nl = 1; 277*95c635efSGarrett D'Amore print_node(m, n, &mm); 278*95c635efSGarrett D'Amore putchar('\n'); 279*95c635efSGarrett D'Amore } 280*95c635efSGarrett D'Amore 281*95c635efSGarrett D'Amore static void 282*95c635efSGarrett D'Amore print_node(DECL_ARGS) 283*95c635efSGarrett D'Amore { 284*95c635efSGarrett D'Amore const struct mdoc_node *prev, *sub; 285*95c635efSGarrett D'Amore const struct manact *act; 286*95c635efSGarrett D'Amore int cond, do_sub; 287*95c635efSGarrett D'Amore 288*95c635efSGarrett D'Amore /* 289*95c635efSGarrett D'Amore * Break the line if we were parsed subsequent the current node. 290*95c635efSGarrett D'Amore * This makes the page structure be more consistent. 291*95c635efSGarrett D'Amore */ 292*95c635efSGarrett D'Amore prev = n->prev ? n->prev : n->parent; 293*95c635efSGarrett D'Amore if (prev && prev->line < n->line) 294*95c635efSGarrett D'Amore mm->need_nl = 1; 295*95c635efSGarrett D'Amore 296*95c635efSGarrett D'Amore act = NULL; 297*95c635efSGarrett D'Amore cond = 0; 298*95c635efSGarrett D'Amore do_sub = 1; 299*95c635efSGarrett D'Amore 300*95c635efSGarrett D'Amore if (MDOC_TEXT == n->type) { 301*95c635efSGarrett D'Amore /* 302*95c635efSGarrett D'Amore * Make sure that we don't happen to start with a 303*95c635efSGarrett D'Amore * control character at the start of a line. 304*95c635efSGarrett D'Amore */ 305*95c635efSGarrett D'Amore if (mm->need_nl && ('.' == *n->string || 306*95c635efSGarrett D'Amore '\'' == *n->string)) { 307*95c635efSGarrett D'Amore print_word(mm, "\\&"); 308*95c635efSGarrett D'Amore mm->need_space = 0; 309*95c635efSGarrett D'Amore } 310*95c635efSGarrett D'Amore print_word(mm, n->string); 311*95c635efSGarrett D'Amore } else { 312*95c635efSGarrett D'Amore /* 313*95c635efSGarrett D'Amore * Conditionally run the pre-node action handler for a 314*95c635efSGarrett D'Amore * node. 315*95c635efSGarrett D'Amore */ 316*95c635efSGarrett D'Amore act = manacts + n->tok; 317*95c635efSGarrett D'Amore cond = NULL == act->cond || (*act->cond)(m, n, mm); 318*95c635efSGarrett D'Amore if (cond && act->pre) 319*95c635efSGarrett D'Amore do_sub = (*act->pre)(m, n, mm); 320*95c635efSGarrett D'Amore } 321*95c635efSGarrett D'Amore 322*95c635efSGarrett D'Amore /* 323*95c635efSGarrett D'Amore * Conditionally run all child nodes. 324*95c635efSGarrett D'Amore * Note that this iterates over children instead of using 325*95c635efSGarrett D'Amore * recursion. This prevents unnecessary depth in the stack. 326*95c635efSGarrett D'Amore */ 327*95c635efSGarrett D'Amore if (do_sub) 328*95c635efSGarrett D'Amore for (sub = n->child; sub; sub = sub->next) 329*95c635efSGarrett D'Amore print_node(m, sub, mm); 330*95c635efSGarrett D'Amore 331*95c635efSGarrett D'Amore /* 332*95c635efSGarrett D'Amore * Lastly, conditionally run the post-node handler. 333*95c635efSGarrett D'Amore */ 334*95c635efSGarrett D'Amore if (cond && act->post) 335*95c635efSGarrett D'Amore (*act->post)(m, n, mm); 336*95c635efSGarrett D'Amore } 337*95c635efSGarrett D'Amore 338*95c635efSGarrett D'Amore static int 339*95c635efSGarrett D'Amore cond_head(DECL_ARGS) 340*95c635efSGarrett D'Amore { 341*95c635efSGarrett D'Amore 342*95c635efSGarrett D'Amore return(MDOC_HEAD == n->type); 343*95c635efSGarrett D'Amore } 344*95c635efSGarrett D'Amore 345*95c635efSGarrett D'Amore static int 346*95c635efSGarrett D'Amore cond_body(DECL_ARGS) 347*95c635efSGarrett D'Amore { 348*95c635efSGarrett D'Amore 349*95c635efSGarrett D'Amore return(MDOC_BODY == n->type); 350*95c635efSGarrett D'Amore } 351*95c635efSGarrett D'Amore 352*95c635efSGarrett D'Amore /* 353*95c635efSGarrett D'Amore * Output a font encoding before a node, e.g., \fR. 354*95c635efSGarrett D'Amore * This obviously has no trailing space. 355*95c635efSGarrett D'Amore */ 356*95c635efSGarrett D'Amore static int 357*95c635efSGarrett D'Amore pre_enc(DECL_ARGS) 358*95c635efSGarrett D'Amore { 359*95c635efSGarrett D'Amore const char *prefix; 360*95c635efSGarrett D'Amore 361*95c635efSGarrett D'Amore prefix = manacts[n->tok].prefix; 362*95c635efSGarrett D'Amore if (NULL == prefix) 363*95c635efSGarrett D'Amore return(1); 364*95c635efSGarrett D'Amore print_word(mm, prefix); 365*95c635efSGarrett D'Amore mm->need_space = 0; 366*95c635efSGarrett D'Amore return(1); 367*95c635efSGarrett D'Amore } 368*95c635efSGarrett D'Amore 369*95c635efSGarrett D'Amore /* 370*95c635efSGarrett D'Amore * Output a font encoding subsequent a node, e.g., \fP. 371*95c635efSGarrett D'Amore */ 372*95c635efSGarrett D'Amore static void 373*95c635efSGarrett D'Amore post_enc(DECL_ARGS) 374*95c635efSGarrett D'Amore { 375*95c635efSGarrett D'Amore const char *suffix; 376*95c635efSGarrett D'Amore 377*95c635efSGarrett D'Amore suffix = manacts[n->tok].suffix; 378*95c635efSGarrett D'Amore if (NULL == suffix) 379*95c635efSGarrett D'Amore return; 380*95c635efSGarrett D'Amore mm->need_space = 0; 381*95c635efSGarrett D'Amore print_word(mm, suffix); 382*95c635efSGarrett D'Amore } 383*95c635efSGarrett D'Amore 384*95c635efSGarrett D'Amore /* 385*95c635efSGarrett D'Amore * Used in listings (percent = %A, e.g.). 386*95c635efSGarrett D'Amore * FIXME: this is incomplete. 387*95c635efSGarrett D'Amore * It doesn't print a nice ", and" for lists. 388*95c635efSGarrett D'Amore */ 389*95c635efSGarrett D'Amore static void 390*95c635efSGarrett D'Amore post_percent(DECL_ARGS) 391*95c635efSGarrett D'Amore { 392*95c635efSGarrett D'Amore 393*95c635efSGarrett D'Amore post_enc(m, n, mm); 394*95c635efSGarrett D'Amore if (n->next) 395*95c635efSGarrett D'Amore print_word(mm, ","); 396*95c635efSGarrett D'Amore else { 397*95c635efSGarrett D'Amore print_word(mm, "."); 398*95c635efSGarrett D'Amore mm->need_nl = 1; 399*95c635efSGarrett D'Amore } 400*95c635efSGarrett D'Amore } 401*95c635efSGarrett D'Amore 402*95c635efSGarrett D'Amore /* 403*95c635efSGarrett D'Amore * Print before a section header. 404*95c635efSGarrett D'Amore */ 405*95c635efSGarrett D'Amore static int 406*95c635efSGarrett D'Amore pre_sect(DECL_ARGS) 407*95c635efSGarrett D'Amore { 408*95c635efSGarrett D'Amore 409*95c635efSGarrett D'Amore if (MDOC_HEAD != n->type) 410*95c635efSGarrett D'Amore return(1); 411*95c635efSGarrett D'Amore mm->need_nl = 1; 412*95c635efSGarrett D'Amore print_word(mm, manacts[n->tok].prefix); 413*95c635efSGarrett D'Amore print_word(mm, "\""); 414*95c635efSGarrett D'Amore mm->need_space = 0; 415*95c635efSGarrett D'Amore return(1); 416*95c635efSGarrett D'Amore } 417*95c635efSGarrett D'Amore 418*95c635efSGarrett D'Amore /* 419*95c635efSGarrett D'Amore * Print subsequent a section header. 420*95c635efSGarrett D'Amore */ 421*95c635efSGarrett D'Amore static void 422*95c635efSGarrett D'Amore post_sect(DECL_ARGS) 423*95c635efSGarrett D'Amore { 424*95c635efSGarrett D'Amore 425*95c635efSGarrett D'Amore if (MDOC_HEAD != n->type) 426*95c635efSGarrett D'Amore return; 427*95c635efSGarrett D'Amore mm->need_space = 0; 428*95c635efSGarrett D'Amore print_word(mm, "\""); 429*95c635efSGarrett D'Amore mm->need_nl = 1; 430*95c635efSGarrett D'Amore } 431*95c635efSGarrett D'Amore 432*95c635efSGarrett D'Amore static int 433*95c635efSGarrett D'Amore pre_ap(DECL_ARGS) 434*95c635efSGarrett D'Amore { 435*95c635efSGarrett D'Amore 436*95c635efSGarrett D'Amore mm->need_space = 0; 437*95c635efSGarrett D'Amore print_word(mm, "'"); 438*95c635efSGarrett D'Amore mm->need_space = 0; 439*95c635efSGarrett D'Amore return(0); 440*95c635efSGarrett D'Amore } 441*95c635efSGarrett D'Amore 442*95c635efSGarrett D'Amore static int 443*95c635efSGarrett D'Amore pre_bd(DECL_ARGS) 444*95c635efSGarrett D'Amore { 445*95c635efSGarrett D'Amore 446*95c635efSGarrett D'Amore if (DISP_unfilled == n->norm->Bd.type || 447*95c635efSGarrett D'Amore DISP_literal == n->norm->Bd.type) { 448*95c635efSGarrett D'Amore mm->need_nl = 1; 449*95c635efSGarrett D'Amore print_word(mm, ".nf"); 450*95c635efSGarrett D'Amore } 451*95c635efSGarrett D'Amore mm->need_nl = 1; 452*95c635efSGarrett D'Amore return(1); 453*95c635efSGarrett D'Amore } 454*95c635efSGarrett D'Amore 455*95c635efSGarrett D'Amore static void 456*95c635efSGarrett D'Amore post_bd(DECL_ARGS) 457*95c635efSGarrett D'Amore { 458*95c635efSGarrett D'Amore 459*95c635efSGarrett D'Amore if (DISP_unfilled == n->norm->Bd.type || 460*95c635efSGarrett D'Amore DISP_literal == n->norm->Bd.type) { 461*95c635efSGarrett D'Amore mm->need_nl = 1; 462*95c635efSGarrett D'Amore print_word(mm, ".fi"); 463*95c635efSGarrett D'Amore } 464*95c635efSGarrett D'Amore mm->need_nl = 1; 465*95c635efSGarrett D'Amore } 466*95c635efSGarrett D'Amore 467*95c635efSGarrett D'Amore static int 468*95c635efSGarrett D'Amore pre_br(DECL_ARGS) 469*95c635efSGarrett D'Amore { 470*95c635efSGarrett D'Amore 471*95c635efSGarrett D'Amore mm->need_nl = 1; 472*95c635efSGarrett D'Amore print_word(mm, ".br"); 473*95c635efSGarrett D'Amore mm->need_nl = 1; 474*95c635efSGarrett D'Amore return(0); 475*95c635efSGarrett D'Amore } 476*95c635efSGarrett D'Amore 477*95c635efSGarrett D'Amore static int 478*95c635efSGarrett D'Amore pre_bx(DECL_ARGS) 479*95c635efSGarrett D'Amore { 480*95c635efSGarrett D'Amore 481*95c635efSGarrett D'Amore n = n->child; 482*95c635efSGarrett D'Amore if (n) { 483*95c635efSGarrett D'Amore print_word(mm, n->string); 484*95c635efSGarrett D'Amore mm->need_space = 0; 485*95c635efSGarrett D'Amore n = n->next; 486*95c635efSGarrett D'Amore } 487*95c635efSGarrett D'Amore print_word(mm, "BSD"); 488*95c635efSGarrett D'Amore if (NULL == n) 489*95c635efSGarrett D'Amore return(0); 490*95c635efSGarrett D'Amore mm->need_space = 0; 491*95c635efSGarrett D'Amore print_word(mm, "-"); 492*95c635efSGarrett D'Amore mm->need_space = 0; 493*95c635efSGarrett D'Amore print_word(mm, n->string); 494*95c635efSGarrett D'Amore return(0); 495*95c635efSGarrett D'Amore } 496*95c635efSGarrett D'Amore 497*95c635efSGarrett D'Amore static int 498*95c635efSGarrett D'Amore pre_dl(DECL_ARGS) 499*95c635efSGarrett D'Amore { 500*95c635efSGarrett D'Amore 501*95c635efSGarrett D'Amore mm->need_nl = 1; 502*95c635efSGarrett D'Amore print_word(mm, ".RS 6n"); 503*95c635efSGarrett D'Amore mm->need_nl = 1; 504*95c635efSGarrett D'Amore return(1); 505*95c635efSGarrett D'Amore } 506*95c635efSGarrett D'Amore 507*95c635efSGarrett D'Amore static void 508*95c635efSGarrett D'Amore post_dl(DECL_ARGS) 509*95c635efSGarrett D'Amore { 510*95c635efSGarrett D'Amore 511*95c635efSGarrett D'Amore mm->need_nl = 1; 512*95c635efSGarrett D'Amore print_word(mm, ".RE"); 513*95c635efSGarrett D'Amore mm->need_nl = 1; 514*95c635efSGarrett D'Amore } 515*95c635efSGarrett D'Amore 516*95c635efSGarrett D'Amore static int 517*95c635efSGarrett D'Amore pre_it(DECL_ARGS) 518*95c635efSGarrett D'Amore { 519*95c635efSGarrett D'Amore const struct mdoc_node *bln; 520*95c635efSGarrett D'Amore 521*95c635efSGarrett D'Amore if (MDOC_HEAD == n->type) { 522*95c635efSGarrett D'Amore mm->need_nl = 1; 523*95c635efSGarrett D'Amore print_word(mm, ".TP"); 524*95c635efSGarrett D'Amore bln = n->parent->parent->prev; 525*95c635efSGarrett D'Amore switch (bln->norm->Bl.type) { 526*95c635efSGarrett D'Amore case (LIST_bullet): 527*95c635efSGarrett D'Amore print_word(mm, "4n"); 528*95c635efSGarrett D'Amore mm->need_nl = 1; 529*95c635efSGarrett D'Amore print_word(mm, "\\fBo\\fP"); 530*95c635efSGarrett D'Amore break; 531*95c635efSGarrett D'Amore default: 532*95c635efSGarrett D'Amore if (bln->norm->Bl.width) 533*95c635efSGarrett D'Amore print_word(mm, bln->norm->Bl.width); 534*95c635efSGarrett D'Amore break; 535*95c635efSGarrett D'Amore } 536*95c635efSGarrett D'Amore mm->need_nl = 1; 537*95c635efSGarrett D'Amore } 538*95c635efSGarrett D'Amore return(1); 539*95c635efSGarrett D'Amore } 540*95c635efSGarrett D'Amore 541*95c635efSGarrett D'Amore static int 542*95c635efSGarrett D'Amore pre_nm(DECL_ARGS) 543*95c635efSGarrett D'Amore { 544*95c635efSGarrett D'Amore 545*95c635efSGarrett D'Amore if (MDOC_ELEM != n->type && MDOC_HEAD != n->type) 546*95c635efSGarrett D'Amore return(1); 547*95c635efSGarrett D'Amore print_word(mm, "\\fB"); 548*95c635efSGarrett D'Amore mm->need_space = 0; 549*95c635efSGarrett D'Amore if (NULL == n->child) 550*95c635efSGarrett D'Amore print_word(mm, m->name); 551*95c635efSGarrett D'Amore return(1); 552*95c635efSGarrett D'Amore } 553*95c635efSGarrett D'Amore 554*95c635efSGarrett D'Amore static void 555*95c635efSGarrett D'Amore post_nm(DECL_ARGS) 556*95c635efSGarrett D'Amore { 557*95c635efSGarrett D'Amore 558*95c635efSGarrett D'Amore if (MDOC_ELEM != n->type && MDOC_HEAD != n->type) 559*95c635efSGarrett D'Amore return; 560*95c635efSGarrett D'Amore mm->need_space = 0; 561*95c635efSGarrett D'Amore print_word(mm, "\\fP"); 562*95c635efSGarrett D'Amore } 563*95c635efSGarrett D'Amore 564*95c635efSGarrett D'Amore static int 565*95c635efSGarrett D'Amore pre_ns(DECL_ARGS) 566*95c635efSGarrett D'Amore { 567*95c635efSGarrett D'Amore 568*95c635efSGarrett D'Amore mm->need_space = 0; 569*95c635efSGarrett D'Amore return(0); 570*95c635efSGarrett D'Amore } 571*95c635efSGarrett D'Amore 572*95c635efSGarrett D'Amore static void 573*95c635efSGarrett D'Amore post_pf(DECL_ARGS) 574*95c635efSGarrett D'Amore { 575*95c635efSGarrett D'Amore 576*95c635efSGarrett D'Amore mm->need_space = 0; 577*95c635efSGarrett D'Amore } 578*95c635efSGarrett D'Amore 579*95c635efSGarrett D'Amore static int 580*95c635efSGarrett D'Amore pre_pp(DECL_ARGS) 581*95c635efSGarrett D'Amore { 582*95c635efSGarrett D'Amore 583*95c635efSGarrett D'Amore mm->need_nl = 1; 584*95c635efSGarrett D'Amore if (MDOC_It == n->parent->tok) 585*95c635efSGarrett D'Amore print_word(mm, ".sp"); 586*95c635efSGarrett D'Amore else 587*95c635efSGarrett D'Amore print_word(mm, ".PP"); 588*95c635efSGarrett D'Amore mm->need_nl = 1; 589*95c635efSGarrett D'Amore return(1); 590*95c635efSGarrett D'Amore } 591*95c635efSGarrett D'Amore 592*95c635efSGarrett D'Amore static int 593*95c635efSGarrett D'Amore pre_sp(DECL_ARGS) 594*95c635efSGarrett D'Amore { 595*95c635efSGarrett D'Amore 596*95c635efSGarrett D'Amore mm->need_nl = 1; 597*95c635efSGarrett D'Amore print_word(mm, ".sp"); 598*95c635efSGarrett D'Amore return(1); 599*95c635efSGarrett D'Amore } 600*95c635efSGarrett D'Amore 601*95c635efSGarrett D'Amore static void 602*95c635efSGarrett D'Amore post_sp(DECL_ARGS) 603*95c635efSGarrett D'Amore { 604*95c635efSGarrett D'Amore 605*95c635efSGarrett D'Amore mm->need_nl = 1; 606*95c635efSGarrett D'Amore } 607*95c635efSGarrett D'Amore 608*95c635efSGarrett D'Amore static int 609*95c635efSGarrett D'Amore pre_xr(DECL_ARGS) 610*95c635efSGarrett D'Amore { 611*95c635efSGarrett D'Amore 612*95c635efSGarrett D'Amore n = n->child; 613*95c635efSGarrett D'Amore if (NULL == n) 614*95c635efSGarrett D'Amore return(0); 615*95c635efSGarrett D'Amore print_node(m, n, mm); 616*95c635efSGarrett D'Amore n = n->next; 617*95c635efSGarrett D'Amore if (NULL == n) 618*95c635efSGarrett D'Amore return(0); 619*95c635efSGarrett D'Amore mm->need_space = 0; 620*95c635efSGarrett D'Amore print_word(mm, "("); 621*95c635efSGarrett D'Amore print_node(m, n, mm); 622*95c635efSGarrett D'Amore print_word(mm, ")"); 623*95c635efSGarrett D'Amore return(0); 624*95c635efSGarrett D'Amore } 625*95c635efSGarrett D'Amore 626*95c635efSGarrett D'Amore static int 627*95c635efSGarrett D'Amore pre_ux(DECL_ARGS) 628*95c635efSGarrett D'Amore { 629*95c635efSGarrett D'Amore 630*95c635efSGarrett D'Amore print_word(mm, manacts[n->tok].prefix); 631*95c635efSGarrett D'Amore if (NULL == n->child) 632*95c635efSGarrett D'Amore return(0); 633*95c635efSGarrett D'Amore mm->need_space = 0; 634*95c635efSGarrett D'Amore print_word(mm, "\\~"); 635*95c635efSGarrett D'Amore mm->need_space = 0; 636*95c635efSGarrett D'Amore return(1); 637*95c635efSGarrett D'Amore } 638