=================================================================== RCS file: /cvs/mandoc/mdoc_validate.c,v retrieving revision 1.162 retrieving revision 1.179 diff -u -p -r1.162 -r1.179 --- mandoc/mdoc_validate.c 2011/03/17 11:30:23 1.162 +++ mandoc/mdoc_validate.c 2011/11/19 13:29:47 1.179 @@ -1,4 +1,4 @@ -/* $Id: mdoc_validate.c,v 1.162 2011/03/17 11:30:23 kristaps Exp $ */ +/* $Id: mdoc_validate.c,v 1.179 2011/11/19 13:29:47 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010, 2011 Ingo Schwarze @@ -33,6 +33,7 @@ #include #include +#include "mdoc.h" #include "mandoc.h" #include "libmdoc.h" #include "libmandoc.h" @@ -71,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); @@ -154,9 +153,9 @@ static v_post posts_notext[] = { ewarn_eq0, NULL }; static v_post posts_ns[] = { post_ns, NULL }; static v_post posts_os[] = { post_os, post_prol, NULL }; static v_post posts_rs[] = { post_rs, NULL }; -static v_post posts_sh[] = { post_ignpar, hwarn_ge1, bwarn_ge1, post_sh, NULL }; +static v_post posts_sh[] = { post_ignpar, hwarn_ge1, post_sh, NULL }; static v_post posts_sp[] = { ewarn_le1, NULL }; -static v_post posts_ss[] = { post_ignpar, hwarn_ge1, bwarn_ge1, NULL }; +static v_post posts_ss[] = { post_ignpar, hwarn_ge1, NULL }; static v_post posts_st[] = { post_st, NULL }; static v_post posts_std[] = { post_std, NULL }; static v_post posts_text[] = { ewarn_ge1, NULL }; @@ -179,7 +178,7 @@ static v_pre pres_sh[] = { pre_sh, NULL }; static v_pre pres_ss[] = { pre_ss, NULL }; static v_pre pres_std[] = { pre_std, NULL }; -const struct valids mdoc_valids[MDOC_MAX] = { +static const struct valids mdoc_valids[MDOC_MAX] = { { NULL, NULL }, /* Ap */ { pres_dd, posts_dd }, /* Dd */ { pres_dt, posts_dt }, /* Dt */ @@ -446,7 +445,7 @@ check_count(struct mdoc *m, enum mdoc_type type, } t = lvl == CHECK_WARN ? MANDOCERR_ARGCWARN : MANDOCERR_ARGCOUNT; - mdoc_vmsg(m, t, m->last->line, m->last->pos, + mandoc_vmsg(t, m->parse, m->last->line, m->last->pos, "want %s%d children (have %d)", p, val, m->last->nchild); return(1); @@ -544,32 +543,13 @@ check_argv(struct mdoc *m, struct mdoc_node *n, struct static void check_text(struct mdoc *m, int ln, int pos, char *p) { - int c; - size_t sz; + char *cp; - for ( ; *p; p++, pos++) { - sz = strcspn(p, "\t\\"); - p += (int)sz; + if (MDOC_LITERAL & m->flags) + return; - if ('\0' == *p) - break; - - pos += (int)sz; - - if ('\t' == *p) { - if ( ! (MDOC_LITERAL & m->flags)) - mdoc_pmsg(m, ln, pos, MANDOCERR_BADTAB); - continue; - } - - if (0 == (c = mandoc_special(p))) { - mdoc_pmsg(m, ln, pos, MANDOCERR_BADESCAPE); - continue; - } - - p += c - 1; - pos += c - 1; - } + for (cp = p; NULL != (p = strchr(p, '\t')); p++) + mdoc_pmsg(m, ln, pos + (int)(p - cp), MANDOCERR_BADTAB); } static int @@ -581,10 +561,9 @@ check_parent(PRE_ARGS, enum mdoct tok, enum mdoc_type (t == n->parent->type)) return(1); - mdoc_vmsg(mdoc, MANDOCERR_SYNTCHILD, - n->line, n->pos, "want parent %s", - MDOC_ROOT == t ? "" : - mdoc_macronames[tok]); + mandoc_vmsg(MANDOCERR_SYNTCHILD, mdoc->parse, n->line, + n->pos, "want parent %s", MDOC_ROOT == t ? + "" : mdoc_macronames[tok]); return(0); } @@ -723,7 +702,7 @@ pre_bl(PRE_ARGS) if (LIST_column == lt) { n->norm->Bl.ncols = n->args->argv[i].sz; - n->norm->Bl.cols = (const char **) + n->norm->Bl.cols = (void *) n->args->argv[i].value; } } @@ -891,7 +870,7 @@ pre_sh(PRE_ARGS) if (MDOC_BLOCK != n->type) return(1); - mdoc->regs->regs[(int)REG_nS].set = 0; + roff_regunset(mdoc->roff, REG_nS); return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT)); } @@ -1125,6 +1104,7 @@ static int post_nm(POST_ARGS) { char buf[BUFSIZ]; + int c; /* If no child specified, make sure we have the meta name. */ @@ -1136,11 +1116,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); } @@ -1332,7 +1315,8 @@ post_it(POST_ARGS) else er = MANDOCERR_SYNTARGCOUNT; - mdoc_vmsg(mdoc, er, mdoc->last->line, mdoc->last->pos, + mandoc_vmsg(er, mdoc->parse, mdoc->last->line, + mdoc->last->pos, "columns == %d (have %d)", cols, i); return(MANDOCERR_ARGCOUNT == er); default: @@ -1410,7 +1394,7 @@ post_bl_block_width(POST_ARGS) assert(i < (int)n->args->argc); - snprintf(buf, NUMSIZ, "%zun", width); + snprintf(buf, NUMSIZ, "%un", (unsigned int)width); free(n->args->argv[i].value[0]); n->args->argv[i].value[0] = mandoc_strdup(buf); @@ -1460,7 +1444,7 @@ post_bl_block_tag(POST_ARGS) /* Defaults to ten ens. */ - snprintf(buf, NUMSIZ, "%zun", sz); + snprintf(buf, NUMSIZ, "%un", (unsigned int)sz); /* * We have to dynamically add this to the macro's argument list. @@ -1526,7 +1510,7 @@ post_bl_head(POST_ARGS) assert(0 == np->args->argv[j].sz); /* - * Accomodate for new-style groff column syntax. Shuffle the + * Accommodate for new-style groff column syntax. Shuffle the * child nodes, all of which must be TEXT, as arguments for the * column field. Then, delete the head children. */ @@ -1536,7 +1520,7 @@ post_bl_head(POST_ARGS) ((size_t)mdoc->last->nchild * sizeof(char *)); mdoc->last->norm->Bl.ncols = np->args->argv[j].sz; - mdoc->last->norm->Bl.cols = (const char **)np->args->argv[j].value; + mdoc->last->norm->Bl.cols = (void *)np->args->argv[j].value; for (i = 0, nn = mdoc->last->child; nn; i++) { np->args->argv[j].value[i] = nn->string; @@ -1710,6 +1694,14 @@ post_rs(POST_ARGS) } /* + * Nothing to sort if only invalid nodes were found + * inside the `Rs' body. + */ + + if (NULL == mdoc->last->child) + return(1); + + /* * The full `Rs' block needs special handling to order the * sub-elements according to `rsord'. Pick through each element * and correctly order it. This is a insertion sort. @@ -1835,6 +1827,7 @@ post_sh_head(POST_ARGS) { char buf[BUFSIZ]; enum mdoc_sec sec; + int c; /* * Process a new section. Sections are either "named" or @@ -1843,11 +1836,14 @@ 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); + } else if (1 == c) + sec = a2sec(buf); - sec = a2sec(buf); - /* The NAME should be first. */ if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed) @@ -1995,22 +1991,27 @@ post_dd(POST_ARGS) { char buf[DATESIZE]; struct mdoc_node *n; + int c; if (mdoc->meta.date) free(mdoc->meta.date); n = mdoc->last; if (NULL == n->child || '\0' == n->child->string[0]) { - mdoc->meta.date = mandoc_normdate(NULL, - mdoc->msg, mdoc->data, n->line, n->pos); + mdoc->meta.date = mandoc_normdate + (mdoc->parse, NULL, n->line, n->pos); 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); + } - mdoc->meta.date = mandoc_normdate(buf, - mdoc->msg, mdoc->data, n->line, n->pos); + assert(c); + mdoc->meta.date = mandoc_normdate + (mdoc->parse, buf, n->line, n->pos); return(1); } @@ -2037,7 +2038,7 @@ post_dt(POST_ARGS) if (NULL != (nn = n->child)) for (p = nn->string; *p; p++) { - if (toupper((u_char)*p) == *p) + if (toupper((unsigned char)*p) == *p) continue; /* @@ -2163,6 +2164,7 @@ post_os(POST_ARGS) { struct mdoc_node *n; char buf[BUFSIZ]; + int c; #ifndef OSNAME struct utsname utsname; #endif @@ -2179,9 +2181,14 @@ 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. */ @@ -2193,7 +2200,7 @@ post_os(POST_ARGS) return(0); } #else /*!OSNAME */ - if (uname(&utsname)) { + if (-1 == uname(&utsname)) { mdoc_nmsg(mdoc, n, MANDOCERR_UNAME); mdoc->meta.os = mandoc_strdup("UNKNOWN"); return(post_prol(mdoc)); @@ -2247,34 +2254,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); + for ( ; NULL != n; n = n->next) { + if (MDOC_TEXT != n->type) return(0); - } - - if (NULL == n->next) - continue; - - if (strlcat(p, " ", sz) >= sz) { - mdoc_nmsg(m, n, MANDOCERR_MEM); - 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);