1322249Sbapt/* $Id: mdoc_html.c,v 1.294 2017/07/15 17:57:51 schwarze Exp $ */ 2241675Suqs/* 3275432Sbapt * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> 4316420Sbapt * Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze <schwarze@openbsd.org> 5241675Suqs * 6241675Suqs * Permission to use, copy, modify, and distribute this software for any 7241675Suqs * purpose with or without fee is hereby granted, provided that the above 8241675Suqs * copyright notice and this permission notice appear in all copies. 9241675Suqs * 10294113Sbapt * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 11241675Suqs * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12294113Sbapt * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR 13241675Suqs * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14241675Suqs * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15241675Suqs * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16241675Suqs * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17241675Suqs */ 18241675Suqs#include "config.h" 19241675Suqs 20241675Suqs#include <sys/types.h> 21241675Suqs 22241675Suqs#include <assert.h> 23241675Suqs#include <ctype.h> 24241675Suqs#include <stdio.h> 25241675Suqs#include <stdlib.h> 26241675Suqs#include <string.h> 27241675Suqs#include <unistd.h> 28241675Suqs 29274880Sbapt#include "mandoc_aux.h" 30322249Sbapt#include "mandoc.h" 31294113Sbapt#include "roff.h" 32276219Sbapt#include "mdoc.h" 33241675Suqs#include "out.h" 34241675Suqs#include "html.h" 35241675Suqs#include "main.h" 36241675Suqs 37241675Suqs#define INDENT 5 38241675Suqs 39294113Sbapt#define MDOC_ARGS const struct roff_meta *meta, \ 40294113Sbapt struct roff_node *n, \ 41241675Suqs struct html *h 42241675Suqs 43241675Suqs#ifndef MIN 44241675Suqs#define MIN(a,b) ((/*CONSTCOND*/(a)<(b))?(a):(b)) 45241675Suqs#endif 46241675Suqs 47241675Suqsstruct htmlmdoc { 48241675Suqs int (*pre)(MDOC_ARGS); 49241675Suqs void (*post)(MDOC_ARGS); 50241675Suqs}; 51241675Suqs 52322249Sbaptstatic char *cond_id(const struct roff_node *); 53241675Suqsstatic void print_mdoc_head(MDOC_ARGS); 54241675Suqsstatic void print_mdoc_node(MDOC_ARGS); 55241675Suqsstatic void print_mdoc_nodelist(MDOC_ARGS); 56274880Sbaptstatic void synopsis_pre(struct html *, 57294113Sbapt const struct roff_node *); 58241675Suqs 59241675Suqsstatic void mdoc_root_post(MDOC_ARGS); 60241675Suqsstatic int mdoc_root_pre(MDOC_ARGS); 61241675Suqs 62241675Suqsstatic void mdoc__x_post(MDOC_ARGS); 63241675Suqsstatic int mdoc__x_pre(MDOC_ARGS); 64241675Suqsstatic int mdoc_ad_pre(MDOC_ARGS); 65241675Suqsstatic int mdoc_an_pre(MDOC_ARGS); 66241675Suqsstatic int mdoc_ap_pre(MDOC_ARGS); 67241675Suqsstatic int mdoc_ar_pre(MDOC_ARGS); 68241675Suqsstatic int mdoc_bd_pre(MDOC_ARGS); 69241675Suqsstatic int mdoc_bf_pre(MDOC_ARGS); 70241675Suqsstatic void mdoc_bk_post(MDOC_ARGS); 71241675Suqsstatic int mdoc_bk_pre(MDOC_ARGS); 72241675Suqsstatic int mdoc_bl_pre(MDOC_ARGS); 73241675Suqsstatic int mdoc_cd_pre(MDOC_ARGS); 74316420Sbaptstatic int mdoc_cm_pre(MDOC_ARGS); 75241675Suqsstatic int mdoc_d1_pre(MDOC_ARGS); 76241675Suqsstatic int mdoc_dv_pre(MDOC_ARGS); 77241675Suqsstatic int mdoc_fa_pre(MDOC_ARGS); 78241675Suqsstatic int mdoc_fd_pre(MDOC_ARGS); 79241675Suqsstatic int mdoc_fl_pre(MDOC_ARGS); 80241675Suqsstatic int mdoc_fn_pre(MDOC_ARGS); 81241675Suqsstatic int mdoc_ft_pre(MDOC_ARGS); 82241675Suqsstatic int mdoc_em_pre(MDOC_ARGS); 83279527Sbaptstatic void mdoc_eo_post(MDOC_ARGS); 84279527Sbaptstatic int mdoc_eo_pre(MDOC_ARGS); 85241675Suqsstatic int mdoc_er_pre(MDOC_ARGS); 86241675Suqsstatic int mdoc_ev_pre(MDOC_ARGS); 87241675Suqsstatic int mdoc_ex_pre(MDOC_ARGS); 88241675Suqsstatic void mdoc_fo_post(MDOC_ARGS); 89241675Suqsstatic int mdoc_fo_pre(MDOC_ARGS); 90241675Suqsstatic int mdoc_ic_pre(MDOC_ARGS); 91241675Suqsstatic int mdoc_igndelim_pre(MDOC_ARGS); 92241675Suqsstatic int mdoc_in_pre(MDOC_ARGS); 93241675Suqsstatic int mdoc_it_pre(MDOC_ARGS); 94241675Suqsstatic int mdoc_lb_pre(MDOC_ARGS); 95241675Suqsstatic int mdoc_li_pre(MDOC_ARGS); 96241675Suqsstatic int mdoc_lk_pre(MDOC_ARGS); 97241675Suqsstatic int mdoc_mt_pre(MDOC_ARGS); 98241675Suqsstatic int mdoc_ms_pre(MDOC_ARGS); 99241675Suqsstatic int mdoc_nd_pre(MDOC_ARGS); 100241675Suqsstatic int mdoc_nm_pre(MDOC_ARGS); 101275432Sbaptstatic int mdoc_no_pre(MDOC_ARGS); 102241675Suqsstatic int mdoc_ns_pre(MDOC_ARGS); 103241675Suqsstatic int mdoc_pa_pre(MDOC_ARGS); 104241675Suqsstatic void mdoc_pf_post(MDOC_ARGS); 105241675Suqsstatic int mdoc_pp_pre(MDOC_ARGS); 106241675Suqsstatic void mdoc_quote_post(MDOC_ARGS); 107241675Suqsstatic int mdoc_quote_pre(MDOC_ARGS); 108241675Suqsstatic int mdoc_rs_pre(MDOC_ARGS); 109241675Suqsstatic int mdoc_sh_pre(MDOC_ARGS); 110274880Sbaptstatic int mdoc_skip_pre(MDOC_ARGS); 111241675Suqsstatic int mdoc_sm_pre(MDOC_ARGS); 112241675Suqsstatic int mdoc_ss_pre(MDOC_ARGS); 113322249Sbaptstatic int mdoc_st_pre(MDOC_ARGS); 114241675Suqsstatic int mdoc_sx_pre(MDOC_ARGS); 115241675Suqsstatic int mdoc_sy_pre(MDOC_ARGS); 116241675Suqsstatic int mdoc_va_pre(MDOC_ARGS); 117241675Suqsstatic int mdoc_vt_pre(MDOC_ARGS); 118241675Suqsstatic int mdoc_xr_pre(MDOC_ARGS); 119241675Suqsstatic int mdoc_xx_pre(MDOC_ARGS); 120241675Suqs 121322249Sbaptstatic const struct htmlmdoc __mdocs[MDOC_MAX - MDOC_Dd] = { 122241675Suqs {NULL, NULL}, /* Dd */ 123241675Suqs {NULL, NULL}, /* Dt */ 124241675Suqs {NULL, NULL}, /* Os */ 125241675Suqs {mdoc_sh_pre, NULL }, /* Sh */ 126274880Sbapt {mdoc_ss_pre, NULL }, /* Ss */ 127274880Sbapt {mdoc_pp_pre, NULL}, /* Pp */ 128241675Suqs {mdoc_d1_pre, NULL}, /* D1 */ 129241675Suqs {mdoc_d1_pre, NULL}, /* Dl */ 130241675Suqs {mdoc_bd_pre, NULL}, /* Bd */ 131241675Suqs {NULL, NULL}, /* Ed */ 132241675Suqs {mdoc_bl_pre, NULL}, /* Bl */ 133241675Suqs {NULL, NULL}, /* El */ 134241675Suqs {mdoc_it_pre, NULL}, /* It */ 135274880Sbapt {mdoc_ad_pre, NULL}, /* Ad */ 136241675Suqs {mdoc_an_pre, NULL}, /* An */ 137322249Sbapt {mdoc_ap_pre, NULL}, /* Ap */ 138241675Suqs {mdoc_ar_pre, NULL}, /* Ar */ 139241675Suqs {mdoc_cd_pre, NULL}, /* Cd */ 140316420Sbapt {mdoc_cm_pre, NULL}, /* Cm */ 141274880Sbapt {mdoc_dv_pre, NULL}, /* Dv */ 142274880Sbapt {mdoc_er_pre, NULL}, /* Er */ 143274880Sbapt {mdoc_ev_pre, NULL}, /* Ev */ 144241675Suqs {mdoc_ex_pre, NULL}, /* Ex */ 145274880Sbapt {mdoc_fa_pre, NULL}, /* Fa */ 146274880Sbapt {mdoc_fd_pre, NULL}, /* Fd */ 147241675Suqs {mdoc_fl_pre, NULL}, /* Fl */ 148274880Sbapt {mdoc_fn_pre, NULL}, /* Fn */ 149274880Sbapt {mdoc_ft_pre, NULL}, /* Ft */ 150274880Sbapt {mdoc_ic_pre, NULL}, /* Ic */ 151274880Sbapt {mdoc_in_pre, NULL}, /* In */ 152241675Suqs {mdoc_li_pre, NULL}, /* Li */ 153274880Sbapt {mdoc_nd_pre, NULL}, /* Nd */ 154274880Sbapt {mdoc_nm_pre, NULL}, /* Nm */ 155241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Op */ 156274880Sbapt {mdoc_ft_pre, NULL}, /* Ot */ 157241675Suqs {mdoc_pa_pre, NULL}, /* Pa */ 158316420Sbapt {mdoc_ex_pre, NULL}, /* Rv */ 159322249Sbapt {mdoc_st_pre, NULL}, /* St */ 160241675Suqs {mdoc_va_pre, NULL}, /* Va */ 161274880Sbapt {mdoc_vt_pre, NULL}, /* Vt */ 162241675Suqs {mdoc_xr_pre, NULL}, /* Xr */ 163241675Suqs {mdoc__x_pre, mdoc__x_post}, /* %A */ 164241675Suqs {mdoc__x_pre, mdoc__x_post}, /* %B */ 165241675Suqs {mdoc__x_pre, mdoc__x_post}, /* %D */ 166241675Suqs {mdoc__x_pre, mdoc__x_post}, /* %I */ 167241675Suqs {mdoc__x_pre, mdoc__x_post}, /* %J */ 168241675Suqs {mdoc__x_pre, mdoc__x_post}, /* %N */ 169241675Suqs {mdoc__x_pre, mdoc__x_post}, /* %O */ 170241675Suqs {mdoc__x_pre, mdoc__x_post}, /* %P */ 171241675Suqs {mdoc__x_pre, mdoc__x_post}, /* %R */ 172241675Suqs {mdoc__x_pre, mdoc__x_post}, /* %T */ 173241675Suqs {mdoc__x_pre, mdoc__x_post}, /* %V */ 174241675Suqs {NULL, NULL}, /* Ac */ 175241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Ao */ 176241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Aq */ 177322249Sbapt {mdoc_xx_pre, NULL}, /* At */ 178241675Suqs {NULL, NULL}, /* Bc */ 179274880Sbapt {mdoc_bf_pre, NULL}, /* Bf */ 180241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Bo */ 181241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Bq */ 182241675Suqs {mdoc_xx_pre, NULL}, /* Bsx */ 183316420Sbapt {mdoc_xx_pre, NULL}, /* Bx */ 184275432Sbapt {mdoc_skip_pre, NULL}, /* Db */ 185241675Suqs {NULL, NULL}, /* Dc */ 186241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Do */ 187241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Dq */ 188241675Suqs {NULL, NULL}, /* Ec */ /* FIXME: no space */ 189241675Suqs {NULL, NULL}, /* Ef */ 190274880Sbapt {mdoc_em_pre, NULL}, /* Em */ 191279527Sbapt {mdoc_eo_pre, mdoc_eo_post}, /* Eo */ 192241675Suqs {mdoc_xx_pre, NULL}, /* Fx */ 193241675Suqs {mdoc_ms_pre, NULL}, /* Ms */ 194275432Sbapt {mdoc_no_pre, NULL}, /* No */ 195241675Suqs {mdoc_ns_pre, NULL}, /* Ns */ 196241675Suqs {mdoc_xx_pre, NULL}, /* Nx */ 197241675Suqs {mdoc_xx_pre, NULL}, /* Ox */ 198241675Suqs {NULL, NULL}, /* Pc */ 199241675Suqs {mdoc_igndelim_pre, mdoc_pf_post}, /* Pf */ 200241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Po */ 201241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Pq */ 202241675Suqs {NULL, NULL}, /* Qc */ 203241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Ql */ 204241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Qo */ 205241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Qq */ 206241675Suqs {NULL, NULL}, /* Re */ 207241675Suqs {mdoc_rs_pre, NULL}, /* Rs */ 208241675Suqs {NULL, NULL}, /* Sc */ 209241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* So */ 210241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Sq */ 211274880Sbapt {mdoc_sm_pre, NULL}, /* Sm */ 212241675Suqs {mdoc_sx_pre, NULL}, /* Sx */ 213241675Suqs {mdoc_sy_pre, NULL}, /* Sy */ 214241675Suqs {NULL, NULL}, /* Tn */ 215241675Suqs {mdoc_xx_pre, NULL}, /* Ux */ 216241675Suqs {NULL, NULL}, /* Xc */ 217241675Suqs {NULL, NULL}, /* Xo */ 218274880Sbapt {mdoc_fo_pre, mdoc_fo_post}, /* Fo */ 219274880Sbapt {NULL, NULL}, /* Fc */ 220241675Suqs {mdoc_quote_pre, mdoc_quote_post}, /* Oo */ 221241675Suqs {NULL, NULL}, /* Oc */ 222241675Suqs {mdoc_bk_pre, mdoc_bk_post}, /* Bk */ 223241675Suqs {NULL, NULL}, /* Ek */ 224316420Sbapt {NULL, NULL}, /* Bt */ 225241675Suqs {NULL, NULL}, /* Hf */ 226274880Sbapt {mdoc_em_pre, NULL}, /* Fr */ 227316420Sbapt {NULL, NULL}, /* Ud */ 228241675Suqs {mdoc_lb_pre, NULL}, /* Lb */ 229274880Sbapt {mdoc_pp_pre, NULL}, /* Lp */ 230274880Sbapt {mdoc_lk_pre, NULL}, /* Lk */ 231274880Sbapt {mdoc_mt_pre, NULL}, /* Mt */ 232274880Sbapt {mdoc_quote_pre, mdoc_quote_post}, /* Brq */ 233274880Sbapt {mdoc_quote_pre, mdoc_quote_post}, /* Bro */ 234274880Sbapt {NULL, NULL}, /* Brc */ 235274880Sbapt {mdoc__x_pre, mdoc__x_post}, /* %C */ 236274880Sbapt {mdoc_skip_pre, NULL}, /* Es */ 237274880Sbapt {mdoc_quote_pre, mdoc_quote_post}, /* En */ 238274880Sbapt {mdoc_xx_pre, NULL}, /* Dx */ 239274880Sbapt {mdoc__x_pre, mdoc__x_post}, /* %Q */ 240274880Sbapt {mdoc__x_pre, mdoc__x_post}, /* %U */ 241274880Sbapt {NULL, NULL}, /* Ta */ 242241675Suqs}; 243322249Sbaptstatic const struct htmlmdoc *const mdocs = __mdocs - MDOC_Dd; 244241675Suqs 245241675Suqs 246241675Suqs/* 247241675Suqs * See the same function in mdoc_term.c for documentation. 248241675Suqs */ 249241675Suqsstatic void 250294113Sbaptsynopsis_pre(struct html *h, const struct roff_node *n) 251241675Suqs{ 252241675Suqs 253316420Sbapt if (NULL == n->prev || ! (NODE_SYNPRETTY & n->flags)) 254241675Suqs return; 255241675Suqs 256274880Sbapt if (n->prev->tok == n->tok && 257274880Sbapt MDOC_Fo != n->tok && 258274880Sbapt MDOC_Ft != n->tok && 259274880Sbapt MDOC_Fn != n->tok) { 260316420Sbapt print_otag(h, TAG_BR, ""); 261241675Suqs return; 262241675Suqs } 263241675Suqs 264241675Suqs switch (n->prev->tok) { 265274880Sbapt case MDOC_Fd: 266274880Sbapt case MDOC_Fn: 267274880Sbapt case MDOC_Fo: 268274880Sbapt case MDOC_In: 269274880Sbapt case MDOC_Vt: 270275432Sbapt print_paragraph(h); 271241675Suqs break; 272274880Sbapt case MDOC_Ft: 273241675Suqs if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) { 274275432Sbapt print_paragraph(h); 275241675Suqs break; 276241675Suqs } 277241675Suqs /* FALLTHROUGH */ 278241675Suqs default: 279316420Sbapt print_otag(h, TAG_BR, ""); 280241675Suqs break; 281241675Suqs } 282241675Suqs} 283241675Suqs 284294113Sbaptvoid 285294113Sbapthtml_mdoc(void *arg, const struct roff_man *mdoc) 286241675Suqs{ 287294113Sbapt struct html *h; 288316420Sbapt struct tag *t; 289241675Suqs 290294113Sbapt h = (struct html *)arg; 291241675Suqs 292316420Sbapt if ((h->oflags & HTML_FRAGMENT) == 0) { 293241675Suqs print_gen_decls(h); 294316420Sbapt print_otag(h, TAG_HTML, ""); 295316420Sbapt t = print_otag(h, TAG_HEAD, ""); 296294113Sbapt print_mdoc_head(&mdoc->meta, mdoc->first->child, h); 297316420Sbapt print_tagq(h, t); 298316420Sbapt print_otag(h, TAG_BODY, ""); 299316420Sbapt } 300241675Suqs 301294113Sbapt mdoc_root_pre(&mdoc->meta, mdoc->first->child, h); 302316420Sbapt t = print_otag(h, TAG_DIV, "c", "manual-text"); 303294113Sbapt print_mdoc_nodelist(&mdoc->meta, mdoc->first->child, h); 304316420Sbapt print_tagq(h, t); 305294113Sbapt mdoc_root_post(&mdoc->meta, mdoc->first->child, h); 306316420Sbapt print_tagq(h, NULL); 307241675Suqs} 308241675Suqs 309241675Suqsstatic void 310241675Suqsprint_mdoc_head(MDOC_ARGS) 311241675Suqs{ 312316420Sbapt char *cp; 313241675Suqs 314241675Suqs print_gen_head(h); 315241675Suqs 316316420Sbapt if (meta->arch != NULL && meta->msec != NULL) 317316420Sbapt mandoc_asprintf(&cp, "%s(%s) (%s)", meta->title, 318316420Sbapt meta->msec, meta->arch); 319316420Sbapt else if (meta->msec != NULL) 320316420Sbapt mandoc_asprintf(&cp, "%s(%s)", meta->title, meta->msec); 321316420Sbapt else if (meta->arch != NULL) 322316420Sbapt mandoc_asprintf(&cp, "%s (%s)", meta->title, meta->arch); 323316420Sbapt else 324316420Sbapt cp = mandoc_strdup(meta->title); 325316420Sbapt 326316420Sbapt print_otag(h, TAG_TITLE, ""); 327316420Sbapt print_text(h, cp); 328316420Sbapt free(cp); 329241675Suqs} 330241675Suqs 331241675Suqsstatic void 332241675Suqsprint_mdoc_nodelist(MDOC_ARGS) 333241675Suqs{ 334241675Suqs 335279527Sbapt while (n != NULL) { 336279527Sbapt print_mdoc_node(meta, n, h); 337279527Sbapt n = n->next; 338279527Sbapt } 339241675Suqs} 340241675Suqs 341241675Suqsstatic void 342241675Suqsprint_mdoc_node(MDOC_ARGS) 343241675Suqs{ 344241675Suqs int child; 345241675Suqs struct tag *t; 346241675Suqs 347316420Sbapt if (n->flags & NODE_NOPRT) 348316420Sbapt return; 349316420Sbapt 350241675Suqs child = 1; 351322249Sbapt t = h->tag; 352316420Sbapt n->flags &= ~NODE_ENDED; 353241675Suqs 354241675Suqs switch (n->type) { 355294113Sbapt case ROFFT_TEXT: 356241675Suqs /* No tables in this mode... */ 357241675Suqs assert(NULL == h->tblt); 358241675Suqs 359241675Suqs /* 360241675Suqs * Make sure that if we're in a literal mode already 361241675Suqs * (i.e., within a <PRE>) don't print the newline. 362241675Suqs */ 363322249Sbapt if (*n->string == ' ' && n->flags & NODE_LINE && 364322249Sbapt (h->flags & (HTML_LITERAL | HTML_NONEWLINE)) == 0) 365322249Sbapt print_otag(h, TAG_BR, ""); 366316420Sbapt if (NODE_DELIMC & n->flags) 367241675Suqs h->flags |= HTML_NOSPACE; 368241675Suqs print_text(h, n->string); 369316420Sbapt if (NODE_DELIMO & n->flags) 370241675Suqs h->flags |= HTML_NOSPACE; 371241675Suqs return; 372294113Sbapt case ROFFT_EQN: 373241675Suqs print_eqn(h, n->eqn); 374241675Suqs break; 375294113Sbapt case ROFFT_TBL: 376241675Suqs /* 377241675Suqs * This will take care of initialising all of the table 378241675Suqs * state data for the first table, then tearing it down 379241675Suqs * for the last one. 380241675Suqs */ 381241675Suqs print_tbl(h, n->span); 382241675Suqs return; 383241675Suqs default: 384241675Suqs /* 385241675Suqs * Close out the current table, if it's open, and unset 386241675Suqs * the "meta" table state. This will be reopened on the 387241675Suqs * next table element. 388241675Suqs */ 389275432Sbapt if (h->tblt != NULL) { 390241675Suqs print_tblclose(h); 391322249Sbapt t = h->tag; 392241675Suqs } 393275432Sbapt assert(h->tblt == NULL); 394322249Sbapt if (n->tok < ROFF_MAX) { 395322249Sbapt roff_html_pre(h, n); 396322249Sbapt child = 0; 397322249Sbapt break; 398322249Sbapt } 399322249Sbapt assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX); 400322249Sbapt if (mdocs[n->tok].pre != NULL && 401322249Sbapt (n->end == ENDBODY_NOT || n->child != NULL)) 402261344Suqs child = (*mdocs[n->tok].pre)(meta, n, h); 403241675Suqs break; 404241675Suqs } 405241675Suqs 406316420Sbapt if (h->flags & HTML_KEEP && n->flags & NODE_LINE) { 407279527Sbapt h->flags &= ~HTML_KEEP; 408279527Sbapt h->flags |= HTML_PREKEEP; 409241675Suqs } 410241675Suqs 411241675Suqs if (child && n->child) 412261344Suqs print_mdoc_nodelist(meta, n->child, h); 413241675Suqs 414241675Suqs print_stagq(h, t); 415241675Suqs 416241675Suqs switch (n->type) { 417294113Sbapt case ROFFT_EQN: 418241675Suqs break; 419241675Suqs default: 420322249Sbapt if (n->tok < ROFF_MAX || 421322249Sbapt mdocs[n->tok].post == NULL || 422322249Sbapt n->flags & NODE_ENDED) 423275432Sbapt break; 424275432Sbapt (*mdocs[n->tok].post)(meta, n, h); 425275432Sbapt if (n->end != ENDBODY_NOT) 426316420Sbapt n->body->flags |= NODE_ENDED; 427241675Suqs break; 428241675Suqs } 429241675Suqs} 430241675Suqs 431241675Suqsstatic void 432241675Suqsmdoc_root_post(MDOC_ARGS) 433241675Suqs{ 434241675Suqs struct tag *t, *tt; 435241675Suqs 436316420Sbapt t = print_otag(h, TAG_TABLE, "c", "foot"); 437316420Sbapt tt = print_otag(h, TAG_TR, ""); 438241675Suqs 439316420Sbapt print_otag(h, TAG_TD, "c", "foot-date"); 440261344Suqs print_text(h, meta->date); 441241675Suqs print_stagq(h, tt); 442241675Suqs 443316420Sbapt print_otag(h, TAG_TD, "c", "foot-os"); 444261344Suqs print_text(h, meta->os); 445241675Suqs print_tagq(h, t); 446241675Suqs} 447241675Suqs 448241675Suqsstatic int 449241675Suqsmdoc_root_pre(MDOC_ARGS) 450241675Suqs{ 451241675Suqs struct tag *t, *tt; 452274880Sbapt char *volume, *title; 453241675Suqs 454274880Sbapt if (NULL == meta->arch) 455274880Sbapt volume = mandoc_strdup(meta->vol); 456274880Sbapt else 457274880Sbapt mandoc_asprintf(&volume, "%s (%s)", 458274880Sbapt meta->vol, meta->arch); 459241675Suqs 460274880Sbapt if (NULL == meta->msec) 461274880Sbapt title = mandoc_strdup(meta->title); 462274880Sbapt else 463274880Sbapt mandoc_asprintf(&title, "%s(%s)", 464274880Sbapt meta->title, meta->msec); 465241675Suqs 466316420Sbapt t = print_otag(h, TAG_TABLE, "c", "head"); 467316420Sbapt tt = print_otag(h, TAG_TR, ""); 468241675Suqs 469316420Sbapt print_otag(h, TAG_TD, "c", "head-ltitle"); 470241675Suqs print_text(h, title); 471241675Suqs print_stagq(h, tt); 472241675Suqs 473316420Sbapt print_otag(h, TAG_TD, "c", "head-vol"); 474274880Sbapt print_text(h, volume); 475241675Suqs print_stagq(h, tt); 476241675Suqs 477316420Sbapt print_otag(h, TAG_TD, "c", "head-rtitle"); 478241675Suqs print_text(h, title); 479241675Suqs print_tagq(h, t); 480274880Sbapt 481274880Sbapt free(title); 482274880Sbapt free(volume); 483294113Sbapt return 1; 484241675Suqs} 485241675Suqs 486316420Sbaptstatic char * 487322249Sbaptcond_id(const struct roff_node *n) 488316420Sbapt{ 489322249Sbapt if (n->child != NULL && 490322249Sbapt n->child->type == ROFFT_TEXT && 491322249Sbapt (n->prev == NULL || 492322249Sbapt (n->prev->type == ROFFT_TEXT && 493322249Sbapt strcmp(n->prev->string, "|") == 0)) && 494322249Sbapt (n->parent->tok == MDOC_It || 495322249Sbapt (n->parent->tok == MDOC_Xo && 496322249Sbapt n->parent->parent->prev == NULL && 497322249Sbapt n->parent->parent->parent->tok == MDOC_It))) 498322249Sbapt return html_make_id(n); 499322249Sbapt return NULL; 500316420Sbapt} 501316420Sbapt 502241675Suqsstatic int 503241675Suqsmdoc_sh_pre(MDOC_ARGS) 504241675Suqs{ 505316420Sbapt char *id; 506241675Suqs 507275432Sbapt switch (n->type) { 508322249Sbapt case ROFFT_HEAD: 509322249Sbapt id = html_make_id(n); 510322249Sbapt print_otag(h, TAG_H1, "cTi", "Sh", id); 511322249Sbapt if (id != NULL) 512322249Sbapt print_otag(h, TAG_A, "chR", "selflink", id); 513322249Sbapt free(id); 514322249Sbapt break; 515294113Sbapt case ROFFT_BODY: 516275432Sbapt if (n->sec == SEC_AUTHORS) 517275432Sbapt h->flags &= ~(HTML_SPLIT|HTML_NOSPLIT); 518322249Sbapt break; 519275432Sbapt default: 520275432Sbapt break; 521275432Sbapt } 522294113Sbapt return 1; 523241675Suqs} 524241675Suqs 525241675Suqsstatic int 526241675Suqsmdoc_ss_pre(MDOC_ARGS) 527241675Suqs{ 528316420Sbapt char *id; 529241675Suqs 530316420Sbapt if (n->type != ROFFT_HEAD) 531294113Sbapt return 1; 532241675Suqs 533322249Sbapt id = html_make_id(n); 534322249Sbapt print_otag(h, TAG_H2, "cTi", "Ss", id); 535322249Sbapt if (id != NULL) 536322249Sbapt print_otag(h, TAG_A, "chR", "selflink", id); 537322249Sbapt free(id); 538294113Sbapt return 1; 539241675Suqs} 540241675Suqs 541241675Suqsstatic int 542241675Suqsmdoc_fl_pre(MDOC_ARGS) 543241675Suqs{ 544322249Sbapt char *id; 545322249Sbapt 546322249Sbapt if ((id = cond_id(n)) != NULL) 547322249Sbapt print_otag(h, TAG_A, "chR", "selflink", id); 548322249Sbapt print_otag(h, TAG_B, "cTi", "Fl", id); 549322249Sbapt free(id); 550322249Sbapt 551241675Suqs print_text(h, "\\-"); 552294113Sbapt if (!(n->child == NULL && 553275432Sbapt (n->next == NULL || 554294113Sbapt n->next->type == ROFFT_TEXT || 555316420Sbapt n->next->flags & NODE_LINE))) 556241675Suqs h->flags |= HTML_NOSPACE; 557241675Suqs 558294113Sbapt return 1; 559241675Suqs} 560241675Suqs 561241675Suqsstatic int 562316420Sbaptmdoc_cm_pre(MDOC_ARGS) 563316420Sbapt{ 564322249Sbapt char *id; 565322249Sbapt 566322249Sbapt if ((id = cond_id(n)) != NULL) 567322249Sbapt print_otag(h, TAG_A, "chR", "selflink", id); 568322249Sbapt print_otag(h, TAG_B, "cTi", "Cm", id); 569322249Sbapt free(id); 570316420Sbapt return 1; 571316420Sbapt} 572316420Sbapt 573316420Sbaptstatic int 574241675Suqsmdoc_nd_pre(MDOC_ARGS) 575241675Suqs{ 576294113Sbapt if (n->type != ROFFT_BODY) 577294113Sbapt return 1; 578241675Suqs 579241675Suqs /* XXX: this tag in theory can contain block elements. */ 580241675Suqs 581241675Suqs print_text(h, "\\(em"); 582322249Sbapt print_otag(h, TAG_SPAN, "cT", "Nd"); 583294113Sbapt return 1; 584241675Suqs} 585241675Suqs 586241675Suqsstatic int 587241675Suqsmdoc_nm_pre(MDOC_ARGS) 588241675Suqs{ 589241675Suqs switch (n->type) { 590294113Sbapt case ROFFT_HEAD: 591316420Sbapt print_otag(h, TAG_TD, ""); 592294113Sbapt /* FALLTHROUGH */ 593294113Sbapt case ROFFT_ELEM: 594322249Sbapt print_otag(h, TAG_B, "cT", "Nm"); 595294113Sbapt return 1; 596294113Sbapt case ROFFT_BODY: 597316420Sbapt print_otag(h, TAG_TD, ""); 598294113Sbapt return 1; 599241675Suqs default: 600241675Suqs break; 601241675Suqs } 602241675Suqs synopsis_pre(h, n); 603316420Sbapt print_otag(h, TAG_TABLE, "c", "Nm"); 604316420Sbapt print_otag(h, TAG_TR, ""); 605294113Sbapt return 1; 606241675Suqs} 607241675Suqs 608241675Suqsstatic int 609241675Suqsmdoc_xr_pre(MDOC_ARGS) 610241675Suqs{ 611241675Suqs if (NULL == n->child) 612294113Sbapt return 0; 613241675Suqs 614316420Sbapt if (h->base_man) 615322249Sbapt print_otag(h, TAG_A, "cThM", "Xr", 616316420Sbapt n->child->string, n->child->next == NULL ? 617316420Sbapt NULL : n->child->next->string); 618316420Sbapt else 619322249Sbapt print_otag(h, TAG_A, "cT", "Xr"); 620241675Suqs 621241675Suqs n = n->child; 622241675Suqs print_text(h, n->string); 623241675Suqs 624241675Suqs if (NULL == (n = n->next)) 625294113Sbapt return 0; 626241675Suqs 627241675Suqs h->flags |= HTML_NOSPACE; 628241675Suqs print_text(h, "("); 629241675Suqs h->flags |= HTML_NOSPACE; 630241675Suqs print_text(h, n->string); 631241675Suqs h->flags |= HTML_NOSPACE; 632241675Suqs print_text(h, ")"); 633294113Sbapt return 0; 634241675Suqs} 635241675Suqs 636241675Suqsstatic int 637241675Suqsmdoc_ns_pre(MDOC_ARGS) 638241675Suqs{ 639241675Suqs 640316420Sbapt if ( ! (NODE_LINE & n->flags)) 641241675Suqs h->flags |= HTML_NOSPACE; 642294113Sbapt return 1; 643241675Suqs} 644241675Suqs 645241675Suqsstatic int 646241675Suqsmdoc_ar_pre(MDOC_ARGS) 647241675Suqs{ 648322249Sbapt print_otag(h, TAG_VAR, "cT", "Ar"); 649294113Sbapt return 1; 650241675Suqs} 651241675Suqs 652241675Suqsstatic int 653241675Suqsmdoc_xx_pre(MDOC_ARGS) 654241675Suqs{ 655316420Sbapt print_otag(h, TAG_SPAN, "c", "Ux"); 656316420Sbapt return 1; 657241675Suqs} 658241675Suqs 659241675Suqsstatic int 660241675Suqsmdoc_it_pre(MDOC_ARGS) 661241675Suqs{ 662316420Sbapt const struct roff_node *bl; 663322249Sbapt struct tag *t; 664316420Sbapt const char *cattr; 665316420Sbapt enum mdoc_list type; 666241675Suqs 667241675Suqs bl = n->parent; 668322249Sbapt while (bl->tok != MDOC_Bl) 669241675Suqs bl = bl->parent; 670241675Suqs type = bl->norm->Bl.type; 671241675Suqs 672316420Sbapt switch (type) { 673316420Sbapt case LIST_bullet: 674316420Sbapt cattr = "It-bullet"; 675316420Sbapt break; 676316420Sbapt case LIST_dash: 677316420Sbapt case LIST_hyphen: 678316420Sbapt cattr = "It-dash"; 679316420Sbapt break; 680316420Sbapt case LIST_item: 681316420Sbapt cattr = "It-item"; 682316420Sbapt break; 683316420Sbapt case LIST_enum: 684316420Sbapt cattr = "It-enum"; 685316420Sbapt break; 686316420Sbapt case LIST_diag: 687316420Sbapt cattr = "It-diag"; 688316420Sbapt break; 689316420Sbapt case LIST_hang: 690316420Sbapt cattr = "It-hang"; 691316420Sbapt break; 692316420Sbapt case LIST_inset: 693316420Sbapt cattr = "It-inset"; 694316420Sbapt break; 695316420Sbapt case LIST_ohang: 696316420Sbapt cattr = "It-ohang"; 697316420Sbapt break; 698316420Sbapt case LIST_tag: 699316420Sbapt cattr = "It-tag"; 700316420Sbapt break; 701316420Sbapt case LIST_column: 702316420Sbapt cattr = "It-column"; 703316420Sbapt break; 704316420Sbapt default: 705316420Sbapt break; 706316420Sbapt } 707241675Suqs 708316420Sbapt switch (type) { 709316420Sbapt case LIST_bullet: 710316420Sbapt case LIST_dash: 711316420Sbapt case LIST_hyphen: 712316420Sbapt case LIST_item: 713316420Sbapt case LIST_enum: 714316420Sbapt switch (n->type) { 715316420Sbapt case ROFFT_HEAD: 716294113Sbapt return 0; 717316420Sbapt case ROFFT_BODY: 718322249Sbapt print_otag(h, TAG_LI, "c", cattr); 719241675Suqs break; 720241675Suqs default: 721241675Suqs break; 722241675Suqs } 723316420Sbapt break; 724316420Sbapt case LIST_diag: 725316420Sbapt case LIST_hang: 726316420Sbapt case LIST_inset: 727316420Sbapt case LIST_ohang: 728316420Sbapt switch (n->type) { 729316420Sbapt case ROFFT_HEAD: 730322249Sbapt print_otag(h, TAG_DT, "c", cattr); 731316420Sbapt if (type == LIST_diag) 732316420Sbapt print_otag(h, TAG_B, "c", cattr); 733241675Suqs break; 734316420Sbapt case ROFFT_BODY: 735322249Sbapt print_otag(h, TAG_DD, "csw*+l", cattr, 736322249Sbapt bl->norm->Bl.width); 737322249Sbapt break; 738322249Sbapt default: 739322249Sbapt break; 740322249Sbapt } 741322249Sbapt break; 742322249Sbapt case LIST_tag: 743322249Sbapt switch (n->type) { 744322249Sbapt case ROFFT_HEAD: 745322249Sbapt if (h->style != NULL && !bl->norm->Bl.comp && 746322249Sbapt (n->parent->prev == NULL || 747322249Sbapt n->parent->prev->body == NULL || 748322249Sbapt n->parent->prev->body->child != NULL)) { 749322249Sbapt t = print_otag(h, TAG_DT, "csw*+-l", 750322249Sbapt cattr, bl->norm->Bl.width); 751322249Sbapt print_text(h, "\\ "); 752322249Sbapt print_tagq(h, t); 753322249Sbapt t = print_otag(h, TAG_DD, "c", cattr); 754322249Sbapt print_text(h, "\\ "); 755322249Sbapt print_tagq(h, t); 756322249Sbapt } 757322249Sbapt print_otag(h, TAG_DT, "csw*+-l", cattr, 758322249Sbapt bl->norm->Bl.width); 759322249Sbapt break; 760322249Sbapt case ROFFT_BODY: 761322249Sbapt if (n->child == NULL) { 762322249Sbapt print_otag(h, TAG_DD, "css?", cattr, 763322249Sbapt "width", "auto"); 764322249Sbapt print_text(h, "\\ "); 765322249Sbapt } else 766316420Sbapt print_otag(h, TAG_DD, "c", cattr); 767241675Suqs break; 768241675Suqs default: 769241675Suqs break; 770241675Suqs } 771316420Sbapt break; 772316420Sbapt case LIST_column: 773316420Sbapt switch (n->type) { 774316420Sbapt case ROFFT_HEAD: 775241675Suqs break; 776316420Sbapt case ROFFT_BODY: 777322249Sbapt print_otag(h, TAG_TD, "c", cattr); 778316420Sbapt break; 779241675Suqs default: 780316420Sbapt print_otag(h, TAG_TR, "c", cattr); 781241675Suqs } 782316420Sbapt default: 783316420Sbapt break; 784241675Suqs } 785241675Suqs 786294113Sbapt return 1; 787241675Suqs} 788241675Suqs 789241675Suqsstatic int 790241675Suqsmdoc_bl_pre(MDOC_ARGS) 791241675Suqs{ 792322249Sbapt char cattr[21]; 793322249Sbapt struct tag *t; 794322249Sbapt struct mdoc_bl *bl; 795322249Sbapt size_t i; 796316420Sbapt enum htmltag elemtype; 797241675Suqs 798322249Sbapt bl = &n->norm->Bl; 799322249Sbapt 800322249Sbapt switch (n->type) { 801322249Sbapt case ROFFT_BODY: 802294113Sbapt return 1; 803241675Suqs 804322249Sbapt case ROFFT_HEAD: 805322249Sbapt if (bl->type != LIST_column || bl->ncols == 0) 806294113Sbapt return 0; 807241675Suqs 808241675Suqs /* 809241675Suqs * For each column, print out the <COL> tag with our 810241675Suqs * suggested width. The last column gets min-width, as 811241675Suqs * in terminal mode it auto-sizes to the width of the 812241675Suqs * screen and we want to preserve that behaviour. 813241675Suqs */ 814241675Suqs 815322249Sbapt t = print_otag(h, TAG_COLGROUP, ""); 816322249Sbapt for (i = 0; i < bl->ncols - 1; i++) 817322249Sbapt print_otag(h, TAG_COL, "sw+w", bl->cols[i]); 818322249Sbapt print_otag(h, TAG_COL, "swW", bl->cols[i]); 819322249Sbapt print_tagq(h, t); 820322249Sbapt return 0; 821241675Suqs 822322249Sbapt default: 823322249Sbapt break; 824241675Suqs } 825241675Suqs 826322249Sbapt switch (bl->type) { 827274880Sbapt case LIST_bullet: 828316420Sbapt elemtype = TAG_UL; 829322249Sbapt (void)strlcpy(cattr, "Bl-bullet", sizeof(cattr)); 830316420Sbapt break; 831274880Sbapt case LIST_dash: 832274880Sbapt case LIST_hyphen: 833316420Sbapt elemtype = TAG_UL; 834322249Sbapt (void)strlcpy(cattr, "Bl-dash", sizeof(cattr)); 835316420Sbapt break; 836274880Sbapt case LIST_item: 837316420Sbapt elemtype = TAG_UL; 838322249Sbapt (void)strlcpy(cattr, "Bl-item", sizeof(cattr)); 839241675Suqs break; 840274880Sbapt case LIST_enum: 841316420Sbapt elemtype = TAG_OL; 842322249Sbapt (void)strlcpy(cattr, "Bl-enum", sizeof(cattr)); 843241675Suqs break; 844274880Sbapt case LIST_diag: 845316420Sbapt elemtype = TAG_DL; 846322249Sbapt (void)strlcpy(cattr, "Bl-diag", sizeof(cattr)); 847316420Sbapt break; 848274880Sbapt case LIST_hang: 849316420Sbapt elemtype = TAG_DL; 850322249Sbapt (void)strlcpy(cattr, "Bl-hang", sizeof(cattr)); 851316420Sbapt break; 852274880Sbapt case LIST_inset: 853316420Sbapt elemtype = TAG_DL; 854322249Sbapt (void)strlcpy(cattr, "Bl-inset", sizeof(cattr)); 855316420Sbapt break; 856274880Sbapt case LIST_ohang: 857316420Sbapt elemtype = TAG_DL; 858322249Sbapt (void)strlcpy(cattr, "Bl-ohang", sizeof(cattr)); 859316420Sbapt break; 860274880Sbapt case LIST_tag: 861322249Sbapt if (bl->offs) 862322249Sbapt print_otag(h, TAG_DIV, "cswl", "Bl-tag", bl->offs); 863322249Sbapt print_otag(h, TAG_DL, "csw*+l", bl->comp ? 864322249Sbapt "Bl-tag Bl-compact" : "Bl-tag", bl->width); 865322249Sbapt return 1; 866274880Sbapt case LIST_column: 867316420Sbapt elemtype = TAG_TABLE; 868322249Sbapt (void)strlcpy(cattr, "Bl-column", sizeof(cattr)); 869241675Suqs break; 870241675Suqs default: 871241675Suqs abort(); 872241675Suqs } 873322249Sbapt if (bl->comp) 874322249Sbapt (void)strlcat(cattr, " Bl-compact", sizeof(cattr)); 875322249Sbapt print_otag(h, elemtype, "cswl", cattr, bl->offs); 876294113Sbapt return 1; 877241675Suqs} 878241675Suqs 879241675Suqsstatic int 880241675Suqsmdoc_ex_pre(MDOC_ARGS) 881241675Suqs{ 882241675Suqs if (n->prev) 883316420Sbapt print_otag(h, TAG_BR, ""); 884316420Sbapt return 1; 885241675Suqs} 886241675Suqs 887241675Suqsstatic int 888322249Sbaptmdoc_st_pre(MDOC_ARGS) 889322249Sbapt{ 890322249Sbapt print_otag(h, TAG_SPAN, "cT", "St"); 891322249Sbapt return 1; 892322249Sbapt} 893322249Sbapt 894322249Sbaptstatic int 895241675Suqsmdoc_em_pre(MDOC_ARGS) 896241675Suqs{ 897322249Sbapt print_otag(h, TAG_I, "cT", "Em"); 898294113Sbapt return 1; 899241675Suqs} 900241675Suqs 901241675Suqsstatic int 902241675Suqsmdoc_d1_pre(MDOC_ARGS) 903241675Suqs{ 904294113Sbapt if (n->type != ROFFT_BLOCK) 905294113Sbapt return 1; 906241675Suqs 907316420Sbapt print_otag(h, TAG_DIV, "c", "D1"); 908241675Suqs 909316420Sbapt if (n->tok == MDOC_Dl) 910316420Sbapt print_otag(h, TAG_CODE, "c", "Li"); 911241675Suqs 912294113Sbapt return 1; 913241675Suqs} 914241675Suqs 915241675Suqsstatic int 916241675Suqsmdoc_sx_pre(MDOC_ARGS) 917241675Suqs{ 918316420Sbapt char *id; 919241675Suqs 920322249Sbapt id = html_make_id(n); 921322249Sbapt print_otag(h, TAG_A, "cThR", "Sx", id); 922322249Sbapt free(id); 923294113Sbapt return 1; 924241675Suqs} 925241675Suqs 926241675Suqsstatic int 927241675Suqsmdoc_bd_pre(MDOC_ARGS) 928241675Suqs{ 929316420Sbapt int comp, offs, sv; 930294113Sbapt struct roff_node *nn; 931241675Suqs 932294113Sbapt if (n->type == ROFFT_HEAD) 933294113Sbapt return 0; 934241675Suqs 935294113Sbapt if (n->type == ROFFT_BLOCK) { 936241675Suqs comp = n->norm->Bd.comp; 937241675Suqs for (nn = n; nn && ! comp; nn = nn->parent) { 938294113Sbapt if (nn->type != ROFFT_BLOCK) 939241675Suqs continue; 940241675Suqs if (MDOC_Ss == nn->tok || MDOC_Sh == nn->tok) 941241675Suqs comp = 1; 942241675Suqs if (nn->prev) 943241675Suqs break; 944241675Suqs } 945241675Suqs if ( ! comp) 946275432Sbapt print_paragraph(h); 947294113Sbapt return 1; 948241675Suqs } 949241675Suqs 950275432Sbapt /* Handle the -offset argument. */ 951274880Sbapt 952275432Sbapt if (n->norm->Bd.offs == NULL || 953275432Sbapt ! strcmp(n->norm->Bd.offs, "left")) 954316420Sbapt offs = 0; 955275432Sbapt else if ( ! strcmp(n->norm->Bd.offs, "indent")) 956316420Sbapt offs = INDENT; 957275432Sbapt else if ( ! strcmp(n->norm->Bd.offs, "indent-two")) 958316420Sbapt offs = INDENT * 2; 959275432Sbapt else 960316420Sbapt offs = -1; 961275432Sbapt 962316420Sbapt if (offs == -1) 963316420Sbapt print_otag(h, TAG_DIV, "cswl", "Bd", n->norm->Bd.offs); 964316420Sbapt else 965316420Sbapt print_otag(h, TAG_DIV, "cshl", "Bd", offs); 966241675Suqs 967316420Sbapt if (n->norm->Bd.type != DISP_unfilled && 968316420Sbapt n->norm->Bd.type != DISP_literal) 969294113Sbapt return 1; 970241675Suqs 971316420Sbapt print_otag(h, TAG_PRE, "c", "Li"); 972241675Suqs 973241675Suqs /* This can be recursive: save & set our literal state. */ 974241675Suqs 975241675Suqs sv = h->flags & HTML_LITERAL; 976241675Suqs h->flags |= HTML_LITERAL; 977241675Suqs 978241675Suqs for (nn = n->child; nn; nn = nn->next) { 979261344Suqs print_mdoc_node(meta, nn, h); 980241675Suqs /* 981241675Suqs * If the printed node flushes its own line, then we 982241675Suqs * needn't do it here as well. This is hacky, but the 983241675Suqs * notion of selective eoln whitespace is pretty dumb 984241675Suqs * anyway, so don't sweat it. 985241675Suqs */ 986241675Suqs switch (nn->tok) { 987322249Sbapt case ROFF_br: 988322249Sbapt case ROFF_sp: 989274880Sbapt case MDOC_Sm: 990274880Sbapt case MDOC_Bl: 991274880Sbapt case MDOC_D1: 992274880Sbapt case MDOC_Dl: 993274880Sbapt case MDOC_Lp: 994274880Sbapt case MDOC_Pp: 995241675Suqs continue; 996241675Suqs default: 997241675Suqs break; 998241675Suqs } 999276219Sbapt if (h->flags & HTML_NONEWLINE || 1000316420Sbapt (nn->next && ! (nn->next->flags & NODE_LINE))) 1001241675Suqs continue; 1002241675Suqs else if (nn->next) 1003241675Suqs print_text(h, "\n"); 1004241675Suqs 1005241675Suqs h->flags |= HTML_NOSPACE; 1006241675Suqs } 1007241675Suqs 1008241675Suqs if (0 == sv) 1009241675Suqs h->flags &= ~HTML_LITERAL; 1010241675Suqs 1011294113Sbapt return 0; 1012241675Suqs} 1013241675Suqs 1014241675Suqsstatic int 1015241675Suqsmdoc_pa_pre(MDOC_ARGS) 1016241675Suqs{ 1017322249Sbapt print_otag(h, TAG_I, "cT", "Pa"); 1018294113Sbapt return 1; 1019241675Suqs} 1020241675Suqs 1021241675Suqsstatic int 1022241675Suqsmdoc_ad_pre(MDOC_ARGS) 1023241675Suqs{ 1024316420Sbapt print_otag(h, TAG_I, "c", "Ad"); 1025294113Sbapt return 1; 1026241675Suqs} 1027241675Suqs 1028241675Suqsstatic int 1029241675Suqsmdoc_an_pre(MDOC_ARGS) 1030241675Suqs{ 1031275432Sbapt if (n->norm->An.auth == AUTH_split) { 1032275432Sbapt h->flags &= ~HTML_NOSPLIT; 1033275432Sbapt h->flags |= HTML_SPLIT; 1034294113Sbapt return 0; 1035275432Sbapt } 1036275432Sbapt if (n->norm->An.auth == AUTH_nosplit) { 1037275432Sbapt h->flags &= ~HTML_SPLIT; 1038275432Sbapt h->flags |= HTML_NOSPLIT; 1039294113Sbapt return 0; 1040275432Sbapt } 1041241675Suqs 1042275432Sbapt if (h->flags & HTML_SPLIT) 1043316420Sbapt print_otag(h, TAG_BR, ""); 1044275432Sbapt 1045275432Sbapt if (n->sec == SEC_AUTHORS && ! (h->flags & HTML_NOSPLIT)) 1046275432Sbapt h->flags |= HTML_SPLIT; 1047275432Sbapt 1048322249Sbapt print_otag(h, TAG_SPAN, "cT", "An"); 1049294113Sbapt return 1; 1050241675Suqs} 1051241675Suqs 1052241675Suqsstatic int 1053241675Suqsmdoc_cd_pre(MDOC_ARGS) 1054241675Suqs{ 1055241675Suqs synopsis_pre(h, n); 1056322249Sbapt print_otag(h, TAG_B, "cT", "Cd"); 1057294113Sbapt return 1; 1058241675Suqs} 1059241675Suqs 1060241675Suqsstatic int 1061241675Suqsmdoc_dv_pre(MDOC_ARGS) 1062241675Suqs{ 1063322249Sbapt char *id; 1064322249Sbapt 1065322249Sbapt if ((id = cond_id(n)) != NULL) 1066322249Sbapt print_otag(h, TAG_A, "chR", "selflink", id); 1067322249Sbapt print_otag(h, TAG_CODE, "cTi", "Dv", id); 1068322249Sbapt free(id); 1069294113Sbapt return 1; 1070241675Suqs} 1071241675Suqs 1072241675Suqsstatic int 1073241675Suqsmdoc_ev_pre(MDOC_ARGS) 1074241675Suqs{ 1075322249Sbapt char *id; 1076322249Sbapt 1077322249Sbapt if ((id = cond_id(n)) != NULL) 1078322249Sbapt print_otag(h, TAG_A, "chR", "selflink", id); 1079322249Sbapt print_otag(h, TAG_CODE, "cTi", "Ev", id); 1080322249Sbapt free(id); 1081294113Sbapt return 1; 1082241675Suqs} 1083241675Suqs 1084241675Suqsstatic int 1085241675Suqsmdoc_er_pre(MDOC_ARGS) 1086241675Suqs{ 1087322249Sbapt char *id; 1088322249Sbapt 1089322249Sbapt id = n->sec == SEC_ERRORS && 1090322249Sbapt (n->parent->tok == MDOC_It || 1091322249Sbapt (n->parent->tok == MDOC_Bq && 1092322249Sbapt n->parent->parent->parent->tok == MDOC_It)) ? 1093322249Sbapt html_make_id(n) : NULL; 1094322249Sbapt 1095322249Sbapt if (id != NULL) 1096322249Sbapt print_otag(h, TAG_A, "chR", "selflink", id); 1097322249Sbapt print_otag(h, TAG_CODE, "cTi", "Er", id); 1098322249Sbapt free(id); 1099294113Sbapt return 1; 1100241675Suqs} 1101241675Suqs 1102241675Suqsstatic int 1103241675Suqsmdoc_fa_pre(MDOC_ARGS) 1104241675Suqs{ 1105294113Sbapt const struct roff_node *nn; 1106241675Suqs struct tag *t; 1107241675Suqs 1108241675Suqs if (n->parent->tok != MDOC_Fo) { 1109322249Sbapt print_otag(h, TAG_VAR, "cT", "Fa"); 1110294113Sbapt return 1; 1111241675Suqs } 1112241675Suqs 1113241675Suqs for (nn = n->child; nn; nn = nn->next) { 1114322249Sbapt t = print_otag(h, TAG_VAR, "cT", "Fa"); 1115241675Suqs print_text(h, nn->string); 1116241675Suqs print_tagq(h, t); 1117241675Suqs if (nn->next) { 1118241675Suqs h->flags |= HTML_NOSPACE; 1119241675Suqs print_text(h, ","); 1120241675Suqs } 1121241675Suqs } 1122241675Suqs 1123241675Suqs if (n->child && n->next && n->next->tok == MDOC_Fa) { 1124241675Suqs h->flags |= HTML_NOSPACE; 1125241675Suqs print_text(h, ","); 1126241675Suqs } 1127241675Suqs 1128294113Sbapt return 0; 1129241675Suqs} 1130241675Suqs 1131241675Suqsstatic int 1132241675Suqsmdoc_fd_pre(MDOC_ARGS) 1133241675Suqs{ 1134241675Suqs struct tag *t; 1135316420Sbapt char *buf, *cp; 1136241675Suqs 1137241675Suqs synopsis_pre(h, n); 1138241675Suqs 1139241675Suqs if (NULL == (n = n->child)) 1140294113Sbapt return 0; 1141241675Suqs 1142294113Sbapt assert(n->type == ROFFT_TEXT); 1143241675Suqs 1144241675Suqs if (strcmp(n->string, "#include")) { 1145322249Sbapt print_otag(h, TAG_B, "cT", "Fd"); 1146294113Sbapt return 1; 1147241675Suqs } 1148241675Suqs 1149322249Sbapt print_otag(h, TAG_B, "cT", "In"); 1150241675Suqs print_text(h, n->string); 1151241675Suqs 1152241675Suqs if (NULL != (n = n->next)) { 1153294113Sbapt assert(n->type == ROFFT_TEXT); 1154241675Suqs 1155241675Suqs if (h->base_includes) { 1156316420Sbapt cp = n->string; 1157316420Sbapt if (*cp == '<' || *cp == '"') 1158316420Sbapt cp++; 1159316420Sbapt buf = mandoc_strdup(cp); 1160316420Sbapt cp = strchr(buf, '\0') - 1; 1161316420Sbapt if (cp >= buf && (*cp == '>' || *cp == '"')) 1162316420Sbapt *cp = '\0'; 1163322249Sbapt t = print_otag(h, TAG_A, "cThI", "In", buf); 1164316420Sbapt free(buf); 1165316420Sbapt } else 1166322249Sbapt t = print_otag(h, TAG_A, "cT", "In"); 1167241675Suqs 1168241675Suqs print_text(h, n->string); 1169241675Suqs print_tagq(h, t); 1170241675Suqs 1171241675Suqs n = n->next; 1172241675Suqs } 1173241675Suqs 1174241675Suqs for ( ; n; n = n->next) { 1175294113Sbapt assert(n->type == ROFFT_TEXT); 1176241675Suqs print_text(h, n->string); 1177241675Suqs } 1178241675Suqs 1179294113Sbapt return 0; 1180241675Suqs} 1181241675Suqs 1182241675Suqsstatic int 1183241675Suqsmdoc_vt_pre(MDOC_ARGS) 1184241675Suqs{ 1185294113Sbapt if (n->type == ROFFT_BLOCK) { 1186241675Suqs synopsis_pre(h, n); 1187294113Sbapt return 1; 1188294113Sbapt } else if (n->type == ROFFT_ELEM) { 1189241675Suqs synopsis_pre(h, n); 1190294113Sbapt } else if (n->type == ROFFT_HEAD) 1191294113Sbapt return 0; 1192241675Suqs 1193322249Sbapt print_otag(h, TAG_VAR, "cT", "Vt"); 1194294113Sbapt return 1; 1195241675Suqs} 1196241675Suqs 1197241675Suqsstatic int 1198241675Suqsmdoc_ft_pre(MDOC_ARGS) 1199241675Suqs{ 1200241675Suqs synopsis_pre(h, n); 1201322249Sbapt print_otag(h, TAG_VAR, "cT", "Ft"); 1202294113Sbapt return 1; 1203241675Suqs} 1204241675Suqs 1205241675Suqsstatic int 1206241675Suqsmdoc_fn_pre(MDOC_ARGS) 1207241675Suqs{ 1208241675Suqs struct tag *t; 1209241675Suqs char nbuf[BUFSIZ]; 1210241675Suqs const char *sp, *ep; 1211316420Sbapt int sz, pretty; 1212241675Suqs 1213316420Sbapt pretty = NODE_SYNPRETTY & n->flags; 1214241675Suqs synopsis_pre(h, n); 1215241675Suqs 1216241675Suqs /* Split apart into type and name. */ 1217241675Suqs assert(n->child->string); 1218241675Suqs sp = n->child->string; 1219241675Suqs 1220241675Suqs ep = strchr(sp, ' '); 1221241675Suqs if (NULL != ep) { 1222322249Sbapt t = print_otag(h, TAG_VAR, "cT", "Ft"); 1223274880Sbapt 1224241675Suqs while (ep) { 1225241675Suqs sz = MIN((int)(ep - sp), BUFSIZ - 1); 1226241675Suqs (void)memcpy(nbuf, sp, (size_t)sz); 1227241675Suqs nbuf[sz] = '\0'; 1228241675Suqs print_text(h, nbuf); 1229241675Suqs sp = ++ep; 1230241675Suqs ep = strchr(sp, ' '); 1231241675Suqs } 1232241675Suqs print_tagq(h, t); 1233241675Suqs } 1234241675Suqs 1235322249Sbapt t = print_otag(h, TAG_B, "cT", "Fn"); 1236241675Suqs 1237274880Sbapt if (sp) 1238274880Sbapt print_text(h, sp); 1239241675Suqs 1240241675Suqs print_tagq(h, t); 1241241675Suqs 1242241675Suqs h->flags |= HTML_NOSPACE; 1243241675Suqs print_text(h, "("); 1244241675Suqs h->flags |= HTML_NOSPACE; 1245241675Suqs 1246241675Suqs for (n = n->child->next; n; n = n->next) { 1247316420Sbapt if (NODE_SYNPRETTY & n->flags) 1248322249Sbapt t = print_otag(h, TAG_VAR, "cTss?", "Fa", 1249316420Sbapt "white-space", "nowrap"); 1250316420Sbapt else 1251322249Sbapt t = print_otag(h, TAG_VAR, "cT", "Fa"); 1252241675Suqs print_text(h, n->string); 1253241675Suqs print_tagq(h, t); 1254241675Suqs if (n->next) { 1255241675Suqs h->flags |= HTML_NOSPACE; 1256241675Suqs print_text(h, ","); 1257241675Suqs } 1258241675Suqs } 1259241675Suqs 1260241675Suqs h->flags |= HTML_NOSPACE; 1261241675Suqs print_text(h, ")"); 1262241675Suqs 1263241675Suqs if (pretty) { 1264241675Suqs h->flags |= HTML_NOSPACE; 1265241675Suqs print_text(h, ";"); 1266241675Suqs } 1267241675Suqs 1268294113Sbapt return 0; 1269241675Suqs} 1270241675Suqs 1271241675Suqsstatic int 1272241675Suqsmdoc_sm_pre(MDOC_ARGS) 1273241675Suqs{ 1274241675Suqs 1275274880Sbapt if (NULL == n->child) 1276274880Sbapt h->flags ^= HTML_NONOSPACE; 1277274880Sbapt else if (0 == strcmp("on", n->child->string)) 1278241675Suqs h->flags &= ~HTML_NONOSPACE; 1279274880Sbapt else 1280241675Suqs h->flags |= HTML_NONOSPACE; 1281241675Suqs 1282274880Sbapt if ( ! (HTML_NONOSPACE & h->flags)) 1283274880Sbapt h->flags &= ~HTML_NOSPACE; 1284274880Sbapt 1285294113Sbapt return 0; 1286241675Suqs} 1287241675Suqs 1288241675Suqsstatic int 1289274880Sbaptmdoc_skip_pre(MDOC_ARGS) 1290274880Sbapt{ 1291274880Sbapt 1292294113Sbapt return 0; 1293274880Sbapt} 1294274880Sbapt 1295274880Sbaptstatic int 1296241675Suqsmdoc_pp_pre(MDOC_ARGS) 1297241675Suqs{ 1298241675Suqs 1299275432Sbapt print_paragraph(h); 1300294113Sbapt return 0; 1301241675Suqs} 1302241675Suqs 1303241675Suqsstatic int 1304322249Sbaptmdoc_lk_pre(MDOC_ARGS) 1305241675Suqs{ 1306322249Sbapt const struct roff_node *link, *descr, *punct; 1307322249Sbapt struct tag *t; 1308241675Suqs 1309322249Sbapt if ((link = n->child) == NULL) 1310294113Sbapt return 0; 1311241675Suqs 1312322249Sbapt /* Find beginning of trailing punctuation. */ 1313322249Sbapt punct = n->last; 1314322249Sbapt while (punct != link && punct->flags & NODE_DELIMC) 1315322249Sbapt punct = punct->prev; 1316322249Sbapt punct = punct->next; 1317241675Suqs 1318322249Sbapt /* Link target and link text. */ 1319322249Sbapt descr = link->next; 1320322249Sbapt if (descr == punct) 1321322249Sbapt descr = link; /* no text */ 1322322249Sbapt t = print_otag(h, TAG_A, "cTh", "Lk", link->string); 1323322249Sbapt do { 1324322249Sbapt if (descr->flags & (NODE_DELIMC | NODE_DELIMO)) 1325322249Sbapt h->flags |= HTML_NOSPACE; 1326322249Sbapt print_text(h, descr->string); 1327322249Sbapt descr = descr->next; 1328322249Sbapt } while (descr != punct); 1329322249Sbapt print_tagq(h, t); 1330241675Suqs 1331322249Sbapt /* Trailing punctuation. */ 1332322249Sbapt while (punct != NULL) { 1333322249Sbapt h->flags |= HTML_NOSPACE; 1334322249Sbapt print_text(h, punct->string); 1335322249Sbapt punct = punct->next; 1336322249Sbapt } 1337294113Sbapt return 0; 1338241675Suqs} 1339241675Suqs 1340241675Suqsstatic int 1341241675Suqsmdoc_mt_pre(MDOC_ARGS) 1342241675Suqs{ 1343241675Suqs struct tag *t; 1344316420Sbapt char *cp; 1345241675Suqs 1346241675Suqs for (n = n->child; n; n = n->next) { 1347294113Sbapt assert(n->type == ROFFT_TEXT); 1348241675Suqs 1349316420Sbapt mandoc_asprintf(&cp, "mailto:%s", n->string); 1350322249Sbapt t = print_otag(h, TAG_A, "cTh", "Mt", cp); 1351241675Suqs print_text(h, n->string); 1352241675Suqs print_tagq(h, t); 1353316420Sbapt free(cp); 1354241675Suqs } 1355274880Sbapt 1356294113Sbapt return 0; 1357241675Suqs} 1358241675Suqs 1359241675Suqsstatic int 1360241675Suqsmdoc_fo_pre(MDOC_ARGS) 1361241675Suqs{ 1362241675Suqs struct tag *t; 1363241675Suqs 1364294113Sbapt if (n->type == ROFFT_BODY) { 1365241675Suqs h->flags |= HTML_NOSPACE; 1366241675Suqs print_text(h, "("); 1367241675Suqs h->flags |= HTML_NOSPACE; 1368294113Sbapt return 1; 1369294113Sbapt } else if (n->type == ROFFT_BLOCK) { 1370241675Suqs synopsis_pre(h, n); 1371294113Sbapt return 1; 1372241675Suqs } 1373241675Suqs 1374294113Sbapt if (n->child == NULL) 1375294113Sbapt return 0; 1376241675Suqs 1377241675Suqs assert(n->child->string); 1378322249Sbapt t = print_otag(h, TAG_B, "cT", "Fn"); 1379241675Suqs print_text(h, n->child->string); 1380241675Suqs print_tagq(h, t); 1381294113Sbapt return 0; 1382241675Suqs} 1383241675Suqs 1384241675Suqsstatic void 1385241675Suqsmdoc_fo_post(MDOC_ARGS) 1386241675Suqs{ 1387241675Suqs 1388294113Sbapt if (n->type != ROFFT_BODY) 1389241675Suqs return; 1390241675Suqs h->flags |= HTML_NOSPACE; 1391241675Suqs print_text(h, ")"); 1392241675Suqs h->flags |= HTML_NOSPACE; 1393241675Suqs print_text(h, ";"); 1394241675Suqs} 1395241675Suqs 1396241675Suqsstatic int 1397241675Suqsmdoc_in_pre(MDOC_ARGS) 1398241675Suqs{ 1399241675Suqs struct tag *t; 1400241675Suqs 1401241675Suqs synopsis_pre(h, n); 1402322249Sbapt print_otag(h, TAG_B, "cT", "In"); 1403241675Suqs 1404241675Suqs /* 1405241675Suqs * The first argument of the `In' gets special treatment as 1406241675Suqs * being a linked value. Subsequent values are printed 1407241675Suqs * afterward. groff does similarly. This also handles the case 1408241675Suqs * of no children. 1409241675Suqs */ 1410241675Suqs 1411316420Sbapt if (NODE_SYNPRETTY & n->flags && NODE_LINE & n->flags) 1412241675Suqs print_text(h, "#include"); 1413241675Suqs 1414241675Suqs print_text(h, "<"); 1415241675Suqs h->flags |= HTML_NOSPACE; 1416241675Suqs 1417241675Suqs if (NULL != (n = n->child)) { 1418294113Sbapt assert(n->type == ROFFT_TEXT); 1419241675Suqs 1420316420Sbapt if (h->base_includes) 1421322249Sbapt t = print_otag(h, TAG_A, "cThI", "In", n->string); 1422316420Sbapt else 1423322249Sbapt t = print_otag(h, TAG_A, "cT", "In"); 1424241675Suqs print_text(h, n->string); 1425241675Suqs print_tagq(h, t); 1426241675Suqs 1427241675Suqs n = n->next; 1428241675Suqs } 1429241675Suqs 1430241675Suqs h->flags |= HTML_NOSPACE; 1431241675Suqs print_text(h, ">"); 1432241675Suqs 1433241675Suqs for ( ; n; n = n->next) { 1434294113Sbapt assert(n->type == ROFFT_TEXT); 1435241675Suqs print_text(h, n->string); 1436241675Suqs } 1437241675Suqs 1438294113Sbapt return 0; 1439241675Suqs} 1440241675Suqs 1441241675Suqsstatic int 1442241675Suqsmdoc_ic_pre(MDOC_ARGS) 1443241675Suqs{ 1444322249Sbapt char *id; 1445322249Sbapt 1446322249Sbapt if ((id = cond_id(n)) != NULL) 1447322249Sbapt print_otag(h, TAG_A, "chR", "selflink", id); 1448322249Sbapt print_otag(h, TAG_B, "cTi", "Ic", id); 1449322249Sbapt free(id); 1450294113Sbapt return 1; 1451241675Suqs} 1452241675Suqs 1453241675Suqsstatic int 1454241675Suqsmdoc_va_pre(MDOC_ARGS) 1455241675Suqs{ 1456322249Sbapt print_otag(h, TAG_VAR, "cT", "Va"); 1457294113Sbapt return 1; 1458241675Suqs} 1459241675Suqs 1460241675Suqsstatic int 1461241675Suqsmdoc_ap_pre(MDOC_ARGS) 1462241675Suqs{ 1463274880Sbapt 1464241675Suqs h->flags |= HTML_NOSPACE; 1465241675Suqs print_text(h, "\\(aq"); 1466241675Suqs h->flags |= HTML_NOSPACE; 1467294113Sbapt return 1; 1468241675Suqs} 1469241675Suqs 1470241675Suqsstatic int 1471241675Suqsmdoc_bf_pre(MDOC_ARGS) 1472241675Suqs{ 1473316420Sbapt const char *cattr; 1474241675Suqs 1475294113Sbapt if (n->type == ROFFT_HEAD) 1476294113Sbapt return 0; 1477294113Sbapt else if (n->type != ROFFT_BODY) 1478294113Sbapt return 1; 1479241675Suqs 1480274880Sbapt if (FONT_Em == n->norm->Bf.font) 1481316420Sbapt cattr = "Em"; 1482274880Sbapt else if (FONT_Sy == n->norm->Bf.font) 1483316420Sbapt cattr = "Sy"; 1484274880Sbapt else if (FONT_Li == n->norm->Bf.font) 1485316420Sbapt cattr = "Li"; 1486241675Suqs else 1487322249Sbapt cattr = "No"; 1488241675Suqs 1489274880Sbapt /* 1490241675Suqs * We want this to be inline-formatted, but needs to be div to 1491274880Sbapt * accept block children. 1492241675Suqs */ 1493316420Sbapt 1494316420Sbapt print_otag(h, TAG_DIV, "css?hl", cattr, "display", "inline", 1); 1495294113Sbapt return 1; 1496241675Suqs} 1497241675Suqs 1498241675Suqsstatic int 1499241675Suqsmdoc_ms_pre(MDOC_ARGS) 1500241675Suqs{ 1501322249Sbapt char *id; 1502322249Sbapt 1503322249Sbapt if ((id = cond_id(n)) != NULL) 1504322249Sbapt print_otag(h, TAG_A, "chR", "selflink", id); 1505322249Sbapt print_otag(h, TAG_B, "cTi", "Ms", id); 1506322249Sbapt free(id); 1507294113Sbapt return 1; 1508241675Suqs} 1509241675Suqs 1510241675Suqsstatic int 1511241675Suqsmdoc_igndelim_pre(MDOC_ARGS) 1512241675Suqs{ 1513241675Suqs 1514241675Suqs h->flags |= HTML_IGNDELIM; 1515294113Sbapt return 1; 1516241675Suqs} 1517241675Suqs 1518241675Suqsstatic void 1519241675Suqsmdoc_pf_post(MDOC_ARGS) 1520241675Suqs{ 1521241675Suqs 1522316420Sbapt if ( ! (n->next == NULL || n->next->flags & NODE_LINE)) 1523276219Sbapt h->flags |= HTML_NOSPACE; 1524241675Suqs} 1525241675Suqs 1526241675Suqsstatic int 1527241675Suqsmdoc_rs_pre(MDOC_ARGS) 1528241675Suqs{ 1529294113Sbapt if (n->type != ROFFT_BLOCK) 1530294113Sbapt return 1; 1531241675Suqs 1532241675Suqs if (n->prev && SEC_SEE_ALSO == n->sec) 1533275432Sbapt print_paragraph(h); 1534241675Suqs 1535322249Sbapt print_otag(h, TAG_CITE, "cT", "Rs"); 1536294113Sbapt return 1; 1537241675Suqs} 1538241675Suqs 1539241675Suqsstatic int 1540275432Sbaptmdoc_no_pre(MDOC_ARGS) 1541275432Sbapt{ 1542322249Sbapt char *id; 1543322249Sbapt 1544322249Sbapt if ((id = cond_id(n)) != NULL) 1545322249Sbapt print_otag(h, TAG_A, "chR", "selflink", id); 1546322249Sbapt print_otag(h, TAG_SPAN, "ci", "No", id); 1547322249Sbapt free(id); 1548294113Sbapt return 1; 1549275432Sbapt} 1550275432Sbapt 1551275432Sbaptstatic int 1552241675Suqsmdoc_li_pre(MDOC_ARGS) 1553241675Suqs{ 1554322249Sbapt char *id; 1555322249Sbapt 1556322249Sbapt if ((id = cond_id(n)) != NULL) 1557322249Sbapt print_otag(h, TAG_A, "chR", "selflink", id); 1558322249Sbapt print_otag(h, TAG_CODE, "ci", "Li", id); 1559322249Sbapt free(id); 1560294113Sbapt return 1; 1561241675Suqs} 1562241675Suqs 1563241675Suqsstatic int 1564241675Suqsmdoc_sy_pre(MDOC_ARGS) 1565241675Suqs{ 1566322249Sbapt print_otag(h, TAG_B, "cT", "Sy"); 1567294113Sbapt return 1; 1568241675Suqs} 1569241675Suqs 1570241675Suqsstatic int 1571241675Suqsmdoc_lb_pre(MDOC_ARGS) 1572241675Suqs{ 1573316420Sbapt if (SEC_LIBRARY == n->sec && NODE_LINE & n->flags && n->prev) 1574316420Sbapt print_otag(h, TAG_BR, ""); 1575241675Suqs 1576322249Sbapt print_otag(h, TAG_SPAN, "cT", "Lb"); 1577294113Sbapt return 1; 1578241675Suqs} 1579241675Suqs 1580241675Suqsstatic int 1581241675Suqsmdoc__x_pre(MDOC_ARGS) 1582241675Suqs{ 1583316420Sbapt const char *cattr; 1584316420Sbapt enum htmltag t; 1585241675Suqs 1586241675Suqs t = TAG_SPAN; 1587241675Suqs 1588241675Suqs switch (n->tok) { 1589274880Sbapt case MDOC__A: 1590316420Sbapt cattr = "RsA"; 1591241675Suqs if (n->prev && MDOC__A == n->prev->tok) 1592241675Suqs if (NULL == n->next || MDOC__A != n->next->tok) 1593241675Suqs print_text(h, "and"); 1594241675Suqs break; 1595274880Sbapt case MDOC__B: 1596241675Suqs t = TAG_I; 1597316420Sbapt cattr = "RsB"; 1598241675Suqs break; 1599274880Sbapt case MDOC__C: 1600316420Sbapt cattr = "RsC"; 1601241675Suqs break; 1602274880Sbapt case MDOC__D: 1603316420Sbapt cattr = "RsD"; 1604241675Suqs break; 1605274880Sbapt case MDOC__I: 1606241675Suqs t = TAG_I; 1607316420Sbapt cattr = "RsI"; 1608241675Suqs break; 1609274880Sbapt case MDOC__J: 1610241675Suqs t = TAG_I; 1611316420Sbapt cattr = "RsJ"; 1612241675Suqs break; 1613274880Sbapt case MDOC__N: 1614316420Sbapt cattr = "RsN"; 1615241675Suqs break; 1616274880Sbapt case MDOC__O: 1617316420Sbapt cattr = "RsO"; 1618241675Suqs break; 1619274880Sbapt case MDOC__P: 1620316420Sbapt cattr = "RsP"; 1621241675Suqs break; 1622274880Sbapt case MDOC__Q: 1623316420Sbapt cattr = "RsQ"; 1624241675Suqs break; 1625274880Sbapt case MDOC__R: 1626316420Sbapt cattr = "RsR"; 1627241675Suqs break; 1628274880Sbapt case MDOC__T: 1629316420Sbapt cattr = "RsT"; 1630241675Suqs break; 1631274880Sbapt case MDOC__U: 1632316420Sbapt print_otag(h, TAG_A, "ch", "RsU", n->child->string); 1633316420Sbapt return 1; 1634274880Sbapt case MDOC__V: 1635316420Sbapt cattr = "RsV"; 1636241675Suqs break; 1637241675Suqs default: 1638241675Suqs abort(); 1639241675Suqs } 1640241675Suqs 1641316420Sbapt print_otag(h, t, "c", cattr); 1642294113Sbapt return 1; 1643241675Suqs} 1644241675Suqs 1645241675Suqsstatic void 1646241675Suqsmdoc__x_post(MDOC_ARGS) 1647241675Suqs{ 1648241675Suqs 1649241675Suqs if (MDOC__A == n->tok && n->next && MDOC__A == n->next->tok) 1650241675Suqs if (NULL == n->next->next || MDOC__A != n->next->next->tok) 1651241675Suqs if (NULL == n->prev || MDOC__A != n->prev->tok) 1652241675Suqs return; 1653241675Suqs 1654241675Suqs /* TODO: %U */ 1655241675Suqs 1656241675Suqs if (NULL == n->parent || MDOC_Rs != n->parent->tok) 1657241675Suqs return; 1658241675Suqs 1659241675Suqs h->flags |= HTML_NOSPACE; 1660241675Suqs print_text(h, n->next ? "," : "."); 1661241675Suqs} 1662241675Suqs 1663241675Suqsstatic int 1664241675Suqsmdoc_bk_pre(MDOC_ARGS) 1665241675Suqs{ 1666241675Suqs 1667241675Suqs switch (n->type) { 1668294113Sbapt case ROFFT_BLOCK: 1669241675Suqs break; 1670294113Sbapt case ROFFT_HEAD: 1671294113Sbapt return 0; 1672294113Sbapt case ROFFT_BODY: 1673294113Sbapt if (n->parent->args != NULL || n->prev->child == NULL) 1674241675Suqs h->flags |= HTML_PREKEEP; 1675241675Suqs break; 1676241675Suqs default: 1677241675Suqs abort(); 1678241675Suqs } 1679241675Suqs 1680294113Sbapt return 1; 1681241675Suqs} 1682241675Suqs 1683241675Suqsstatic void 1684241675Suqsmdoc_bk_post(MDOC_ARGS) 1685241675Suqs{ 1686241675Suqs 1687294113Sbapt if (n->type == ROFFT_BODY) 1688241675Suqs h->flags &= ~(HTML_KEEP | HTML_PREKEEP); 1689241675Suqs} 1690241675Suqs 1691241675Suqsstatic int 1692241675Suqsmdoc_quote_pre(MDOC_ARGS) 1693241675Suqs{ 1694294113Sbapt if (n->type != ROFFT_BODY) 1695294113Sbapt return 1; 1696241675Suqs 1697241675Suqs switch (n->tok) { 1698274880Sbapt case MDOC_Ao: 1699274880Sbapt case MDOC_Aq: 1700294113Sbapt print_text(h, n->child != NULL && n->child->next == NULL && 1701279527Sbapt n->child->tok == MDOC_Mt ? "<" : "\\(la"); 1702241675Suqs break; 1703274880Sbapt case MDOC_Bro: 1704274880Sbapt case MDOC_Brq: 1705241675Suqs print_text(h, "\\(lC"); 1706241675Suqs break; 1707274880Sbapt case MDOC_Bo: 1708274880Sbapt case MDOC_Bq: 1709241675Suqs print_text(h, "\\(lB"); 1710241675Suqs break; 1711274880Sbapt case MDOC_Oo: 1712274880Sbapt case MDOC_Op: 1713241675Suqs print_text(h, "\\(lB"); 1714241675Suqs h->flags |= HTML_NOSPACE; 1715316420Sbapt print_otag(h, TAG_SPAN, "c", "Op"); 1716241675Suqs break; 1717274880Sbapt case MDOC_En: 1718274880Sbapt if (NULL == n->norm->Es || 1719274880Sbapt NULL == n->norm->Es->child) 1720294113Sbapt return 1; 1721274880Sbapt print_text(h, n->norm->Es->child->string); 1722241675Suqs break; 1723274880Sbapt case MDOC_Do: 1724274880Sbapt case MDOC_Dq: 1725274880Sbapt case MDOC_Qo: 1726274880Sbapt case MDOC_Qq: 1727241675Suqs print_text(h, "\\(lq"); 1728241675Suqs break; 1729274880Sbapt case MDOC_Po: 1730274880Sbapt case MDOC_Pq: 1731241675Suqs print_text(h, "("); 1732241675Suqs break; 1733274880Sbapt case MDOC_Ql: 1734241675Suqs print_text(h, "\\(oq"); 1735241675Suqs h->flags |= HTML_NOSPACE; 1736316420Sbapt print_otag(h, TAG_CODE, "c", "Li"); 1737241675Suqs break; 1738274880Sbapt case MDOC_So: 1739274880Sbapt case MDOC_Sq: 1740241675Suqs print_text(h, "\\(oq"); 1741241675Suqs break; 1742241675Suqs default: 1743241675Suqs abort(); 1744241675Suqs } 1745241675Suqs 1746241675Suqs h->flags |= HTML_NOSPACE; 1747294113Sbapt return 1; 1748241675Suqs} 1749241675Suqs 1750241675Suqsstatic void 1751241675Suqsmdoc_quote_post(MDOC_ARGS) 1752241675Suqs{ 1753241675Suqs 1754294113Sbapt if (n->type != ROFFT_BODY && n->type != ROFFT_ELEM) 1755241675Suqs return; 1756241675Suqs 1757279527Sbapt h->flags |= HTML_NOSPACE; 1758241675Suqs 1759241675Suqs switch (n->tok) { 1760274880Sbapt case MDOC_Ao: 1761274880Sbapt case MDOC_Aq: 1762294113Sbapt print_text(h, n->child != NULL && n->child->next == NULL && 1763279527Sbapt n->child->tok == MDOC_Mt ? ">" : "\\(ra"); 1764241675Suqs break; 1765274880Sbapt case MDOC_Bro: 1766274880Sbapt case MDOC_Brq: 1767241675Suqs print_text(h, "\\(rC"); 1768241675Suqs break; 1769274880Sbapt case MDOC_Oo: 1770274880Sbapt case MDOC_Op: 1771274880Sbapt case MDOC_Bo: 1772274880Sbapt case MDOC_Bq: 1773241675Suqs print_text(h, "\\(rB"); 1774241675Suqs break; 1775274880Sbapt case MDOC_En: 1776279527Sbapt if (n->norm->Es == NULL || 1777279527Sbapt n->norm->Es->child == NULL || 1778279527Sbapt n->norm->Es->child->next == NULL) 1779279527Sbapt h->flags &= ~HTML_NOSPACE; 1780279527Sbapt else 1781274880Sbapt print_text(h, n->norm->Es->child->next->string); 1782241675Suqs break; 1783274880Sbapt case MDOC_Qo: 1784274880Sbapt case MDOC_Qq: 1785274880Sbapt case MDOC_Do: 1786274880Sbapt case MDOC_Dq: 1787241675Suqs print_text(h, "\\(rq"); 1788241675Suqs break; 1789274880Sbapt case MDOC_Po: 1790274880Sbapt case MDOC_Pq: 1791241675Suqs print_text(h, ")"); 1792241675Suqs break; 1793274880Sbapt case MDOC_Ql: 1794274880Sbapt case MDOC_So: 1795274880Sbapt case MDOC_Sq: 1796261344Suqs print_text(h, "\\(cq"); 1797241675Suqs break; 1798241675Suqs default: 1799241675Suqs abort(); 1800241675Suqs } 1801241675Suqs} 1802279527Sbapt 1803279527Sbaptstatic int 1804279527Sbaptmdoc_eo_pre(MDOC_ARGS) 1805279527Sbapt{ 1806279527Sbapt 1807294113Sbapt if (n->type != ROFFT_BODY) 1808294113Sbapt return 1; 1809279527Sbapt 1810279527Sbapt if (n->end == ENDBODY_NOT && 1811279527Sbapt n->parent->head->child == NULL && 1812279527Sbapt n->child != NULL && 1813279527Sbapt n->child->end != ENDBODY_NOT) 1814279527Sbapt print_text(h, "\\&"); 1815279527Sbapt else if (n->end != ENDBODY_NOT ? n->child != NULL : 1816279527Sbapt n->parent->head->child != NULL && (n->child != NULL || 1817279527Sbapt (n->parent->tail != NULL && n->parent->tail->child != NULL))) 1818279527Sbapt h->flags |= HTML_NOSPACE; 1819294113Sbapt return 1; 1820279527Sbapt} 1821279527Sbapt 1822279527Sbaptstatic void 1823279527Sbaptmdoc_eo_post(MDOC_ARGS) 1824279527Sbapt{ 1825279527Sbapt int body, tail; 1826279527Sbapt 1827294113Sbapt if (n->type != ROFFT_BODY) 1828279527Sbapt return; 1829279527Sbapt 1830279527Sbapt if (n->end != ENDBODY_NOT) { 1831279527Sbapt h->flags &= ~HTML_NOSPACE; 1832279527Sbapt return; 1833279527Sbapt } 1834279527Sbapt 1835279527Sbapt body = n->child != NULL || n->parent->head->child != NULL; 1836279527Sbapt tail = n->parent->tail != NULL && n->parent->tail->child != NULL; 1837279527Sbapt 1838279527Sbapt if (body && tail) 1839279527Sbapt h->flags |= HTML_NOSPACE; 1840279527Sbapt else if ( ! tail) 1841279527Sbapt h->flags &= ~HTML_NOSPACE; 1842279527Sbapt} 1843