=================================================================== RCS file: /cvs/mandoc/mdoc_validate.c,v retrieving revision 1.2 retrieving revision 1.9 diff -u -p -r1.2 -r1.9 --- mandoc/mdoc_validate.c 2009/03/31 13:50:19 1.2 +++ mandoc/mdoc_validate.c 2009/06/12 09:18:00 1.9 @@ -1,20 +1,18 @@ -/* $Id: mdoc_validate.c,v 1.2 2009/03/31 13:50:19 kristaps Exp $ */ +/* $Id: mdoc_validate.c,v 1.9 2009/06/12 09:18:00 kristaps Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons + * Copyright (c) 2008, 2009 Kristaps Dzonsons * * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include @@ -51,7 +49,11 @@ enum merr { }; enum mwarn { + WPRINT, + WNOWIDTH, + WMISSWIDTH, WESCAPE, + WDEPCOL, WWRONGMSEC, WSECOOO, WSECREP, @@ -95,6 +97,7 @@ static int warn_child_gt(struct mdoc *, const char *, static int err_child_eq(struct mdoc *, const char *, int); static int warn_child_eq(struct mdoc *, const char *, int); static int count_child(struct mdoc *); +static int warn_print(struct mdoc *, int, int); static int warn_count(struct mdoc *, const char *, int, const char *, int); static int err_count(struct mdoc *, const char *, @@ -297,7 +300,7 @@ const struct valids mdoc_valids[MDOC_MAX] = { { pres_lb, posts_lb }, /* Lb */ { NULL, NULL }, /* Ap */ { NULL, posts_pp }, /* Lp */ - { NULL, posts_text }, /* Lk */ + { NULL, NULL }, /* Lk */ { NULL, posts_text }, /* Mt */ { NULL, posts_wline }, /* Brq */ { NULL, NULL }, /* Bro */ @@ -311,7 +314,6 @@ const struct valids mdoc_valids[MDOC_MAX] = { #ifdef __linux__ -extern size_t strlcpy(char *, const char *, size_t); extern size_t strlcat(char *, const char *, size_t); #endif @@ -461,6 +463,19 @@ pwarn(struct mdoc *m, int line, int pos, enum mwarn ty p = "prologue macros out-of-order"; c = WARN_COMPAT; break; + case (WDEPCOL): + p = "deprecated column argument syntax"; + c = WARN_COMPAT; + break; + case (WNOWIDTH): + p = "superfluous width argument"; + break; + case (WMISSWIDTH): + p = "missing width argument"; + break; + case (WPRINT): + p = "invalid character"; + break; case (WESCAPE): p = "invalid escape sequence"; break; @@ -498,7 +513,15 @@ pwarn(struct mdoc *m, int line, int pos, enum mwarn ty } +static int +warn_print(struct mdoc *m, int ln, int pos) +{ + if (MDOC_IGN_CHARS & m->pflags) + return(pwarn(m, ln, pos, WPRINT)); + return(perr(m, ln, pos, EPRINT)); +} + static inline int warn_count(struct mdoc *m, const char *k, int want, const char *v, int has) @@ -700,9 +723,11 @@ check_text(struct mdoc *mdoc, int line, int pos, const for ( ; *p; p++) { if ('\t' == *p) { if ( ! (MDOC_LITERAL & mdoc->flags)) - return(perr(mdoc, line, pos, EPRINT)); + if ( ! warn_print(mdoc, line, pos)) + return(0); } else if ( ! isprint((u_char)*p)) - return(perr(mdoc, line, pos, EPRINT)); + if ( ! warn_print(mdoc, line, pos)) + return(0); if ('\\' != *p) continue; @@ -764,7 +789,7 @@ pre_display(PRE_ARGS) static int pre_bl(PRE_ARGS) { - int i, type, width, offset; + int pos, col, type, width, offset; if (MDOC_BLOCK != n->type) return(1); @@ -773,11 +798,11 @@ pre_bl(PRE_ARGS) /* Make sure that only one type of list is specified. */ - type = offset = width = -1; + type = offset = width = col = -1; /* LINTED */ - for (i = 0; i < (int)n->args->argc; i++) - switch (n->args->argv[i].arg) { + for (pos = 0; pos < (int)n->args->argc; pos++) + switch (n->args->argv[pos].arg) { case (MDOC_Bullet): /* FALLTHROUGH */ case (MDOC_Dash): @@ -799,23 +824,21 @@ pre_bl(PRE_ARGS) case (MDOC_Inset): /* FALLTHROUGH */ case (MDOC_Column): - if (-1 == type) { - type = n->args->argv[i].arg; - break; - } - return(nerr(mdoc, n, EMULTILIST)); + if (-1 != type) + return(nerr(mdoc, n, EMULTILIST)); + type = n->args->argv[pos].arg; + col = pos; + break; case (MDOC_Width): - if (-1 == width) { - width = n->args->argv[i].arg; - break; - } - return(nerr(mdoc, n, EARGREP)); + if (-1 != width) + return(nerr(mdoc, n, EARGREP)); + width = n->args->argv[pos].arg; + break; case (MDOC_Offset): - if (-1 == offset) { - offset = n->args->argv[i].arg; - break; - } - return(nerr(mdoc, n, EARGREP)); + if (-1 != offset) + return(nerr(mdoc, n, EARGREP)); + offset = n->args->argv[pos].arg; + break; default: break; } @@ -823,7 +846,17 @@ pre_bl(PRE_ARGS) if (-1 == type) return(nerr(mdoc, n, ELISTTYPE)); + /* + * Validate the width field. Some list types don't need width + * types and should be warned about them. Others should have it + * and must also be warned. + */ + switch (type) { + case (MDOC_Tag): + if (-1 == width && ! nwarn(mdoc, n, WMISSWIDTH)) + return(0); + break; case (MDOC_Column): /* FALLTHROUGH */ case (MDOC_Diag): @@ -831,17 +864,25 @@ pre_bl(PRE_ARGS) case (MDOC_Inset): /* FALLTHROUGH */ case (MDOC_Item): - if (-1 == width) + if (-1 != width && ! nwarn(mdoc, n, WNOWIDTH)) + return(0); + break; + default: + break; + } + + /* + * General validation of fields. + */ + + switch (type) { + case (MDOC_Column): + assert(col >= 0); + if (0 == n->args->argv[col].sz) break; - return(mdoc_nwarn(mdoc, n, WARN_SYNTAX, - "superfluous %s argument", - mdoc_argnames[MDOC_Width])); - case (MDOC_Tag): - if (-1 != width) - break; - return(mdoc_nwarn(mdoc, n, WARN_SYNTAX, - "suggest %s argument", - mdoc_argnames[MDOC_Width])); + if ( ! nwarn(mdoc, n, WDEPCOL)) + return(0); + break; default: break; } @@ -960,7 +1001,7 @@ static int pre_er(PRE_ARGS) { - return(check_msec(mdoc, n, 2, 0)); + return(check_msec(mdoc, n, 2, 3, 9, 0)); } @@ -1352,6 +1393,7 @@ post_sh_head(POST_ARGS) /* This is just concat() inlined, which is irritating. */ + buf[0] = 0; for (n = mdoc->last->child; n; n = n->next) { assert(MDOC_TEXT == n->type); if (strlcat(buf, n->string, 64) >= 64)