1*645bcdadSschwarze /* $OpenBSD: mdoc_html.c,v 1.228 2025/01/25 00:19:23 schwarze Exp $ */ 24175bdabSschwarze /* 30aa8d661Sschwarze * Copyright (c) 2014-2022, 2025 Ingo Schwarze <schwarze@openbsd.org> 40ac7e6ecSschwarze * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> 5b3005203Sschwarze * Copyright (c) 2022 Anna Vyalkova <cyber@sysrq.in> 64175bdabSschwarze * 74175bdabSschwarze * Permission to use, copy, modify, and distribute this software for any 84175bdabSschwarze * purpose with or without fee is hereby granted, provided that the above 94175bdabSschwarze * copyright notice and this permission notice appear in all copies. 104175bdabSschwarze * 11d1982c71Sschwarze * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 124175bdabSschwarze * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13d1982c71Sschwarze * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR 144175bdabSschwarze * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 154175bdabSschwarze * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 164175bdabSschwarze * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 174175bdabSschwarze * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 180ac7e6ecSschwarze * 190ac7e6ecSschwarze * HTML formatter for mdoc(7) used by mandoc(1). 204175bdabSschwarze */ 214175bdabSschwarze #include <sys/types.h> 224175bdabSschwarze 234175bdabSschwarze #include <assert.h> 244175bdabSschwarze #include <ctype.h> 254175bdabSschwarze #include <stdio.h> 264175bdabSschwarze #include <stdlib.h> 274175bdabSschwarze #include <string.h> 284175bdabSschwarze #include <unistd.h> 294175bdabSschwarze 30a92c1cd8Sschwarze #include "mandoc_aux.h" 312e362670Sschwarze #include "mandoc.h" 32d1982c71Sschwarze #include "roff.h" 33dd617d76Sschwarze #include "mdoc.h" 344175bdabSschwarze #include "out.h" 354175bdabSschwarze #include "html.h" 364175bdabSschwarze #include "main.h" 374175bdabSschwarze 382a238f45Sschwarze #define MDOC_ARGS const struct roff_meta *meta, \ 393a0d07afSschwarze struct roff_node *n, \ 404175bdabSschwarze struct html *h 414175bdabSschwarze 425d7d1836Sschwarze #ifndef MIN 435d7d1836Sschwarze #define MIN(a,b) ((/*CONSTCOND*/(a)<(b))?(a):(b)) 445d7d1836Sschwarze #endif 455d7d1836Sschwarze 4616fe0cfcSschwarze struct mdoc_html_act { 474175bdabSschwarze int (*pre)(MDOC_ARGS); 484175bdabSschwarze void (*post)(MDOC_ARGS); 494175bdabSschwarze }; 504175bdabSschwarze 51cc202ecaSschwarze static void print_mdoc_head(const struct roff_meta *, 52cc202ecaSschwarze struct html *); 534175bdabSschwarze static void print_mdoc_node(MDOC_ARGS); 544175bdabSschwarze static void print_mdoc_nodelist(MDOC_ARGS); 557ebbefbeSschwarze static void synopsis_pre(struct html *, struct roff_node *); 564175bdabSschwarze 57cc202ecaSschwarze static void mdoc_root_post(const struct roff_meta *, 58cc202ecaSschwarze struct html *); 59cc202ecaSschwarze static int mdoc_root_pre(const struct roff_meta *, 60cc202ecaSschwarze struct html *); 614175bdabSschwarze 624175bdabSschwarze static void mdoc__x_post(MDOC_ARGS); 634175bdabSschwarze static int mdoc__x_pre(MDOC_ARGS); 647c539ecbSschwarze static int mdoc_abort_pre(MDOC_ARGS); 654175bdabSschwarze static int mdoc_ad_pre(MDOC_ARGS); 664175bdabSschwarze static int mdoc_an_pre(MDOC_ARGS); 674175bdabSschwarze static int mdoc_ap_pre(MDOC_ARGS); 684175bdabSschwarze static int mdoc_ar_pre(MDOC_ARGS); 694175bdabSschwarze static int mdoc_bd_pre(MDOC_ARGS); 704175bdabSschwarze static int mdoc_bf_pre(MDOC_ARGS); 71769ee804Sschwarze static void mdoc_bk_post(MDOC_ARGS); 72769ee804Sschwarze static int mdoc_bk_pre(MDOC_ARGS); 734175bdabSschwarze static int mdoc_bl_pre(MDOC_ARGS); 744175bdabSschwarze static int mdoc_cd_pre(MDOC_ARGS); 750ac7e6ecSschwarze static int mdoc_code_pre(MDOC_ARGS); 764175bdabSschwarze static int mdoc_d1_pre(MDOC_ARGS); 774175bdabSschwarze static int mdoc_fa_pre(MDOC_ARGS); 784175bdabSschwarze static int mdoc_fd_pre(MDOC_ARGS); 794175bdabSschwarze static int mdoc_fl_pre(MDOC_ARGS); 804175bdabSschwarze static int mdoc_fn_pre(MDOC_ARGS); 814175bdabSschwarze static int mdoc_ft_pre(MDOC_ARGS); 824175bdabSschwarze static int mdoc_em_pre(MDOC_ARGS); 8303ed6ec9Sschwarze static void mdoc_eo_post(MDOC_ARGS); 8403ed6ec9Sschwarze static int mdoc_eo_pre(MDOC_ARGS); 854175bdabSschwarze static int mdoc_ex_pre(MDOC_ARGS); 864175bdabSschwarze static void mdoc_fo_post(MDOC_ARGS); 874175bdabSschwarze static int mdoc_fo_pre(MDOC_ARGS); 8837e2f24fSschwarze static int mdoc_igndelim_pre(MDOC_ARGS); 894175bdabSschwarze static int mdoc_in_pre(MDOC_ARGS); 904175bdabSschwarze static int mdoc_it_pre(MDOC_ARGS); 914175bdabSschwarze static int mdoc_lb_pre(MDOC_ARGS); 924175bdabSschwarze static int mdoc_lk_pre(MDOC_ARGS); 934175bdabSschwarze static int mdoc_mt_pre(MDOC_ARGS); 944175bdabSschwarze static int mdoc_nd_pre(MDOC_ARGS); 954175bdabSschwarze static int mdoc_nm_pre(MDOC_ARGS); 966f9818f6Sschwarze static int mdoc_no_pre(MDOC_ARGS); 974175bdabSschwarze static int mdoc_ns_pre(MDOC_ARGS); 984175bdabSschwarze static int mdoc_pa_pre(MDOC_ARGS); 994175bdabSschwarze static void mdoc_pf_post(MDOC_ARGS); 100467b61c6Sschwarze static int mdoc_pp_pre(MDOC_ARGS); 1012c3450fcSschwarze static void mdoc_quote_post(MDOC_ARGS); 1022c3450fcSschwarze static int mdoc_quote_pre(MDOC_ARGS); 1034175bdabSschwarze static int mdoc_rs_pre(MDOC_ARGS); 1044175bdabSschwarze static int mdoc_sh_pre(MDOC_ARGS); 105551cd4a8Sschwarze static int mdoc_skip_pre(MDOC_ARGS); 106ddce0b0cSschwarze static int mdoc_sm_pre(MDOC_ARGS); 1074175bdabSschwarze static int mdoc_ss_pre(MDOC_ARGS); 108dd15d0f1Sschwarze static int mdoc_st_pre(MDOC_ARGS); 1094175bdabSschwarze static int mdoc_sx_pre(MDOC_ARGS); 1104175bdabSschwarze static int mdoc_sy_pre(MDOC_ARGS); 11192929bf6Sschwarze static int mdoc_tg_pre(MDOC_ARGS); 1124175bdabSschwarze static int mdoc_va_pre(MDOC_ARGS); 1134175bdabSschwarze static int mdoc_vt_pre(MDOC_ARGS); 1144175bdabSschwarze static int mdoc_xr_pre(MDOC_ARGS); 1154175bdabSschwarze static int mdoc_xx_pre(MDOC_ARGS); 1164175bdabSschwarze 11716fe0cfcSschwarze static const struct mdoc_html_act mdoc_html_acts[MDOC_MAX - MDOC_Dd] = { 1184175bdabSschwarze {NULL, NULL}, /* Dd */ 1194175bdabSschwarze {NULL, NULL}, /* Dt */ 1204175bdabSschwarze {NULL, NULL}, /* Os */ 1214175bdabSschwarze {mdoc_sh_pre, NULL }, /* Sh */ 1224175bdabSschwarze {mdoc_ss_pre, NULL }, /* Ss */ 123467b61c6Sschwarze {mdoc_pp_pre, NULL}, /* Pp */ 1244175bdabSschwarze {mdoc_d1_pre, NULL}, /* D1 */ 1254175bdabSschwarze {mdoc_d1_pre, NULL}, /* Dl */ 1264175bdabSschwarze {mdoc_bd_pre, NULL}, /* Bd */ 1274175bdabSschwarze {NULL, NULL}, /* Ed */ 128467b61c6Sschwarze {mdoc_bl_pre, NULL}, /* Bl */ 1294175bdabSschwarze {NULL, NULL}, /* El */ 1304175bdabSschwarze {mdoc_it_pre, NULL}, /* It */ 1314175bdabSschwarze {mdoc_ad_pre, NULL}, /* Ad */ 1324175bdabSschwarze {mdoc_an_pre, NULL}, /* An */ 13314a309e3Sschwarze {mdoc_ap_pre, NULL}, /* Ap */ 1344175bdabSschwarze {mdoc_ar_pre, NULL}, /* Ar */ 1354175bdabSschwarze {mdoc_cd_pre, NULL}, /* Cd */ 1360ac7e6ecSschwarze {mdoc_code_pre, NULL}, /* Cm */ 1370ac7e6ecSschwarze {mdoc_code_pre, NULL}, /* Dv */ 1380ac7e6ecSschwarze {mdoc_code_pre, NULL}, /* Er */ 1390ac7e6ecSschwarze {mdoc_code_pre, NULL}, /* Ev */ 1404175bdabSschwarze {mdoc_ex_pre, NULL}, /* Ex */ 1414175bdabSschwarze {mdoc_fa_pre, NULL}, /* Fa */ 1429a98b8a1Sschwarze {mdoc_fd_pre, NULL}, /* Fd */ 1434175bdabSschwarze {mdoc_fl_pre, NULL}, /* Fl */ 1444175bdabSschwarze {mdoc_fn_pre, NULL}, /* Fn */ 1454175bdabSschwarze {mdoc_ft_pre, NULL}, /* Ft */ 1460ac7e6ecSschwarze {mdoc_code_pre, NULL}, /* Ic */ 1474175bdabSschwarze {mdoc_in_pre, NULL}, /* In */ 1480ac7e6ecSschwarze {mdoc_code_pre, NULL}, /* Li */ 1494175bdabSschwarze {mdoc_nd_pre, NULL}, /* Nd */ 1504175bdabSschwarze {mdoc_nm_pre, NULL}, /* Nm */ 1512c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Op */ 1527c539ecbSschwarze {mdoc_abort_pre, NULL}, /* Ot */ 1534175bdabSschwarze {mdoc_pa_pre, NULL}, /* Pa */ 1548ccddcd3Sschwarze {mdoc_ex_pre, NULL}, /* Rv */ 155dd15d0f1Sschwarze {mdoc_st_pre, NULL}, /* St */ 1564175bdabSschwarze {mdoc_va_pre, NULL}, /* Va */ 1574175bdabSschwarze {mdoc_vt_pre, NULL}, /* Vt */ 1584175bdabSschwarze {mdoc_xr_pre, NULL}, /* Xr */ 1594175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %A */ 1604175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %B */ 1614175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %D */ 1624175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %I */ 1634175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %J */ 1644175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %N */ 1654175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %O */ 1664175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %P */ 1674175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %R */ 1684175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %T */ 1694175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %V */ 1704175bdabSschwarze {NULL, NULL}, /* Ac */ 1712c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Ao */ 1722c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Aq */ 173dd15d0f1Sschwarze {mdoc_xx_pre, NULL}, /* At */ 1744175bdabSschwarze {NULL, NULL}, /* Bc */ 1754175bdabSschwarze {mdoc_bf_pre, NULL}, /* Bf */ 1762c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Bo */ 1772c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Bq */ 1784175bdabSschwarze {mdoc_xx_pre, NULL}, /* Bsx */ 1793af8e8d7Sschwarze {mdoc_xx_pre, NULL}, /* Bx */ 18078bbbab4Sschwarze {mdoc_skip_pre, NULL}, /* Db */ 1814175bdabSschwarze {NULL, NULL}, /* Dc */ 1822c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Do */ 1832c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Dq */ 184b16e7ddfSschwarze {NULL, NULL}, /* Ec */ /* FIXME: no space */ 1854175bdabSschwarze {NULL, NULL}, /* Ef */ 1864175bdabSschwarze {mdoc_em_pre, NULL}, /* Em */ 18703ed6ec9Sschwarze {mdoc_eo_pre, mdoc_eo_post}, /* Eo */ 1884175bdabSschwarze {mdoc_xx_pre, NULL}, /* Fx */ 1890ac7e6ecSschwarze {mdoc_no_pre, NULL}, /* Ms */ 1906f9818f6Sschwarze {mdoc_no_pre, NULL}, /* No */ 1914175bdabSschwarze {mdoc_ns_pre, NULL}, /* Ns */ 1924175bdabSschwarze {mdoc_xx_pre, NULL}, /* Nx */ 1934175bdabSschwarze {mdoc_xx_pre, NULL}, /* Ox */ 1944175bdabSschwarze {NULL, NULL}, /* Pc */ 19537e2f24fSschwarze {mdoc_igndelim_pre, mdoc_pf_post}, /* Pf */ 1962c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Po */ 1972c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Pq */ 1984175bdabSschwarze {NULL, NULL}, /* Qc */ 1992c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Ql */ 2002c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Qo */ 2012c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Qq */ 2024175bdabSschwarze {NULL, NULL}, /* Re */ 2034175bdabSschwarze {mdoc_rs_pre, NULL}, /* Rs */ 2044175bdabSschwarze {NULL, NULL}, /* Sc */ 2052c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* So */ 2062c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Sq */ 207ddce0b0cSschwarze {mdoc_sm_pre, NULL}, /* Sm */ 2084175bdabSschwarze {mdoc_sx_pre, NULL}, /* Sx */ 2094175bdabSschwarze {mdoc_sy_pre, NULL}, /* Sy */ 2104175bdabSschwarze {NULL, NULL}, /* Tn */ 2114175bdabSschwarze {mdoc_xx_pre, NULL}, /* Ux */ 2124175bdabSschwarze {NULL, NULL}, /* Xc */ 2134175bdabSschwarze {NULL, NULL}, /* Xo */ 2144175bdabSschwarze {mdoc_fo_pre, mdoc_fo_post}, /* Fo */ 2154175bdabSschwarze {NULL, NULL}, /* Fc */ 2162c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Oo */ 2174175bdabSschwarze {NULL, NULL}, /* Oc */ 218769ee804Sschwarze {mdoc_bk_pre, mdoc_bk_post}, /* Bk */ 2194175bdabSschwarze {NULL, NULL}, /* Ek */ 2208ccddcd3Sschwarze {NULL, NULL}, /* Bt */ 2214175bdabSschwarze {NULL, NULL}, /* Hf */ 222551cd4a8Sschwarze {mdoc_em_pre, NULL}, /* Fr */ 2238ccddcd3Sschwarze {NULL, NULL}, /* Ud */ 2244175bdabSschwarze {mdoc_lb_pre, NULL}, /* Lb */ 2257c539ecbSschwarze {mdoc_abort_pre, NULL}, /* Lp */ 2264175bdabSschwarze {mdoc_lk_pre, NULL}, /* Lk */ 2274175bdabSschwarze {mdoc_mt_pre, NULL}, /* Mt */ 2282c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Brq */ 2292c3450fcSschwarze {mdoc_quote_pre, mdoc_quote_post}, /* Bro */ 2304175bdabSschwarze {NULL, NULL}, /* Brc */ 2314175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %C */ 232551cd4a8Sschwarze {mdoc_skip_pre, NULL}, /* Es */ 233551cd4a8Sschwarze {mdoc_quote_pre, mdoc_quote_post}, /* En */ 2344175bdabSschwarze {mdoc_xx_pre, NULL}, /* Dx */ 2354175bdabSschwarze {mdoc__x_pre, mdoc__x_post}, /* %Q */ 236b822ca0dSschwarze {mdoc__x_pre, mdoc__x_post}, /* %U */ 2376093755cSschwarze {NULL, NULL}, /* Ta */ 23892929bf6Sschwarze {mdoc_tg_pre, NULL}, /* Tg */ 2394175bdabSschwarze }; 2404175bdabSschwarze 24149aff9f8Sschwarze 2424175bdabSschwarze /* 2439a98b8a1Sschwarze * See the same function in mdoc_term.c for documentation. 2449a98b8a1Sschwarze */ 2459a98b8a1Sschwarze static void 2467ebbefbeSschwarze synopsis_pre(struct html *h, struct roff_node *n) 2479a98b8a1Sschwarze { 2487ebbefbeSschwarze struct roff_node *np; 2499a98b8a1Sschwarze 2507ebbefbeSschwarze if ((n->flags & NODE_SYNPRETTY) == 0 || 2517ebbefbeSschwarze (np = roff_node_prev(n)) == NULL) 2529a98b8a1Sschwarze return; 2539a98b8a1Sschwarze 2547ebbefbeSschwarze if (np->tok == n->tok && 2559a98b8a1Sschwarze MDOC_Fo != n->tok && 2569a98b8a1Sschwarze MDOC_Ft != n->tok && 2579a98b8a1Sschwarze MDOC_Fn != n->tok) { 258229cc7fdSschwarze print_otag(h, TAG_BR, ""); 2599a98b8a1Sschwarze return; 2609a98b8a1Sschwarze } 2619a98b8a1Sschwarze 2627ebbefbeSschwarze switch (np->tok) { 26349aff9f8Sschwarze case MDOC_Fd: 26449aff9f8Sschwarze case MDOC_Fn: 26549aff9f8Sschwarze case MDOC_Fo: 26649aff9f8Sschwarze case MDOC_In: 26749aff9f8Sschwarze case MDOC_Vt: 2689a98b8a1Sschwarze break; 26949aff9f8Sschwarze case MDOC_Ft: 2702dd33770Sschwarze if (n->tok != MDOC_Fn && n->tok != MDOC_Fo) 2719a98b8a1Sschwarze break; 2729a98b8a1Sschwarze /* FALLTHROUGH */ 2739a98b8a1Sschwarze default: 274229cc7fdSschwarze print_otag(h, TAG_BR, ""); 2752dd33770Sschwarze return; 2769a98b8a1Sschwarze } 2772dd33770Sschwarze html_close_paragraph(h); 2782dd33770Sschwarze print_otag(h, TAG_P, "c", "Pp"); 2799a98b8a1Sschwarze } 2809a98b8a1Sschwarze 2816d0e9b63Sschwarze void 2826b86842eSschwarze html_mdoc(void *arg, const struct roff_meta *mdoc) 2834175bdabSschwarze { 2846d0e9b63Sschwarze struct html *h; 285cc202ecaSschwarze struct roff_node *n; 286ce781f36Sschwarze struct tag *t; 2874175bdabSschwarze 2886d0e9b63Sschwarze h = (struct html *)arg; 289cc202ecaSschwarze n = mdoc->first->child; 290ca0ce676Sschwarze 291ce781f36Sschwarze if ((h->oflags & HTML_FRAGMENT) == 0) { 292ca0ce676Sschwarze print_gen_decls(h); 293ce781f36Sschwarze print_otag(h, TAG_HTML, ""); 294ce781f36Sschwarze t = print_otag(h, TAG_HEAD, ""); 2956b86842eSschwarze print_mdoc_head(mdoc, h); 296ce781f36Sschwarze print_tagq(h, t); 297501adfefSschwarze if (n != NULL && n->type == ROFFT_COMMENT) 298501adfefSschwarze print_gen_comment(h, n); 299229cc7fdSschwarze print_otag(h, TAG_BODY, ""); 300ce781f36Sschwarze } 3014175bdabSschwarze 3026b86842eSschwarze mdoc_root_pre(mdoc, h); 3036774f271Sschwarze t = print_otag(h, TAG_MAIN, "c", "manual-text"); 3046b86842eSschwarze print_mdoc_nodelist(mdoc, n, h); 305c7402a19Sschwarze print_tagq(h, t); 3066b86842eSschwarze mdoc_root_post(mdoc, h); 307ce781f36Sschwarze print_tagq(h, NULL); 3084175bdabSschwarze } 3094175bdabSschwarze 3104175bdabSschwarze static void 311cc202ecaSschwarze print_mdoc_head(const struct roff_meta *meta, struct html *h) 3124175bdabSschwarze { 313fef1eecdSschwarze char *cp; 3144175bdabSschwarze 3154175bdabSschwarze print_gen_head(h); 316fef1eecdSschwarze 317fef1eecdSschwarze if (meta->arch != NULL && meta->msec != NULL) 318fef1eecdSschwarze mandoc_asprintf(&cp, "%s(%s) (%s)", meta->title, 319fef1eecdSschwarze meta->msec, meta->arch); 320fef1eecdSschwarze else if (meta->msec != NULL) 321fef1eecdSschwarze mandoc_asprintf(&cp, "%s(%s)", meta->title, meta->msec); 322fef1eecdSschwarze else if (meta->arch != NULL) 323fef1eecdSschwarze mandoc_asprintf(&cp, "%s (%s)", meta->title, meta->arch); 324fef1eecdSschwarze else 325fef1eecdSschwarze cp = mandoc_strdup(meta->title); 3264175bdabSschwarze 327229cc7fdSschwarze print_otag(h, TAG_TITLE, ""); 328fef1eecdSschwarze print_text(h, cp); 329fef1eecdSschwarze free(cp); 3304175bdabSschwarze } 3314175bdabSschwarze 3324175bdabSschwarze static void 3334175bdabSschwarze print_mdoc_nodelist(MDOC_ARGS) 3344175bdabSschwarze { 3354175bdabSschwarze 336e4534905Sschwarze while (n != NULL) { 3377ead8a4eSschwarze print_mdoc_node(meta, n, h); 338e4534905Sschwarze n = n->next; 339e4534905Sschwarze } 3404175bdabSschwarze } 3414175bdabSschwarze 3424175bdabSschwarze static void 3434175bdabSschwarze print_mdoc_node(MDOC_ARGS) 3444175bdabSschwarze { 3454175bdabSschwarze struct tag *t; 3462dd33770Sschwarze int child; 3474175bdabSschwarze 3484c293873Sschwarze if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT) 34943808411Sschwarze return; 35043808411Sschwarze 35152e71e33Sschwarze if ((n->flags & NODE_NOFILL) == 0) 352e2edd184Sschwarze html_fillmode(h, ROFF_fi); 35352e71e33Sschwarze else if (html_fillmode(h, ROFF_nf) == ROFF_nf && 35452e71e33Sschwarze n->tok != ROFF_fi && n->flags & NODE_LINE) 35552e71e33Sschwarze print_endline(h); 3562dd33770Sschwarze 3574175bdabSschwarze child = 1; 3582dd33770Sschwarze n->flags &= ~NODE_ENDED; 3594175bdabSschwarze switch (n->type) { 360d1982c71Sschwarze case ROFFT_TEXT: 361e2edd184Sschwarze if (n->flags & NODE_LINE) { 362e2edd184Sschwarze switch (*n->string) { 363e2edd184Sschwarze case '\0': 364e2edd184Sschwarze h->col = 1; 365e2edd184Sschwarze print_endline(h); 366e2edd184Sschwarze return; 367e2edd184Sschwarze case ' ': 368e2edd184Sschwarze if ((h->flags & HTML_NONEWLINE) == 0 && 36941dbcad6Sschwarze (n->flags & NODE_NOFILL) == 0) 370229cc7fdSschwarze print_otag(h, TAG_BR, ""); 371e2edd184Sschwarze break; 372e2edd184Sschwarze default: 373e2edd184Sschwarze break; 374e2edd184Sschwarze } 375e2edd184Sschwarze } 376e2edd184Sschwarze t = h->tag; 377e2edd184Sschwarze t->refcnt++; 3786e2a0df9Sschwarze if (n->flags & NODE_DELIMC) 379a35fc07aSschwarze h->flags |= HTML_NOSPACE; 3806e2a0df9Sschwarze if (n->flags & NODE_HREF) 3816e2a0df9Sschwarze print_tagged_text(h, n->string, n); 3826e2a0df9Sschwarze else 3834175bdabSschwarze print_text(h, n->string); 3846e2a0df9Sschwarze if (n->flags & NODE_DELIMO) 385a35fc07aSschwarze h->flags |= HTML_NOSPACE; 3862dd33770Sschwarze break; 387d1982c71Sschwarze case ROFFT_EQN: 388520a575cSschwarze t = h->tag; 389520a575cSschwarze t->refcnt++; 390f8618d99Sschwarze print_eqn(h, n->eqn); 39119a69263Sschwarze break; 392d1982c71Sschwarze case ROFFT_TBL: 393366f22eeSschwarze /* 394366f22eeSschwarze * This will take care of initialising all of the table 395366f22eeSschwarze * state data for the first table, then tearing it down 396366f22eeSschwarze * for the last one. 397366f22eeSschwarze */ 3982791bd1cSschwarze print_tbl(h, n->span); 399366f22eeSschwarze return; 4004175bdabSschwarze default: 401366f22eeSschwarze /* 402366f22eeSschwarze * Close out the current table, if it's open, and unset 403366f22eeSschwarze * the "meta" table state. This will be reopened on the 404366f22eeSschwarze * next table element. 405366f22eeSschwarze */ 406520a575cSschwarze if (h->tblt != NULL) 407366f22eeSschwarze print_tblclose(h); 4087d18a139Sschwarze assert(h->tblt == NULL); 409520a575cSschwarze t = h->tag; 410520a575cSschwarze t->refcnt++; 41129478532Sschwarze if (n->tok < ROFF_MAX) { 41296a5de47Sschwarze roff_html_pre(h, n); 413520a575cSschwarze t->refcnt--; 4142dd33770Sschwarze print_stagq(h, t); 4152dd33770Sschwarze return; 41629478532Sschwarze } 41714a309e3Sschwarze assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX); 41816fe0cfcSschwarze if (mdoc_html_acts[n->tok - MDOC_Dd].pre != NULL && 41914a309e3Sschwarze (n->end == ENDBODY_NOT || n->child != NULL)) 42016fe0cfcSschwarze child = (*mdoc_html_acts[n->tok - MDOC_Dd].pre)(meta, 42116fe0cfcSschwarze n, h); 4224175bdabSschwarze break; 4234175bdabSschwarze } 4244175bdabSschwarze 425c4b0939cSschwarze if (h->flags & HTML_KEEP && n->flags & NODE_LINE) { 426769ee804Sschwarze h->flags &= ~HTML_KEEP; 427769ee804Sschwarze h->flags |= HTML_PREKEEP; 428769ee804Sschwarze } 429769ee804Sschwarze 4302dd33770Sschwarze if (child && n->child != NULL) 4317ead8a4eSschwarze print_mdoc_nodelist(meta, n->child, h); 4324175bdabSschwarze 433520a575cSschwarze t->refcnt--; 4344175bdabSschwarze print_stagq(h, t); 4354175bdabSschwarze 4364175bdabSschwarze switch (n->type) { 4372dd33770Sschwarze case ROFFT_TEXT: 438d1982c71Sschwarze case ROFFT_EQN: 43919a69263Sschwarze break; 4404175bdabSschwarze default: 4412dd33770Sschwarze if (mdoc_html_acts[n->tok - MDOC_Dd].post == NULL || 44229478532Sschwarze n->flags & NODE_ENDED) 4437d18a139Sschwarze break; 44416fe0cfcSschwarze (*mdoc_html_acts[n->tok - MDOC_Dd].post)(meta, n, h); 4457d18a139Sschwarze if (n->end != ENDBODY_NOT) 446c4b0939cSschwarze n->body->flags |= NODE_ENDED; 4474175bdabSschwarze break; 4484175bdabSschwarze } 4494175bdabSschwarze } 4504175bdabSschwarze 4514175bdabSschwarze static void 452cc202ecaSschwarze mdoc_root_post(const struct roff_meta *meta, struct html *h) 4534175bdabSschwarze { 4548f48bc46Sschwarze struct tag *t; 4554175bdabSschwarze 4568f48bc46Sschwarze t = print_otag(h, TAG_DIV, "cr?", "foot", "doc-pagefooter", 457f0f927fcSschwarze "aria-label", "Manual footer line"); 458b009ccebSschwarze 4598f48bc46Sschwarze print_otag(h, TAG_SPAN, "c", "foot-left"); 4608f48bc46Sschwarze print_stagq(h, t); 4618f48bc46Sschwarze 4628f48bc46Sschwarze print_otag(h, TAG_SPAN, "c", "foot-date"); 4637ead8a4eSschwarze print_text(h, meta->date); 4648f48bc46Sschwarze print_stagq(h, t); 4654175bdabSschwarze 4668f48bc46Sschwarze print_otag(h, TAG_SPAN, "c", "foot-os"); 4677ead8a4eSschwarze print_text(h, meta->os); 4684175bdabSschwarze print_tagq(h, t); 4694175bdabSschwarze } 4704175bdabSschwarze 4714175bdabSschwarze static int 472cc202ecaSschwarze mdoc_root_pre(const struct roff_meta *meta, struct html *h) 4734175bdabSschwarze { 4748f48bc46Sschwarze struct tag *t; 4750b2f1307Sschwarze char *volume, *title; 4764175bdabSschwarze 4770b2f1307Sschwarze if (NULL == meta->arch) 4780b2f1307Sschwarze volume = mandoc_strdup(meta->vol); 4790b2f1307Sschwarze else 4800b2f1307Sschwarze mandoc_asprintf(&volume, "%s (%s)", 4810b2f1307Sschwarze meta->vol, meta->arch); 4824175bdabSschwarze 4833fdead0cSschwarze if (NULL == meta->msec) 4843fdead0cSschwarze title = mandoc_strdup(meta->title); 4853fdead0cSschwarze else 4863fdead0cSschwarze mandoc_asprintf(&title, "%s(%s)", 4873fdead0cSschwarze meta->title, meta->msec); 4884175bdabSschwarze 4898f48bc46Sschwarze t = print_otag(h, TAG_DIV, "cr?", "head", "doc-pageheader", 490f0f927fcSschwarze "aria-label", "Manual header line"); 491a66b65d0Sschwarze 4928f48bc46Sschwarze print_otag(h, TAG_SPAN, "c", "head-ltitle"); 4934175bdabSschwarze print_text(h, title); 4948f48bc46Sschwarze print_stagq(h, t); 4954175bdabSschwarze 4968f48bc46Sschwarze print_otag(h, TAG_SPAN, "c", "head-vol"); 4970b2f1307Sschwarze print_text(h, volume); 4988f48bc46Sschwarze print_stagq(h, t); 4994175bdabSschwarze 5008f48bc46Sschwarze print_otag(h, TAG_SPAN, "c", "head-rtitle"); 5014175bdabSschwarze print_text(h, title); 5024175bdabSschwarze print_tagq(h, t); 503a92c1cd8Sschwarze 504a92c1cd8Sschwarze free(title); 5050b2f1307Sschwarze free(volume); 506526e306bSschwarze return 1; 5074175bdabSschwarze } 5084175bdabSschwarze 5090ac7e6ecSschwarze static int 5100ac7e6ecSschwarze mdoc_code_pre(MDOC_ARGS) 5116306e64dSschwarze { 5120ac7e6ecSschwarze print_otag_id(h, TAG_CODE, roff_name[n->tok], n); 5130ac7e6ecSschwarze return 1; 5146306e64dSschwarze } 5156306e64dSschwarze 5164175bdabSschwarze static int 5174175bdabSschwarze mdoc_sh_pre(MDOC_ARGS) 5184175bdabSschwarze { 5197150bda1Sschwarze struct roff_node *sn, *subn; 52088e033f9Sschwarze struct tag *t, *tnav, *tsec, *tsub; 521fef1eecdSschwarze char *id; 5223327fa00Sschwarze int sc; 523fef1eecdSschwarze 524bf997c2cSschwarze switch (n->type) { 5253327fa00Sschwarze case ROFFT_BLOCK: 5262dd33770Sschwarze html_close_paragraph(h); 5273327fa00Sschwarze if ((h->oflags & HTML_TOC) == 0 || 5283327fa00Sschwarze h->flags & HTML_TOCDONE || 5291a2b7b3cSschwarze n->sec <= SEC_SYNOPSIS) { 5301a2b7b3cSschwarze print_otag(h, TAG_SECTION, "c", "Sh"); 5313327fa00Sschwarze break; 5321a2b7b3cSschwarze } 5333327fa00Sschwarze h->flags |= HTML_TOCDONE; 5343327fa00Sschwarze sc = 0; 5353327fa00Sschwarze for (sn = n->next; sn != NULL; sn = sn->next) 5363327fa00Sschwarze if (sn->sec == SEC_CUSTOM) 5373327fa00Sschwarze if (++sc == 2) 5383327fa00Sschwarze break; 5393327fa00Sschwarze if (sc < 2) 5403327fa00Sschwarze break; 54188e033f9Sschwarze tnav = print_otag(h, TAG_NAV, "r", "doc-toc"); 54200b92a3fSschwarze t = print_otag(h, TAG_H2, "c", "Sh"); 5433327fa00Sschwarze print_text(h, "TABLE OF CONTENTS"); 5443327fa00Sschwarze print_tagq(h, t); 5453327fa00Sschwarze t = print_otag(h, TAG_UL, "c", "Bl-compact"); 5467150bda1Sschwarze for (sn = n; sn != NULL; sn = sn->next) { 5477150bda1Sschwarze tsec = print_otag(h, TAG_LI, ""); 5483327fa00Sschwarze id = html_make_id(sn->head, 0); 54972a0eb32Sschwarze tsub = print_otag(h, TAG_A, "hR", id); 5503327fa00Sschwarze free(id); 5517150bda1Sschwarze print_mdoc_nodelist(meta, sn->head->child, h); 55272a0eb32Sschwarze print_tagq(h, tsub); 5537150bda1Sschwarze tsub = NULL; 5547150bda1Sschwarze for (subn = sn->body->child; subn != NULL; 5557150bda1Sschwarze subn = subn->next) { 5567150bda1Sschwarze if (subn->tok != MDOC_Ss) 5577150bda1Sschwarze continue; 5581d794ce3Sschwarze id = html_make_id(subn->head, 0); 5591d794ce3Sschwarze if (id == NULL) 5601d794ce3Sschwarze continue; 5617150bda1Sschwarze if (tsub == NULL) 5627150bda1Sschwarze print_otag(h, TAG_UL, 5637150bda1Sschwarze "c", "Bl-compact"); 5647150bda1Sschwarze tsub = print_otag(h, TAG_LI, ""); 5657150bda1Sschwarze print_otag(h, TAG_A, "hR", id); 5667150bda1Sschwarze free(id); 5677150bda1Sschwarze print_mdoc_nodelist(meta, 5687150bda1Sschwarze subn->head->child, h); 5697150bda1Sschwarze print_tagq(h, tsub); 5707150bda1Sschwarze } 5717150bda1Sschwarze print_tagq(h, tsec); 5723327fa00Sschwarze } 57388e033f9Sschwarze print_tagq(h, tnav); 5741a2b7b3cSschwarze print_otag(h, TAG_SECTION, "c", "Sh"); 5753327fa00Sschwarze break; 5761e98cf61Sschwarze case ROFFT_HEAD: 57700b92a3fSschwarze print_otag_id(h, TAG_H2, "Sh", n); 5781e98cf61Sschwarze break; 579d1982c71Sschwarze case ROFFT_BODY: 580bf997c2cSschwarze if (n->sec == SEC_AUTHORS) 581bf997c2cSschwarze h->flags &= ~(HTML_SPLIT|HTML_NOSPLIT); 5821e98cf61Sschwarze break; 583bf997c2cSschwarze default: 584bf997c2cSschwarze break; 585bf997c2cSschwarze } 586526e306bSschwarze return 1; 5874175bdabSschwarze } 5884175bdabSschwarze 5894175bdabSschwarze static int 5904175bdabSschwarze mdoc_ss_pre(MDOC_ARGS) 5914175bdabSschwarze { 5922dd33770Sschwarze switch (n->type) { 5932dd33770Sschwarze case ROFFT_BLOCK: 5942dd33770Sschwarze html_close_paragraph(h); 5951a2b7b3cSschwarze print_otag(h, TAG_SECTION, "c", "Ss"); 5960ac7e6ecSschwarze break; 5972dd33770Sschwarze case ROFFT_HEAD: 59800b92a3fSschwarze print_otag_id(h, TAG_H3, "Ss", n); 5992dd33770Sschwarze break; 6002dd33770Sschwarze case ROFFT_BODY: 6010ac7e6ecSschwarze break; 6022dd33770Sschwarze default: 6032dd33770Sschwarze abort(); 6042dd33770Sschwarze } 605526e306bSschwarze return 1; 6064175bdabSschwarze } 6074175bdabSschwarze 6084175bdabSschwarze static int 6094175bdabSschwarze mdoc_fl_pre(MDOC_ARGS) 6104175bdabSschwarze { 6117ebbefbeSschwarze struct roff_node *nn; 6125d7d1836Sschwarze 6130ac7e6ecSschwarze print_otag_id(h, TAG_CODE, "Fl", n); 6146306e64dSschwarze print_text(h, "\\-"); 6157ebbefbeSschwarze if (n->child != NULL || 6167ebbefbeSschwarze ((nn = roff_node_next(n)) != NULL && 6177ebbefbeSschwarze nn->type != ROFFT_TEXT && 6187ebbefbeSschwarze (nn->flags & NODE_LINE) == 0)) 619b16e7ddfSschwarze h->flags |= HTML_NOSPACE; 6205d7d1836Sschwarze 621526e306bSschwarze return 1; 6224175bdabSschwarze } 6234175bdabSschwarze 6244175bdabSschwarze static int 6254175bdabSschwarze mdoc_nd_pre(MDOC_ARGS) 6264175bdabSschwarze { 6272dd33770Sschwarze switch (n->type) { 6282dd33770Sschwarze case ROFFT_BLOCK: 629526e306bSschwarze return 1; 6302dd33770Sschwarze case ROFFT_HEAD: 6312dd33770Sschwarze return 0; 6322dd33770Sschwarze case ROFFT_BODY: 6332dd33770Sschwarze break; 6342dd33770Sschwarze default: 6352dd33770Sschwarze abort(); 6362dd33770Sschwarze } 6374175bdabSschwarze print_text(h, "\\(em"); 63893a46bdfSschwarze print_otag(h, TAG_SPAN, "cr", "Nd", "doc-subtitle"); 639526e306bSschwarze return 1; 6404175bdabSschwarze } 6414175bdabSschwarze 6424175bdabSschwarze static int 6434175bdabSschwarze mdoc_nm_pre(MDOC_ARGS) 6444175bdabSschwarze { 645467b61c6Sschwarze switch (n->type) { 6462dd33770Sschwarze case ROFFT_BLOCK: 6472dd33770Sschwarze break; 648909abc6fSschwarze case ROFFT_HEAD: 649229cc7fdSschwarze print_otag(h, TAG_TD, ""); 650909abc6fSschwarze /* FALLTHROUGH */ 651d1982c71Sschwarze case ROFFT_ELEM: 6520ce603abSschwarze print_otag(h, TAG_CODE, "c", "Nm"); 653526e306bSschwarze return 1; 654d1982c71Sschwarze case ROFFT_BODY: 655229cc7fdSschwarze print_otag(h, TAG_TD, ""); 656526e306bSschwarze return 1; 657467b61c6Sschwarze default: 6582dd33770Sschwarze abort(); 659769ee804Sschwarze } 6602dd33770Sschwarze html_close_paragraph(h); 661467b61c6Sschwarze synopsis_pre(h, n); 662774a248cSschwarze print_otag(h, TAG_TABLE, "c", "Nm"); 663229cc7fdSschwarze print_otag(h, TAG_TR, ""); 664526e306bSschwarze return 1; 6654175bdabSschwarze } 6664175bdabSschwarze 6674175bdabSschwarze static int 6684175bdabSschwarze mdoc_xr_pre(MDOC_ARGS) 6694175bdabSschwarze { 670b3005203Sschwarze char *name, *section, *label; 671b3005203Sschwarze 672b3005203Sschwarze if (n->child == NULL) 673526e306bSschwarze return 0; 674b4dec12aSschwarze 675b3005203Sschwarze name = n->child->string; 676b3005203Sschwarze if (n->child->next != NULL) { 677b3005203Sschwarze section = n->child->next->string; 678b3005203Sschwarze mandoc_asprintf(&label, "%s, section %s", name, section); 679b3005203Sschwarze } else 680b3005203Sschwarze section = label = NULL; 681b3005203Sschwarze 6823f160fd1Sschwarze if (h->base_man1) 683b3005203Sschwarze print_otag(h, TAG_A, "chM?", "Xr", 684b3005203Sschwarze name, section, "aria-label", label); 685fef1eecdSschwarze else 686b3005203Sschwarze print_otag(h, TAG_A, "c?", "Xr", "aria-label", label); 6874175bdabSschwarze 688b3005203Sschwarze free(label); 689b3005203Sschwarze print_text(h, name); 6904175bdabSschwarze 691b3005203Sschwarze if (section == NULL) 692526e306bSschwarze return 0; 6934175bdabSschwarze 6944175bdabSschwarze h->flags |= HTML_NOSPACE; 6954175bdabSschwarze print_text(h, "("); 6964175bdabSschwarze h->flags |= HTML_NOSPACE; 697b3005203Sschwarze print_text(h, section); 6984175bdabSschwarze h->flags |= HTML_NOSPACE; 6994175bdabSschwarze print_text(h, ")"); 700526e306bSschwarze return 0; 7014175bdabSschwarze } 7024175bdabSschwarze 7034175bdabSschwarze static int 70492929bf6Sschwarze mdoc_tg_pre(MDOC_ARGS) 70592929bf6Sschwarze { 70692929bf6Sschwarze char *id; 70792929bf6Sschwarze 7086e69d8cfSschwarze if ((id = html_make_id(n, 1)) != NULL) { 70966c5de26Sschwarze print_tagq(h, print_otag(h, TAG_MARK, "i", id)); 7106e69d8cfSschwarze free(id); 7116e69d8cfSschwarze } 71292929bf6Sschwarze return 0; 71392929bf6Sschwarze } 71492929bf6Sschwarze 71592929bf6Sschwarze static int 7164175bdabSschwarze mdoc_ns_pre(MDOC_ARGS) 7174175bdabSschwarze { 7184175bdabSschwarze 719c4b0939cSschwarze if ( ! (NODE_LINE & n->flags)) 7204175bdabSschwarze h->flags |= HTML_NOSPACE; 721526e306bSschwarze return 1; 7224175bdabSschwarze } 7234175bdabSschwarze 7244175bdabSschwarze static int 7254175bdabSschwarze mdoc_ar_pre(MDOC_ARGS) 7264175bdabSschwarze { 7270ce603abSschwarze print_otag(h, TAG_VAR, "c", "Ar"); 728526e306bSschwarze return 1; 7294175bdabSschwarze } 7304175bdabSschwarze 7314175bdabSschwarze static int 7324175bdabSschwarze mdoc_xx_pre(MDOC_ARGS) 7334175bdabSschwarze { 7340a282dffSschwarze print_otag(h, TAG_SPAN, "c", "Ux"); 735816c3c54Sschwarze return 1; 7364175bdabSschwarze } 7374175bdabSschwarze 7384175bdabSschwarze static int 7394175bdabSschwarze mdoc_it_pre(MDOC_ARGS) 7404175bdabSschwarze { 7413a0d07afSschwarze const struct roff_node *bl; 742297116b8Sschwarze enum mdoc_list type; 7434175bdabSschwarze 744467b61c6Sschwarze bl = n->parent; 7459b423113Sschwarze while (bl->tok != MDOC_Bl) 7464175bdabSschwarze bl = bl->parent; 7478c62fbf5Sschwarze type = bl->norm->Bl.type; 74831e23753Sschwarze 7494175bdabSschwarze switch (type) { 75049aff9f8Sschwarze case LIST_bullet: 75149aff9f8Sschwarze case LIST_dash: 752297116b8Sschwarze case LIST_hyphen: 75349aff9f8Sschwarze case LIST_item: 754297116b8Sschwarze case LIST_enum: 755297116b8Sschwarze switch (n->type) { 756297116b8Sschwarze case ROFFT_HEAD: 757297116b8Sschwarze return 0; 758297116b8Sschwarze case ROFFT_BODY: 759e053e0fdSschwarze print_otag_id(h, TAG_LI, NULL, n); 760467b61c6Sschwarze break; 761297116b8Sschwarze default: 762297116b8Sschwarze break; 763297116b8Sschwarze } 764297116b8Sschwarze break; 76549aff9f8Sschwarze case LIST_diag: 76649aff9f8Sschwarze case LIST_hang: 76749aff9f8Sschwarze case LIST_inset: 76849aff9f8Sschwarze case LIST_ohang: 769297116b8Sschwarze switch (n->type) { 770297116b8Sschwarze case ROFFT_HEAD: 771e053e0fdSschwarze print_otag_id(h, TAG_DT, NULL, n); 772467b61c6Sschwarze break; 773297116b8Sschwarze case ROFFT_BODY: 774da5c23dcSschwarze print_otag(h, TAG_DD, ""); 775467b61c6Sschwarze break; 776297116b8Sschwarze default: 777297116b8Sschwarze break; 778297116b8Sschwarze } 779297116b8Sschwarze break; 7807c6e1b3aSschwarze case LIST_tag: 7817c6e1b3aSschwarze switch (n->type) { 7827c6e1b3aSschwarze case ROFFT_HEAD: 783e053e0fdSschwarze print_otag_id(h, TAG_DT, NULL, n); 7847c6e1b3aSschwarze break; 7857c6e1b3aSschwarze case ROFFT_BODY: 7867c6e1b3aSschwarze if (n->child == NULL) { 7875c9781a4Sschwarze print_otag(h, TAG_DD, "s", "width", "auto"); 7887c6e1b3aSschwarze print_text(h, "\\ "); 7897c6e1b3aSschwarze } else 790492a74caSschwarze print_otag(h, TAG_DD, ""); 7917c6e1b3aSschwarze break; 7927c6e1b3aSschwarze default: 7937c6e1b3aSschwarze break; 7947c6e1b3aSschwarze } 7957c6e1b3aSschwarze break; 79649aff9f8Sschwarze case LIST_column: 797297116b8Sschwarze switch (n->type) { 798297116b8Sschwarze case ROFFT_HEAD: 799297116b8Sschwarze break; 800297116b8Sschwarze case ROFFT_BODY: 801492a74caSschwarze print_otag(h, TAG_TD, ""); 802467b61c6Sschwarze break; 803467b61c6Sschwarze default: 804e053e0fdSschwarze print_otag_id(h, TAG_TR, NULL, n); 805467b61c6Sschwarze } 806467b61c6Sschwarze default: 807467b61c6Sschwarze break; 808467b61c6Sschwarze } 8094175bdabSschwarze 810526e306bSschwarze return 1; 8114175bdabSschwarze } 8124175bdabSschwarze 8134175bdabSschwarze static int 8144175bdabSschwarze mdoc_bl_pre(MDOC_ARGS) 8154175bdabSschwarze { 8168c00a69aSschwarze char cattr[32]; 817b19679ceSschwarze struct mdoc_bl *bl; 818229cc7fdSschwarze enum htmltag elemtype; 8194175bdabSschwarze 820408a904eSschwarze switch (n->type) { 8212dd33770Sschwarze case ROFFT_BLOCK: 8222dd33770Sschwarze html_close_paragraph(h); 8232dd33770Sschwarze break; 824408a904eSschwarze case ROFFT_HEAD: 825526e306bSschwarze return 0; 8262dd33770Sschwarze case ROFFT_BODY: 8272dd33770Sschwarze return 1; 828408a904eSschwarze default: 8292dd33770Sschwarze abort(); 8304175bdabSschwarze } 8314175bdabSschwarze 8327056f56aSschwarze bl = &n->norm->Bl; 833b19679ceSschwarze switch (bl->type) { 83449aff9f8Sschwarze case LIST_bullet: 835297116b8Sschwarze elemtype = TAG_UL; 836c67bdbbdSschwarze (void)strlcpy(cattr, "Bl-bullet", sizeof(cattr)); 837297116b8Sschwarze break; 83849aff9f8Sschwarze case LIST_dash: 83949aff9f8Sschwarze case LIST_hyphen: 840297116b8Sschwarze elemtype = TAG_UL; 841c67bdbbdSschwarze (void)strlcpy(cattr, "Bl-dash", sizeof(cattr)); 842297116b8Sschwarze break; 84349aff9f8Sschwarze case LIST_item: 844229cc7fdSschwarze elemtype = TAG_UL; 845c67bdbbdSschwarze (void)strlcpy(cattr, "Bl-item", sizeof(cattr)); 846467b61c6Sschwarze break; 84749aff9f8Sschwarze case LIST_enum: 848229cc7fdSschwarze elemtype = TAG_OL; 849c67bdbbdSschwarze (void)strlcpy(cattr, "Bl-enum", sizeof(cattr)); 850467b61c6Sschwarze break; 85149aff9f8Sschwarze case LIST_diag: 852297116b8Sschwarze elemtype = TAG_DL; 853c67bdbbdSschwarze (void)strlcpy(cattr, "Bl-diag", sizeof(cattr)); 854297116b8Sschwarze break; 85549aff9f8Sschwarze case LIST_hang: 856297116b8Sschwarze elemtype = TAG_DL; 857c67bdbbdSschwarze (void)strlcpy(cattr, "Bl-hang", sizeof(cattr)); 858297116b8Sschwarze break; 85949aff9f8Sschwarze case LIST_inset: 860297116b8Sschwarze elemtype = TAG_DL; 861c67bdbbdSschwarze (void)strlcpy(cattr, "Bl-inset", sizeof(cattr)); 862297116b8Sschwarze break; 86349aff9f8Sschwarze case LIST_ohang: 864297116b8Sschwarze elemtype = TAG_DL; 865c67bdbbdSschwarze (void)strlcpy(cattr, "Bl-ohang", sizeof(cattr)); 866297116b8Sschwarze break; 86749aff9f8Sschwarze case LIST_tag: 868b19679ceSschwarze if (bl->offs) 8697bdf9c46Sschwarze print_otag(h, TAG_DIV, "c", "Bd-indent"); 870e053e0fdSschwarze print_otag_id(h, TAG_DL, 871e053e0fdSschwarze bl->comp ? "Bl-tag Bl-compact" : "Bl-tag", n->body); 8727c6e1b3aSschwarze return 1; 87349aff9f8Sschwarze case LIST_column: 874229cc7fdSschwarze elemtype = TAG_TABLE; 875c67bdbbdSschwarze (void)strlcpy(cattr, "Bl-column", sizeof(cattr)); 876467b61c6Sschwarze break; 877467b61c6Sschwarze default: 878467b61c6Sschwarze abort(); 879467b61c6Sschwarze } 8807bdf9c46Sschwarze if (bl->offs != NULL) 8817bdf9c46Sschwarze (void)strlcat(cattr, " Bd-indent", sizeof(cattr)); 882c67bdbbdSschwarze if (bl->comp) 883c67bdbbdSschwarze (void)strlcat(cattr, " Bl-compact", sizeof(cattr)); 884e053e0fdSschwarze print_otag_id(h, elemtype, cattr, n->body); 885526e306bSschwarze return 1; 886467b61c6Sschwarze } 8874175bdabSschwarze 8884175bdabSschwarze static int 8894175bdabSschwarze mdoc_ex_pre(MDOC_ARGS) 8904175bdabSschwarze { 8917ebbefbeSschwarze if (roff_node_prev(n) != NULL) 892229cc7fdSschwarze print_otag(h, TAG_BR, ""); 8938ccddcd3Sschwarze return 1; 8944175bdabSschwarze } 8954175bdabSschwarze 8964175bdabSschwarze static int 897dd15d0f1Sschwarze mdoc_st_pre(MDOC_ARGS) 898dd15d0f1Sschwarze { 8990ce603abSschwarze print_otag(h, TAG_SPAN, "c", "St"); 900dd15d0f1Sschwarze return 1; 901dd15d0f1Sschwarze } 902dd15d0f1Sschwarze 903dd15d0f1Sschwarze static int 9044175bdabSschwarze mdoc_em_pre(MDOC_ARGS) 9054175bdabSschwarze { 9060ac7e6ecSschwarze print_otag_id(h, TAG_I, "Em", n); 907526e306bSschwarze return 1; 9084175bdabSschwarze } 9094175bdabSschwarze 9104175bdabSschwarze static int 9114175bdabSschwarze mdoc_d1_pre(MDOC_ARGS) 9124175bdabSschwarze { 9132dd33770Sschwarze switch (n->type) { 9142dd33770Sschwarze case ROFFT_BLOCK: 9152dd33770Sschwarze html_close_paragraph(h); 916e053e0fdSschwarze return 1; 9172dd33770Sschwarze case ROFFT_HEAD: 9182dd33770Sschwarze return 0; 9192dd33770Sschwarze case ROFFT_BODY: 920e053e0fdSschwarze break; 9212dd33770Sschwarze default: 9222dd33770Sschwarze abort(); 9232dd33770Sschwarze } 924e053e0fdSschwarze print_otag_id(h, TAG_DIV, "Bd Bd-indent", n); 925fea50678Sschwarze if (n->tok == MDOC_Dl) 926fea50678Sschwarze print_otag(h, TAG_CODE, "c", "Li"); 927526e306bSschwarze return 1; 9284175bdabSschwarze } 9294175bdabSschwarze 9304175bdabSschwarze static int 9314175bdabSschwarze mdoc_sx_pre(MDOC_ARGS) 9324175bdabSschwarze { 933fef1eecdSschwarze char *id; 9344175bdabSschwarze 935762c1016Sschwarze id = html_make_id(n, 0); 9360ce603abSschwarze print_otag(h, TAG_A, "chR", "Sx", id); 937fef1eecdSschwarze free(id); 938526e306bSschwarze return 1; 9394175bdabSschwarze } 9404175bdabSschwarze 9414175bdabSschwarze static int 9424175bdabSschwarze mdoc_bd_pre(MDOC_ARGS) 9434175bdabSschwarze { 9444529325aSschwarze char buf[20]; 9453a0d07afSschwarze struct roff_node *nn; 9462dd33770Sschwarze int comp; 9474175bdabSschwarze 9482dd33770Sschwarze switch (n->type) { 9492dd33770Sschwarze case ROFFT_BLOCK: 9502dd33770Sschwarze html_close_paragraph(h); 9512dd33770Sschwarze return 1; 9522dd33770Sschwarze case ROFFT_HEAD: 953526e306bSschwarze return 0; 9542dd33770Sschwarze case ROFFT_BODY: 9552dd33770Sschwarze break; 9562dd33770Sschwarze default: 9572dd33770Sschwarze abort(); 9582dd33770Sschwarze } 9594175bdabSschwarze 9602dd33770Sschwarze /* Handle preceding whitespace. */ 9612dd33770Sschwarze 9628c62fbf5Sschwarze comp = n->norm->Bd.comp; 9632dd33770Sschwarze for (nn = n; nn != NULL && comp == 0; nn = nn->parent) { 964d1982c71Sschwarze if (nn->type != ROFFT_BLOCK) 9654175bdabSschwarze continue; 9662dd33770Sschwarze if (nn->tok == MDOC_Sh || nn->tok == MDOC_Ss) 9674175bdabSschwarze comp = 1; 9687ebbefbeSschwarze if (roff_node_prev(nn) != NULL) 9694175bdabSschwarze break; 9704175bdabSschwarze } 9712dd33770Sschwarze (void)strlcpy(buf, "Bd", sizeof(buf)); 9722dd33770Sschwarze if (comp == 0) 9732dd33770Sschwarze (void)strlcat(buf, " Pp", sizeof(buf)); 974467b61c6Sschwarze 97590d52a15Sschwarze /* Handle the -offset argument. */ 97690d52a15Sschwarze 9772dd33770Sschwarze if (n->norm->Bd.offs != NULL && 9782dd33770Sschwarze strcmp(n->norm->Bd.offs, "left") != 0) 9792dd33770Sschwarze (void)strlcat(buf, " Bd-indent", sizeof(buf)); 980467b61c6Sschwarze 9814529325aSschwarze if (n->norm->Bd.type == DISP_literal) 9824529325aSschwarze (void)strlcat(buf, " Li", sizeof(buf)); 9834529325aSschwarze 984e053e0fdSschwarze print_otag_id(h, TAG_DIV, buf, n); 98535030e67Sschwarze return 1; 9864175bdabSschwarze } 9874175bdabSschwarze 9884175bdabSschwarze static int 9894175bdabSschwarze mdoc_pa_pre(MDOC_ARGS) 9904175bdabSschwarze { 9910ce603abSschwarze print_otag(h, TAG_SPAN, "c", "Pa"); 992526e306bSschwarze return 1; 9934175bdabSschwarze } 9944175bdabSschwarze 9954175bdabSschwarze static int 9964175bdabSschwarze mdoc_ad_pre(MDOC_ARGS) 9974175bdabSschwarze { 998e34b78c5Sschwarze print_otag(h, TAG_SPAN, "c", "Ad"); 999526e306bSschwarze return 1; 10004175bdabSschwarze } 10014175bdabSschwarze 10024175bdabSschwarze static int 10034175bdabSschwarze mdoc_an_pre(MDOC_ARGS) 10044175bdabSschwarze { 1005bf997c2cSschwarze if (n->norm->An.auth == AUTH_split) { 1006bf997c2cSschwarze h->flags &= ~HTML_NOSPLIT; 1007bf997c2cSschwarze h->flags |= HTML_SPLIT; 1008526e306bSschwarze return 0; 1009bf997c2cSschwarze } 1010bf997c2cSschwarze if (n->norm->An.auth == AUTH_nosplit) { 1011bf997c2cSschwarze h->flags &= ~HTML_SPLIT; 1012bf997c2cSschwarze h->flags |= HTML_NOSPLIT; 1013526e306bSschwarze return 0; 1014bf997c2cSschwarze } 1015bf997c2cSschwarze 1016bf997c2cSschwarze if (h->flags & HTML_SPLIT) 1017229cc7fdSschwarze print_otag(h, TAG_BR, ""); 1018bf997c2cSschwarze 1019bf997c2cSschwarze if (n->sec == SEC_AUTHORS && ! (h->flags & HTML_NOSPLIT)) 1020bf997c2cSschwarze h->flags |= HTML_SPLIT; 10214175bdabSschwarze 10220ce603abSschwarze print_otag(h, TAG_SPAN, "c", "An"); 1023526e306bSschwarze return 1; 10244175bdabSschwarze } 10254175bdabSschwarze 10264175bdabSschwarze static int 10274175bdabSschwarze mdoc_cd_pre(MDOC_ARGS) 10284175bdabSschwarze { 10299a98b8a1Sschwarze synopsis_pre(h, n); 10300ce603abSschwarze print_otag(h, TAG_CODE, "c", "Cd"); 1031526e306bSschwarze return 1; 10324175bdabSschwarze } 10334175bdabSschwarze 10344175bdabSschwarze static int 10354175bdabSschwarze mdoc_fa_pre(MDOC_ARGS) 10364175bdabSschwarze { 10373a0d07afSschwarze const struct roff_node *nn; 10384175bdabSschwarze struct tag *t; 10394175bdabSschwarze 10404175bdabSschwarze if (n->parent->tok != MDOC_Fo) { 10410ce603abSschwarze print_otag(h, TAG_VAR, "c", "Fa"); 1042526e306bSschwarze return 1; 10434175bdabSschwarze } 10447ebbefbeSschwarze for (nn = n->child; nn != NULL; nn = nn->next) { 10450ce603abSschwarze t = print_otag(h, TAG_VAR, "c", "Fa"); 10464175bdabSschwarze print_text(h, nn->string); 10474175bdabSschwarze print_tagq(h, t); 10487ebbefbeSschwarze if (nn->next != NULL) { 1049a35fc07aSschwarze h->flags |= HTML_NOSPACE; 10504175bdabSschwarze print_text(h, ","); 10514175bdabSschwarze } 1052a35fc07aSschwarze } 10537ebbefbeSschwarze if (n->child != NULL && 10547ebbefbeSschwarze (nn = roff_node_next(n)) != NULL && 10557ebbefbeSschwarze nn->tok == MDOC_Fa) { 1056a35fc07aSschwarze h->flags |= HTML_NOSPACE; 10574175bdabSschwarze print_text(h, ","); 1058a35fc07aSschwarze } 1059526e306bSschwarze return 0; 10604175bdabSschwarze } 10614175bdabSschwarze 10624175bdabSschwarze static int 10634175bdabSschwarze mdoc_fd_pre(MDOC_ARGS) 10644175bdabSschwarze { 1065a35fc07aSschwarze struct tag *t; 1066fef1eecdSschwarze char *buf, *cp; 10674175bdabSschwarze 10689a98b8a1Sschwarze synopsis_pre(h, n); 10699a98b8a1Sschwarze 1070a35fc07aSschwarze if (NULL == (n = n->child)) 1071526e306bSschwarze return 0; 1072a35fc07aSschwarze 1073d1982c71Sschwarze assert(n->type == ROFFT_TEXT); 1074a35fc07aSschwarze 1075a35fc07aSschwarze if (strcmp(n->string, "#include")) { 10760ce603abSschwarze print_otag(h, TAG_CODE, "c", "Fd"); 1077526e306bSschwarze return 1; 10784175bdabSschwarze } 10794175bdabSschwarze 10800ce603abSschwarze print_otag(h, TAG_CODE, "c", "In"); 1081a35fc07aSschwarze print_text(h, n->string); 1082a35fc07aSschwarze 1083a35fc07aSschwarze if (NULL != (n = n->next)) { 1084d1982c71Sschwarze assert(n->type == ROFFT_TEXT); 10850b2f1307Sschwarze 1086a35fc07aSschwarze if (h->base_includes) { 1087fef1eecdSschwarze cp = n->string; 1088fef1eecdSschwarze if (*cp == '<' || *cp == '"') 1089fef1eecdSschwarze cp++; 1090fef1eecdSschwarze buf = mandoc_strdup(cp); 1091fef1eecdSschwarze cp = strchr(buf, '\0') - 1; 1092fef1eecdSschwarze if (cp >= buf && (*cp == '>' || *cp == '"')) 1093fef1eecdSschwarze *cp = '\0'; 10940ce603abSschwarze t = print_otag(h, TAG_A, "chI", "In", buf); 1095fef1eecdSschwarze free(buf); 1096229cc7fdSschwarze } else 10970ce603abSschwarze t = print_otag(h, TAG_A, "c", "In"); 1098a35fc07aSschwarze 1099a35fc07aSschwarze print_text(h, n->string); 1100a35fc07aSschwarze print_tagq(h, t); 1101a35fc07aSschwarze 1102a35fc07aSschwarze n = n->next; 1103a35fc07aSschwarze } 1104a35fc07aSschwarze 1105a35fc07aSschwarze for ( ; n; n = n->next) { 1106d1982c71Sschwarze assert(n->type == ROFFT_TEXT); 1107a35fc07aSschwarze print_text(h, n->string); 1108a35fc07aSschwarze } 1109a35fc07aSschwarze 1110526e306bSschwarze return 0; 1111a35fc07aSschwarze } 1112a35fc07aSschwarze 11134175bdabSschwarze static int 11144175bdabSschwarze mdoc_vt_pre(MDOC_ARGS) 11154175bdabSschwarze { 1116d1982c71Sschwarze if (n->type == ROFFT_BLOCK) { 11179a98b8a1Sschwarze synopsis_pre(h, n); 1118526e306bSschwarze return 1; 1119d1982c71Sschwarze } else if (n->type == ROFFT_ELEM) { 11209a98b8a1Sschwarze synopsis_pre(h, n); 1121d1982c71Sschwarze } else if (n->type == ROFFT_HEAD) 1122526e306bSschwarze return 0; 11234175bdabSschwarze 11240ce603abSschwarze print_otag(h, TAG_VAR, "c", "Vt"); 1125526e306bSschwarze return 1; 11264175bdabSschwarze } 11274175bdabSschwarze 11284175bdabSschwarze static int 11294175bdabSschwarze mdoc_ft_pre(MDOC_ARGS) 11304175bdabSschwarze { 11319a98b8a1Sschwarze synopsis_pre(h, n); 11320ce603abSschwarze print_otag(h, TAG_VAR, "c", "Ft"); 1133526e306bSschwarze return 1; 11344175bdabSschwarze } 11354175bdabSschwarze 11364175bdabSschwarze static int 11374175bdabSschwarze mdoc_fn_pre(MDOC_ARGS) 11384175bdabSschwarze { 11394175bdabSschwarze struct tag *t; 11404175bdabSschwarze char nbuf[BUFSIZ]; 11414175bdabSschwarze const char *sp, *ep; 1142229cc7fdSschwarze int sz, pretty; 11434175bdabSschwarze 1144c4b0939cSschwarze pretty = NODE_SYNPRETTY & n->flags; 11459a98b8a1Sschwarze synopsis_pre(h, n); 11464175bdabSschwarze 11474175bdabSschwarze /* Split apart into type and name. */ 11484175bdabSschwarze assert(n->child->string); 11494175bdabSschwarze sp = n->child->string; 11504175bdabSschwarze 11514175bdabSschwarze ep = strchr(sp, ' '); 11524175bdabSschwarze if (NULL != ep) { 11530ce603abSschwarze t = print_otag(h, TAG_VAR, "c", "Ft"); 11544175bdabSschwarze 11554175bdabSschwarze while (ep) { 11564175bdabSschwarze sz = MIN((int)(ep - sp), BUFSIZ - 1); 11574175bdabSschwarze (void)memcpy(nbuf, sp, (size_t)sz); 11584175bdabSschwarze nbuf[sz] = '\0'; 11594175bdabSschwarze print_text(h, nbuf); 11604175bdabSschwarze sp = ++ep; 11614175bdabSschwarze ep = strchr(sp, ' '); 11624175bdabSschwarze } 11634175bdabSschwarze print_tagq(h, t); 11644175bdabSschwarze } 11654175bdabSschwarze 11660ac7e6ecSschwarze t = print_otag_id(h, TAG_CODE, "Fn", n); 11674175bdabSschwarze 11680b2f1307Sschwarze if (sp) 11690b2f1307Sschwarze print_text(h, sp); 11704175bdabSschwarze 11714175bdabSschwarze print_tagq(h, t); 11724175bdabSschwarze 11734175bdabSschwarze h->flags |= HTML_NOSPACE; 11744175bdabSschwarze print_text(h, "("); 1175a35fc07aSschwarze h->flags |= HTML_NOSPACE; 11764175bdabSschwarze 1177a35fc07aSschwarze for (n = n->child->next; n; n = n->next) { 1178c4b0939cSschwarze if (NODE_SYNPRETTY & n->flags) 11790ce603abSschwarze t = print_otag(h, TAG_VAR, "cs", "Fa", 1180229cc7fdSschwarze "white-space", "nowrap"); 1181229cc7fdSschwarze else 11820ce603abSschwarze t = print_otag(h, TAG_VAR, "c", "Fa"); 1183a35fc07aSschwarze print_text(h, n->string); 11844175bdabSschwarze print_tagq(h, t); 1185a35fc07aSschwarze if (n->next) { 1186a35fc07aSschwarze h->flags |= HTML_NOSPACE; 11874175bdabSschwarze print_text(h, ","); 11884175bdabSschwarze } 1189a35fc07aSschwarze } 11904175bdabSschwarze 1191a35fc07aSschwarze h->flags |= HTML_NOSPACE; 11924175bdabSschwarze print_text(h, ")"); 1193a35fc07aSschwarze 1194a35fc07aSschwarze if (pretty) { 1195a35fc07aSschwarze h->flags |= HTML_NOSPACE; 11964175bdabSschwarze print_text(h, ";"); 1197a35fc07aSschwarze } 11984175bdabSschwarze 1199526e306bSschwarze return 0; 12004175bdabSschwarze } 12014175bdabSschwarze 12024175bdabSschwarze static int 1203ddce0b0cSschwarze mdoc_sm_pre(MDOC_ARGS) 1204ddce0b0cSschwarze { 1205ddce0b0cSschwarze 1206f9e7bf99Sschwarze if (NULL == n->child) 1207f9e7bf99Sschwarze h->flags ^= HTML_NONOSPACE; 1208f9e7bf99Sschwarze else if (0 == strcmp("on", n->child->string)) 1209ddce0b0cSschwarze h->flags &= ~HTML_NONOSPACE; 1210f9e7bf99Sschwarze else 1211ddce0b0cSschwarze h->flags |= HTML_NONOSPACE; 1212ddce0b0cSschwarze 1213f9e7bf99Sschwarze if ( ! (HTML_NONOSPACE & h->flags)) 1214f9e7bf99Sschwarze h->flags &= ~HTML_NOSPACE; 1215f9e7bf99Sschwarze 1216526e306bSschwarze return 0; 1217ddce0b0cSschwarze } 1218ddce0b0cSschwarze 1219467b61c6Sschwarze static int 1220551cd4a8Sschwarze mdoc_skip_pre(MDOC_ARGS) 12215281506aSschwarze { 12225281506aSschwarze 1223526e306bSschwarze return 0; 12245281506aSschwarze } 12255281506aSschwarze 12265281506aSschwarze static int 1227467b61c6Sschwarze mdoc_pp_pre(MDOC_ARGS) 1228467b61c6Sschwarze { 12296e69d8cfSschwarze char *id; 12306e69d8cfSschwarze 1231e2edd184Sschwarze if (n->flags & NODE_NOFILL) { 1232e2edd184Sschwarze print_endline(h); 1233e053e0fdSschwarze if (n->flags & NODE_ID) 1234e053e0fdSschwarze mdoc_tg_pre(meta, n, h); 1235e053e0fdSschwarze else { 1236e2edd184Sschwarze h->col = 1; 1237e2edd184Sschwarze print_endline(h); 1238e053e0fdSschwarze } 1239e2edd184Sschwarze } else { 12402dd33770Sschwarze html_close_paragraph(h); 12416e69d8cfSschwarze id = n->flags & NODE_ID ? html_make_id(n, 1) : NULL; 12426e69d8cfSschwarze print_otag(h, TAG_P, "ci", "Pp", id); 12436e69d8cfSschwarze free(id); 12442dd33770Sschwarze } 1245526e306bSschwarze return 0; 1246467b61c6Sschwarze } 1247ddce0b0cSschwarze 1248ddce0b0cSschwarze static int 12494175bdabSschwarze mdoc_lk_pre(MDOC_ARGS) 12504175bdabSschwarze { 1251eb4d0f30Sschwarze const struct roff_node *link, *descr, *punct; 125296aebfb3Sschwarze struct tag *t; 125396aebfb3Sschwarze 1254eb4d0f30Sschwarze if ((link = n->child) == NULL) 1255526e306bSschwarze return 0; 1256a35fc07aSschwarze 1257eb4d0f30Sschwarze /* Find beginning of trailing punctuation. */ 1258eb4d0f30Sschwarze punct = n->last; 1259eb4d0f30Sschwarze while (punct != link && punct->flags & NODE_DELIMC) 1260eb4d0f30Sschwarze punct = punct->prev; 1261eb4d0f30Sschwarze punct = punct->next; 1262eb4d0f30Sschwarze 126396aebfb3Sschwarze /* Link target and link text. */ 1264fd01a48eSschwarze descr = link->next; 1265fd01a48eSschwarze if (descr == punct) 1266fd01a48eSschwarze descr = link; /* no text */ 12670ce603abSschwarze t = print_otag(h, TAG_A, "ch", "Lk", link->string); 1268fd01a48eSschwarze do { 1269eb4d0f30Sschwarze if (descr->flags & (NODE_DELIMC | NODE_DELIMO)) 1270eb4d0f30Sschwarze h->flags |= HTML_NOSPACE; 1271eb4d0f30Sschwarze print_text(h, descr->string); 1272fd01a48eSschwarze descr = descr->next; 1273fd01a48eSschwarze } while (descr != punct); 127496aebfb3Sschwarze print_tagq(h, t); 12754175bdabSschwarze 127696aebfb3Sschwarze /* Trailing punctuation. */ 1277eb4d0f30Sschwarze while (punct != NULL) { 127896aebfb3Sschwarze h->flags |= HTML_NOSPACE; 1279eb4d0f30Sschwarze print_text(h, punct->string); 1280eb4d0f30Sschwarze punct = punct->next; 128196aebfb3Sschwarze } 1282526e306bSschwarze return 0; 12834175bdabSschwarze } 12844175bdabSschwarze 12854175bdabSschwarze static int 12864175bdabSschwarze mdoc_mt_pre(MDOC_ARGS) 12874175bdabSschwarze { 12884175bdabSschwarze struct tag *t; 1289fef1eecdSschwarze char *cp; 12904175bdabSschwarze 1291a35fc07aSschwarze for (n = n->child; n; n = n->next) { 1292d1982c71Sschwarze assert(n->type == ROFFT_TEXT); 1293fef1eecdSschwarze mandoc_asprintf(&cp, "mailto:%s", n->string); 12940ce603abSschwarze t = print_otag(h, TAG_A, "ch", "Mt", cp); 1295a35fc07aSschwarze print_text(h, n->string); 12964175bdabSschwarze print_tagq(h, t); 1297fef1eecdSschwarze free(cp); 12984175bdabSschwarze } 1299526e306bSschwarze return 0; 13004175bdabSschwarze } 13014175bdabSschwarze 13024175bdabSschwarze static int 13034175bdabSschwarze mdoc_fo_pre(MDOC_ARGS) 13044175bdabSschwarze { 13056093755cSschwarze struct tag *t; 13064175bdabSschwarze 13070ac7e6ecSschwarze switch (n->type) { 13080ac7e6ecSschwarze case ROFFT_BLOCK: 13090ac7e6ecSschwarze synopsis_pre(h, n); 13100ac7e6ecSschwarze return 1; 13110ac7e6ecSschwarze case ROFFT_HEAD: 13120ac7e6ecSschwarze if (n->child != NULL) { 13130ac7e6ecSschwarze t = print_otag_id(h, TAG_CODE, "Fn", n); 13140ac7e6ecSschwarze print_text(h, n->child->string); 13150ac7e6ecSschwarze print_tagq(h, t); 13160ac7e6ecSschwarze } 13170ac7e6ecSschwarze return 0; 13180ac7e6ecSschwarze case ROFFT_BODY: 13194175bdabSschwarze h->flags |= HTML_NOSPACE; 13204175bdabSschwarze print_text(h, "("); 13214175bdabSschwarze h->flags |= HTML_NOSPACE; 1322526e306bSschwarze return 1; 13230ac7e6ecSschwarze default: 13240ac7e6ecSschwarze abort(); 1325b16e7ddfSschwarze } 13264175bdabSschwarze } 13274175bdabSschwarze 13284175bdabSschwarze static void 13294175bdabSschwarze mdoc_fo_post(MDOC_ARGS) 13304175bdabSschwarze { 1331d1982c71Sschwarze if (n->type != ROFFT_BODY) 13324175bdabSschwarze return; 1333a35fc07aSschwarze h->flags |= HTML_NOSPACE; 13344175bdabSschwarze print_text(h, ")"); 1335a35fc07aSschwarze h->flags |= HTML_NOSPACE; 13364175bdabSschwarze print_text(h, ";"); 13374175bdabSschwarze } 13384175bdabSschwarze 13394175bdabSschwarze static int 13404175bdabSschwarze mdoc_in_pre(MDOC_ARGS) 13414175bdabSschwarze { 13424175bdabSschwarze struct tag *t; 13434175bdabSschwarze 13449a98b8a1Sschwarze synopsis_pre(h, n); 13450ce603abSschwarze print_otag(h, TAG_CODE, "c", "In"); 13464175bdabSschwarze 1347a35fc07aSschwarze /* 1348a35fc07aSschwarze * The first argument of the `In' gets special treatment as 1349a35fc07aSschwarze * being a linked value. Subsequent values are printed 1350a35fc07aSschwarze * afterward. groff does similarly. This also handles the case 1351a35fc07aSschwarze * of no children. 1352a35fc07aSschwarze */ 1353a35fc07aSschwarze 1354c4b0939cSschwarze if (NODE_SYNPRETTY & n->flags && NODE_LINE & n->flags) 13554175bdabSschwarze print_text(h, "#include"); 13564175bdabSschwarze 13574175bdabSschwarze print_text(h, "<"); 13584175bdabSschwarze h->flags |= HTML_NOSPACE; 13594175bdabSschwarze 1360a35fc07aSschwarze if (NULL != (n = n->child)) { 1361d1982c71Sschwarze assert(n->type == ROFFT_TEXT); 1362a35fc07aSschwarze 1363fef1eecdSschwarze if (h->base_includes) 13640ce603abSschwarze t = print_otag(h, TAG_A, "chI", "In", n->string); 1365fef1eecdSschwarze else 13660ce603abSschwarze t = print_otag(h, TAG_A, "c", "In"); 1367a35fc07aSschwarze print_text(h, n->string); 13684175bdabSschwarze print_tagq(h, t); 1369a35fc07aSschwarze 1370a35fc07aSschwarze n = n->next; 13714175bdabSschwarze } 13724175bdabSschwarze 13734175bdabSschwarze h->flags |= HTML_NOSPACE; 13744175bdabSschwarze print_text(h, ">"); 13754175bdabSschwarze 1376a35fc07aSschwarze for ( ; n; n = n->next) { 1377d1982c71Sschwarze assert(n->type == ROFFT_TEXT); 1378a35fc07aSschwarze print_text(h, n->string); 1379a35fc07aSschwarze } 1380526e306bSschwarze return 0; 13814175bdabSschwarze } 13824175bdabSschwarze 13834175bdabSschwarze static int 13844175bdabSschwarze mdoc_va_pre(MDOC_ARGS) 13854175bdabSschwarze { 13860ce603abSschwarze print_otag(h, TAG_VAR, "c", "Va"); 1387526e306bSschwarze return 1; 13884175bdabSschwarze } 13894175bdabSschwarze 13904175bdabSschwarze static int 13914175bdabSschwarze mdoc_ap_pre(MDOC_ARGS) 13924175bdabSschwarze { 13934175bdabSschwarze h->flags |= HTML_NOSPACE; 13944175bdabSschwarze print_text(h, "\\(aq"); 13954175bdabSschwarze h->flags |= HTML_NOSPACE; 1396526e306bSschwarze return 1; 13974175bdabSschwarze } 13984175bdabSschwarze 13994175bdabSschwarze static int 14004175bdabSschwarze mdoc_bf_pre(MDOC_ARGS) 14014175bdabSschwarze { 1402229cc7fdSschwarze const char *cattr; 14034175bdabSschwarze 14042dd33770Sschwarze switch (n->type) { 14052dd33770Sschwarze case ROFFT_BLOCK: 14062dd33770Sschwarze html_close_paragraph(h); 1407526e306bSschwarze return 1; 14082dd33770Sschwarze case ROFFT_HEAD: 14092dd33770Sschwarze return 0; 14102dd33770Sschwarze case ROFFT_BODY: 14112dd33770Sschwarze break; 14122dd33770Sschwarze default: 14132dd33770Sschwarze abort(); 14142dd33770Sschwarze } 14154175bdabSschwarze 1416d257d942Sschwarze if (FONT_Em == n->norm->Bf.font) 14172e36b507Sschwarze cattr = "Bf Em"; 1418d257d942Sschwarze else if (FONT_Sy == n->norm->Bf.font) 14192e36b507Sschwarze cattr = "Bf Sy"; 14208c62fbf5Sschwarze else if (FONT_Li == n->norm->Bf.font) 14212e36b507Sschwarze cattr = "Bf Li"; 1422769ee804Sschwarze else 14232e36b507Sschwarze cattr = "Bf No"; 14244175bdabSschwarze 14252e36b507Sschwarze /* Cannot use TAG_SPAN because it may contain blocks. */ 142670a5f756Sschwarze print_otag(h, TAG_DIV, "c", cattr); 1427526e306bSschwarze return 1; 14284175bdabSschwarze } 14294175bdabSschwarze 14304175bdabSschwarze static int 143137e2f24fSschwarze mdoc_igndelim_pre(MDOC_ARGS) 14324175bdabSschwarze { 14334175bdabSschwarze h->flags |= HTML_IGNDELIM; 1434526e306bSschwarze return 1; 14354175bdabSschwarze } 14364175bdabSschwarze 14374175bdabSschwarze static void 14384175bdabSschwarze mdoc_pf_post(MDOC_ARGS) 14394175bdabSschwarze { 1440c4b0939cSschwarze if ( ! (n->next == NULL || n->next->flags & NODE_LINE)) 14414175bdabSschwarze h->flags |= HTML_NOSPACE; 14424175bdabSschwarze } 14434175bdabSschwarze 14444175bdabSschwarze static int 14454175bdabSschwarze mdoc_rs_pre(MDOC_ARGS) 14464175bdabSschwarze { 14472dd33770Sschwarze switch (n->type) { 14482dd33770Sschwarze case ROFFT_BLOCK: 14492dd33770Sschwarze if (n->sec == SEC_SEE_ALSO) 14502dd33770Sschwarze html_close_paragraph(h); 14512dd33770Sschwarze break; 14522dd33770Sschwarze case ROFFT_HEAD: 14532dd33770Sschwarze return 0; 14542dd33770Sschwarze case ROFFT_BODY: 14552dd33770Sschwarze if (n->sec == SEC_SEE_ALSO) 14562dd33770Sschwarze print_otag(h, TAG_P, "c", "Pp"); 1457*645bcdadSschwarze print_otag(h, TAG_SPAN, "c", "Rs"); 14582dd33770Sschwarze break; 14592dd33770Sschwarze default: 14602dd33770Sschwarze abort(); 14612dd33770Sschwarze } 1462526e306bSschwarze return 1; 14634175bdabSschwarze } 14644175bdabSschwarze 14654175bdabSschwarze static int 14666f9818f6Sschwarze mdoc_no_pre(MDOC_ARGS) 14676f9818f6Sschwarze { 14680ac7e6ecSschwarze print_otag_id(h, TAG_SPAN, roff_name[n->tok], n); 1469526e306bSschwarze return 1; 14704175bdabSschwarze } 14714175bdabSschwarze 14724175bdabSschwarze static int 14734175bdabSschwarze mdoc_sy_pre(MDOC_ARGS) 14744175bdabSschwarze { 14750ac7e6ecSschwarze print_otag_id(h, TAG_B, "Sy", n); 1476526e306bSschwarze return 1; 14774175bdabSschwarze } 14784175bdabSschwarze 14794175bdabSschwarze static int 14804175bdabSschwarze mdoc_lb_pre(MDOC_ARGS) 14814175bdabSschwarze { 14827ebbefbeSschwarze if (n->sec == SEC_LIBRARY && 14837ebbefbeSschwarze n->flags & NODE_LINE && 14847ebbefbeSschwarze roff_node_prev(n) != NULL) 1485229cc7fdSschwarze print_otag(h, TAG_BR, ""); 1486467b61c6Sschwarze 14870ce603abSschwarze print_otag(h, TAG_SPAN, "c", "Lb"); 1488526e306bSschwarze return 1; 14894175bdabSschwarze } 14904175bdabSschwarze 14914175bdabSschwarze static int 14924175bdabSschwarze mdoc__x_pre(MDOC_ARGS) 14934175bdabSschwarze { 14947ebbefbeSschwarze struct roff_node *nn; 14950aa8d661Sschwarze const unsigned char *cp; 14960aa8d661Sschwarze const char *cattr, *arg; 14970aa8d661Sschwarze char *url; 1498b009ccebSschwarze enum htmltag t; 1499b009ccebSschwarze 1500b009ccebSschwarze t = TAG_SPAN; 15010aa8d661Sschwarze arg = n->child->string; 15024175bdabSschwarze 15034175bdabSschwarze switch (n->tok) { 150449aff9f8Sschwarze case MDOC__A: 1505186d9410Sschwarze cattr = "RsA"; 15067ebbefbeSschwarze if ((nn = roff_node_prev(n)) != NULL && nn->tok == MDOC__A && 15077ebbefbeSschwarze ((nn = roff_node_next(n)) == NULL || nn->tok != MDOC__A)) 1508bf782e42Sschwarze print_text(h, "and"); 15094175bdabSschwarze break; 151049aff9f8Sschwarze case MDOC__B: 1511*645bcdadSschwarze t = TAG_CITE; 1512186d9410Sschwarze cattr = "RsB"; 15134175bdabSschwarze break; 151449aff9f8Sschwarze case MDOC__C: 1515186d9410Sschwarze cattr = "RsC"; 15164175bdabSschwarze break; 151749aff9f8Sschwarze case MDOC__D: 1518186d9410Sschwarze cattr = "RsD"; 15194175bdabSschwarze break; 152049aff9f8Sschwarze case MDOC__I: 1521b009ccebSschwarze t = TAG_I; 1522186d9410Sschwarze cattr = "RsI"; 15234175bdabSschwarze break; 152449aff9f8Sschwarze case MDOC__J: 1525b009ccebSschwarze t = TAG_I; 1526186d9410Sschwarze cattr = "RsJ"; 15274175bdabSschwarze break; 152849aff9f8Sschwarze case MDOC__N: 1529186d9410Sschwarze cattr = "RsN"; 15304175bdabSschwarze break; 153149aff9f8Sschwarze case MDOC__O: 1532186d9410Sschwarze cattr = "RsO"; 15334175bdabSschwarze break; 153449aff9f8Sschwarze case MDOC__P: 1535186d9410Sschwarze cattr = "RsP"; 15364175bdabSschwarze break; 153749aff9f8Sschwarze case MDOC__Q: 1538186d9410Sschwarze cattr = "RsQ"; 15394175bdabSschwarze break; 154049aff9f8Sschwarze case MDOC__R: 15410aa8d661Sschwarze if (strncmp(arg, "RFC ", 4) == 0) { 15420aa8d661Sschwarze cp = arg += 4; 15430aa8d661Sschwarze while (isdigit(*cp)) 15440aa8d661Sschwarze cp++; 15450aa8d661Sschwarze if (*cp == '\0') { 15460aa8d661Sschwarze mandoc_asprintf(&url, "https://www.rfc-" 15470aa8d661Sschwarze "editor.org/rfc/rfc%s.html", arg); 15480aa8d661Sschwarze print_otag(h, TAG_A, "ch", "RsR", url); 15490aa8d661Sschwarze free(url); 15500aa8d661Sschwarze return 1; 15510aa8d661Sschwarze } 15520aa8d661Sschwarze } 1553186d9410Sschwarze cattr = "RsR"; 15544175bdabSschwarze break; 155549aff9f8Sschwarze case MDOC__T: 1556*645bcdadSschwarze t = TAG_CITE; 155761a57034Sschwarze if (n->parent != NULL && n->parent->tok == MDOC_Rs && 155861a57034Sschwarze n->parent->norm->Rs.quote_T) { 155961a57034Sschwarze print_text(h, "\\(lq"); 156061a57034Sschwarze h->flags |= HTML_NOSPACE; 1561186d9410Sschwarze cattr = "RsT"; 156261a57034Sschwarze } else 156361a57034Sschwarze cattr = "RsB"; 15644175bdabSschwarze break; 156549aff9f8Sschwarze case MDOC__U: 15660aa8d661Sschwarze print_otag(h, TAG_A, "ch", "RsU", arg); 1567186d9410Sschwarze return 1; 156849aff9f8Sschwarze case MDOC__V: 1569186d9410Sschwarze cattr = "RsV"; 15704175bdabSschwarze break; 15714175bdabSschwarze default: 15724175bdabSschwarze abort(); 15734175bdabSschwarze } 15744175bdabSschwarze 1575229cc7fdSschwarze print_otag(h, t, "c", cattr); 1576526e306bSschwarze return 1; 1577b822ca0dSschwarze } 1578b822ca0dSschwarze 15794175bdabSschwarze static void 15804175bdabSschwarze mdoc__x_post(MDOC_ARGS) 15814175bdabSschwarze { 15827ebbefbeSschwarze struct roff_node *nn; 15834175bdabSschwarze 158461a57034Sschwarze switch (n->tok) { 158561a57034Sschwarze case MDOC__A: 158661a57034Sschwarze if ((nn = roff_node_next(n)) != NULL && nn->tok == MDOC__A && 15877ebbefbeSschwarze ((nn = roff_node_next(nn)) == NULL || nn->tok != MDOC__A) && 15887ebbefbeSschwarze ((nn = roff_node_prev(n)) == NULL || nn->tok != MDOC__A)) 1589bf782e42Sschwarze return; 159061a57034Sschwarze break; 159161a57034Sschwarze case MDOC__T: 159261a57034Sschwarze if (n->parent != NULL && n->parent->tok == MDOC_Rs && 159361a57034Sschwarze n->parent->norm->Rs.quote_T) { 159461a57034Sschwarze h->flags |= HTML_NOSPACE; 159561a57034Sschwarze print_text(h, "\\(rq"); 159661a57034Sschwarze } 159761a57034Sschwarze break; 159861a57034Sschwarze default: 159961a57034Sschwarze break; 160061a57034Sschwarze } 16017ebbefbeSschwarze if (n->parent == NULL || n->parent->tok != MDOC_Rs) 1602d967b250Sschwarze return; 1603d967b250Sschwarze 1604a35fc07aSschwarze h->flags |= HTML_NOSPACE; 16057ebbefbeSschwarze print_text(h, roff_node_next(n) ? "," : "."); 16064175bdabSschwarze } 1607769ee804Sschwarze 1608769ee804Sschwarze static int 1609769ee804Sschwarze mdoc_bk_pre(MDOC_ARGS) 1610769ee804Sschwarze { 1611769ee804Sschwarze 1612769ee804Sschwarze switch (n->type) { 1613d1982c71Sschwarze case ROFFT_BLOCK: 1614769ee804Sschwarze break; 1615d1982c71Sschwarze case ROFFT_HEAD: 1616526e306bSschwarze return 0; 1617d1982c71Sschwarze case ROFFT_BODY: 161830e5ee06Sschwarze if (n->parent->args != NULL || n->prev->child == NULL) 1619769ee804Sschwarze h->flags |= HTML_PREKEEP; 1620769ee804Sschwarze break; 1621769ee804Sschwarze default: 1622769ee804Sschwarze abort(); 1623769ee804Sschwarze } 1624769ee804Sschwarze 1625526e306bSschwarze return 1; 1626769ee804Sschwarze } 1627769ee804Sschwarze 1628769ee804Sschwarze static void 1629769ee804Sschwarze mdoc_bk_post(MDOC_ARGS) 1630769ee804Sschwarze { 1631769ee804Sschwarze 1632d1982c71Sschwarze if (n->type == ROFFT_BODY) 1633769ee804Sschwarze h->flags &= ~(HTML_KEEP | HTML_PREKEEP); 1634769ee804Sschwarze } 16352c3450fcSschwarze 16362c3450fcSschwarze static int 16372c3450fcSschwarze mdoc_quote_pre(MDOC_ARGS) 16382c3450fcSschwarze { 1639d1982c71Sschwarze if (n->type != ROFFT_BODY) 1640526e306bSschwarze return 1; 16412c3450fcSschwarze 16422c3450fcSschwarze switch (n->tok) { 164349aff9f8Sschwarze case MDOC_Ao: 164449aff9f8Sschwarze case MDOC_Aq: 164530e5ee06Sschwarze print_text(h, n->child != NULL && n->child->next == NULL && 1646ba61527cSschwarze n->child->tok == MDOC_Mt ? "<" : "\\(la"); 16472c3450fcSschwarze break; 164849aff9f8Sschwarze case MDOC_Bro: 164949aff9f8Sschwarze case MDOC_Brq: 16502c3450fcSschwarze print_text(h, "\\(lC"); 16512c3450fcSschwarze break; 165249aff9f8Sschwarze case MDOC_Bo: 165349aff9f8Sschwarze case MDOC_Bq: 16542c3450fcSschwarze print_text(h, "\\(lB"); 16552c3450fcSschwarze break; 165649aff9f8Sschwarze case MDOC_Oo: 165749aff9f8Sschwarze case MDOC_Op: 16582c3450fcSschwarze print_text(h, "\\(lB"); 16592dd33770Sschwarze /* 16602dd33770Sschwarze * Give up on semantic markup for now. 16612dd33770Sschwarze * We cannot use TAG_SPAN because .Oo may contain blocks. 1662c5914f85Sschwarze * We cannot use TAG_DIV because we might be in a 16632dd33770Sschwarze * phrasing context (like .Dl or .Pp); we cannot 16642dd33770Sschwarze * close out a .Pp at this point either because 16652dd33770Sschwarze * that would break the line. 16662dd33770Sschwarze */ 16672dd33770Sschwarze /* XXX print_otag(h, TAG_???, "c", "Op"); */ 16682c3450fcSschwarze break; 1669551cd4a8Sschwarze case MDOC_En: 1670551cd4a8Sschwarze if (NULL == n->norm->Es || 1671551cd4a8Sschwarze NULL == n->norm->Es->child) 1672526e306bSschwarze return 1; 1673551cd4a8Sschwarze print_text(h, n->norm->Es->child->string); 1674551cd4a8Sschwarze break; 167549aff9f8Sschwarze case MDOC_Do: 167649aff9f8Sschwarze case MDOC_Dq: 1677ac01d98fSbentley print_text(h, "\\(lq"); 1678ac01d98fSbentley break; 167949aff9f8Sschwarze case MDOC_Qo: 168049aff9f8Sschwarze case MDOC_Qq: 1681ac01d98fSbentley print_text(h, "\""); 16822c3450fcSschwarze break; 168349aff9f8Sschwarze case MDOC_Po: 168449aff9f8Sschwarze case MDOC_Pq: 16852c3450fcSschwarze print_text(h, "("); 16862c3450fcSschwarze break; 168749aff9f8Sschwarze case MDOC_Ql: 168804e980cbSschwarze print_text(h, "\\(oq"); 168904e980cbSschwarze h->flags |= HTML_NOSPACE; 1690fea50678Sschwarze print_otag(h, TAG_CODE, "c", "Li"); 169104e980cbSschwarze break; 169249aff9f8Sschwarze case MDOC_So: 169349aff9f8Sschwarze case MDOC_Sq: 16942c3450fcSschwarze print_text(h, "\\(oq"); 16952c3450fcSschwarze break; 16962c3450fcSschwarze default: 16972c3450fcSschwarze abort(); 16982c3450fcSschwarze } 16992c3450fcSschwarze 17002c3450fcSschwarze h->flags |= HTML_NOSPACE; 1701526e306bSschwarze return 1; 17022c3450fcSschwarze } 17032c3450fcSschwarze 17042c3450fcSschwarze static void 17052c3450fcSschwarze mdoc_quote_post(MDOC_ARGS) 17062c3450fcSschwarze { 17072c3450fcSschwarze 1708d1982c71Sschwarze if (n->type != ROFFT_BODY && n->type != ROFFT_ELEM) 17092c3450fcSschwarze return; 17102c3450fcSschwarze 17112c3450fcSschwarze h->flags |= HTML_NOSPACE; 17122c3450fcSschwarze 17132c3450fcSschwarze switch (n->tok) { 171449aff9f8Sschwarze case MDOC_Ao: 171549aff9f8Sschwarze case MDOC_Aq: 171630e5ee06Sschwarze print_text(h, n->child != NULL && n->child->next == NULL && 1717ba61527cSschwarze n->child->tok == MDOC_Mt ? ">" : "\\(ra"); 17182c3450fcSschwarze break; 171949aff9f8Sschwarze case MDOC_Bro: 172049aff9f8Sschwarze case MDOC_Brq: 17212c3450fcSschwarze print_text(h, "\\(rC"); 17222c3450fcSschwarze break; 172349aff9f8Sschwarze case MDOC_Oo: 172449aff9f8Sschwarze case MDOC_Op: 172549aff9f8Sschwarze case MDOC_Bo: 172649aff9f8Sschwarze case MDOC_Bq: 17272c3450fcSschwarze print_text(h, "\\(rB"); 17282c3450fcSschwarze break; 1729551cd4a8Sschwarze case MDOC_En: 173003ed6ec9Sschwarze if (n->norm->Es == NULL || 173103ed6ec9Sschwarze n->norm->Es->child == NULL || 173203ed6ec9Sschwarze n->norm->Es->child->next == NULL) 173303ed6ec9Sschwarze h->flags &= ~HTML_NOSPACE; 173403ed6ec9Sschwarze else 1735551cd4a8Sschwarze print_text(h, n->norm->Es->child->next->string); 1736a1d10d08Sschwarze break; 173749aff9f8Sschwarze case MDOC_Do: 173849aff9f8Sschwarze case MDOC_Dq: 17392c3450fcSschwarze print_text(h, "\\(rq"); 17402c3450fcSschwarze break; 1741ac01d98fSbentley case MDOC_Qo: 1742ac01d98fSbentley case MDOC_Qq: 1743ac01d98fSbentley print_text(h, "\""); 1744ac01d98fSbentley break; 174549aff9f8Sschwarze case MDOC_Po: 174649aff9f8Sschwarze case MDOC_Pq: 17472c3450fcSschwarze print_text(h, ")"); 17482c3450fcSschwarze break; 174949aff9f8Sschwarze case MDOC_Ql: 175049aff9f8Sschwarze case MDOC_So: 175149aff9f8Sschwarze case MDOC_Sq: 1752f5ff5c49Smatthew print_text(h, "\\(cq"); 17532c3450fcSschwarze break; 17542c3450fcSschwarze default: 17552c3450fcSschwarze abort(); 17562c3450fcSschwarze } 17572c3450fcSschwarze } 175803ed6ec9Sschwarze 175903ed6ec9Sschwarze static int 176003ed6ec9Sschwarze mdoc_eo_pre(MDOC_ARGS) 176103ed6ec9Sschwarze { 176203ed6ec9Sschwarze 1763d1982c71Sschwarze if (n->type != ROFFT_BODY) 1764526e306bSschwarze return 1; 176503ed6ec9Sschwarze 176603ed6ec9Sschwarze if (n->end == ENDBODY_NOT && 176703ed6ec9Sschwarze n->parent->head->child == NULL && 176803ed6ec9Sschwarze n->child != NULL && 176903ed6ec9Sschwarze n->child->end != ENDBODY_NOT) 177003ed6ec9Sschwarze print_text(h, "\\&"); 177103ed6ec9Sschwarze else if (n->end != ENDBODY_NOT ? n->child != NULL : 1772c69b5c37Sschwarze n->parent->head->child != NULL && (n->child != NULL || 1773c69b5c37Sschwarze (n->parent->tail != NULL && n->parent->tail->child != NULL))) 177403ed6ec9Sschwarze h->flags |= HTML_NOSPACE; 1775526e306bSschwarze return 1; 177603ed6ec9Sschwarze } 177703ed6ec9Sschwarze 177803ed6ec9Sschwarze static void 177903ed6ec9Sschwarze mdoc_eo_post(MDOC_ARGS) 178003ed6ec9Sschwarze { 178103ed6ec9Sschwarze int body, tail; 178203ed6ec9Sschwarze 1783d1982c71Sschwarze if (n->type != ROFFT_BODY) 178403ed6ec9Sschwarze return; 178503ed6ec9Sschwarze 178603ed6ec9Sschwarze if (n->end != ENDBODY_NOT) { 178703ed6ec9Sschwarze h->flags &= ~HTML_NOSPACE; 178803ed6ec9Sschwarze return; 178903ed6ec9Sschwarze } 179003ed6ec9Sschwarze 179103ed6ec9Sschwarze body = n->child != NULL || n->parent->head->child != NULL; 179203ed6ec9Sschwarze tail = n->parent->tail != NULL && n->parent->tail->child != NULL; 179303ed6ec9Sschwarze 179403ed6ec9Sschwarze if (body && tail) 179503ed6ec9Sschwarze h->flags |= HTML_NOSPACE; 179603ed6ec9Sschwarze else if ( ! tail) 179703ed6ec9Sschwarze h->flags &= ~HTML_NOSPACE; 179803ed6ec9Sschwarze } 17997c539ecbSschwarze 18007c539ecbSschwarze static int 18017c539ecbSschwarze mdoc_abort_pre(MDOC_ARGS) 18027c539ecbSschwarze { 18037c539ecbSschwarze abort(); 18047c539ecbSschwarze } 1805