1294113Sbapt/* $Id: mdoc_man.c,v 1.96 2016/01/08 17:48:09 schwarze Exp $ */ 2241675Suqs/* 3294113Sbapt * Copyright (c) 2011-2016 Ingo Schwarze <schwarze@openbsd.org> 4241675Suqs * 5241675Suqs * Permission to use, copy, modify, and distribute this software for any 6241675Suqs * purpose with or without fee is hereby granted, provided that the above 7241675Suqs * copyright notice and this permission notice appear in all copies. 8241675Suqs * 9241675Suqs * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10241675Suqs * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11241675Suqs * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12241675Suqs * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13241675Suqs * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14241675Suqs * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15241675Suqs * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16241675Suqs */ 17241675Suqs#include "config.h" 18241675Suqs 19275432Sbapt#include <sys/types.h> 20275432Sbapt 21261344Suqs#include <assert.h> 22241675Suqs#include <stdio.h> 23241675Suqs#include <string.h> 24241675Suqs 25294113Sbapt#include "mandoc_aux.h" 26241675Suqs#include "mandoc.h" 27294113Sbapt#include "roff.h" 28294113Sbapt#include "mdoc.h" 29294113Sbapt#include "man.h" 30261344Suqs#include "out.h" 31241675Suqs#include "main.h" 32241675Suqs 33294113Sbapt#define DECL_ARGS const struct roff_meta *meta, struct roff_node *n 34241675Suqs 35241675Suqsstruct manact { 36241675Suqs int (*cond)(DECL_ARGS); /* DON'T run actions */ 37241675Suqs int (*pre)(DECL_ARGS); /* pre-node action */ 38241675Suqs void (*post)(DECL_ARGS); /* post-node action */ 39241675Suqs const char *prefix; /* pre-node string constant */ 40241675Suqs const char *suffix; /* post-node string constant */ 41241675Suqs}; 42241675Suqs 43241675Suqsstatic int cond_body(DECL_ARGS); 44241675Suqsstatic int cond_head(DECL_ARGS); 45261344Suqsstatic void font_push(char); 46261344Suqsstatic void font_pop(void); 47261344Suqsstatic void mid_it(void); 48261344Suqsstatic void post__t(DECL_ARGS); 49275432Sbaptstatic void post_aq(DECL_ARGS); 50241675Suqsstatic void post_bd(DECL_ARGS); 51261344Suqsstatic void post_bf(DECL_ARGS); 52261344Suqsstatic void post_bk(DECL_ARGS); 53261344Suqsstatic void post_bl(DECL_ARGS); 54241675Suqsstatic void post_dl(DECL_ARGS); 55274880Sbaptstatic void post_en(DECL_ARGS); 56241675Suqsstatic void post_enc(DECL_ARGS); 57261344Suqsstatic void post_eo(DECL_ARGS); 58261344Suqsstatic void post_fa(DECL_ARGS); 59261344Suqsstatic void post_fd(DECL_ARGS); 60261344Suqsstatic void post_fl(DECL_ARGS); 61261344Suqsstatic void post_fn(DECL_ARGS); 62261344Suqsstatic void post_fo(DECL_ARGS); 63261344Suqsstatic void post_font(DECL_ARGS); 64261344Suqsstatic void post_in(DECL_ARGS); 65261344Suqsstatic void post_it(DECL_ARGS); 66261344Suqsstatic void post_lb(DECL_ARGS); 67241675Suqsstatic void post_nm(DECL_ARGS); 68241675Suqsstatic void post_percent(DECL_ARGS); 69241675Suqsstatic void post_pf(DECL_ARGS); 70241675Suqsstatic void post_sect(DECL_ARGS); 71241675Suqsstatic void post_sp(DECL_ARGS); 72261344Suqsstatic void post_vt(DECL_ARGS); 73261344Suqsstatic int pre__t(DECL_ARGS); 74261344Suqsstatic int pre_an(DECL_ARGS); 75241675Suqsstatic int pre_ap(DECL_ARGS); 76275432Sbaptstatic int pre_aq(DECL_ARGS); 77241675Suqsstatic int pre_bd(DECL_ARGS); 78261344Suqsstatic int pre_bf(DECL_ARGS); 79261344Suqsstatic int pre_bk(DECL_ARGS); 80261344Suqsstatic int pre_bl(DECL_ARGS); 81241675Suqsstatic int pre_br(DECL_ARGS); 82241675Suqsstatic int pre_bx(DECL_ARGS); 83241675Suqsstatic int pre_dl(DECL_ARGS); 84274880Sbaptstatic int pre_en(DECL_ARGS); 85241675Suqsstatic int pre_enc(DECL_ARGS); 86261344Suqsstatic int pre_em(DECL_ARGS); 87275432Sbaptstatic int pre_skip(DECL_ARGS); 88275432Sbaptstatic int pre_eo(DECL_ARGS); 89274880Sbaptstatic int pre_ex(DECL_ARGS); 90261344Suqsstatic int pre_fa(DECL_ARGS); 91261344Suqsstatic int pre_fd(DECL_ARGS); 92261344Suqsstatic int pre_fl(DECL_ARGS); 93261344Suqsstatic int pre_fn(DECL_ARGS); 94261344Suqsstatic int pre_fo(DECL_ARGS); 95261344Suqsstatic int pre_ft(DECL_ARGS); 96261344Suqsstatic int pre_in(DECL_ARGS); 97241675Suqsstatic int pre_it(DECL_ARGS); 98261344Suqsstatic int pre_lk(DECL_ARGS); 99261344Suqsstatic int pre_li(DECL_ARGS); 100274880Sbaptstatic int pre_ll(DECL_ARGS); 101241675Suqsstatic int pre_nm(DECL_ARGS); 102261344Suqsstatic int pre_no(DECL_ARGS); 103241675Suqsstatic int pre_ns(DECL_ARGS); 104241675Suqsstatic int pre_pp(DECL_ARGS); 105261344Suqsstatic int pre_rs(DECL_ARGS); 106274880Sbaptstatic int pre_rv(DECL_ARGS); 107261344Suqsstatic int pre_sm(DECL_ARGS); 108241675Suqsstatic int pre_sp(DECL_ARGS); 109241675Suqsstatic int pre_sect(DECL_ARGS); 110261344Suqsstatic int pre_sy(DECL_ARGS); 111294113Sbaptstatic void pre_syn(const struct roff_node *); 112261344Suqsstatic int pre_vt(DECL_ARGS); 113241675Suqsstatic int pre_ux(DECL_ARGS); 114241675Suqsstatic int pre_xr(DECL_ARGS); 115261344Suqsstatic void print_word(const char *); 116261344Suqsstatic void print_line(const char *, int); 117261344Suqsstatic void print_block(const char *, int); 118275432Sbaptstatic void print_offs(const char *, int); 119279527Sbaptstatic void print_width(const struct mdoc_bl *, 120294113Sbapt const struct roff_node *); 121261344Suqsstatic void print_count(int *); 122241675Suqsstatic void print_node(DECL_ARGS); 123241675Suqs 124241675Suqsstatic const struct manact manacts[MDOC_MAX + 1] = { 125241675Suqs { NULL, pre_ap, NULL, NULL, NULL }, /* Ap */ 126241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Dd */ 127241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Dt */ 128241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Os */ 129241675Suqs { NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */ 130241675Suqs { NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */ 131241675Suqs { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */ 132241675Suqs { cond_body, pre_dl, post_dl, NULL, NULL }, /* D1 */ 133241675Suqs { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */ 134241675Suqs { cond_body, pre_bd, post_bd, NULL, NULL }, /* Bd */ 135241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Ed */ 136261344Suqs { cond_body, pre_bl, post_bl, NULL, NULL }, /* Bl */ 137241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* El */ 138261344Suqs { NULL, pre_it, post_it, NULL, NULL }, /* It */ 139261344Suqs { NULL, pre_em, post_font, NULL, NULL }, /* Ad */ 140261344Suqs { NULL, pre_an, NULL, NULL, NULL }, /* An */ 141261344Suqs { NULL, pre_em, post_font, NULL, NULL }, /* Ar */ 142261344Suqs { NULL, pre_sy, post_font, NULL, NULL }, /* Cd */ 143261344Suqs { NULL, pre_sy, post_font, NULL, NULL }, /* Cm */ 144261344Suqs { NULL, pre_li, post_font, NULL, NULL }, /* Dv */ 145261344Suqs { NULL, pre_li, post_font, NULL, NULL }, /* Er */ 146261344Suqs { NULL, pre_li, post_font, NULL, NULL }, /* Ev */ 147274880Sbapt { NULL, pre_ex, NULL, NULL, NULL }, /* Ex */ 148261344Suqs { NULL, pre_fa, post_fa, NULL, NULL }, /* Fa */ 149261344Suqs { NULL, pre_fd, post_fd, NULL, NULL }, /* Fd */ 150261344Suqs { NULL, pre_fl, post_fl, NULL, NULL }, /* Fl */ 151261344Suqs { NULL, pre_fn, post_fn, NULL, NULL }, /* Fn */ 152261344Suqs { NULL, pre_ft, post_font, NULL, NULL }, /* Ft */ 153261344Suqs { NULL, pre_sy, post_font, NULL, NULL }, /* Ic */ 154261344Suqs { NULL, pre_in, post_in, NULL, NULL }, /* In */ 155261344Suqs { NULL, pre_li, post_font, NULL, NULL }, /* Li */ 156241675Suqs { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */ 157241675Suqs { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */ 158241675Suqs { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */ 159274880Sbapt { NULL, pre_ft, post_font, NULL, NULL }, /* Ot */ 160261344Suqs { NULL, pre_em, post_font, NULL, NULL }, /* Pa */ 161274880Sbapt { NULL, pre_rv, NULL, NULL, NULL }, /* Rv */ 162241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* St */ 163261344Suqs { NULL, pre_em, post_font, NULL, NULL }, /* Va */ 164261344Suqs { NULL, pre_vt, post_vt, NULL, NULL }, /* Vt */ 165241675Suqs { NULL, pre_xr, NULL, NULL, NULL }, /* Xr */ 166261344Suqs { NULL, NULL, post_percent, NULL, NULL }, /* %A */ 167261344Suqs { NULL, pre_em, post_percent, NULL, NULL }, /* %B */ 168261344Suqs { NULL, NULL, post_percent, NULL, NULL }, /* %D */ 169261344Suqs { NULL, pre_em, post_percent, NULL, NULL }, /* %I */ 170261344Suqs { NULL, pre_em, post_percent, NULL, NULL }, /* %J */ 171261344Suqs { NULL, NULL, post_percent, NULL, NULL }, /* %N */ 172261344Suqs { NULL, NULL, post_percent, NULL, NULL }, /* %O */ 173261344Suqs { NULL, NULL, post_percent, NULL, NULL }, /* %P */ 174261344Suqs { NULL, NULL, post_percent, NULL, NULL }, /* %R */ 175261344Suqs { NULL, pre__t, post__t, NULL, NULL }, /* %T */ 176261344Suqs { NULL, NULL, post_percent, NULL, NULL }, /* %V */ 177241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Ac */ 178275432Sbapt { cond_body, pre_aq, post_aq, NULL, NULL }, /* Ao */ 179275432Sbapt { cond_body, pre_aq, post_aq, NULL, NULL }, /* Aq */ 180241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* At */ 181241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Bc */ 182261344Suqs { NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */ 183241675Suqs { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */ 184241675Suqs { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */ 185241675Suqs { NULL, pre_ux, NULL, "BSD/OS", NULL }, /* Bsx */ 186241675Suqs { NULL, pre_bx, NULL, NULL, NULL }, /* Bx */ 187275432Sbapt { NULL, pre_skip, NULL, NULL, NULL }, /* Db */ 188241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Dc */ 189279527Sbapt { cond_body, pre_enc, post_enc, "\\(Lq", "\\(Rq" }, /* Do */ 190279527Sbapt { cond_body, pre_enc, post_enc, "\\(Lq", "\\(Rq" }, /* Dq */ 191261344Suqs { NULL, NULL, NULL, NULL, NULL }, /* Ec */ 192261344Suqs { NULL, NULL, NULL, NULL, NULL }, /* Ef */ 193261344Suqs { NULL, pre_em, post_font, NULL, NULL }, /* Em */ 194275432Sbapt { cond_body, pre_eo, post_eo, NULL, NULL }, /* Eo */ 195241675Suqs { NULL, pre_ux, NULL, "FreeBSD", NULL }, /* Fx */ 196261344Suqs { NULL, pre_sy, post_font, NULL, NULL }, /* Ms */ 197261344Suqs { NULL, pre_no, NULL, NULL, NULL }, /* No */ 198241675Suqs { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */ 199241675Suqs { NULL, pre_ux, NULL, "NetBSD", NULL }, /* Nx */ 200241675Suqs { NULL, pre_ux, NULL, "OpenBSD", NULL }, /* Ox */ 201241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Pc */ 202241675Suqs { NULL, NULL, post_pf, NULL, NULL }, /* Pf */ 203241675Suqs { cond_body, pre_enc, post_enc, "(", ")" }, /* Po */ 204241675Suqs { cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */ 205241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Qc */ 206261344Suqs { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Ql */ 207241675Suqs { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */ 208241675Suqs { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */ 209241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Re */ 210261344Suqs { cond_body, pre_rs, NULL, NULL, NULL }, /* Rs */ 211241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Sc */ 212261344Suqs { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* So */ 213261344Suqs { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Sq */ 214261344Suqs { NULL, pre_sm, NULL, NULL, NULL }, /* Sm */ 215261344Suqs { NULL, pre_em, post_font, NULL, NULL }, /* Sx */ 216261344Suqs { NULL, pre_sy, post_font, NULL, NULL }, /* Sy */ 217261344Suqs { NULL, pre_li, post_font, NULL, NULL }, /* Tn */ 218241675Suqs { NULL, pre_ux, NULL, "UNIX", NULL }, /* Ux */ 219261344Suqs { NULL, NULL, NULL, NULL, NULL }, /* Xc */ 220261344Suqs { NULL, NULL, NULL, NULL, NULL }, /* Xo */ 221261344Suqs { NULL, pre_fo, post_fo, NULL, NULL }, /* Fo */ 222261344Suqs { NULL, NULL, NULL, NULL, NULL }, /* Fc */ 223241675Suqs { cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */ 224241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Oc */ 225261344Suqs { NULL, pre_bk, post_bk, NULL, NULL }, /* Bk */ 226261344Suqs { NULL, NULL, NULL, NULL, NULL }, /* Ek */ 227241675Suqs { NULL, pre_ux, NULL, "is currently in beta test.", NULL }, /* Bt */ 228241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Hf */ 229274880Sbapt { NULL, pre_em, post_font, NULL, NULL }, /* Fr */ 230241675Suqs { NULL, pre_ux, NULL, "currently under development.", NULL }, /* Ud */ 231261344Suqs { NULL, NULL, post_lb, NULL, NULL }, /* Lb */ 232241675Suqs { NULL, pre_pp, NULL, NULL, NULL }, /* Lp */ 233261344Suqs { NULL, pre_lk, NULL, NULL, NULL }, /* Lk */ 234261344Suqs { NULL, pre_em, post_font, NULL, NULL }, /* Mt */ 235241675Suqs { cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */ 236241675Suqs { cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */ 237241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* Brc */ 238261344Suqs { NULL, NULL, post_percent, NULL, NULL }, /* %C */ 239275432Sbapt { NULL, pre_skip, NULL, NULL, NULL }, /* Es */ 240274880Sbapt { cond_body, pre_en, post_en, NULL, NULL }, /* En */ 241241675Suqs { NULL, pre_ux, NULL, "DragonFly", NULL }, /* Dx */ 242261344Suqs { NULL, NULL, post_percent, NULL, NULL }, /* %Q */ 243241675Suqs { NULL, pre_br, NULL, NULL, NULL }, /* br */ 244241675Suqs { NULL, pre_sp, post_sp, NULL, NULL }, /* sp */ 245261344Suqs { NULL, NULL, post_percent, NULL, NULL }, /* %U */ 246261344Suqs { NULL, NULL, NULL, NULL, NULL }, /* Ta */ 247274880Sbapt { NULL, pre_ll, post_sp, NULL, NULL }, /* ll */ 248241675Suqs { NULL, NULL, NULL, NULL, NULL }, /* ROOT */ 249241675Suqs}; 250241675Suqs 251261344Suqsstatic int outflags; 252261344Suqs#define MMAN_spc (1 << 0) /* blank character before next word */ 253261344Suqs#define MMAN_spc_force (1 << 1) /* even before trailing punctuation */ 254261344Suqs#define MMAN_nl (1 << 2) /* break man(7) code line */ 255261344Suqs#define MMAN_br (1 << 3) /* break output line */ 256261344Suqs#define MMAN_sp (1 << 4) /* insert a blank output line */ 257261344Suqs#define MMAN_PP (1 << 5) /* reset indentation etc. */ 258261344Suqs#define MMAN_Sm (1 << 6) /* horizontal spacing mode */ 259261344Suqs#define MMAN_Bk (1 << 7) /* word keep mode */ 260261344Suqs#define MMAN_Bk_susp (1 << 8) /* suspend this (after a macro) */ 261261344Suqs#define MMAN_An_split (1 << 9) /* author mode is "split" */ 262261344Suqs#define MMAN_An_nosplit (1 << 10) /* author mode is "nosplit" */ 263261344Suqs#define MMAN_PD (1 << 11) /* inter-paragraph spacing disabled */ 264261344Suqs#define MMAN_nbrword (1 << 12) /* do not break the next word */ 265261344Suqs 266261344Suqs#define BL_STACK_MAX 32 267261344Suqs 268279527Sbaptstatic int Bl_stack[BL_STACK_MAX]; /* offsets [chars] */ 269261344Suqsstatic int Bl_stack_post[BL_STACK_MAX]; /* add final .RE */ 270261344Suqsstatic int Bl_stack_len; /* number of nested Bl blocks */ 271261344Suqsstatic int TPremain; /* characters before tag is full */ 272261344Suqs 273261344Suqsstatic struct { 274261344Suqs char *head; 275261344Suqs char *tail; 276261344Suqs size_t size; 277261344Suqs} fontqueue; 278261344Suqs 279274880Sbapt 280241675Suqsstatic void 281261344Suqsfont_push(char newfont) 282241675Suqs{ 283241675Suqs 284261344Suqs if (fontqueue.head + fontqueue.size <= ++fontqueue.tail) { 285261344Suqs fontqueue.size += 8; 286261344Suqs fontqueue.head = mandoc_realloc(fontqueue.head, 287274880Sbapt fontqueue.size); 288261344Suqs } 289261344Suqs *fontqueue.tail = newfont; 290261344Suqs print_word(""); 291261344Suqs printf("\\f"); 292261344Suqs putchar(newfont); 293261344Suqs outflags &= ~MMAN_spc; 294261344Suqs} 295261344Suqs 296261344Suqsstatic void 297261344Suqsfont_pop(void) 298261344Suqs{ 299261344Suqs 300261344Suqs if (fontqueue.tail > fontqueue.head) 301261344Suqs fontqueue.tail--; 302261344Suqs outflags &= ~MMAN_spc; 303261344Suqs print_word(""); 304261344Suqs printf("\\f"); 305261344Suqs putchar(*fontqueue.tail); 306261344Suqs} 307261344Suqs 308261344Suqsstatic void 309261344Suqsprint_word(const char *s) 310261344Suqs{ 311261344Suqs 312261344Suqs if ((MMAN_PP | MMAN_sp | MMAN_br | MMAN_nl) & outflags) { 313274880Sbapt /* 314241675Suqs * If we need a newline, print it now and start afresh. 315241675Suqs */ 316261344Suqs if (MMAN_PP & outflags) { 317261344Suqs if (MMAN_sp & outflags) { 318261344Suqs if (MMAN_PD & outflags) { 319261344Suqs printf("\n.PD"); 320261344Suqs outflags &= ~MMAN_PD; 321261344Suqs } 322261344Suqs } else if ( ! (MMAN_PD & outflags)) { 323261344Suqs printf("\n.PD 0"); 324261344Suqs outflags |= MMAN_PD; 325261344Suqs } 326261344Suqs printf("\n.PP\n"); 327261344Suqs } else if (MMAN_sp & outflags) 328261344Suqs printf("\n.sp\n"); 329261344Suqs else if (MMAN_br & outflags) 330261344Suqs printf("\n.br\n"); 331261344Suqs else if (MMAN_nl & outflags) 332261344Suqs putchar('\n'); 333261344Suqs outflags &= ~(MMAN_PP|MMAN_sp|MMAN_br|MMAN_nl|MMAN_spc); 334261344Suqs if (1 == TPremain) 335261344Suqs printf(".br\n"); 336261344Suqs TPremain = 0; 337261344Suqs } else if (MMAN_spc & outflags) { 338241675Suqs /* 339261344Suqs * If we need a space, only print it if 340261344Suqs * (1) it is forced by `No' or 341261344Suqs * (2) what follows is not terminating punctuation or 342261344Suqs * (3) what follows is longer than one character. 343241675Suqs */ 344261344Suqs if (MMAN_spc_force & outflags || '\0' == s[0] || 345261344Suqs NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) { 346261344Suqs if (MMAN_Bk & outflags && 347261344Suqs ! (MMAN_Bk_susp & outflags)) 348261344Suqs putchar('\\'); 349241675Suqs putchar(' '); 350261344Suqs if (TPremain) 351261344Suqs TPremain--; 352261344Suqs } 353261344Suqs } 354241675Suqs 355241675Suqs /* 356241675Suqs * Reassign needing space if we're not following opening 357241675Suqs * punctuation. 358241675Suqs */ 359261344Suqs if (MMAN_Sm & outflags && ('\0' == s[0] || 360261344Suqs (('(' != s[0] && '[' != s[0]) || '\0' != s[1]))) 361261344Suqs outflags |= MMAN_spc; 362261344Suqs else 363261344Suqs outflags &= ~MMAN_spc; 364261344Suqs outflags &= ~(MMAN_spc_force | MMAN_Bk_susp); 365241675Suqs 366241675Suqs for ( ; *s; s++) { 367241675Suqs switch (*s) { 368274880Sbapt case ASCII_NBRSP: 369261344Suqs printf("\\ "); 370241675Suqs break; 371274880Sbapt case ASCII_HYPH: 372241675Suqs putchar('-'); 373241675Suqs break; 374274880Sbapt case ASCII_BREAK: 375274880Sbapt printf("\\:"); 376274880Sbapt break; 377274880Sbapt case ' ': 378261344Suqs if (MMAN_nbrword & outflags) { 379261344Suqs printf("\\ "); 380261344Suqs break; 381261344Suqs } 382261344Suqs /* FALLTHROUGH */ 383241675Suqs default: 384241675Suqs putchar((unsigned char)*s); 385241675Suqs break; 386241675Suqs } 387261344Suqs if (TPremain) 388261344Suqs TPremain--; 389241675Suqs } 390261344Suqs outflags &= ~MMAN_nbrword; 391241675Suqs} 392241675Suqs 393261344Suqsstatic void 394261344Suqsprint_line(const char *s, int newflags) 395261344Suqs{ 396261344Suqs 397261344Suqs outflags &= ~MMAN_br; 398261344Suqs outflags |= MMAN_nl; 399261344Suqs print_word(s); 400261344Suqs outflags |= newflags; 401261344Suqs} 402261344Suqs 403261344Suqsstatic void 404261344Suqsprint_block(const char *s, int newflags) 405261344Suqs{ 406261344Suqs 407261344Suqs outflags &= ~MMAN_PP; 408261344Suqs if (MMAN_sp & outflags) { 409261344Suqs outflags &= ~(MMAN_sp | MMAN_br); 410261344Suqs if (MMAN_PD & outflags) { 411261344Suqs print_line(".PD", 0); 412261344Suqs outflags &= ~MMAN_PD; 413261344Suqs } 414261344Suqs } else if (! (MMAN_PD & outflags)) 415261344Suqs print_line(".PD 0", MMAN_PD); 416261344Suqs outflags |= MMAN_nl; 417261344Suqs print_word(s); 418261344Suqs outflags |= MMAN_Bk_susp | newflags; 419261344Suqs} 420261344Suqs 421261344Suqsstatic void 422275432Sbaptprint_offs(const char *v, int keywords) 423261344Suqs{ 424261344Suqs char buf[24]; 425261344Suqs struct roffsu su; 426279527Sbapt int sz; 427261344Suqs 428261344Suqs print_line(".RS", MMAN_Bk_susp); 429261344Suqs 430261344Suqs /* Convert v into a number (of characters). */ 431275432Sbapt if (NULL == v || '\0' == *v || (keywords && !strcmp(v, "left"))) 432261344Suqs sz = 0; 433275432Sbapt else if (keywords && !strcmp(v, "indent")) 434261344Suqs sz = 6; 435275432Sbapt else if (keywords && !strcmp(v, "indent-two")) 436261344Suqs sz = 12; 437279527Sbapt else if (a2roffsu(v, &su, SCALE_EN) > 1) { 438261344Suqs if (SCALE_EN == su.unit) 439261344Suqs sz = su.scale; 440261344Suqs else { 441261344Suqs /* 442261344Suqs * XXX 443261344Suqs * If we are inside an enclosing list, 444261344Suqs * there is no easy way to add the two 445261344Suqs * indentations because they are provided 446261344Suqs * in terms of different units. 447261344Suqs */ 448261344Suqs print_word(v); 449261344Suqs outflags |= MMAN_nl; 450261344Suqs return; 451261344Suqs } 452261344Suqs } else 453261344Suqs sz = strlen(v); 454261344Suqs 455261344Suqs /* 456261344Suqs * We are inside an enclosing list. 457261344Suqs * Add the two indentations. 458261344Suqs */ 459261344Suqs if (Bl_stack_len) 460261344Suqs sz += Bl_stack[Bl_stack_len - 1]; 461261344Suqs 462279527Sbapt (void)snprintf(buf, sizeof(buf), "%dn", sz); 463261344Suqs print_word(buf); 464261344Suqs outflags |= MMAN_nl; 465261344Suqs} 466261344Suqs 467261344Suqs/* 468261344Suqs * Set up the indentation for a list item; used from pre_it(). 469261344Suqs */ 470274880Sbaptstatic void 471294113Sbaptprint_width(const struct mdoc_bl *bl, const struct roff_node *child) 472261344Suqs{ 473261344Suqs char buf[24]; 474261344Suqs struct roffsu su; 475279527Sbapt int numeric, remain, sz, chsz; 476261344Suqs 477261344Suqs numeric = 1; 478261344Suqs remain = 0; 479261344Suqs 480279527Sbapt /* Convert the width into a number (of characters). */ 481279527Sbapt if (bl->width == NULL) 482279527Sbapt sz = (bl->type == LIST_hang) ? 6 : 0; 483279527Sbapt else if (a2roffsu(bl->width, &su, SCALE_MAX) > 1) { 484261344Suqs if (SCALE_EN == su.unit) 485261344Suqs sz = su.scale; 486261344Suqs else { 487261344Suqs sz = 0; 488261344Suqs numeric = 0; 489261344Suqs } 490261344Suqs } else 491279527Sbapt sz = strlen(bl->width); 492261344Suqs 493261344Suqs /* XXX Rough estimation, might have multiple parts. */ 494279527Sbapt if (bl->type == LIST_enum) 495279527Sbapt chsz = (bl->count > 8) + 1; 496294113Sbapt else if (child != NULL && child->type == ROFFT_TEXT) 497279527Sbapt chsz = strlen(child->string); 498279527Sbapt else 499279527Sbapt chsz = 0; 500261344Suqs 501261344Suqs /* Maybe we are inside an enclosing list? */ 502261344Suqs mid_it(); 503261344Suqs 504261344Suqs /* 505261344Suqs * Save our own indentation, 506261344Suqs * such that child lists can use it. 507261344Suqs */ 508261344Suqs Bl_stack[Bl_stack_len++] = sz + 2; 509261344Suqs 510261344Suqs /* Set up the current list. */ 511279527Sbapt if (chsz > sz && bl->type != LIST_tag) 512261344Suqs print_block(".HP", 0); 513261344Suqs else { 514261344Suqs print_block(".TP", 0); 515261344Suqs remain = sz + 2; 516261344Suqs } 517261344Suqs if (numeric) { 518279527Sbapt (void)snprintf(buf, sizeof(buf), "%dn", sz + 2); 519261344Suqs print_word(buf); 520261344Suqs } else 521279527Sbapt print_word(bl->width); 522261344Suqs TPremain = remain; 523261344Suqs} 524261344Suqs 525274880Sbaptstatic void 526261344Suqsprint_count(int *count) 527261344Suqs{ 528274880Sbapt char buf[24]; 529261344Suqs 530279527Sbapt (void)snprintf(buf, sizeof(buf), "%d.\\&", ++*count); 531261344Suqs print_word(buf); 532261344Suqs} 533261344Suqs 534261344Suqsvoid 535294113Sbaptman_man(void *arg, const struct roff_man *man) 536241675Suqs{ 537241675Suqs 538241675Suqs /* 539241675Suqs * Dump the keep buffer. 540241675Suqs * We're guaranteed by now that this exists (is non-NULL). 541241675Suqs * Flush stdout afterward, just in case. 542241675Suqs */ 543241675Suqs fputs(mparse_getkeep(man_mparse(man)), stdout); 544241675Suqs fflush(stdout); 545241675Suqs} 546241675Suqs 547241675Suqsvoid 548294113Sbaptman_mdoc(void *arg, const struct roff_man *mdoc) 549241675Suqs{ 550294113Sbapt struct roff_node *n; 551241675Suqs 552261344Suqs printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", 553294113Sbapt mdoc->meta.title, 554294113Sbapt (mdoc->meta.msec == NULL ? "" : mdoc->meta.msec), 555294113Sbapt mdoc->meta.date, mdoc->meta.os, mdoc->meta.vol); 556241675Suqs 557261344Suqs /* Disable hyphenation and if nroff, disable justification. */ 558261344Suqs printf(".nh\n.if n .ad l"); 559241675Suqs 560261344Suqs outflags = MMAN_nl | MMAN_Sm; 561261344Suqs if (0 == fontqueue.size) { 562261344Suqs fontqueue.size = 8; 563261344Suqs fontqueue.head = fontqueue.tail = mandoc_malloc(8); 564261344Suqs *fontqueue.tail = 'R'; 565261344Suqs } 566294113Sbapt for (n = mdoc->first->child; n != NULL; n = n->next) 567294113Sbapt print_node(&mdoc->meta, n); 568241675Suqs putchar('\n'); 569241675Suqs} 570241675Suqs 571241675Suqsstatic void 572241675Suqsprint_node(DECL_ARGS) 573241675Suqs{ 574241675Suqs const struct manact *act; 575294113Sbapt struct roff_node *sub; 576241675Suqs int cond, do_sub; 577261344Suqs 578241675Suqs /* 579241675Suqs * Break the line if we were parsed subsequent the current node. 580241675Suqs * This makes the page structure be more consistent. 581241675Suqs */ 582261344Suqs if (MMAN_spc & outflags && MDOC_LINE & n->flags) 583261344Suqs outflags |= MMAN_nl; 584241675Suqs 585241675Suqs act = NULL; 586241675Suqs cond = 0; 587241675Suqs do_sub = 1; 588279527Sbapt n->flags &= ~MDOC_ENDED; 589241675Suqs 590294113Sbapt if (n->type == ROFFT_TEXT) { 591241675Suqs /* 592241675Suqs * Make sure that we don't happen to start with a 593241675Suqs * control character at the start of a line. 594241675Suqs */ 595274880Sbapt if (MMAN_nl & outflags && 596274880Sbapt ('.' == *n->string || '\'' == *n->string)) { 597261344Suqs print_word(""); 598261344Suqs printf("\\&"); 599261344Suqs outflags &= ~MMAN_spc; 600241675Suqs } 601275432Sbapt if (outflags & MMAN_Sm && ! (n->flags & MDOC_DELIMC)) 602275432Sbapt outflags |= MMAN_spc_force; 603261344Suqs print_word(n->string); 604275432Sbapt if (outflags & MMAN_Sm && ! (n->flags & MDOC_DELIMO)) 605275432Sbapt outflags |= MMAN_spc; 606241675Suqs } else { 607241675Suqs /* 608241675Suqs * Conditionally run the pre-node action handler for a 609241675Suqs * node. 610241675Suqs */ 611241675Suqs act = manacts + n->tok; 612275432Sbapt cond = act->cond == NULL || (*act->cond)(meta, n); 613294113Sbapt if (cond && act->pre != NULL && 614294113Sbapt (n->end == ENDBODY_NOT || n->child != NULL)) 615261344Suqs do_sub = (*act->pre)(meta, n); 616241675Suqs } 617241675Suqs 618274880Sbapt /* 619241675Suqs * Conditionally run all child nodes. 620241675Suqs * Note that this iterates over children instead of using 621241675Suqs * recursion. This prevents unnecessary depth in the stack. 622241675Suqs */ 623241675Suqs if (do_sub) 624241675Suqs for (sub = n->child; sub; sub = sub->next) 625261344Suqs print_node(meta, sub); 626241675Suqs 627241675Suqs /* 628241675Suqs * Lastly, conditionally run the post-node handler. 629241675Suqs */ 630274880Sbapt if (MDOC_ENDED & n->flags) 631274880Sbapt return; 632274880Sbapt 633241675Suqs if (cond && act->post) 634261344Suqs (*act->post)(meta, n); 635274880Sbapt 636274880Sbapt if (ENDBODY_NOT != n->end) 637279527Sbapt n->body->flags |= MDOC_ENDED; 638274880Sbapt 639274880Sbapt if (ENDBODY_NOSPACE == n->end) 640274880Sbapt outflags &= ~(MMAN_spc | MMAN_nl); 641241675Suqs} 642241675Suqs 643241675Suqsstatic int 644241675Suqscond_head(DECL_ARGS) 645241675Suqs{ 646241675Suqs 647294113Sbapt return n->type == ROFFT_HEAD; 648241675Suqs} 649241675Suqs 650241675Suqsstatic int 651241675Suqscond_body(DECL_ARGS) 652241675Suqs{ 653241675Suqs 654294113Sbapt return n->type == ROFFT_BODY; 655241675Suqs} 656241675Suqs 657241675Suqsstatic int 658241675Suqspre_enc(DECL_ARGS) 659241675Suqs{ 660241675Suqs const char *prefix; 661241675Suqs 662241675Suqs prefix = manacts[n->tok].prefix; 663241675Suqs if (NULL == prefix) 664294113Sbapt return 1; 665261344Suqs print_word(prefix); 666261344Suqs outflags &= ~MMAN_spc; 667294113Sbapt return 1; 668241675Suqs} 669241675Suqs 670241675Suqsstatic void 671241675Suqspost_enc(DECL_ARGS) 672241675Suqs{ 673241675Suqs const char *suffix; 674241675Suqs 675241675Suqs suffix = manacts[n->tok].suffix; 676241675Suqs if (NULL == suffix) 677241675Suqs return; 678274880Sbapt outflags &= ~(MMAN_spc | MMAN_nl); 679261344Suqs print_word(suffix); 680241675Suqs} 681241675Suqs 682274880Sbaptstatic int 683274880Sbaptpre_ex(DECL_ARGS) 684274880Sbapt{ 685294113Sbapt struct roff_node *nch; 686274880Sbapt 687274880Sbapt outflags |= MMAN_br | MMAN_nl; 688274880Sbapt 689274880Sbapt print_word("The"); 690274880Sbapt 691294113Sbapt for (nch = n->child; nch != NULL; nch = nch->next) { 692274880Sbapt font_push('B'); 693294113Sbapt print_word(nch->string); 694274880Sbapt font_pop(); 695274880Sbapt 696294113Sbapt if (nch->next == NULL) 697274880Sbapt continue; 698274880Sbapt 699294113Sbapt if (nch->prev != NULL || nch->next->next != NULL) { 700274880Sbapt outflags &= ~MMAN_spc; 701274880Sbapt print_word(","); 702274880Sbapt } 703294113Sbapt if (nch->next->next == NULL) 704274880Sbapt print_word("and"); 705274880Sbapt } 706274880Sbapt 707294113Sbapt if (n->child != NULL && n->child->next != NULL) 708274880Sbapt print_word("utilities exit\\~0"); 709274880Sbapt else 710274880Sbapt print_word("utility exits\\~0"); 711274880Sbapt 712274880Sbapt print_word("on success, and\\~>0 if an error occurs."); 713274880Sbapt outflags |= MMAN_nl; 714294113Sbapt return 0; 715274880Sbapt} 716274880Sbapt 717241675Suqsstatic void 718261344Suqspost_font(DECL_ARGS) 719261344Suqs{ 720261344Suqs 721261344Suqs font_pop(); 722261344Suqs} 723261344Suqs 724261344Suqsstatic void 725241675Suqspost_percent(DECL_ARGS) 726241675Suqs{ 727241675Suqs 728261344Suqs if (pre_em == manacts[n->tok].pre) 729261344Suqs font_pop(); 730261344Suqs if (n->next) { 731261344Suqs print_word(","); 732261344Suqs if (n->prev && n->prev->tok == n->tok && 733261344Suqs n->next->tok == n->tok) 734261344Suqs print_word("and"); 735261344Suqs } else { 736261344Suqs print_word("."); 737261344Suqs outflags |= MMAN_nl; 738241675Suqs } 739241675Suqs} 740241675Suqs 741261344Suqsstatic int 742261344Suqspre__t(DECL_ARGS) 743261344Suqs{ 744261344Suqs 745274880Sbapt if (n->parent && MDOC_Rs == n->parent->tok && 746274880Sbapt n->parent->norm->Rs.quote_T) { 747261344Suqs print_word(""); 748261344Suqs putchar('\"'); 749261344Suqs outflags &= ~MMAN_spc; 750261344Suqs } else 751261344Suqs font_push('I'); 752294113Sbapt return 1; 753261344Suqs} 754261344Suqs 755261344Suqsstatic void 756261344Suqspost__t(DECL_ARGS) 757261344Suqs{ 758261344Suqs 759274880Sbapt if (n->parent && MDOC_Rs == n->parent->tok && 760274880Sbapt n->parent->norm->Rs.quote_T) { 761261344Suqs outflags &= ~MMAN_spc; 762261344Suqs print_word(""); 763261344Suqs putchar('\"'); 764261344Suqs } else 765261344Suqs font_pop(); 766261344Suqs post_percent(meta, n); 767261344Suqs} 768261344Suqs 769241675Suqs/* 770241675Suqs * Print before a section header. 771241675Suqs */ 772241675Suqsstatic int 773241675Suqspre_sect(DECL_ARGS) 774241675Suqs{ 775241675Suqs 776294113Sbapt if (n->type == ROFFT_HEAD) { 777261344Suqs outflags |= MMAN_sp; 778261344Suqs print_block(manacts[n->tok].prefix, 0); 779261344Suqs print_word(""); 780261344Suqs putchar('\"'); 781261344Suqs outflags &= ~MMAN_spc; 782261344Suqs } 783294113Sbapt return 1; 784241675Suqs} 785241675Suqs 786241675Suqs/* 787241675Suqs * Print subsequent a section header. 788241675Suqs */ 789241675Suqsstatic void 790241675Suqspost_sect(DECL_ARGS) 791241675Suqs{ 792241675Suqs 793294113Sbapt if (n->type != ROFFT_HEAD) 794241675Suqs return; 795261344Suqs outflags &= ~MMAN_spc; 796261344Suqs print_word(""); 797261344Suqs putchar('\"'); 798261344Suqs outflags |= MMAN_nl; 799261344Suqs if (MDOC_Sh == n->tok && SEC_AUTHORS == n->sec) 800261344Suqs outflags &= ~(MMAN_An_split | MMAN_An_nosplit); 801241675Suqs} 802241675Suqs 803261344Suqs/* See mdoc_term.c, synopsis_pre() for comments. */ 804261344Suqsstatic void 805294113Sbaptpre_syn(const struct roff_node *n) 806261344Suqs{ 807261344Suqs 808261344Suqs if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags)) 809261344Suqs return; 810261344Suqs 811261344Suqs if (n->prev->tok == n->tok && 812274880Sbapt MDOC_Ft != n->tok && 813274880Sbapt MDOC_Fo != n->tok && 814274880Sbapt MDOC_Fn != n->tok) { 815261344Suqs outflags |= MMAN_br; 816261344Suqs return; 817261344Suqs } 818261344Suqs 819261344Suqs switch (n->prev->tok) { 820274880Sbapt case MDOC_Fd: 821274880Sbapt case MDOC_Fn: 822274880Sbapt case MDOC_Fo: 823274880Sbapt case MDOC_In: 824274880Sbapt case MDOC_Vt: 825261344Suqs outflags |= MMAN_sp; 826261344Suqs break; 827274880Sbapt case MDOC_Ft: 828261344Suqs if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) { 829261344Suqs outflags |= MMAN_sp; 830261344Suqs break; 831261344Suqs } 832261344Suqs /* FALLTHROUGH */ 833261344Suqs default: 834261344Suqs outflags |= MMAN_br; 835261344Suqs break; 836261344Suqs } 837261344Suqs} 838261344Suqs 839241675Suqsstatic int 840261344Suqspre_an(DECL_ARGS) 841261344Suqs{ 842261344Suqs 843261344Suqs switch (n->norm->An.auth) { 844274880Sbapt case AUTH_split: 845261344Suqs outflags &= ~MMAN_An_nosplit; 846261344Suqs outflags |= MMAN_An_split; 847294113Sbapt return 0; 848274880Sbapt case AUTH_nosplit: 849261344Suqs outflags &= ~MMAN_An_split; 850261344Suqs outflags |= MMAN_An_nosplit; 851294113Sbapt return 0; 852261344Suqs default: 853261344Suqs if (MMAN_An_split & outflags) 854261344Suqs outflags |= MMAN_br; 855261344Suqs else if (SEC_AUTHORS == n->sec && 856261344Suqs ! (MMAN_An_nosplit & outflags)) 857261344Suqs outflags |= MMAN_An_split; 858294113Sbapt return 1; 859261344Suqs } 860261344Suqs} 861261344Suqs 862261344Suqsstatic int 863241675Suqspre_ap(DECL_ARGS) 864241675Suqs{ 865241675Suqs 866261344Suqs outflags &= ~MMAN_spc; 867261344Suqs print_word("'"); 868261344Suqs outflags &= ~MMAN_spc; 869294113Sbapt return 0; 870241675Suqs} 871241675Suqs 872241675Suqsstatic int 873275432Sbaptpre_aq(DECL_ARGS) 874275432Sbapt{ 875275432Sbapt 876294113Sbapt print_word(n->child != NULL && n->child->next == NULL && 877279527Sbapt n->child->tok == MDOC_Mt ? "<" : "\\(la"); 878275432Sbapt outflags &= ~MMAN_spc; 879294113Sbapt return 1; 880275432Sbapt} 881275432Sbapt 882275432Sbaptstatic void 883275432Sbaptpost_aq(DECL_ARGS) 884275432Sbapt{ 885275432Sbapt 886275432Sbapt outflags &= ~(MMAN_spc | MMAN_nl); 887294113Sbapt print_word(n->child != NULL && n->child->next == NULL && 888279527Sbapt n->child->tok == MDOC_Mt ? ">" : "\\(ra"); 889275432Sbapt} 890275432Sbapt 891275432Sbaptstatic int 892241675Suqspre_bd(DECL_ARGS) 893241675Suqs{ 894241675Suqs 895261344Suqs outflags &= ~(MMAN_PP | MMAN_sp | MMAN_br); 896261344Suqs 897241675Suqs if (DISP_unfilled == n->norm->Bd.type || 898261344Suqs DISP_literal == n->norm->Bd.type) 899261344Suqs print_line(".nf", 0); 900261344Suqs if (0 == n->norm->Bd.comp && NULL != n->parent->prev) 901261344Suqs outflags |= MMAN_sp; 902275432Sbapt print_offs(n->norm->Bd.offs, 1); 903294113Sbapt return 1; 904241675Suqs} 905241675Suqs 906241675Suqsstatic void 907241675Suqspost_bd(DECL_ARGS) 908241675Suqs{ 909241675Suqs 910261344Suqs /* Close out this display. */ 911261344Suqs print_line(".RE", MMAN_nl); 912241675Suqs if (DISP_unfilled == n->norm->Bd.type || 913261344Suqs DISP_literal == n->norm->Bd.type) 914261344Suqs print_line(".fi", MMAN_nl); 915261344Suqs 916261344Suqs /* Maybe we are inside an enclosing list? */ 917261344Suqs if (NULL != n->parent->next) 918261344Suqs mid_it(); 919261344Suqs} 920261344Suqs 921261344Suqsstatic int 922261344Suqspre_bf(DECL_ARGS) 923261344Suqs{ 924261344Suqs 925261344Suqs switch (n->type) { 926294113Sbapt case ROFFT_BLOCK: 927294113Sbapt return 1; 928294113Sbapt case ROFFT_BODY: 929261344Suqs break; 930261344Suqs default: 931294113Sbapt return 0; 932241675Suqs } 933261344Suqs switch (n->norm->Bf.font) { 934274880Sbapt case FONT_Em: 935261344Suqs font_push('I'); 936261344Suqs break; 937274880Sbapt case FONT_Sy: 938261344Suqs font_push('B'); 939261344Suqs break; 940261344Suqs default: 941261344Suqs font_push('R'); 942261344Suqs break; 943261344Suqs } 944294113Sbapt return 1; 945241675Suqs} 946241675Suqs 947261344Suqsstatic void 948261344Suqspost_bf(DECL_ARGS) 949261344Suqs{ 950261344Suqs 951294113Sbapt if (n->type == ROFFT_BODY) 952261344Suqs font_pop(); 953261344Suqs} 954261344Suqs 955241675Suqsstatic int 956261344Suqspre_bk(DECL_ARGS) 957261344Suqs{ 958261344Suqs 959261344Suqs switch (n->type) { 960294113Sbapt case ROFFT_BLOCK: 961294113Sbapt return 1; 962294113Sbapt case ROFFT_BODY: 963261344Suqs outflags |= MMAN_Bk; 964294113Sbapt return 1; 965261344Suqs default: 966294113Sbapt return 0; 967261344Suqs } 968261344Suqs} 969261344Suqs 970261344Suqsstatic void 971261344Suqspost_bk(DECL_ARGS) 972261344Suqs{ 973261344Suqs 974294113Sbapt if (n->type == ROFFT_BODY) 975261344Suqs outflags &= ~MMAN_Bk; 976261344Suqs} 977261344Suqs 978261344Suqsstatic int 979261344Suqspre_bl(DECL_ARGS) 980261344Suqs{ 981261344Suqs size_t icol; 982261344Suqs 983261344Suqs /* 984261344Suqs * print_offs() will increase the -offset to account for 985261344Suqs * a possible enclosing .It, but any enclosed .It blocks 986261344Suqs * just nest and do not add up their indentation. 987261344Suqs */ 988261344Suqs if (n->norm->Bl.offs) { 989275432Sbapt print_offs(n->norm->Bl.offs, 0); 990261344Suqs Bl_stack[Bl_stack_len++] = 0; 991261344Suqs } 992261344Suqs 993261344Suqs switch (n->norm->Bl.type) { 994274880Sbapt case LIST_enum: 995261344Suqs n->norm->Bl.count = 0; 996294113Sbapt return 1; 997274880Sbapt case LIST_column: 998261344Suqs break; 999261344Suqs default: 1000294113Sbapt return 1; 1001261344Suqs } 1002261344Suqs 1003294113Sbapt if (n->child != NULL) { 1004279527Sbapt print_line(".TS", MMAN_nl); 1005279527Sbapt for (icol = 0; icol < n->norm->Bl.ncols; icol++) 1006279527Sbapt print_word("l"); 1007279527Sbapt print_word("."); 1008279527Sbapt } 1009261344Suqs outflags |= MMAN_nl; 1010294113Sbapt return 1; 1011261344Suqs} 1012261344Suqs 1013261344Suqsstatic void 1014261344Suqspost_bl(DECL_ARGS) 1015261344Suqs{ 1016261344Suqs 1017261344Suqs switch (n->norm->Bl.type) { 1018274880Sbapt case LIST_column: 1019294113Sbapt if (n->child != NULL) 1020279527Sbapt print_line(".TE", 0); 1021261344Suqs break; 1022274880Sbapt case LIST_enum: 1023261344Suqs n->norm->Bl.count = 0; 1024261344Suqs break; 1025261344Suqs default: 1026261344Suqs break; 1027261344Suqs } 1028261344Suqs 1029261344Suqs if (n->norm->Bl.offs) { 1030261344Suqs print_line(".RE", MMAN_nl); 1031261344Suqs assert(Bl_stack_len); 1032261344Suqs Bl_stack_len--; 1033261344Suqs assert(0 == Bl_stack[Bl_stack_len]); 1034261344Suqs } else { 1035261344Suqs outflags |= MMAN_PP | MMAN_nl; 1036261344Suqs outflags &= ~(MMAN_sp | MMAN_br); 1037261344Suqs } 1038261344Suqs 1039261344Suqs /* Maybe we are inside an enclosing list? */ 1040261344Suqs if (NULL != n->parent->next) 1041261344Suqs mid_it(); 1042261344Suqs 1043261344Suqs} 1044261344Suqs 1045261344Suqsstatic int 1046241675Suqspre_br(DECL_ARGS) 1047241675Suqs{ 1048241675Suqs 1049261344Suqs outflags |= MMAN_br; 1050294113Sbapt return 0; 1051241675Suqs} 1052241675Suqs 1053241675Suqsstatic int 1054241675Suqspre_bx(DECL_ARGS) 1055241675Suqs{ 1056241675Suqs 1057241675Suqs n = n->child; 1058241675Suqs if (n) { 1059261344Suqs print_word(n->string); 1060261344Suqs outflags &= ~MMAN_spc; 1061241675Suqs n = n->next; 1062241675Suqs } 1063261344Suqs print_word("BSD"); 1064241675Suqs if (NULL == n) 1065294113Sbapt return 0; 1066261344Suqs outflags &= ~MMAN_spc; 1067261344Suqs print_word("-"); 1068261344Suqs outflags &= ~MMAN_spc; 1069261344Suqs print_word(n->string); 1070294113Sbapt return 0; 1071241675Suqs} 1072241675Suqs 1073241675Suqsstatic int 1074241675Suqspre_dl(DECL_ARGS) 1075241675Suqs{ 1076241675Suqs 1077275432Sbapt print_offs("6n", 0); 1078294113Sbapt return 1; 1079241675Suqs} 1080241675Suqs 1081241675Suqsstatic void 1082241675Suqspost_dl(DECL_ARGS) 1083241675Suqs{ 1084241675Suqs 1085261344Suqs print_line(".RE", MMAN_nl); 1086261344Suqs 1087261344Suqs /* Maybe we are inside an enclosing list? */ 1088261344Suqs if (NULL != n->parent->next) 1089261344Suqs mid_it(); 1090241675Suqs} 1091241675Suqs 1092241675Suqsstatic int 1093261344Suqspre_em(DECL_ARGS) 1094261344Suqs{ 1095261344Suqs 1096261344Suqs font_push('I'); 1097294113Sbapt return 1; 1098261344Suqs} 1099261344Suqs 1100274880Sbaptstatic int 1101274880Sbaptpre_en(DECL_ARGS) 1102274880Sbapt{ 1103274880Sbapt 1104274880Sbapt if (NULL == n->norm->Es || 1105274880Sbapt NULL == n->norm->Es->child) 1106294113Sbapt return 1; 1107274880Sbapt 1108274880Sbapt print_word(n->norm->Es->child->string); 1109274880Sbapt outflags &= ~MMAN_spc; 1110294113Sbapt return 1; 1111274880Sbapt} 1112274880Sbapt 1113261344Suqsstatic void 1114274880Sbaptpost_en(DECL_ARGS) 1115274880Sbapt{ 1116274880Sbapt 1117274880Sbapt if (NULL == n->norm->Es || 1118274880Sbapt NULL == n->norm->Es->child || 1119274880Sbapt NULL == n->norm->Es->child->next) 1120274880Sbapt return; 1121274880Sbapt 1122274880Sbapt outflags &= ~MMAN_spc; 1123274880Sbapt print_word(n->norm->Es->child->next->string); 1124274880Sbapt return; 1125274880Sbapt} 1126274880Sbapt 1127275432Sbaptstatic int 1128275432Sbaptpre_eo(DECL_ARGS) 1129261344Suqs{ 1130261344Suqs 1131279527Sbapt if (n->end == ENDBODY_NOT && 1132279527Sbapt n->parent->head->child == NULL && 1133279527Sbapt n->child != NULL && 1134279527Sbapt n->child->end != ENDBODY_NOT) 1135279527Sbapt print_word("\\&"); 1136279527Sbapt else if (n->end != ENDBODY_NOT ? n->child != NULL : 1137279527Sbapt n->parent->head->child != NULL && (n->child != NULL || 1138279527Sbapt (n->parent->tail != NULL && n->parent->tail->child != NULL))) 1139279527Sbapt outflags &= ~(MMAN_spc | MMAN_nl); 1140294113Sbapt return 1; 1141261344Suqs} 1142261344Suqs 1143275432Sbaptstatic void 1144275432Sbaptpost_eo(DECL_ARGS) 1145274880Sbapt{ 1146279527Sbapt int body, tail; 1147274880Sbapt 1148279527Sbapt if (n->end != ENDBODY_NOT) { 1149279527Sbapt outflags |= MMAN_spc; 1150279527Sbapt return; 1151279527Sbapt } 1152279527Sbapt 1153279527Sbapt body = n->child != NULL || n->parent->head->child != NULL; 1154279527Sbapt tail = n->parent->tail != NULL && n->parent->tail->child != NULL; 1155279527Sbapt 1156279527Sbapt if (body && tail) 1157275432Sbapt outflags &= ~MMAN_spc; 1158279527Sbapt else if ( ! (body || tail)) 1159279527Sbapt print_word("\\&"); 1160279527Sbapt else if ( ! tail) 1161279527Sbapt outflags |= MMAN_spc; 1162274880Sbapt} 1163274880Sbapt 1164274880Sbaptstatic int 1165261344Suqspre_fa(DECL_ARGS) 1166261344Suqs{ 1167261344Suqs int am_Fa; 1168261344Suqs 1169261344Suqs am_Fa = MDOC_Fa == n->tok; 1170261344Suqs 1171261344Suqs if (am_Fa) 1172261344Suqs n = n->child; 1173261344Suqs 1174261344Suqs while (NULL != n) { 1175261344Suqs font_push('I'); 1176261344Suqs if (am_Fa || MDOC_SYNPRETTY & n->flags) 1177261344Suqs outflags |= MMAN_nbrword; 1178261344Suqs print_node(meta, n); 1179261344Suqs font_pop(); 1180261344Suqs if (NULL != (n = n->next)) 1181261344Suqs print_word(","); 1182261344Suqs } 1183294113Sbapt return 0; 1184261344Suqs} 1185261344Suqs 1186261344Suqsstatic void 1187261344Suqspost_fa(DECL_ARGS) 1188261344Suqs{ 1189261344Suqs 1190261344Suqs if (NULL != n->next && MDOC_Fa == n->next->tok) 1191261344Suqs print_word(","); 1192261344Suqs} 1193261344Suqs 1194261344Suqsstatic int 1195261344Suqspre_fd(DECL_ARGS) 1196261344Suqs{ 1197261344Suqs 1198261344Suqs pre_syn(n); 1199261344Suqs font_push('B'); 1200294113Sbapt return 1; 1201261344Suqs} 1202261344Suqs 1203261344Suqsstatic void 1204261344Suqspost_fd(DECL_ARGS) 1205261344Suqs{ 1206261344Suqs 1207261344Suqs font_pop(); 1208261344Suqs outflags |= MMAN_br; 1209261344Suqs} 1210261344Suqs 1211261344Suqsstatic int 1212261344Suqspre_fl(DECL_ARGS) 1213261344Suqs{ 1214261344Suqs 1215261344Suqs font_push('B'); 1216261344Suqs print_word("\\-"); 1217294113Sbapt if (n->child != NULL) 1218275432Sbapt outflags &= ~MMAN_spc; 1219294113Sbapt return 1; 1220261344Suqs} 1221261344Suqs 1222261344Suqsstatic void 1223261344Suqspost_fl(DECL_ARGS) 1224261344Suqs{ 1225261344Suqs 1226261344Suqs font_pop(); 1227294113Sbapt if (!(n->child != NULL || 1228275432Sbapt n->next == NULL || 1229294113Sbapt n->next->type == ROFFT_TEXT || 1230275432Sbapt n->next->flags & MDOC_LINE)) 1231261344Suqs outflags &= ~MMAN_spc; 1232261344Suqs} 1233261344Suqs 1234261344Suqsstatic int 1235261344Suqspre_fn(DECL_ARGS) 1236261344Suqs{ 1237261344Suqs 1238261344Suqs pre_syn(n); 1239261344Suqs 1240261344Suqs n = n->child; 1241261344Suqs if (NULL == n) 1242294113Sbapt return 0; 1243261344Suqs 1244261344Suqs if (MDOC_SYNPRETTY & n->flags) 1245261344Suqs print_block(".HP 4n", MMAN_nl); 1246261344Suqs 1247261344Suqs font_push('B'); 1248261344Suqs print_node(meta, n); 1249261344Suqs font_pop(); 1250261344Suqs outflags &= ~MMAN_spc; 1251261344Suqs print_word("("); 1252261344Suqs outflags &= ~MMAN_spc; 1253261344Suqs 1254261344Suqs n = n->next; 1255261344Suqs if (NULL != n) 1256261344Suqs pre_fa(meta, n); 1257294113Sbapt return 0; 1258261344Suqs} 1259261344Suqs 1260261344Suqsstatic void 1261261344Suqspost_fn(DECL_ARGS) 1262261344Suqs{ 1263261344Suqs 1264261344Suqs print_word(")"); 1265261344Suqs if (MDOC_SYNPRETTY & n->flags) { 1266261344Suqs print_word(";"); 1267261344Suqs outflags |= MMAN_PP; 1268261344Suqs } 1269261344Suqs} 1270261344Suqs 1271261344Suqsstatic int 1272261344Suqspre_fo(DECL_ARGS) 1273261344Suqs{ 1274261344Suqs 1275261344Suqs switch (n->type) { 1276294113Sbapt case ROFFT_BLOCK: 1277261344Suqs pre_syn(n); 1278261344Suqs break; 1279294113Sbapt case ROFFT_HEAD: 1280279527Sbapt if (n->child == NULL) 1281294113Sbapt return 0; 1282261344Suqs if (MDOC_SYNPRETTY & n->flags) 1283261344Suqs print_block(".HP 4n", MMAN_nl); 1284261344Suqs font_push('B'); 1285261344Suqs break; 1286294113Sbapt case ROFFT_BODY: 1287279527Sbapt outflags &= ~(MMAN_spc | MMAN_nl); 1288261344Suqs print_word("("); 1289261344Suqs outflags &= ~MMAN_spc; 1290261344Suqs break; 1291261344Suqs default: 1292261344Suqs break; 1293261344Suqs } 1294294113Sbapt return 1; 1295261344Suqs} 1296261344Suqs 1297261344Suqsstatic void 1298261344Suqspost_fo(DECL_ARGS) 1299261344Suqs{ 1300261344Suqs 1301261344Suqs switch (n->type) { 1302294113Sbapt case ROFFT_HEAD: 1303279527Sbapt if (n->child != NULL) 1304279527Sbapt font_pop(); 1305261344Suqs break; 1306294113Sbapt case ROFFT_BODY: 1307261344Suqs post_fn(meta, n); 1308261344Suqs break; 1309261344Suqs default: 1310261344Suqs break; 1311261344Suqs } 1312261344Suqs} 1313261344Suqs 1314261344Suqsstatic int 1315261344Suqspre_ft(DECL_ARGS) 1316261344Suqs{ 1317261344Suqs 1318261344Suqs pre_syn(n); 1319261344Suqs font_push('I'); 1320294113Sbapt return 1; 1321261344Suqs} 1322261344Suqs 1323261344Suqsstatic int 1324261344Suqspre_in(DECL_ARGS) 1325261344Suqs{ 1326261344Suqs 1327261344Suqs if (MDOC_SYNPRETTY & n->flags) { 1328261344Suqs pre_syn(n); 1329261344Suqs font_push('B'); 1330261344Suqs print_word("#include <"); 1331261344Suqs outflags &= ~MMAN_spc; 1332261344Suqs } else { 1333261344Suqs print_word("<"); 1334261344Suqs outflags &= ~MMAN_spc; 1335261344Suqs font_push('I'); 1336261344Suqs } 1337294113Sbapt return 1; 1338261344Suqs} 1339261344Suqs 1340261344Suqsstatic void 1341261344Suqspost_in(DECL_ARGS) 1342261344Suqs{ 1343261344Suqs 1344261344Suqs if (MDOC_SYNPRETTY & n->flags) { 1345261344Suqs outflags &= ~MMAN_spc; 1346261344Suqs print_word(">"); 1347261344Suqs font_pop(); 1348261344Suqs outflags |= MMAN_br; 1349261344Suqs } else { 1350261344Suqs font_pop(); 1351261344Suqs outflags &= ~MMAN_spc; 1352261344Suqs print_word(">"); 1353261344Suqs } 1354261344Suqs} 1355261344Suqs 1356261344Suqsstatic int 1357241675Suqspre_it(DECL_ARGS) 1358241675Suqs{ 1359294113Sbapt const struct roff_node *bln; 1360241675Suqs 1361261344Suqs switch (n->type) { 1362294113Sbapt case ROFFT_HEAD: 1363261344Suqs outflags |= MMAN_PP | MMAN_nl; 1364261344Suqs bln = n->parent->parent; 1365261344Suqs if (0 == bln->norm->Bl.comp || 1366261344Suqs (NULL == n->parent->prev && 1367261344Suqs NULL == bln->parent->prev)) 1368261344Suqs outflags |= MMAN_sp; 1369261344Suqs outflags &= ~MMAN_br; 1370241675Suqs switch (bln->norm->Bl.type) { 1371274880Sbapt case LIST_item: 1372294113Sbapt return 0; 1373274880Sbapt case LIST_inset: 1374274880Sbapt case LIST_diag: 1375274880Sbapt case LIST_ohang: 1376261344Suqs if (bln->norm->Bl.type == LIST_diag) 1377261344Suqs print_line(".B \"", 0); 1378261344Suqs else 1379261344Suqs print_line(".R \"", 0); 1380261344Suqs outflags &= ~MMAN_spc; 1381294113Sbapt return 1; 1382274880Sbapt case LIST_bullet: 1383274880Sbapt case LIST_dash: 1384274880Sbapt case LIST_hyphen: 1385279527Sbapt print_width(&bln->norm->Bl, NULL); 1386261344Suqs TPremain = 0; 1387261344Suqs outflags |= MMAN_nl; 1388261344Suqs font_push('B'); 1389261344Suqs if (LIST_bullet == bln->norm->Bl.type) 1390275432Sbapt print_word("\\(bu"); 1391261344Suqs else 1392261344Suqs print_word("-"); 1393261344Suqs font_pop(); 1394274880Sbapt outflags |= MMAN_nl; 1395294113Sbapt return 0; 1396274880Sbapt case LIST_enum: 1397279527Sbapt print_width(&bln->norm->Bl, NULL); 1398261344Suqs TPremain = 0; 1399261344Suqs outflags |= MMAN_nl; 1400261344Suqs print_count(&bln->norm->Bl.count); 1401274880Sbapt outflags |= MMAN_nl; 1402294113Sbapt return 0; 1403274880Sbapt case LIST_hang: 1404279527Sbapt print_width(&bln->norm->Bl, n->child); 1405261344Suqs TPremain = 0; 1406274880Sbapt outflags |= MMAN_nl; 1407294113Sbapt return 1; 1408274880Sbapt case LIST_tag: 1409279527Sbapt print_width(&bln->norm->Bl, n->child); 1410261344Suqs putchar('\n'); 1411261344Suqs outflags &= ~MMAN_spc; 1412294113Sbapt return 1; 1413241675Suqs default: 1414294113Sbapt return 1; 1415261344Suqs } 1416261344Suqs default: 1417261344Suqs break; 1418261344Suqs } 1419294113Sbapt return 1; 1420261344Suqs} 1421261344Suqs 1422261344Suqs/* 1423261344Suqs * This function is called after closing out an indented block. 1424261344Suqs * If we are inside an enclosing list, restore its indentation. 1425261344Suqs */ 1426261344Suqsstatic void 1427261344Suqsmid_it(void) 1428261344Suqs{ 1429261344Suqs char buf[24]; 1430261344Suqs 1431261344Suqs /* Nothing to do outside a list. */ 1432261344Suqs if (0 == Bl_stack_len || 0 == Bl_stack[Bl_stack_len - 1]) 1433261344Suqs return; 1434261344Suqs 1435261344Suqs /* The indentation has already been set up. */ 1436261344Suqs if (Bl_stack_post[Bl_stack_len - 1]) 1437261344Suqs return; 1438261344Suqs 1439261344Suqs /* Restore the indentation of the enclosing list. */ 1440261344Suqs print_line(".RS", MMAN_Bk_susp); 1441279527Sbapt (void)snprintf(buf, sizeof(buf), "%dn", 1442274880Sbapt Bl_stack[Bl_stack_len - 1]); 1443261344Suqs print_word(buf); 1444261344Suqs 1445261344Suqs /* Remeber to close out this .RS block later. */ 1446261344Suqs Bl_stack_post[Bl_stack_len - 1] = 1; 1447261344Suqs} 1448261344Suqs 1449261344Suqsstatic void 1450261344Suqspost_it(DECL_ARGS) 1451261344Suqs{ 1452294113Sbapt const struct roff_node *bln; 1453261344Suqs 1454261344Suqs bln = n->parent->parent; 1455261344Suqs 1456261344Suqs switch (n->type) { 1457294113Sbapt case ROFFT_HEAD: 1458261344Suqs switch (bln->norm->Bl.type) { 1459274880Sbapt case LIST_diag: 1460261344Suqs outflags &= ~MMAN_spc; 1461261344Suqs print_word("\\ "); 1462241675Suqs break; 1463274880Sbapt case LIST_ohang: 1464261344Suqs outflags |= MMAN_br; 1465261344Suqs break; 1466261344Suqs default: 1467261344Suqs break; 1468241675Suqs } 1469261344Suqs break; 1470294113Sbapt case ROFFT_BODY: 1471261344Suqs switch (bln->norm->Bl.type) { 1472274880Sbapt case LIST_bullet: 1473274880Sbapt case LIST_dash: 1474274880Sbapt case LIST_hyphen: 1475274880Sbapt case LIST_enum: 1476274880Sbapt case LIST_hang: 1477274880Sbapt case LIST_tag: 1478261344Suqs assert(Bl_stack_len); 1479261344Suqs Bl_stack[--Bl_stack_len] = 0; 1480261344Suqs 1481261344Suqs /* 1482261344Suqs * Our indentation had to be restored 1483261344Suqs * after a child display or child list. 1484261344Suqs * Close out that indentation block now. 1485261344Suqs */ 1486261344Suqs if (Bl_stack_post[Bl_stack_len]) { 1487261344Suqs print_line(".RE", MMAN_nl); 1488261344Suqs Bl_stack_post[Bl_stack_len] = 0; 1489261344Suqs } 1490261344Suqs break; 1491274880Sbapt case LIST_column: 1492261344Suqs if (NULL != n->next) { 1493261344Suqs putchar('\t'); 1494261344Suqs outflags &= ~MMAN_spc; 1495261344Suqs } 1496261344Suqs break; 1497261344Suqs default: 1498261344Suqs break; 1499261344Suqs } 1500261344Suqs break; 1501261344Suqs default: 1502261344Suqs break; 1503241675Suqs } 1504261344Suqs} 1505261344Suqs 1506261344Suqsstatic void 1507261344Suqspost_lb(DECL_ARGS) 1508261344Suqs{ 1509261344Suqs 1510261344Suqs if (SEC_LIBRARY == n->sec) 1511261344Suqs outflags |= MMAN_br; 1512261344Suqs} 1513261344Suqs 1514261344Suqsstatic int 1515261344Suqspre_lk(DECL_ARGS) 1516261344Suqs{ 1517294113Sbapt const struct roff_node *link, *descr; 1518261344Suqs 1519261344Suqs if (NULL == (link = n->child)) 1520294113Sbapt return 0; 1521261344Suqs 1522261344Suqs if (NULL != (descr = link->next)) { 1523261344Suqs font_push('I'); 1524261344Suqs while (NULL != descr) { 1525261344Suqs print_word(descr->string); 1526261344Suqs descr = descr->next; 1527261344Suqs } 1528261344Suqs print_word(":"); 1529261344Suqs font_pop(); 1530261344Suqs } 1531261344Suqs 1532261344Suqs font_push('B'); 1533261344Suqs print_word(link->string); 1534261344Suqs font_pop(); 1535294113Sbapt return 0; 1536261344Suqs} 1537261344Suqs 1538261344Suqsstatic int 1539274880Sbaptpre_ll(DECL_ARGS) 1540274880Sbapt{ 1541274880Sbapt 1542274880Sbapt print_line(".ll", 0); 1543294113Sbapt return 1; 1544274880Sbapt} 1545274880Sbapt 1546274880Sbaptstatic int 1547261344Suqspre_li(DECL_ARGS) 1548261344Suqs{ 1549261344Suqs 1550261344Suqs font_push('R'); 1551294113Sbapt return 1; 1552241675Suqs} 1553241675Suqs 1554241675Suqsstatic int 1555241675Suqspre_nm(DECL_ARGS) 1556241675Suqs{ 1557261344Suqs char *name; 1558241675Suqs 1559294113Sbapt if (n->type == ROFFT_BLOCK) { 1560261344Suqs outflags |= MMAN_Bk; 1561261344Suqs pre_syn(n); 1562261344Suqs } 1563294113Sbapt if (n->type != ROFFT_ELEM && n->type != ROFFT_HEAD) 1564294113Sbapt return 1; 1565261344Suqs name = n->child ? n->child->string : meta->name; 1566261344Suqs if (NULL == name) 1567294113Sbapt return 0; 1568294113Sbapt if (n->type == ROFFT_HEAD) { 1569261344Suqs if (NULL == n->parent->prev) 1570261344Suqs outflags |= MMAN_sp; 1571261344Suqs print_block(".HP", 0); 1572261344Suqs printf(" %zun", strlen(name) + 1); 1573261344Suqs outflags |= MMAN_nl; 1574261344Suqs } 1575261344Suqs font_push('B'); 1576241675Suqs if (NULL == n->child) 1577261344Suqs print_word(meta->name); 1578294113Sbapt return 1; 1579241675Suqs} 1580241675Suqs 1581241675Suqsstatic void 1582241675Suqspost_nm(DECL_ARGS) 1583241675Suqs{ 1584241675Suqs 1585261344Suqs switch (n->type) { 1586294113Sbapt case ROFFT_BLOCK: 1587261344Suqs outflags &= ~MMAN_Bk; 1588261344Suqs break; 1589294113Sbapt case ROFFT_HEAD: 1590294113Sbapt case ROFFT_ELEM: 1591274880Sbapt if (n->child != NULL || meta->name != NULL) 1592274880Sbapt font_pop(); 1593261344Suqs break; 1594261344Suqs default: 1595261344Suqs break; 1596261344Suqs } 1597241675Suqs} 1598241675Suqs 1599241675Suqsstatic int 1600261344Suqspre_no(DECL_ARGS) 1601261344Suqs{ 1602261344Suqs 1603261344Suqs outflags |= MMAN_spc_force; 1604294113Sbapt return 1; 1605261344Suqs} 1606261344Suqs 1607261344Suqsstatic int 1608241675Suqspre_ns(DECL_ARGS) 1609241675Suqs{ 1610241675Suqs 1611261344Suqs outflags &= ~MMAN_spc; 1612294113Sbapt return 0; 1613241675Suqs} 1614241675Suqs 1615241675Suqsstatic void 1616241675Suqspost_pf(DECL_ARGS) 1617241675Suqs{ 1618241675Suqs 1619276219Sbapt if ( ! (n->next == NULL || n->next->flags & MDOC_LINE)) 1620276219Sbapt outflags &= ~MMAN_spc; 1621241675Suqs} 1622241675Suqs 1623241675Suqsstatic int 1624241675Suqspre_pp(DECL_ARGS) 1625241675Suqs{ 1626241675Suqs 1627261344Suqs if (MDOC_It != n->parent->tok) 1628261344Suqs outflags |= MMAN_PP; 1629261344Suqs outflags |= MMAN_sp | MMAN_nl; 1630261344Suqs outflags &= ~MMAN_br; 1631294113Sbapt return 0; 1632261344Suqs} 1633261344Suqs 1634261344Suqsstatic int 1635261344Suqspre_rs(DECL_ARGS) 1636261344Suqs{ 1637261344Suqs 1638261344Suqs if (SEC_SEE_ALSO == n->sec) { 1639261344Suqs outflags |= MMAN_PP | MMAN_sp | MMAN_nl; 1640261344Suqs outflags &= ~MMAN_br; 1641261344Suqs } 1642294113Sbapt return 1; 1643241675Suqs} 1644241675Suqs 1645241675Suqsstatic int 1646274880Sbaptpre_rv(DECL_ARGS) 1647274880Sbapt{ 1648294113Sbapt struct roff_node *nch; 1649274880Sbapt 1650274880Sbapt outflags |= MMAN_br | MMAN_nl; 1651274880Sbapt 1652294113Sbapt if (n->child != NULL) { 1653274880Sbapt print_word("The"); 1654274880Sbapt 1655294113Sbapt for (nch = n->child; nch != NULL; nch = nch->next) { 1656274880Sbapt font_push('B'); 1657294113Sbapt print_word(nch->string); 1658274880Sbapt font_pop(); 1659274880Sbapt 1660274880Sbapt outflags &= ~MMAN_spc; 1661274880Sbapt print_word("()"); 1662274880Sbapt 1663294113Sbapt if (nch->next == NULL) 1664274880Sbapt continue; 1665274880Sbapt 1666294113Sbapt if (nch->prev != NULL || nch->next->next != NULL) { 1667274880Sbapt outflags &= ~MMAN_spc; 1668274880Sbapt print_word(","); 1669274880Sbapt } 1670294113Sbapt if (nch->next->next == NULL) 1671274880Sbapt print_word("and"); 1672274880Sbapt } 1673274880Sbapt 1674294113Sbapt if (n->child != NULL && n->child->next != NULL) 1675274880Sbapt print_word("functions return"); 1676274880Sbapt else 1677274880Sbapt print_word("function returns"); 1678274880Sbapt 1679274880Sbapt print_word("the value\\~0 if successful;"); 1680274880Sbapt } else 1681274880Sbapt print_word("Upon successful completion, " 1682274880Sbapt "the value\\~0 is returned;"); 1683274880Sbapt 1684274880Sbapt print_word("otherwise the value\\~\\-1 is returned" 1685274880Sbapt " and the global variable"); 1686274880Sbapt 1687274880Sbapt font_push('I'); 1688274880Sbapt print_word("errno"); 1689274880Sbapt font_pop(); 1690274880Sbapt 1691274880Sbapt print_word("is set to indicate the error."); 1692274880Sbapt outflags |= MMAN_nl; 1693294113Sbapt return 0; 1694274880Sbapt} 1695274880Sbapt 1696274880Sbaptstatic int 1697275432Sbaptpre_skip(DECL_ARGS) 1698275432Sbapt{ 1699275432Sbapt 1700294113Sbapt return 0; 1701275432Sbapt} 1702275432Sbapt 1703275432Sbaptstatic int 1704261344Suqspre_sm(DECL_ARGS) 1705261344Suqs{ 1706261344Suqs 1707274880Sbapt if (NULL == n->child) 1708274880Sbapt outflags ^= MMAN_Sm; 1709274880Sbapt else if (0 == strcmp("on", n->child->string)) 1710274880Sbapt outflags |= MMAN_Sm; 1711261344Suqs else 1712261344Suqs outflags &= ~MMAN_Sm; 1713274880Sbapt 1714274880Sbapt if (MMAN_Sm & outflags) 1715274880Sbapt outflags |= MMAN_spc; 1716274880Sbapt 1717294113Sbapt return 0; 1718261344Suqs} 1719261344Suqs 1720261344Suqsstatic int 1721241675Suqspre_sp(DECL_ARGS) 1722241675Suqs{ 1723241675Suqs 1724261344Suqs if (MMAN_PP & outflags) { 1725261344Suqs outflags &= ~MMAN_PP; 1726261344Suqs print_line(".PP", 0); 1727261344Suqs } else 1728261344Suqs print_line(".sp", 0); 1729294113Sbapt return 1; 1730241675Suqs} 1731241675Suqs 1732241675Suqsstatic void 1733241675Suqspost_sp(DECL_ARGS) 1734241675Suqs{ 1735241675Suqs 1736261344Suqs outflags |= MMAN_nl; 1737241675Suqs} 1738241675Suqs 1739241675Suqsstatic int 1740261344Suqspre_sy(DECL_ARGS) 1741261344Suqs{ 1742261344Suqs 1743261344Suqs font_push('B'); 1744294113Sbapt return 1; 1745261344Suqs} 1746261344Suqs 1747261344Suqsstatic int 1748261344Suqspre_vt(DECL_ARGS) 1749261344Suqs{ 1750261344Suqs 1751261344Suqs if (MDOC_SYNPRETTY & n->flags) { 1752261344Suqs switch (n->type) { 1753294113Sbapt case ROFFT_BLOCK: 1754261344Suqs pre_syn(n); 1755294113Sbapt return 1; 1756294113Sbapt case ROFFT_BODY: 1757261344Suqs break; 1758261344Suqs default: 1759294113Sbapt return 0; 1760261344Suqs } 1761261344Suqs } 1762261344Suqs font_push('I'); 1763294113Sbapt return 1; 1764261344Suqs} 1765261344Suqs 1766261344Suqsstatic void 1767261344Suqspost_vt(DECL_ARGS) 1768261344Suqs{ 1769261344Suqs 1770294113Sbapt if (n->flags & MDOC_SYNPRETTY && n->type != ROFFT_BODY) 1771261344Suqs return; 1772261344Suqs font_pop(); 1773261344Suqs} 1774261344Suqs 1775261344Suqsstatic int 1776241675Suqspre_xr(DECL_ARGS) 1777241675Suqs{ 1778241675Suqs 1779241675Suqs n = n->child; 1780241675Suqs if (NULL == n) 1781294113Sbapt return 0; 1782261344Suqs print_node(meta, n); 1783241675Suqs n = n->next; 1784241675Suqs if (NULL == n) 1785294113Sbapt return 0; 1786261344Suqs outflags &= ~MMAN_spc; 1787261344Suqs print_word("("); 1788261344Suqs print_node(meta, n); 1789261344Suqs print_word(")"); 1790294113Sbapt return 0; 1791241675Suqs} 1792241675Suqs 1793241675Suqsstatic int 1794241675Suqspre_ux(DECL_ARGS) 1795241675Suqs{ 1796241675Suqs 1797261344Suqs print_word(manacts[n->tok].prefix); 1798241675Suqs if (NULL == n->child) 1799294113Sbapt return 0; 1800261344Suqs outflags &= ~MMAN_spc; 1801261344Suqs print_word("\\ "); 1802261344Suqs outflags &= ~MMAN_spc; 1803294113Sbapt return 1; 1804241675Suqs} 1805