summaryrefslogtreecommitdiff
path: root/usr.bin/mandoc
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2020-04-06 09:55:51 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2020-04-06 09:55:51 +0000
commit8b440b4adf0207c9d0637b16817fda9700a8a0e9 (patch)
tree32ef9dde1ac1a79fc25501c9f0d7b80395e0a540 /usr.bin/mandoc
parentcd810fb4ab3cd85588a2f3e795b5c12ca43b1b28 (diff)
Support manual tagging of .Pp, .Bd, .D1, .Dl, .Bl, and .It.
In HTML output, improve the logic for writing inside permalinks: skip them when there is no child content or when there is a risk that the children might contain flow content.
Diffstat (limited to 'usr.bin/mandoc')
-rw-r--r--usr.bin/mandoc/html.c23
-rw-r--r--usr.bin/mandoc/mdoc.c13
-rw-r--r--usr.bin/mandoc/mdoc_html.c35
-rw-r--r--usr.bin/mandoc/mdoc_term.c23
-rw-r--r--usr.bin/mandoc/mdoc_validate.c48
-rw-r--r--usr.bin/mandoc/roff.c10
-rw-r--r--usr.bin/mandoc/roff.h5
7 files changed, 113 insertions, 44 deletions
diff --git a/usr.bin/mandoc/html.c b/usr.bin/mandoc/html.c
index c7c87c67a4e..e15c680b296 100644
--- a/usr.bin/mandoc/html.c
+++ b/usr.bin/mandoc/html.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: html.c,v 1.135 2020/03/13 00:31:04 schwarze Exp $ */
+/* $OpenBSD: html.c,v 1.136 2020/04/06 09:55:49 schwarze Exp $ */
/*
* Copyright (c) 2011-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -360,7 +360,7 @@ html_make_id(const struct roff_node *n, int unique)
return NULL;
break;
default:
- if (n->child->type != ROFFT_TEXT)
+ if (n->child == NULL || n->child->type != ROFFT_TEXT)
return NULL;
buf = mandoc_strdup(n->child->string);
break;
@@ -767,13 +767,15 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
/*
* Print an element with an optional "id=" attribute.
- * If there is an "id=" attribute, also add a permalink:
- * outside if it's a phrasing element, or inside otherwise.
+ * If the element has phrasing content and an "id=" attribute,
+ * also add a permalink: outside if it can be in phrasing context,
+ * inside otherwise.
*/
struct tag *
print_otag_id(struct html *h, enum htmltag elemtype, const char *cattr,
struct roff_node *n)
{
+ struct roff_node *nch;
struct tag *ret, *t;
const char *id;
@@ -786,8 +788,17 @@ print_otag_id(struct html *h, enum htmltag elemtype, const char *cattr,
t = print_otag(h, elemtype, "ci", cattr, id);
if (ret == NULL) {
ret = t;
- if (id != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
+ if (id != NULL && (nch = n->child) != NULL) {
+ /* man(7) is safe, it tags phrasing content only. */
+ if (n->tok > MDOC_MAX ||
+ htmltags[elemtype].flags & HTML_TOPHRASE)
+ nch = NULL;
+ else /* For mdoc(7), beware of nested blocks. */
+ while (nch != NULL && nch->type == ROFFT_TEXT)
+ nch = nch->next;
+ if (nch == NULL)
+ print_otag(h, TAG_A, "chR", "permalink", id);
+ }
}
return ret;
}
diff --git a/usr.bin/mandoc/mdoc.c b/usr.bin/mandoc/mdoc.c
index a24da770c1a..7920985e33a 100644
--- a/usr.bin/mandoc/mdoc.c
+++ b/usr.bin/mandoc/mdoc.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: mdoc.c,v 1.163 2018/12/31 07:45:42 schwarze Exp $ */
+/* $OpenBSD: mdoc.c,v 1.164 2020/04/06 09:55:49 schwarze Exp $ */
/*
+ * Copyright (c) 2010, 2012-2018, 2020 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2012-2018 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,6 +14,8 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Top level and utility functions of the mdoc(7) parser for mandoc(1).
*/
#include <sys/types.h>
@@ -350,12 +352,13 @@ mdoc_pmacro(struct roff_man *mdoc, int ln, char *buf, int offs)
mandoc_msg(MANDOCERR_SPACE_EOL, ln, offs - 1, NULL);
/*
- * If an initial macro or a list invocation, divert directly
- * into macro processing.
+ * If an initial or transparent macro or a list invocation,
+ * divert directly into macro processing.
*/
n = mdoc->last;
- if (n == NULL || tok == MDOC_It || tok == MDOC_El) {
+ if (n == NULL || tok == MDOC_It || tok == MDOC_El ||
+ roff_tok_transparent(tok)) {
(*mdoc_macro(tok)->fp)(mdoc, tok, ln, sv, &offs, buf);
return 1;
}
diff --git a/usr.bin/mandoc/mdoc_html.c b/usr.bin/mandoc/mdoc_html.c
index 5bf9519941f..d55cb75d0ca 100644
--- a/usr.bin/mandoc/mdoc_html.c
+++ b/usr.bin/mandoc/mdoc_html.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mdoc_html.c,v 1.212 2020/04/01 20:10:17 schwarze Exp $ */
+/* $OpenBSD: mdoc_html.c,v 1.213 2020/04/06 09:55:49 schwarze Exp $ */
/*
* Copyright (c) 2014-2020 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -739,7 +739,7 @@ mdoc_it_pre(MDOC_ARGS)
case ROFFT_HEAD:
return 0;
case ROFFT_BODY:
- print_otag(h, TAG_LI, "");
+ print_otag_id(h, TAG_LI, NULL, n);
break;
default:
break;
@@ -751,7 +751,7 @@ mdoc_it_pre(MDOC_ARGS)
case LIST_ohang:
switch (n->type) {
case ROFFT_HEAD:
- print_otag(h, TAG_DT, "");
+ print_otag_id(h, TAG_DT, NULL, n);
break;
case ROFFT_BODY:
print_otag(h, TAG_DD, "");
@@ -763,7 +763,7 @@ mdoc_it_pre(MDOC_ARGS)
case LIST_tag:
switch (n->type) {
case ROFFT_HEAD:
- print_otag(h, TAG_DT, "");
+ print_otag_id(h, TAG_DT, NULL, n);
break;
case ROFFT_BODY:
if (n->child == NULL) {
@@ -784,7 +784,7 @@ mdoc_it_pre(MDOC_ARGS)
print_otag(h, TAG_TD, "");
break;
default:
- print_otag(h, TAG_TR, "");
+ print_otag_id(h, TAG_TR, NULL, n);
}
default:
break;
@@ -850,8 +850,8 @@ mdoc_bl_pre(MDOC_ARGS)
case LIST_tag:
if (bl->offs)
print_otag(h, TAG_DIV, "c", "Bd-indent");
- print_otag(h, TAG_DL, "c", bl->comp ?
- "Bl-tag Bl-compact" : "Bl-tag");
+ print_otag_id(h, TAG_DL,
+ bl->comp ? "Bl-tag Bl-compact" : "Bl-tag", n->body);
return 1;
case LIST_column:
elemtype = TAG_TABLE;
@@ -864,7 +864,7 @@ mdoc_bl_pre(MDOC_ARGS)
(void)strlcat(cattr, " Bd-indent", sizeof(cattr));
if (bl->comp)
(void)strlcat(cattr, " Bl-compact", sizeof(cattr));
- print_otag(h, elemtype, "c", cattr);
+ print_otag_id(h, elemtype, cattr, n->body);
return 1;
}
@@ -896,15 +896,15 @@ mdoc_d1_pre(MDOC_ARGS)
switch (n->type) {
case ROFFT_BLOCK:
html_close_paragraph(h);
- break;
+ return 1;
case ROFFT_HEAD:
return 0;
case ROFFT_BODY:
- return 1;
+ break;
default:
abort();
}
- print_otag(h, TAG_DIV, "c", "Bd Bd-indent");
+ print_otag_id(h, TAG_DIV, "Bd Bd-indent", n);
if (n->tok == MDOC_Dl)
print_otag(h, TAG_CODE, "c", "Li");
return 1;
@@ -961,7 +961,7 @@ mdoc_bd_pre(MDOC_ARGS)
strcmp(n->norm->Bd.offs, "left") != 0)
(void)strlcat(buf, " Bd-indent", sizeof(buf));
- print_otag(h, TAG_DIV, "c", buf);
+ print_otag_id(h, TAG_DIV, buf, n);
return 1;
}
@@ -1208,11 +1208,16 @@ mdoc_pp_pre(MDOC_ARGS)
{
if (n->flags & NODE_NOFILL) {
print_endline(h);
- h->col = 1;
- print_endline(h);
+ if (n->flags & NODE_ID)
+ mdoc_tg_pre(meta, n, h);
+ else {
+ h->col = 1;
+ print_endline(h);
+ }
} else {
html_close_paragraph(h);
- print_otag(h, TAG_P, "c", "Pp");
+ print_otag(h, TAG_P, "ci", "Pp",
+ n->flags & NODE_ID ? html_make_id(n, 1) : NULL);
}
return 0;
}
diff --git a/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c
index edbbec08797..6362a214a22 100644
--- a/usr.bin/mandoc/mdoc_term.c
+++ b/usr.bin/mandoc/mdoc_term.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mdoc_term.c,v 1.278 2020/03/13 00:31:05 schwarze Exp $ */
+/* $OpenBSD: mdoc_term.c,v 1.279 2020/04/06 09:55:49 schwarze Exp $ */
/*
* Copyright (c) 2010, 2012-2020 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -333,7 +333,8 @@ print_mdoc_node(DECL_ARGS)
memset(&npair, 0, sizeof(struct termpair));
npair.ppair = pair;
- if (n->flags & NODE_ID)
+ if (n->flags & NODE_ID && n->tok != MDOC_Pp &&
+ (n->tok != MDOC_It || n->type != ROFFT_BLOCK))
term_tag_write(n, p->line);
/*
@@ -628,6 +629,8 @@ termp_it_pre(DECL_ARGS)
if (n->type == ROFFT_BLOCK) {
print_bvspace(p, n->parent->parent, n);
+ if (n->flags & NODE_ID)
+ term_tag_write(n, p->line);
return 1;
}
@@ -1108,7 +1111,6 @@ termp_ex_pre(DECL_ARGS)
static int
termp_nd_pre(DECL_ARGS)
{
-
if (n->type == ROFFT_BODY)
term_word(p, "\\(en");
return 1;
@@ -1117,14 +1119,20 @@ termp_nd_pre(DECL_ARGS)
static int
termp_bl_pre(DECL_ARGS)
{
-
- return n->type != ROFFT_HEAD;
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ term_newln(p);
+ return 1;
+ case ROFFT_HEAD:
+ return 0;
+ default:
+ return 1;
+ }
}
static void
termp_bl_post(DECL_ARGS)
{
-
if (n->type != ROFFT_BLOCK)
return;
term_newln(p);
@@ -1138,7 +1146,6 @@ termp_bl_post(DECL_ARGS)
static int
termp_xr_pre(DECL_ARGS)
{
-
if (NULL == (n = n->child))
return 0;
@@ -1553,6 +1560,8 @@ static int
termp_pp_pre(DECL_ARGS)
{
term_vspace(p);
+ if (n->flags & NODE_ID)
+ term_tag_write(n, p->line);
return 0;
}
diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c
index 4b22e617e22..b50a92a811b 100644
--- a/usr.bin/mandoc/mdoc_validate.c
+++ b/usr.bin/mandoc/mdoc_validate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mdoc_validate.c,v 1.297 2020/04/02 14:55:29 schwarze Exp $ */
+/* $OpenBSD: mdoc_validate.c,v 1.298 2020/04/06 09:55:49 schwarze Exp $ */
/*
* Copyright (c) 2010-2020 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -1090,6 +1090,7 @@ post_tg(POST_ARGS)
struct roff_node *n; /* The .Tg node. */
struct roff_node *nch; /* The first child of the .Tg node. */
struct roff_node *nn; /* The next node after the .Tg node. */
+ struct roff_node *np; /* The parent of the next node. */
struct roff_node *nt; /* The TEXT node containing the tag. */
size_t len; /* The number of bytes in the tag. */
@@ -1135,7 +1136,7 @@ post_tg(POST_ARGS)
}
/* By default, tag the .Tg node itself. */
- if (nn == NULL)
+ if (nn == NULL || nn->flags & NODE_ID)
nn = n;
/* Explicit tagging of specific macros. */
@@ -1143,8 +1144,41 @@ post_tg(POST_ARGS)
case MDOC_Sh:
case MDOC_Ss:
case MDOC_Fo:
- nn = nn->head;
- /* FALLTHROUGH */
+ nn = nn->head->child == NULL ? n : nn->head;
+ break;
+ case MDOC_It:
+ np = nn->parent;
+ while (np->tok != MDOC_Bl)
+ np = np->parent;
+ switch (np->norm->Bl.type) {
+ case LIST_column:
+ break;
+ case LIST_diag:
+ case LIST_hang:
+ case LIST_inset:
+ case LIST_ohang:
+ case LIST_tag:
+ nn = nn->head;
+ break;
+ case LIST_bullet:
+ case LIST_dash:
+ case LIST_enum:
+ case LIST_hyphen:
+ case LIST_item:
+ nn = nn->body->child == NULL ? n : nn->body;
+ break;
+ default:
+ abort();
+ }
+ break;
+ case MDOC_Bd:
+ case MDOC_Bl:
+ case MDOC_D1:
+ case MDOC_Dl:
+ nn = nn->body->child == NULL ? n : nn->body;
+ break;
+ case MDOC_Pp:
+ break;
case MDOC_Cm:
case MDOC_Dv:
case MDOC_Em:
@@ -1157,9 +1191,9 @@ post_tg(POST_ARGS)
case MDOC_Ms:
case MDOC_No:
case MDOC_Sy:
- if (nn->child != NULL && (nn->flags & NODE_ID) == 0)
- break;
- /* FALLTHROUGH */
+ if (nn->child == NULL)
+ nn = n;
+ break;
default:
nn = n;
break;
diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c
index a69f632a6cb..035f53ac62f 100644
--- a/usr.bin/mandoc/roff.c
+++ b/usr.bin/mandoc/roff.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: roff.c,v 1.244 2020/04/03 11:34:19 schwarze Exp $ */
+/* $OpenBSD: roff.c,v 1.245 2020/04/06 09:55:49 schwarze Exp $ */
/*
* Copyright (c) 2010-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -1121,7 +1121,13 @@ roff_node_transparent(struct roff_node *n)
return 0;
if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT)
return 1;
- switch (n->tok) {
+ return roff_tok_transparent(n->tok);
+}
+
+int
+roff_tok_transparent(enum roff_tok tok)
+{
+ switch (tok) {
case ROFF_ft:
case ROFF_ll:
case ROFF_mc:
diff --git a/usr.bin/mandoc/roff.h b/usr.bin/mandoc/roff.h
index aeb5c68e08a..2f010f1edbf 100644
--- a/usr.bin/mandoc/roff.h
+++ b/usr.bin/mandoc/roff.h
@@ -1,7 +1,7 @@
-/* $OpenBSD: roff.h,v 1.54 2020/02/27 21:38:27 schwarze Exp $ */
+/* $OpenBSD: roff.h,v 1.55 2020/04/06 09:55:49 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -557,3 +557,4 @@ struct roff_node *roff_node_child(struct roff_node *);
struct roff_node *roff_node_next(struct roff_node *);
struct roff_node *roff_node_prev(struct roff_node *);
int roff_node_transparent(struct roff_node *);
+int roff_tok_transparent(enum roff_tok);