diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2020-02-27 21:38:28 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2020-02-27 21:38:28 +0000 |
commit | 90125c0d0616065ac86e41e8a4972b3b73f61bf4 (patch) | |
tree | 5ed29449f400030d01535f26586ee3b69be8f743 /usr.bin/mandoc | |
parent | 224a0398c9757c21eb1f548b2fd698b7f37ffcbe (diff) |
Fully support explicit tagging of .Sh and .Ss.
This fixes the offset of two lines in terminal output
and this improves HTML output by putting the id= attribute
and <a> element into the respective <h1> or <h2> element rather
than writing an additional <mark> element.
To that end, introduce node flags NODE_ID (to make the node a link
target, for example by writing an HTML id= attribute or by calling
tag_put()) and NODE_HREF (to make the node a link source, used only
in HTML output, used only to write an <a class="permalink"> element).
In particular:
* In the validator, generalize the concept of the "next node"
such that it also works before .Sh and .Ss.
* If the first argument of .Tg is empty, don't forget to complain
if there are additional arguments, which will be ignored.
* In the terminal formatter, support writing of explicit tags
for all kinds of nodes, not just for .Tg.
* In deroff(), allow nodes to have an explicit string representation
even when they aren't text nodes. Use this for explicitly tagged
section headers. Suprisingly, this is sufficient to make HTML
output work, without explicit code changes in the HTML formatter.
* In syntax tree output, display NODE_ID and NODE_HREF.
Diffstat (limited to 'usr.bin/mandoc')
-rw-r--r-- | usr.bin/mandoc/mdoc_term.c | 16 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_validate.c | 51 | ||||
-rw-r--r-- | usr.bin/mandoc/roff.c | 4 | ||||
-rw-r--r-- | usr.bin/mandoc/roff.h | 4 | ||||
-rw-r--r-- | usr.bin/mandoc/tree.c | 9 |
5 files changed, 64 insertions, 20 deletions
diff --git a/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c index dab449d9da4..54252473702 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.276 2020/02/27 01:25:57 schwarze Exp $ */ +/* $OpenBSD: mdoc_term.c,v 1.277 2020/02/27 21:38:27 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010, 2012-2020 Ingo Schwarze <schwarze@openbsd.org> @@ -115,7 +115,6 @@ static int termp_pp_pre(DECL_ARGS); static int termp_ss_pre(DECL_ARGS); static int termp_sy_pre(DECL_ARGS); static int termp_tag_pre(DECL_ARGS); -static int termp_tg_pre(DECL_ARGS); static int termp_under_pre(DECL_ARGS); static int termp_vt_pre(DECL_ARGS); static int termp_xr_pre(DECL_ARGS); @@ -242,7 +241,7 @@ static const struct mdoc_term_act mdoc_term_acts[MDOC_MAX - MDOC_Dd] = { { NULL, termp____post }, /* %Q */ { NULL, termp____post }, /* %U */ { NULL, NULL }, /* Ta */ - { termp_tg_pre, NULL }, /* Tg */ + { termp_skip_pre, NULL }, /* Tg */ }; static int fn_prio = TAG_STRONG; @@ -339,6 +338,10 @@ print_mdoc_node(DECL_ARGS) memset(&npair, 0, sizeof(struct termpair)); npair.ppair = pair; + if (n->flags & NODE_ID) + tag_put(n->string == NULL ? n->child->string : n->string, + TAG_MANUAL, p->line); + /* * Keeps only work until the end of a line. If a keep was * invoked in a prior line, revert it to PREKEEP. @@ -2064,13 +2067,6 @@ termp_tag_pre(DECL_ARGS) } static int -termp_tg_pre(DECL_ARGS) -{ - tag_put(n->child->string, TAG_MANUAL, p->line); - return 0; -} - -static int termp_abort_pre(DECL_ARGS) { abort(); diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c index 902294e8d79..033a368cd75 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.293 2020/02/27 01:25:58 schwarze Exp $ */ +/* $OpenBSD: mdoc_validate.c,v 1.294 2020/02/27 21:38:27 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2020 Ingo Schwarze <schwarze@openbsd.org> @@ -1079,21 +1079,32 @@ post_st(POST_ARGS) static void post_tg(POST_ARGS) { - struct roff_node *n, *nch; + struct roff_node *n, *nch, *nn; size_t len; + /* Find the next node. */ n = mdoc->last; + for (nn = n; nn != NULL; nn = nn->parent) { + if (nn->next != NULL) { + nn = nn->next; + break; + } + } + + /* Add the default argument, if needed. */ nch = n->child; - if (nch == NULL && n->next != NULL && - n->next->child->type == ROFFT_TEXT) { + if (nch == NULL && nn != NULL && nn->child->type == ROFFT_TEXT) { mdoc->next = ROFF_NEXT_CHILD; roff_word_alloc(mdoc, n->line, n->pos, n->next->child->string); nch = mdoc->last; nch->flags |= NODE_NOSRC; mdoc->last = n; } - if (nch == NULL || *nch->string == '\0') { + + /* Validate the first argument. */ + if (nch == NULL || *nch->string == '\0') mandoc_msg(MANDOCERR_MACRO_EMPTY, n->line, n->pos, "Tg"); + if (nch == NULL) { roff_node_delete(mdoc, n); return; } @@ -1101,14 +1112,42 @@ post_tg(POST_ARGS) if (nch->string[len] != '\0') mandoc_msg(MANDOCERR_TG_SPC, nch->line, nch->pos + len + 1, "Tg %s", nch->string); + + /* Keep only the first argument. */ if (nch->next != NULL) { mandoc_msg(MANDOCERR_ARG_EXCESS, nch->next->line, nch->next->pos, "Tg ... %s", nch->next->string); while (nch->next != NULL) roff_node_delete(mdoc, nch->next); } - if (nch->string[len] != '\0') + + /* Drop the macro if the first argument is invalid. */ + if (len == 0 || nch->string[len] != '\0') { roff_node_delete(mdoc, n); + return; + } + + /* By default, write a <mark> element. */ + n->flags |= NODE_ID; + if (nn == NULL) + return; + + /* Explicit tagging of specific macros. */ + switch (nn->tok) { + case MDOC_Sh: + case MDOC_Ss: + if (nn->head->flags & NODE_ID || nn->head->child == NULL) + break; + n->flags |= NODE_NOPRT; + nn->head->flags |= NODE_ID | NODE_HREF; + assert(nn->head->string == NULL); + nn->head->string = mandoc_strdup(nch->string); + break; + default: + break; + } + if (n->flags & NODE_NOPRT) + n->flags &= ~NODE_ID; } static void diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index 9a8e77a9893..31670fc500d 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roff.c,v 1.242 2020/02/27 01:25:58 schwarze Exp $ */ +/* $OpenBSD: roff.c,v 1.243 2020/02/27 21:38:27 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org> @@ -1171,7 +1171,7 @@ deroff(char **dest, const struct roff_node *n) char *cp; size_t sz; - if (n->type != ROFFT_TEXT) { + if (n->string == NULL) { for (n = n->child; n != NULL; n = n->next) deroff(dest, n); return; diff --git a/usr.bin/mandoc/roff.h b/usr.bin/mandoc/roff.h index 24c0e39bc1f..aeb5c68e08a 100644 --- a/usr.bin/mandoc/roff.h +++ b/usr.bin/mandoc/roff.h @@ -1,4 +1,4 @@ -/* $OpenBSD: roff.h,v 1.53 2020/02/27 01:25:58 schwarze Exp $ */ +/* $OpenBSD: roff.h,v 1.54 2020/02/27 21:38:27 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2013-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org> @@ -522,6 +522,8 @@ struct roff_node { #define NODE_NOFILL (1 << 8) /* Fill mode switched off. */ #define NODE_NOSRC (1 << 9) /* Generated node, not in input file. */ #define NODE_NOPRT (1 << 10) /* Shall not print anything. */ +#define NODE_ID (1 << 11) /* Target for deep linking. */ +#define NODE_HREF (1 << 12) /* Link to another place in this page. */ int prev_font; /* Before entering this node. */ int aux; /* Decoded node data, type-dependent. */ enum roff_tok tok; /* Request or macro ID. */ diff --git a/usr.bin/mandoc/tree.c b/usr.bin/mandoc/tree.c index 17ea0f60c91..cc123ccf308 100644 --- a/usr.bin/mandoc/tree.c +++ b/usr.bin/mandoc/tree.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tree.c,v 1.52 2020/01/11 16:02:48 schwarze Exp $ */ +/* $OpenBSD: tree.c,v 1.53 2020/02/27 21:38:27 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2013-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org> @@ -197,6 +197,13 @@ print_mdoc(const struct roff_node *n, int indent) putchar(')'); if (n->flags & NODE_EOS) putchar('.'); + if (n->flags & NODE_ID) { + printf(" ID"); + if (n->string != NULL) + printf("=%s", n->string); + } + if (n->flags & NODE_HREF) + printf(" HREF"); if (n->flags & NODE_BROKEN) printf(" BROKEN"); if (n->flags & NODE_NOFILL) |