=================================================================== RCS file: /cvs/mandoc/mdoc_validate.c,v retrieving revision 1.268 retrieving revision 1.273 diff -u -p -r1.268 -r1.273 --- mandoc/mdoc_validate.c 2015/02/04 18:03:47 1.268 +++ mandoc/mdoc_validate.c 2015/02/06 02:04:54 1.273 @@ -1,4 +1,4 @@ -/* $Id: mdoc_validate.c,v 1.268 2015/02/04 18:03:47 schwarze Exp $ */ +/* $Id: mdoc_validate.c,v 1.273 2015/02/06 02:04:54 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010-2015 Ingo Schwarze @@ -70,7 +70,6 @@ static void rewrite_macro2len(char **); static void bwarn_ge1(POST_ARGS); static void ewarn_eq1(POST_ARGS); static void ewarn_ge1(POST_ARGS); -static void hwarn_eq0(POST_ARGS); static void post_an(POST_ARGS); static void post_at(POST_ARGS); @@ -157,7 +156,7 @@ static const struct valids mdoc_valids[MDOC_MAX] = { { NULL, post_fn }, /* Fn */ { NULL, NULL }, /* Ft */ { NULL, NULL }, /* Ic */ - { NULL, ewarn_eq1 }, /* In */ + { NULL, NULL }, /* In */ { NULL, post_defaults }, /* Li */ { NULL, post_nd }, /* Nd */ { NULL, post_nm }, /* Nm */ @@ -168,7 +167,7 @@ static const struct valids mdoc_valids[MDOC_MAX] = { { NULL, post_st }, /* St */ { NULL, NULL }, /* Va */ { NULL, post_vt }, /* Vt */ - { NULL, ewarn_ge1 }, /* Xr */ + { NULL, NULL }, /* Xr */ { NULL, ewarn_ge1 }, /* %A */ { NULL, post_hyphtext }, /* %B */ /* FIXME: can be used outside Rs/Re. */ { NULL, ewarn_ge1 }, /* %D */ @@ -421,12 +420,6 @@ ewarn_ge1(POST_ARGS) } static void -hwarn_eq0(POST_ARGS) -{ - check_count(mdoc, MDOC_HEAD, CHECK_EQ, 0); -} - -static void check_args(struct mdoc *mdoc, struct mdoc_node *n) { int i; @@ -1079,28 +1072,40 @@ post_nd(POST_ARGS) static void post_d1(POST_ARGS) { + struct mdoc_node *n; - bwarn_ge1(mdoc); + n = mdoc->last; + + if (n->type != MDOC_BODY) + return; + + if (n->child == NULL) + mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, + n->line, n->pos, "D1"); + post_hyph(mdoc); } static void post_literal(POST_ARGS) { + struct mdoc_node *n; - if (mdoc->last->tok == MDOC_Bd) - hwarn_eq0(mdoc); - bwarn_ge1(mdoc); + n = mdoc->last; - /* - * The `Dl' (note "el" not "one") and `Bd' macros unset the - * MDOC_LITERAL flag as they leave. Note that `Bd' only sets - * this in literal mode, but it doesn't hurt to just switch it - * off in general since displays can't be nested. - */ + if (n->type != MDOC_BODY) + return; - if (MDOC_BODY == mdoc->last->type) - mdoc->flags &= ~MDOC_LITERAL; + if (n->child == NULL) + mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, + n->line, n->pos, mdoc_macronames[n->tok]); + + if (n->tok == MDOC_Bd && + n->norm->Bd.type != DISP_literal && + n->norm->Bd.type != DISP_unfilled) + return; + + mdoc->flags &= ~MDOC_LITERAL; } static void @@ -1174,14 +1179,17 @@ post_at(POST_ARGS) static void post_an(POST_ARGS) { - struct mdoc_node *np; + struct mdoc_node *np, *nch; np = mdoc->last; - if (AUTH__NONE == np->norm->An.auth) { - if (0 == np->child) - check_count(mdoc, MDOC_ELEM, CHECK_GT, 0); - } else if (np->child) - check_count(mdoc, MDOC_ELEM, CHECK_EQ, 0); + nch = np->child; + if (np->norm->An.auth == AUTH__NONE) { + if (nch == NULL) + mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, + np->line, np->pos, "An"); + } else if (nch != NULL) + mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, + nch->line, nch->pos, "An ... %s", nch->string); } static void @@ -1414,13 +1422,21 @@ post_bl_block_tag(POST_ARGS) static void post_bl_head(POST_ARGS) { - struct mdoc_node *np, *nn, *nnp; + struct mdoc_node *nbl, *nh, *nch, *nnext; struct mdoc_argv *argv; int i, j; - if (LIST_column != mdoc->last->norm->Bl.type) { - /* FIXME: this should be ERROR class... */ - hwarn_eq0(mdoc); + nh = mdoc->last; + + if (nh->norm->Bl.type != LIST_column) { + if ((nch = nh->child) == NULL) + return; + mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, + nch->line, nch->pos, "Bl ... %s", nch->string); + while (nch != NULL) { + mdoc_node_delete(mdoc, nch); + nch = nh->child; + } return; } @@ -1430,17 +1446,15 @@ post_bl_head(POST_ARGS) * lists where they're argument values following -column. */ - if (mdoc->last->child == NULL) + if (nh->child == NULL) return; - np = mdoc->last->parent; - assert(np->args); - - for (j = 0; j < (int)np->args->argc; j++) - if (MDOC_Column == np->args->argv[j].arg) + nbl = nh->parent; + for (j = 0; j < (int)nbl->args->argc; j++) + if (nbl->args->argv[j].arg == MDOC_Column) break; - assert(j < (int)np->args->argc); + assert(j < (int)nbl->args->argc); /* * Accommodate for new-style groff column syntax. Shuffle the @@ -1448,25 +1462,23 @@ post_bl_head(POST_ARGS) * column field. Then, delete the head children. */ - argv = np->args->argv + j; + argv = nbl->args->argv + j; i = argv->sz; - argv->sz += mdoc->last->nchild; + argv->sz += nh->nchild; argv->value = mandoc_reallocarray(argv->value, argv->sz, sizeof(char *)); - mdoc->last->norm->Bl.ncols = argv->sz; - mdoc->last->norm->Bl.cols = (void *)argv->value; + nh->norm->Bl.ncols = argv->sz; + nh->norm->Bl.cols = (void *)argv->value; - for (nn = mdoc->last->child; nn; i++) { - argv->value[i] = nn->string; - nn->string = NULL; - nnp = nn; - nn = nn->next; - mdoc_node_delete(NULL, nnp); + for (nch = nh->child; nch != NULL; nch = nnext) { + argv->value[i++] = nch->string; + nch->string = NULL; + nnext = nch->next; + mdoc_node_delete(NULL, nch); } - - mdoc->last->nchild = 0; - mdoc->last->child = NULL; + nh->nchild = 0; + nh->child = NULL; } static void @@ -1490,10 +1502,13 @@ post_bl(POST_ARGS) return; } - bwarn_ge1(mdoc); - nchild = nbody->child; - while (NULL != nchild) { + if (nchild == NULL) { + mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, + nbody->line, nbody->pos, "Bl"); + return; + } + while (nchild != NULL) { if (nchild->tok == MDOC_It || (nchild->tok == MDOC_Sm && nchild->next != NULL && @@ -1552,9 +1567,15 @@ post_bl(POST_ARGS) static void post_bk(POST_ARGS) { + struct mdoc_node *n; - hwarn_eq0(mdoc); - bwarn_ge1(mdoc); + n = mdoc->last; + + if (n->type == MDOC_BLOCK && n->body->child == NULL) { + mandoc_msg(MANDOCERR_MACRO_EMPTY, + mdoc->parse, n->line, n->pos, "Bk"); + mdoc_node_delete(mdoc, n); + } } static void @@ -1636,13 +1657,6 @@ post_st(POST_ARGS) n = mdoc->last; nch = n->child; - if (NULL == nch) { - mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, - n->line, n->pos, mdoc_macronames[n->tok]); - mdoc_node_delete(mdoc, n); - return; - } - assert(MDOC_TEXT == nch->type); if (NULL == (p = mdoc_a2st(nch->string))) { @@ -1752,33 +1766,17 @@ post_rs(POST_ARGS) static void post_hyph(POST_ARGS) { - struct mdoc_node *n, *nch; + struct mdoc_node *nch; char *cp; - n = mdoc->last; - switch (n->type) { - case MDOC_HEAD: - if (MDOC_Sh == n->tok || MDOC_Ss == n->tok) - break; - return; - case MDOC_BODY: - if (MDOC_D1 == n->tok || MDOC_Nd == n->tok) - break; - return; - case MDOC_ELEM: - break; - default: - return; - } - - for (nch = n->child; nch; nch = nch->next) { - if (MDOC_TEXT != nch->type) + for (nch = mdoc->last->child; nch != NULL; nch = nch->next) { + if (nch->type != MDOC_TEXT) continue; cp = nch->string; - if ('\0' == *cp) + if (*cp == '\0') continue; - while ('\0' != *(++cp)) - if ('-' == *cp && + while (*(++cp) != '\0') + if (*cp == '-' && isalpha((unsigned char)cp[-1]) && isalpha((unsigned char)cp[1])) *cp = ASCII_HYPH; @@ -2072,11 +2070,15 @@ post_ignpar(POST_ARGS) { struct mdoc_node *np; - check_count(mdoc, MDOC_HEAD, CHECK_GT, 0); - post_hyph(mdoc); - - if (MDOC_BODY != mdoc->last->type) + switch (mdoc->last->type) { + case MDOC_HEAD: + post_hyph(mdoc); return; + case MDOC_BODY: + break; + default: + return; + } if (NULL != (np = mdoc->last->child)) if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) { @@ -2134,14 +2136,17 @@ post_par(POST_ARGS) { struct mdoc_node *np; - if (mdoc->last->tok == MDOC_sp) - check_count(mdoc, MDOC_ELEM, CHECK_LT, 2); - else - check_count(mdoc, MDOC_ELEM, CHECK_EQ, 0); + np = mdoc->last; - if (MDOC_ELEM != mdoc->last->type && - MDOC_BLOCK != mdoc->last->type) - return; + if (np->tok == MDOC_sp) { + if (np->nchild > 1) + mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, + np->child->next->line, np->child->next->pos, + "sp ... %s", np->child->next->string); + } else if (np->child != NULL) + mandoc_vmsg(MANDOCERR_ARG_SKIP, + mdoc->parse, np->line, np->pos, "%s %s", + mdoc_macronames[np->tok], np->child->string); if (NULL == (np = mdoc->last->prev)) { np = mdoc->last->parent;