From ffcddd3ed6e06cc3307b16f844664d242efa178f Mon Sep 17 00:00:00 2001 From: Kristaps Dzonsons Date: Wed, 10 Aug 2011 14:07:23 +0000 Subject: Allow `Sx' and `Ss' to have child nodes. Fixes manuals in NetBSD. Originally pointed out by joerg@ then again by Thomas Klausner by way of Nicolas Joy. Note: don't use these constructions as you can't link to the sections with `Sx'. --- mdoc.7 | 16 ++++++++---- mdoc_html.c | 32 +++++++++++++++--------- mdoc_macro.c | 4 +-- mdoc_validate.c | 75 +++++++++++++++++++++++++++++++-------------------------- 4 files changed, 75 insertions(+), 52 deletions(-) diff --git a/mdoc.7 b/mdoc.7 index 5a672dba..4ad9333a 100644 --- a/mdoc.7 +++ b/mdoc.7 @@ -664,11 +664,11 @@ has multiple heads. .Pp .Bl -column -compact -offset indent "MacroX" "CallableX" "ParsedX" "closed by XXXXXXXXXXX" .It Em Macro Ta Em Callable Ta Em Parsed Ta Em Scope -.It Sx \&It Ta \&No Ta Yes Ta closed by Sx \&It , Sx \&El -.It Sx \&Nd Ta \&No Ta \&No Ta closed by Sx \&Sh -.It Sx \&Nm Ta \&No Ta Yes Ta closed by Sx \&Nm , Sx \&Sh , Sx \&Ss -.It Sx \&Sh Ta \&No Ta \&No Ta closed by Sx \&Sh -.It Sx \&Ss Ta \&No Ta \&No Ta closed by Sx \&Sh , Sx \&Ss +.It Sx \&It Ta \&No Ta Yes Ta closed by Sx \&It , Sx \&El +.It Sx \&Nd Ta \&No Ta \&No Ta closed by Sx \&Sh +.It Sx \&Nm Ta \&No Ta Yes Ta closed by Sx \&Nm , Sx \&Sh , Sx \&Ss +.It Sx \&Sh Ta \&No Ta Yes Ta closed by Sx \&Sh +.It Sx \&Ss Ta \&No Ta Yes Ta closed by Sx \&Sh , Sx \&Ss .El .Pp Note that the @@ -2613,6 +2613,9 @@ custom sections be used. .Pp Section names should be unique so that they may be keyed by .Sx \&Sx . +Although this macro is parsed, it should not consist of child node or it +may not be linked with +.Sx \&Sx . .Pp See also .Sx \&Pp , @@ -2656,6 +2659,9 @@ rarely have sub-sections. .Pp Sub-section names should be unique so that they may be keyed by .Sx \&Sx . +Although this macro is parsed, it should not consist of child node or it +may not be linked with +.Sx \&Sx . .Pp See also .Sx \&Pp , diff --git a/mdoc_html.c b/mdoc_html.c index 0317a6ad..85322c73 100644 --- a/mdoc_html.c +++ b/mdoc_html.c @@ -608,18 +608,22 @@ mdoc_sh_pre(MDOC_ARGS) bufinit(h); bufcat(h, "x"); - for (n = n->child; n; n = n->next) { + + for (n = n->child; n && MDOC_TEXT == n->type; ) { bufcat_id(h, n->string); - if (n->next) + if (NULL != (n = n->next)) bufcat_id(h, " "); } - PAIR_ID_INIT(&tag, h->buf); - print_otag(h, TAG_H1, 1, &tag); + if (NULL == n) { + PAIR_ID_INIT(&tag, h->buf); + print_otag(h, TAG_H1, 1, &tag); + } else + print_otag(h, TAG_H1, 0, NULL); + return(1); } - /* ARGSUSED */ static int mdoc_ss_pre(MDOC_ARGS) @@ -635,14 +639,19 @@ mdoc_ss_pre(MDOC_ARGS) bufinit(h); bufcat(h, "x"); - for (n = n->child; n; n = n->next) { + + for (n = n->child; n && MDOC_TEXT == n->type; ) { bufcat_id(h, n->string); - if (n->next) + if (NULL != (n = n->next)) bufcat_id(h, " "); } - PAIR_ID_INIT(&tag, h->buf); - print_otag(h, TAG_H2, 1, &tag); + if (NULL == n) { + PAIR_ID_INIT(&tag, h->buf); + print_otag(h, TAG_H2, 1, &tag); + } else + print_otag(h, TAG_H2, 0, NULL); + return(1); } @@ -1171,9 +1180,10 @@ mdoc_sx_pre(MDOC_ARGS) bufinit(h); bufcat(h, "#x"); - for (n = n->child; n; n = n->next) { + + for (n = n->child; n; ) { bufcat_id(h, n->string); - if (n->next) + if (NULL != (n = n->next)) bufcat_id(h, " "); } diff --git a/mdoc_macro.c b/mdoc_macro.c index d334fea6..84402bcf 100644 --- a/mdoc_macro.c +++ b/mdoc_macro.c @@ -74,8 +74,8 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { in_line_eoln, MDOC_PROLOGUE }, /* Dd */ { in_line_eoln, MDOC_PROLOGUE }, /* Dt */ { in_line_eoln, MDOC_PROLOGUE }, /* Os */ - { blk_full, 0 }, /* Sh */ - { blk_full, 0 }, /* Ss */ + { blk_full, MDOC_PARSED }, /* Sh */ + { blk_full, MDOC_PARSED }, /* Ss */ { in_line_eoln, 0 }, /* Pp */ { blk_part_imp, MDOC_PARSED }, /* D1 */ { blk_part_imp, MDOC_PARSED }, /* Dl */ diff --git a/mdoc_validate.c b/mdoc_validate.c index 77ad71b9..e93c851a 100644 --- a/mdoc_validate.c +++ b/mdoc_validate.c @@ -72,9 +72,7 @@ static void check_text(struct mdoc *, int, int, char *); static void check_argv(struct mdoc *, struct mdoc_node *, struct mdoc_argv *); static void check_args(struct mdoc *, struct mdoc_node *); - -static int concat(struct mdoc *, char *, - const struct mdoc_node *, size_t); +static int concat(char *, const struct mdoc_node *, size_t); static enum mdoc_sec a2sec(const char *); static size_t macro2len(enum mdoct); @@ -1107,6 +1105,7 @@ static int post_nm(POST_ARGS) { char buf[BUFSIZ]; + int c; /* If no child specified, make sure we have the meta name. */ @@ -1118,11 +1117,14 @@ post_nm(POST_ARGS) /* If no meta name, set it from the child. */ - if ( ! concat(mdoc, buf, mdoc->last->child, BUFSIZ)) + buf[0] = '\0'; + if (-1 == (c = concat(buf, mdoc->last->child, BUFSIZ))) { + mdoc_nmsg(mdoc, mdoc->last->child, MANDOCERR_MEM); return(0); + } + assert(c); mdoc->meta.name = mandoc_strdup(buf); - return(1); } @@ -1818,6 +1820,7 @@ post_sh_head(POST_ARGS) { char buf[BUFSIZ]; enum mdoc_sec sec; + int c; /* * Process a new section. Sections are either "named" or @@ -1826,10 +1829,13 @@ post_sh_head(POST_ARGS) * manual sections. */ - if ( ! concat(mdoc, buf, mdoc->last->child, BUFSIZ)) + sec = SEC_CUSTOM; + buf[0] = '\0'; + if (-1 == (c = concat(buf, mdoc->last->child, BUFSIZ))) { + mdoc_nmsg(mdoc, mdoc->last->child, MANDOCERR_MEM); return(0); - - sec = a2sec(buf); + } else if (1 == c) + sec = a2sec(buf); /* The NAME should be first. */ @@ -1978,6 +1984,7 @@ post_dd(POST_ARGS) { char buf[DATESIZE]; struct mdoc_node *n; + int c; if (mdoc->meta.date) free(mdoc->meta.date); @@ -1989,9 +1996,13 @@ post_dd(POST_ARGS) return(1); } - if ( ! concat(mdoc, buf, n->child, DATESIZE)) + buf[0] = '\0'; + if (-1 == (c = concat(buf, n->child, DATESIZE))) { + mdoc_nmsg(mdoc, n->child, MANDOCERR_MEM); return(0); + } + assert(c); mdoc->meta.date = mandoc_normdate (mdoc->parse, buf, n->line, n->pos); @@ -2146,6 +2157,7 @@ post_os(POST_ARGS) { struct mdoc_node *n; char buf[BUFSIZ]; + int c; #ifndef OSNAME struct utsname utsname; #endif @@ -2162,8 +2174,13 @@ post_os(POST_ARGS) if (mdoc->meta.os) free(mdoc->meta.os); - if ( ! concat(mdoc, buf, n->child, BUFSIZ)) + buf[0] = '\0'; + if (-1 == (c = concat(buf, n->child, BUFSIZ))) { + mdoc_nmsg(mdoc, n->child, MANDOCERR_MEM); return(0); + } + + assert(c); /* XXX: yes, these can all be dynamically-adjusted buffers, but * it's really not worth the extra hackery. @@ -2230,34 +2247,24 @@ post_std(POST_ARGS) return(1); } +/* + * Concatenate a node, stopping at the first non-text. + * Concatenation is separated by a single whitespace. + * Returns -1 on fatal (string overrun) error, 0 if child nodes were + * encountered, 1 otherwise. + */ static int -concat(struct mdoc *m, char *p, const struct mdoc_node *n, size_t sz) +concat(char *p, const struct mdoc_node *n, size_t sz) { - p[0] = '\0'; - - /* - * Concatenate sibling nodes together. All siblings must be of - * type MDOC_TEXT or an assertion is raised. Concatenation is - * separated by a single whitespace. Returns 0 on fatal (string - * overrun) error. - */ - - for ( ; n; n = n->next) { - assert(MDOC_TEXT == n->type); - - if (strlcat(p, n->string, sz) >= sz) { - mdoc_nmsg(m, n, MANDOCERR_MEM); - return(0); - } - - if (NULL == n->next) - continue; - - if (strlcat(p, " ", sz) >= sz) { - mdoc_nmsg(m, n, MANDOCERR_MEM); + for ( ; NULL != n; n = n->next) { + if (MDOC_TEXT != n->type) return(0); - } + if ('\0' != p[0] && strlcat(p, " ", sz) >= sz) + return(-1); + if (strlcat(p, n->string, sz) >= sz) + return(-1); + concat(p, n->child, sz); } return(1); -- cgit