=================================================================== RCS file: /cvs/mandoc/mdoc_validate.c,v retrieving revision 1.242 retrieving revision 1.257 diff -u -p -r1.242 -r1.257 --- mandoc/mdoc_validate.c 2014/08/02 00:02:42 1.242 +++ mandoc/mdoc_validate.c 2014/11/27 16:20:31 1.257 @@ -1,4 +1,4 @@ -/* $Id: mdoc_validate.c,v 1.242 2014/08/02 00:02:42 schwarze Exp $ */ +/* $Id: mdoc_validate.c,v 1.257 2014/11/27 16:20:31 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010-2014 Ingo Schwarze @@ -16,16 +16,13 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif +#include #ifndef OSNAME #include #endif -#include - #include #include #include @@ -70,10 +67,11 @@ 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 child_an(const struct mdoc_node *); static enum mdoc_sec a2sec(const char *); static size_t macro2len(enum mdoct); +static void rewrite_macro2len(char **); -static int ebool(POST_ARGS); static int berr_ge1(POST_ARGS); static int bwarn_ge1(POST_ARGS); static int ewarn_eq0(POST_ARGS); @@ -90,7 +88,6 @@ static int post_bf(POST_ARGS); static int post_bk(POST_ARGS); static int post_bl(POST_ARGS); static int post_bl_block(POST_ARGS); -static int post_bl_block_width(POST_ARGS); static int post_bl_block_tag(POST_ARGS); static int post_bl_head(POST_ARGS); static int post_bx(POST_ARGS); @@ -102,6 +99,9 @@ static int post_en(POST_ARGS); static int post_es(POST_ARGS); static int post_eoln(POST_ARGS); static int post_ex(POST_ARGS); +static int post_fa(POST_ARGS); +static int post_fn(POST_ARGS); +static int post_fname(POST_ARGS); static int post_fo(POST_ARGS); static int post_hyph(POST_ARGS); static int post_hyphtext(POST_ARGS); @@ -114,12 +114,14 @@ static int post_nm(POST_ARGS); static int post_ns(POST_ARGS); static int post_os(POST_ARGS); static int post_par(POST_ARGS); -static int post_prol(POST_ARGS); static int post_root(POST_ARGS); static int post_rs(POST_ARGS); static int post_sh(POST_ARGS); -static int post_sh_body(POST_ARGS); static int post_sh_head(POST_ARGS); +static int post_sh_name(POST_ARGS); +static int post_sh_see_also(POST_ARGS); +static int post_sh_authors(POST_ARGS); +static int post_sm(POST_ARGS); static int post_st(POST_ARGS); static int post_vt(POST_ARGS); static int pre_an(PRE_ARGS); @@ -158,10 +160,10 @@ static const struct valids mdoc_valids[MDOC_MAX] = { { NULL, NULL }, /* Er */ { NULL, NULL }, /* Ev */ { pre_std, post_ex }, /* Ex */ - { NULL, NULL }, /* Fa */ + { NULL, post_fa }, /* Fa */ { NULL, ewarn_ge1 }, /* Fd */ { NULL, NULL }, /* Fl */ - { NULL, NULL }, /* Fn */ + { NULL, post_fn }, /* Fn */ { NULL, NULL }, /* Ft */ { NULL, NULL }, /* Ic */ { NULL, ewarn_eq1 }, /* In */ @@ -197,7 +199,7 @@ static const struct valids mdoc_valids[MDOC_MAX] = { { NULL, NULL }, /* Bq */ { NULL, NULL }, /* Bsx */ { NULL, post_bx }, /* Bx */ - { NULL, ebool }, /* Db */ + { pre_obsolete, NULL }, /* Db */ { NULL, NULL }, /* Dc */ { NULL, NULL }, /* Do */ { NULL, NULL }, /* Dq */ @@ -207,7 +209,7 @@ static const struct valids mdoc_valids[MDOC_MAX] = { { NULL, NULL }, /* Eo */ { NULL, NULL }, /* Fx */ { NULL, NULL }, /* Ms */ - { NULL, ewarn_eq0 }, /* No */ + { NULL, NULL }, /* No */ { NULL, post_ns }, /* Ns */ { NULL, NULL }, /* Nx */ { NULL, NULL }, /* Ox */ @@ -224,7 +226,7 @@ static const struct valids mdoc_valids[MDOC_MAX] = { { NULL, NULL }, /* Sc */ { NULL, NULL }, /* So */ { NULL, NULL }, /* Sq */ - { NULL, ebool }, /* Sm */ + { NULL, post_sm }, /* Sm */ { NULL, post_hyph }, /* Sx */ { NULL, NULL }, /* Sy */ { NULL, NULL }, /* Tn */ @@ -351,6 +353,20 @@ mdoc_valid_post(struct mdoc *mdoc) case MDOC_ROOT: return(post_root(mdoc)); default: + + /* + * Closing delimiters are not special at the + * beginning of a block, opening delimiters + * are not special at the end. + */ + + if (n->child != NULL) + n->child->flags &= ~MDOC_DELIMC; + if (n->last != NULL) + n->last->flags &= ~MDOC_DELIMO; + + /* Call the macro's postprocessor. */ + p = mdoc_valids[n->tok].post; return(*p ? (*p)(mdoc) : 1); } @@ -533,7 +549,7 @@ pre_bl(PRE_ARGS) * ones. If we find no list type, we default to LIST_item. */ - wa = n->args->argv; + wa = (n->args == NULL) ? NULL : n->args->argv; mdoclt = MDOC_ARG_MAX; for (i = 0; n->args && i < (int)n->args->argc; i++) { argv = n->args->argv + i; @@ -595,6 +611,7 @@ pre_bl(PRE_ARGS) mdoc->parse, argv->line, argv->pos, "Bl -width %s", argv->value[0]); + rewrite_macro2len(argv->value); n->norm->Bl.width = argv->value[0]; break; case MDOC_Offset: @@ -609,6 +626,7 @@ pre_bl(PRE_ARGS) mdoc->parse, argv->line, argv->pos, "Bl -offset %s", argv->value[0]); + rewrite_macro2len(argv->value); n->norm->Bl.offs = argv->value[0]; break; default: @@ -756,6 +774,7 @@ pre_bd(PRE_ARGS) mdoc->parse, argv->line, argv->pos, "Bd -offset %s", argv->value[0]); + rewrite_macro2len(argv->value); n->norm->Bd.offs = argv->value[0]; break; case MDOC_Compact: @@ -843,14 +862,12 @@ static int pre_dt(PRE_ARGS) { - if (NULL == mdoc->meta.date || mdoc->meta.os) - mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, - n->line, n->pos, "Dt"); - - if (mdoc->meta.title) + if (mdoc->meta.title != NULL) mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse, n->line, n->pos, "Dt"); - + else if (mdoc->meta.os != NULL) + mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, + n->line, n->pos, "Dt after Os"); return(1); } @@ -858,14 +875,12 @@ static int pre_os(PRE_ARGS) { - if (NULL == mdoc->meta.title || NULL == mdoc->meta.date) - mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, - n->line, n->pos, "Os"); - - if (mdoc->meta.os) + if (mdoc->meta.os != NULL) mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse, n->line, n->pos, "Os"); - + else if (mdoc->flags & MDOC_PBODY) + mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse, + n->line, n->pos, "Os"); return(1); } @@ -873,14 +888,18 @@ static int pre_dd(PRE_ARGS) { - if (mdoc->meta.title || mdoc->meta.os) - mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, - n->line, n->pos, "Dd"); - - if (mdoc->meta.date) + if (mdoc->meta.date != NULL) mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse, n->line, n->pos, "Dd"); - + else if (mdoc->flags & MDOC_PBODY) + mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse, + n->line, n->pos, "Dd"); + else if (mdoc->meta.title != NULL) + mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, + n->line, n->pos, "Dd after Dt"); + else if (mdoc->meta.os != NULL) + mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, + n->line, n->pos, "Dd after Os"); return(1); } @@ -1000,15 +1019,64 @@ post_eoln(POST_ARGS) } static int +post_fname(POST_ARGS) +{ + const struct mdoc_node *n; + const char *cp; + size_t pos; + + n = mdoc->last->child; + pos = strcspn(n->string, "()"); + cp = n->string + pos; + if ( ! (cp[0] == '\0' || (cp[0] == '(' && cp[1] == '*'))) + mandoc_msg(MANDOCERR_FN_PAREN, mdoc->parse, + n->line, n->pos + pos, n->string); + return(1); +} + +static int +post_fn(POST_ARGS) +{ + + post_fname(mdoc); + post_fa(mdoc); + return(1); +} + +static int post_fo(POST_ARGS) { hwarn_eq1(mdoc); bwarn_ge1(mdoc); + if (mdoc->last->type == MDOC_HEAD && mdoc->last->nchild) + post_fname(mdoc); return(1); } static int +post_fa(POST_ARGS) +{ + const struct mdoc_node *n; + const char *cp; + + for (n = mdoc->last->child; n != NULL; n = n->next) { + for (cp = n->string; *cp != '\0'; cp++) { + /* Ignore callbacks and alterations. */ + if (*cp == '(' || *cp == '{') + break; + if (*cp != ',') + continue; + mandoc_msg(MANDOCERR_FA_COMMA, mdoc->parse, + n->line, n->pos + (cp - n->string), + n->string); + break; + } + } + return(1); +} + +static int post_vt(POST_ARGS) { const struct mdoc_node *n; @@ -1108,10 +1176,6 @@ post_defaults(POST_ARGS) if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "...")) return(0); break; - case MDOC_Li: - if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "")) - return(0); - break; case MDOC_Pa: /* FALLTHROUGH */ case MDOC_Mt: @@ -1285,10 +1349,6 @@ post_bl_block(POST_ARGS) if ( ! post_bl_block_tag(mdoc)) return(0); assert(n->norm->Bl.width); - } else if (NULL != n->norm->Bl.width) { - if ( ! post_bl_block_width(mdoc)) - return(0); - assert(n->norm->Bl.width); } for (ni = n->body->child; ni; ni = ni->next) { @@ -1328,50 +1388,27 @@ post_bl_block(POST_ARGS) return(1); } -static int -post_bl_block_width(POST_ARGS) +/* + * If the argument of -offset or -width is a macro, + * replace it with the associated default width. + */ +void +rewrite_macro2len(char **arg) { size_t width; - int i; enum mdoct tok; - struct mdoc_node *n; - char buf[24]; - n = mdoc->last; - - /* - * Calculate the real width of a list from the -width string, - * which may contain a macro (with a known default width), a - * literal string, or a scaling width. - * - * If the value to -width is a macro, then we re-write it to be - * the macro's width as set in share/tmac/mdoc/doc-common. - */ - - if (0 == strcmp(n->norm->Bl.width, "Ds")) + if (*arg == NULL) + return; + else if ( ! strcmp(*arg, "Ds")) width = 6; - else if (MDOC_MAX == (tok = mdoc_hash_find(n->norm->Bl.width))) - return(1); + else if ((tok = mdoc_hash_find(*arg)) == MDOC_MAX) + return; else width = macro2len(tok); - /* The value already exists: free and reallocate it. */ - - assert(n->args); - - for (i = 0; i < (int)n->args->argc; i++) - if (MDOC_Width == n->args->argv[i].arg) - break; - - assert(i < (int)n->args->argc); - - (void)snprintf(buf, sizeof(buf), "%un", (unsigned int)width); - free(n->args->argv[i].value[0]); - n->args->argv[i].value[0] = mandoc_strdup(buf); - - /* Set our width! */ - n->norm->Bl.width = n->args->argv[i].value[0]; - return(1); + free(*arg); + mandoc_asprintf(arg, "%zun", width); } static int @@ -1386,7 +1423,7 @@ post_bl_block_tag(POST_ARGS) * Calculate the -width for a `Bl -tag' list if it hasn't been * provided. Uses the first head macro. NOTE AGAIN: this is * ONLY if the -width argument has NOT been provided. See - * post_bl_block_width() for converting the -width string. + * rewrite_macro2len() for converting the -width string. */ sz = 10; @@ -1585,38 +1622,31 @@ post_bk(POST_ARGS) } static int -ebool(struct mdoc *mdoc) +post_sm(struct mdoc *mdoc) { struct mdoc_node *nch; - enum mdoct tok; - tok = mdoc->last->tok; nch = mdoc->last->child; - if (NULL == nch) { - if (MDOC_Sm == tok) - mdoc->flags ^= MDOC_SMOFF; + if (nch == NULL) { + mdoc->flags ^= MDOC_SMOFF; return(1); } - check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_LT, 2); + assert(nch->type == MDOC_TEXT); - assert(MDOC_TEXT == nch->type); - - if (0 == strcmp(nch->string, "on")) { - if (MDOC_Sm == tok) - mdoc->flags &= ~MDOC_SMOFF; + if ( ! strcmp(nch->string, "on")) { + mdoc->flags &= ~MDOC_SMOFF; return(1); } - if (0 == strcmp(nch->string, "off")) { - if (MDOC_Sm == tok) - mdoc->flags |= MDOC_SMOFF; + if ( ! strcmp(nch->string, "off")) { + mdoc->flags |= MDOC_SMOFF; return(1); } mandoc_vmsg(MANDOCERR_SM_BAD, mdoc->parse, nch->line, nch->pos, - "%s %s", mdoc_macronames[tok], nch->string); + "%s %s", mdoc_macronames[mdoc->last->tok], nch->string); return(mdoc_node_relink(mdoc, nch)); } @@ -1627,34 +1657,37 @@ post_root(POST_ARGS) /* Add missing prologue data. */ - if ( ! (MDOC_PBODY & mdoc->flags)) { - mandoc_msg(MANDOCERR_PROLOG_BAD, mdoc->parse, 0, 0, "EOF"); - if (mdoc->meta.date == NULL) - mdoc->meta.date = mdoc->quick ? - mandoc_strdup("") : - mandoc_normdate(mdoc->parse, NULL, 0, 0); - if (mdoc->meta.title == NULL) - mdoc->meta.title = mandoc_strdup("UNKNOWN"); - if (mdoc->meta.vol == NULL) - mdoc->meta.vol = mandoc_strdup("LOCAL"); - if (mdoc->meta.arch == NULL) - mdoc->meta.msec = mandoc_strdup("1"); - if (mdoc->meta.os == NULL) - mdoc->meta.os = mandoc_strdup("UNKNOWN"); + if (mdoc->meta.date == NULL) + mdoc->meta.date = mdoc->quick ? + mandoc_strdup("") : + mandoc_normdate(mdoc->parse, NULL, 0, 0); + + if (mdoc->meta.title == NULL) { + mandoc_msg(MANDOCERR_DT_NOTITLE, + mdoc->parse, 0, 0, "EOF"); + mdoc->meta.title = mandoc_strdup("UNTITLED"); } - n = mdoc->first; - assert(n); + if (mdoc->meta.vol == NULL) + mdoc->meta.vol = mandoc_strdup("LOCAL"); + if (mdoc->meta.os == NULL) { + mandoc_msg(MANDOCERR_OS_MISSING, + mdoc->parse, 0, 0, NULL); + mdoc->meta.os = mandoc_strdup(""); + } + /* Check that we begin with a proper `Sh'. */ - if (NULL == n->child) - mandoc_msg(MANDOCERR_DOC_EMPTY, mdoc->parse, - n->line, n->pos, NULL); - else if (MDOC_Sh != n->child->tok) + n = mdoc->first->child; + while (n != NULL && mdoc_macros[n->tok].flags & MDOC_PROLOGUE) + n = n->next; + + if (n == NULL) + mandoc_msg(MANDOCERR_DOC_EMPTY, mdoc->parse, 0, 0, NULL); + else if (n->tok != MDOC_Sh) mandoc_msg(MANDOCERR_SEC_BEFORE, mdoc->parse, - n->child->line, n->child->pos, - mdoc_macronames[n->child->tok]); + n->line, n->pos, mdoc_macronames[n->tok]); return(1); } @@ -1848,22 +1881,33 @@ post_sh(POST_ARGS) post_ignpar(mdoc); - if (MDOC_HEAD == mdoc->last->type) + switch (mdoc->last->type) { + case MDOC_HEAD: return(post_sh_head(mdoc)); - if (MDOC_BODY == mdoc->last->type) - return(post_sh_body(mdoc)); + case MDOC_BODY: + switch (mdoc->lastsec) { + case SEC_NAME: + return(post_sh_name(mdoc)); + case SEC_SEE_ALSO: + return(post_sh_see_also(mdoc)); + case SEC_AUTHORS: + return(post_sh_authors(mdoc)); + default: + break; + } + break; + default: + break; + } return(1); } static int -post_sh_body(POST_ARGS) +post_sh_name(POST_ARGS) { struct mdoc_node *n; - if (SEC_NAME != mdoc->lastsec) - return(1); - /* * Warn if the NAME section doesn't contain the `Nm' and `Nd' * macros (can have multiple `Nm' and one `Nd'). Note that the @@ -1895,6 +1939,89 @@ post_sh_body(POST_ARGS) } static int +post_sh_see_also(POST_ARGS) +{ + const struct mdoc_node *n; + const char *name, *sec; + const char *lastname, *lastsec, *lastpunct; + int cmp; + + n = mdoc->last->child; + lastname = lastsec = lastpunct = NULL; + while (n != NULL) { + if (n->tok != MDOC_Xr || n->nchild < 2) + break; + + /* Process one .Xr node. */ + + name = n->child->string; + sec = n->child->next->string; + if (lastsec != NULL) { + if (lastpunct[0] != ',' || lastpunct[1] != '\0') + mandoc_vmsg(MANDOCERR_XR_PUNCT, + mdoc->parse, n->line, n->pos, + "%s before %s(%s)", lastpunct, + name, sec); + cmp = strcmp(lastsec, sec); + if (cmp > 0) + mandoc_vmsg(MANDOCERR_XR_ORDER, + mdoc->parse, n->line, n->pos, + "%s(%s) after %s(%s)", name, + sec, lastname, lastsec); + else if (cmp == 0 && + strcasecmp(lastname, name) > 0) + mandoc_vmsg(MANDOCERR_XR_ORDER, + mdoc->parse, n->line, n->pos, + "%s after %s", name, lastname); + } + lastname = name; + lastsec = sec; + + /* Process the following node. */ + + n = n->next; + if (n == NULL) + break; + if (n->tok == MDOC_Xr) { + lastpunct = "none"; + continue; + } + if (n->type != MDOC_TEXT) + break; + for (name = n->string; *name != '\0'; name++) + if (isalpha((const unsigned char)*name)) + return(1); + lastpunct = n->string; + if (n->next == NULL) + mandoc_vmsg(MANDOCERR_XR_PUNCT, mdoc->parse, + n->line, n->pos, "%s after %s(%s)", + lastpunct, lastname, lastsec); + n = n->next; + } + return(1); +} + +static int +child_an(const struct mdoc_node *n) +{ + + for (n = n->child; n != NULL; n = n->next) + if ((n->tok == MDOC_An && n->nchild) || child_an(n)) + return(1); + return(0); +} + +static int +post_sh_authors(POST_ARGS) +{ + + if ( ! child_an(mdoc->last)) + mandoc_msg(MANDOCERR_AN_MISSING, mdoc->parse, + mdoc->last->line, mdoc->last->pos, NULL); + return(1); +} + +static int post_sh_head(POST_ARGS) { struct mdoc_node *n; @@ -1977,7 +2104,10 @@ post_sh_head(POST_ARGS) /* Check particular section/manual conventions. */ - assert(mdoc->meta.msec); + if (mdoc->meta.msec == NULL) { + free(secname); + return(1); + } goodsec = NULL; switch (sec) { @@ -2156,7 +2286,7 @@ post_dd(POST_ARGS) if (NULL == n->child || '\0' == n->child->string[0]) { mdoc->meta.date = mdoc->quick ? mandoc_strdup("") : mandoc_normdate(mdoc->parse, NULL, n->line, n->pos); - return(post_prol(mdoc)); + goto out; } datestr = NULL; @@ -2168,7 +2298,9 @@ post_dd(POST_ARGS) datestr, n->line, n->pos); free(datestr); } - return(post_prol(mdoc)); +out: + mdoc_node_delete(mdoc, n); + return(1); } static int @@ -2180,14 +2312,15 @@ post_dt(POST_ARGS) n = mdoc->last; - if (mdoc->meta.title) - free(mdoc->meta.title); - if (mdoc->meta.vol) - free(mdoc->meta.vol); - if (mdoc->meta.arch) - free(mdoc->meta.arch); + free(mdoc->meta.title); + free(mdoc->meta.msec); + free(mdoc->meta.vol); + free(mdoc->meta.arch); - mdoc->meta.title = mdoc->meta.vol = mdoc->meta.arch = NULL; + mdoc->meta.title = NULL; + mdoc->meta.msec = NULL; + mdoc->meta.vol = NULL; + mdoc->meta.arch = NULL; /* First check that all characters are uppercase. */ @@ -2202,32 +2335,27 @@ post_dt(POST_ARGS) break; } - /* Handles: `.Dt' - * title = unknown, volume = local, msec = 0, arch = NULL - */ + /* No argument: msec and arch remain NULL. */ if (NULL == (nn = n->child)) { - /* XXX: make these macro values. */ - /* FIXME: warn about missing values. */ - mdoc->meta.title = mandoc_strdup("UNKNOWN"); + mandoc_msg(MANDOCERR_DT_NOTITLE, + mdoc->parse, n->line, n->pos, "Dt"); + mdoc->meta.title = mandoc_strdup("UNTITLED"); mdoc->meta.vol = mandoc_strdup("LOCAL"); - mdoc->meta.msec = mandoc_strdup("1"); - return(post_prol(mdoc)); + goto out; } - /* Handles: `.Dt TITLE' - * title = TITLE, volume = local, msec = 0, arch = NULL - */ + /* One argument: msec and arch remain NULL. */ mdoc->meta.title = mandoc_strdup( - '\0' == nn->string[0] ? "UNKNOWN" : nn->string); + '\0' == nn->string[0] ? "UNTITLED" : nn->string); if (NULL == (nn = nn->next)) { - /* FIXME: warn about missing msec. */ - /* XXX: make this a macro value. */ + mandoc_vmsg(MANDOCERR_MSEC_MISSING, + mdoc->parse, n->line, n->pos, + "Dt %s", mdoc->meta.title); mdoc->meta.vol = mandoc_strdup("LOCAL"); - mdoc->meta.msec = mandoc_strdup("1"); - return(post_prol(mdoc)); + goto out; } /* Handles: `.Dt TITLE SEC' @@ -2249,7 +2377,7 @@ post_dt(POST_ARGS) } if (NULL == (nn = nn->next)) - return(post_prol(mdoc)); + goto out; /* Handles: `.Dt TITLE SEC VOL' * title = TITLE, @@ -2275,23 +2403,8 @@ post_dt(POST_ARGS) /* Ignore any subsequent parameters... */ /* FIXME: warn about subsequent parameters. */ - - return(post_prol(mdoc)); -} - -static int -post_prol(POST_ARGS) -{ - /* - * Remove prologue macros from the document after they're - * processed. The final document uses mdoc_meta for these - * values and discards the originals. - */ - - mdoc_node_delete(mdoc, mdoc->last); - if (mdoc->meta.title && mdoc->meta.date && mdoc->meta.os) - mdoc->flags |= MDOC_PBODY; - +out: + mdoc_node_delete(mdoc, n); return(1); } @@ -2337,11 +2450,11 @@ post_os(POST_ARGS) mdoc->meta.os = NULL; mdoc_deroff(&mdoc->meta.os, n); if (mdoc->meta.os) - return(post_prol(mdoc)); + goto out; if (mdoc->defos) { mdoc->meta.os = mandoc_strdup(mdoc->defos); - return(post_prol(mdoc)); + goto out; } #ifdef OSNAME @@ -2358,7 +2471,10 @@ post_os(POST_ARGS) } mdoc->meta.os = mandoc_strdup(defbuf); #endif /*!OSNAME*/ - return(post_prol(mdoc)); + +out: + mdoc_node_delete(mdoc, n); + return(1); } /*