diff options
-rw-r--r-- | mdoc_term.c | 14 | ||||
-rw-r--r-- | mdoc_validate.c | 49 | ||||
-rw-r--r-- | regress/mdoc/Sh/Makefile | 6 | ||||
-rw-r--r-- | regress/mdoc/Sh/tag.in | 21 | ||||
-rw-r--r-- | regress/mdoc/Sh/tag.out_ascii | 22 | ||||
-rw-r--r-- | regress/mdoc/Sh/tag.out_html | 9 | ||||
-rw-r--r-- | regress/mdoc/Sh/tag.out_markdown | 27 | ||||
-rw-r--r-- | roff.c | 2 | ||||
-rw-r--r-- | roff.h | 2 | ||||
-rw-r--r-- | tree.c | 7 |
10 files changed, 141 insertions, 18 deletions
diff --git a/mdoc_term.c b/mdoc_term.c index 776f1130..35e05809 100644 --- a/mdoc_term.c +++ b/mdoc_term.c @@ -117,7 +117,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); @@ -244,7 +243,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; @@ -341,6 +340,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. @@ -2066,13 +2069,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/mdoc_validate.c b/mdoc_validate.c index 6ab715d3..c8e261f9 100644 --- a/mdoc_validate.c +++ b/mdoc_validate.c @@ -1094,21 +1094,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; } @@ -1116,14 +1127,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/regress/mdoc/Sh/Makefile b/regress/mdoc/Sh/Makefile index 213664ec..4b37bb2a 100644 --- a/regress/mdoc/Sh/Makefile +++ b/regress/mdoc/Sh/Makefile @@ -1,11 +1,11 @@ -# $OpenBSD: Makefile,v 1.12 2020/02/27 01:25:58 schwarze Exp $ +# $OpenBSD: Makefile,v 1.13 2020/02/27 21:38:27 schwarze Exp $ REGRESS_TARGETS = badNAME before empty emptyNAME first nohead order REGRESS_TARGETS += orderNAME paragraph parbefore parborder punctNAME -REGRESS_TARGETS += subbefore transp +REGRESS_TARGETS += subbefore tag transp LINT_TARGETS = badNAME before empty emptyNAME first nohead order LINT_TARGETS += orderNAME parbefore parborder punctNAME subbefore -HTML_TARGETS = paragraph +HTML_TARGETS = paragraph tag # groff-1.22.3 defects: # - .Pp before .Sh NAME causes a blank line before the header line diff --git a/regress/mdoc/Sh/tag.in b/regress/mdoc/Sh/tag.in new file mode 100644 index 00000000..c204fc6b --- /dev/null +++ b/regress/mdoc/Sh/tag.in @@ -0,0 +1,21 @@ +.\" $OpenBSD: tag.in,v 1.1 2020/02/27 21:38:27 schwarze Exp $ +.Dd $Mdocdate$ +.Dt SH-TAG 1 +.Os +.Sh NAME +.Nm Sh-tag +.Nd tagging section headers +.Sh DESCRIPTION +Text in the description. +.Ss Subsection +BEGINTEST +.Pp +Text in the subsection. +.Tg examples +.Sh EXAMPLES +Text introducing examples. +.Tg example +.Ss Subsection +Example text. +.Pp +ENDTEST diff --git a/regress/mdoc/Sh/tag.out_ascii b/regress/mdoc/Sh/tag.out_ascii new file mode 100644 index 00000000..df0ab050 --- /dev/null +++ b/regress/mdoc/Sh/tag.out_ascii @@ -0,0 +1,22 @@ +SH-TAG(1) General Commands Manual SH-TAG(1) + +NNAAMMEE + SShh--ttaagg - tagging section headers + +DDEESSCCRRIIPPTTIIOONN + Text in the description. + + SSuubbsseeccttiioonn + BEGINTEST + + Text in the subsection. + +EEXXAAMMPPLLEESS + Text introducing examples. + + SSuubbsseeccttiioonn + Example text. + + ENDTEST + +OpenBSD February 27, 2020 OpenBSD diff --git a/regress/mdoc/Sh/tag.out_html b/regress/mdoc/Sh/tag.out_html new file mode 100644 index 00000000..9722aa8c --- /dev/null +++ b/regress/mdoc/Sh/tag.out_html @@ -0,0 +1,9 @@ +<p class="Pp">Text in the subsection.</p> +</section> +</section> +<section class="Sh"> +<h1 class="Sh" id="examples"><a class="permalink" href="#examples">EXAMPLES</a></h1> +<p class="Pp">Text introducing examples.</p> +<section class="Ss"> +<h2 class="Ss" id="example"><a class="permalink" href="#example">Subsection</a></h2> +<p class="Pp">Example text.</p> diff --git a/regress/mdoc/Sh/tag.out_markdown b/regress/mdoc/Sh/tag.out_markdown new file mode 100644 index 00000000..2813f8f0 --- /dev/null +++ b/regress/mdoc/Sh/tag.out_markdown @@ -0,0 +1,27 @@ +SH-TAG(1) - General Commands Manual + +# NAME + +**Sh-tag** - tagging section headers + +# DESCRIPTION + +Text in the description. + +## Subsection + +BEGINTEST + +Text in the subsection. + +# EXAMPLES + +Text introducing examples. + +## Subsection + +Example text. + +ENDTEST + +OpenBSD - February 27, 2020 @@ -1173,7 +1173,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; @@ -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. */ @@ -199,6 +199,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) |