From 6506abee45c903b6cd5093a2bf6ece5ac7aed4e3 Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Tue, 17 Jan 2017 15:32:43 +0000 Subject: Completely delete the buf field of struct html and all the buf*() interfaces. Such a static buffer was a bad idea in the first place, causing unfixable truncation that was only prevented by triggering an assertion failure. Instead, let the small number of remaining users allocate and free their own, temporary dynamic buffers, or for the case of .Xr and .In, pass the original data to be assembled in print_otag(). --- mdoc_html.c | 152 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 78 insertions(+), 74 deletions(-) (limited to 'mdoc_html.c') diff --git a/mdoc_html.c b/mdoc_html.c index f6994c1a..ad23064b 100644 --- a/mdoc_html.c +++ b/mdoc_html.c @@ -1,4 +1,4 @@ -/* $Id: mdoc_html.c,v 1.248 2017/01/17 01:47:51 schwarze Exp $ */ +/* $Id: mdoc_html.c,v 1.249 2017/01/17 15:32:44 schwarze Exp $ */ /* * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons * Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze @@ -324,17 +324,23 @@ html_mdoc(void *arg, const struct roff_man *mdoc) static void print_mdoc_head(MDOC_ARGS) { + char *cp; print_gen_head(h); - bufinit(h); - bufcat(h, meta->title); - if (meta->msec) - bufcat_fmt(h, "(%s)", meta->msec); - if (meta->arch) - bufcat_fmt(h, " (%s)", meta->arch); + + if (meta->arch != NULL && meta->msec != NULL) + mandoc_asprintf(&cp, "%s(%s) (%s)", meta->title, + meta->msec, meta->arch); + else if (meta->msec != NULL) + mandoc_asprintf(&cp, "%s(%s)", meta->title, meta->msec); + else if (meta->arch != NULL) + mandoc_asprintf(&cp, "%s (%s)", meta->title, meta->arch); + else + cp = mandoc_strdup(meta->title); print_otag(h, TAG_TITLE, ""); - print_text(h, h->buf); + print_text(h, cp); + free(cp); } static void @@ -489,9 +495,33 @@ mdoc_root_pre(MDOC_ARGS) return 1; } +char * +make_id(const struct roff_node *n) +{ + const struct roff_node *nch; + char *buf, *cp; + + for (nch = n->child; nch != NULL; nch = nch->next) + if (nch->type != ROFFT_TEXT) + return NULL; + + buf = NULL; + deroff(&buf, n); + + /* http://www.w3.org/TR/html5/dom.html#the-id-attribute */ + + for (cp = buf; *cp != '\0'; cp++) + if (*cp == ' ') + *cp = '_'; + + return buf; +} + static int mdoc_sh_pre(MDOC_ARGS) { + char *id; + switch (n->type) { case ROFFT_BLOCK: print_otag(h, TAG_DIV, "c", "section"); @@ -504,17 +534,10 @@ mdoc_sh_pre(MDOC_ARGS) break; } - bufinit(h); - - for (n = n->child; n != NULL && n->type == ROFFT_TEXT; ) { - bufcat_id(h, n->string); - if (NULL != (n = n->next)) - bufcat_id(h, " "); - } - - if (NULL == n) - print_otag(h, TAG_H1, "i", h->buf); - else + if ((id = make_id(n)) != NULL) { + print_otag(h, TAG_H1, "i", id); + free(id); + } else print_otag(h, TAG_H1, ""); return 1; @@ -523,23 +546,18 @@ mdoc_sh_pre(MDOC_ARGS) static int mdoc_ss_pre(MDOC_ARGS) { + char *id; + if (n->type == ROFFT_BLOCK) { print_otag(h, TAG_DIV, "c", "subsection"); return 1; } else if (n->type == ROFFT_BODY) return 1; - bufinit(h); - - for (n = n->child; n != NULL && n->type == ROFFT_TEXT; ) { - bufcat_id(h, n->string); - if (NULL != (n = n->next)) - bufcat_id(h, " "); - } - - if (NULL == n) - print_otag(h, TAG_H2, "i", h->buf); - else + if ((id = make_id(n)) != NULL) { + print_otag(h, TAG_H2, "i", id); + free(id); + } else print_otag(h, TAG_H2, ""); return 1; @@ -623,12 +641,11 @@ mdoc_xr_pre(MDOC_ARGS) if (NULL == n->child) return 0; - if (h->base_man) { - buffmt_man(h, n->child->string, - n->child->next ? - n->child->next->string : NULL); - print_otag(h, TAG_A, "ch", "link-man", h->buf); - } else + if (h->base_man) + print_otag(h, TAG_A, "chM", "link-man", + n->child->string, n->child->next == NULL ? + NULL : n->child->next->string); + else print_otag(h, TAG_A, "c", "link-man"); n = n->child; @@ -850,17 +867,15 @@ mdoc_d1_pre(MDOC_ARGS) static int mdoc_sx_pre(MDOC_ARGS) { - bufinit(h); - bufcat(h, "#"); - - for (n = n->child; n; ) { - bufcat_id(h, n->string); - if (NULL != (n = n->next)) - bufcat_id(h, " "); - } + char *id; print_otag(h, TAG_I, "c", "link-sec"); - print_otag(h, TAG_A, "ch", "link-sec", h->buf); + if ((id = make_id(n)) != NULL) { + print_otag(h, TAG_A, "chR", "link-sec", id); + free(id); + } else + print_otag(h, TAG_A, "c", "link-sec"); + return 1; } @@ -1051,9 +1066,8 @@ mdoc_fa_pre(MDOC_ARGS) static int mdoc_fd_pre(MDOC_ARGS) { - char buf[BUFSIZ]; - size_t sz; struct tag *t; + char *buf, *cp; synopsis_pre(h, n); @@ -1073,25 +1087,16 @@ mdoc_fd_pre(MDOC_ARGS) if (NULL != (n = n->next)) { assert(n->type == ROFFT_TEXT); - /* - * XXX This is broken and not easy to fix. - * When using -Oincludes, truncation may occur. - * Dynamic allocation wouldn't help because - * passing long strings to buffmt_includes() - * does not work either. - */ - - strlcpy(buf, '<' == *n->string || '"' == *n->string ? - n->string + 1 : n->string, BUFSIZ); - - sz = strlen(buf); - if (sz && ('>' == buf[sz - 1] || '"' == buf[sz - 1])) - buf[sz - 1] = '\0'; - if (h->base_includes) { - buffmt_includes(h, buf); - t = print_otag(h, TAG_A, "ch", "link-includes", - h->buf); + cp = n->string; + if (*cp == '<' || *cp == '"') + cp++; + buf = mandoc_strdup(cp); + cp = strchr(buf, '\0') - 1; + if (cp >= buf && (*cp == '>' || *cp == '"')) + *cp = '\0'; + t = print_otag(h, TAG_A, "chI", "link-includes", buf); + free(buf); } else t = print_otag(h, TAG_A, "c", "link-includes"); @@ -1279,16 +1284,16 @@ static int mdoc_mt_pre(MDOC_ARGS) { struct tag *t; + char *cp; for (n = n->child; n; n = n->next) { assert(n->type == ROFFT_TEXT); - bufinit(h); - bufcat(h, "mailto:"); - bufcat(h, n->string); - t = print_otag(h, TAG_A, "ch", "link-mail", h->buf); + mandoc_asprintf(&cp, "mailto:%s", n->string); + t = print_otag(h, TAG_A, "ch", "link-mail", cp); print_text(h, n->string); print_tagq(h, t); + free(cp); } return 0; @@ -1355,11 +1360,10 @@ mdoc_in_pre(MDOC_ARGS) if (NULL != (n = n->child)) { assert(n->type == ROFFT_TEXT); - if (h->base_includes) { - buffmt_includes(h, n->string); - t = print_otag(h, TAG_A, "ch", "link-includes", - h->buf); - } else + if (h->base_includes) + t = print_otag(h, TAG_A, "chI", "link-includes", + n->string); + else t = print_otag(h, TAG_A, "c", "link-includes"); print_text(h, n->string); print_tagq(h, t); -- cgit v1.2.3