From 750900b44b04f0713e1d2456b42c728b564c9c39 Mon Sep 17 00:00:00 2001 From: Kristaps Dzonsons Date: Wed, 21 Jan 2009 11:35:26 +0000 Subject: More validation on prologue/first NAME section. --- Makefile | 21 ++++++++++++-- action.c | 6 ++-- mdoc.c | 13 +++++---- private.h | 4 +-- regress/test.name.00 | 6 ++++ regress/test.name.01 | 6 ++++ regress/test.name.02 | 5 ++++ regress/test.name.03 | 7 +++++ regress/test.prologue.05 | 2 ++ regress/test.prologue.07 | 2 ++ regress/test.prologue.08 | 2 ++ regress/test.prologue.09 | 2 ++ regress/test.prologue.10 | 2 ++ regress/test.prologue.11 | 2 ++ regress/test.prologue.12 | 2 ++ regress/test.prologue.14 | 2 ++ regress/test.prologue.17 | 2 ++ regress/test.prologue.20 | 2 ++ regress/test.prologue.25 | 5 ++++ regress/test.prologue.26 | 5 ++++ regress/test.prologue.27 | 5 ++++ regress/test.prologue.28 | 3 ++ regress/test.prologue.29 | 3 ++ regress/test.prologue.30 | 1 + regress/test.prologue.31 | 5 ++++ regress/test.prologue.32 | 4 +++ regress/test.prologue.33 | 4 +++ regress/test.sh.00 | 6 ++++ regress/test.sh.01 | 4 +++ regress/test.sh.02 | 4 +++ regress/test.sh.03 | 5 ++++ validate.c | 71 ++++++++++++++++++++++++++++++++++++++---------- 32 files changed, 184 insertions(+), 29 deletions(-) create mode 100644 regress/test.name.00 create mode 100644 regress/test.name.01 create mode 100644 regress/test.name.02 create mode 100644 regress/test.name.03 create mode 100644 regress/test.prologue.25 create mode 100644 regress/test.prologue.26 create mode 100644 regress/test.prologue.27 create mode 100644 regress/test.prologue.28 create mode 100644 regress/test.prologue.29 create mode 100644 regress/test.prologue.30 create mode 100644 regress/test.prologue.31 create mode 100644 regress/test.prologue.32 create mode 100644 regress/test.prologue.33 create mode 100644 regress/test.sh.00 create mode 100644 regress/test.sh.01 create mode 100644 regress/test.sh.02 create mode 100644 regress/test.sh.03 diff --git a/Makefile b/Makefile index 0497c41f..71f4b41a 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,22 @@ FAIL = regress/test.empty \ regress/test.prologue.21 \ regress/test.prologue.22 \ regress/test.prologue.23 \ - regress/test.prologue.24 + regress/test.prologue.24 \ + regress/test.prologue.25 \ + regress/test.prologue.26 \ + regress/test.prologue.27 \ + regress/test.prologue.28 \ + regress/test.prologue.29 \ + regress/test.prologue.30 \ + regress/test.prologue.31 \ + regress/test.prologue.32 \ + regress/test.prologue.33 \ + regress/test.sh.01 \ + regress/test.sh.02 \ + regress/test.sh.03 \ + regress/test.name.01 \ + regress/test.name.02 \ + regress/test.name.03 SUCCEED = regress/test.prologue.05 \ regress/test.prologue.07 \ @@ -59,7 +74,9 @@ SUCCEED = regress/test.prologue.05 \ regress/test.prologue.12 \ regress/test.prologue.14 \ regress/test.prologue.17 \ - regress/test.prologue.20 + regress/test.prologue.20 \ + regress/test.sh.00 \ + regress/test.name.00 all: $(BINS) diff --git a/action.c b/action.c index d78803ea..e7ece6cd 100644 --- a/action.c +++ b/action.c @@ -193,8 +193,7 @@ post_sh(struct mdoc *mdoc) return(1); if (xstrlcats(buf, mdoc->last->child, 64)) { if (SEC_CUSTOM != (sec = mdoc_atosec(buf))) - mdoc->sec_lastn = sec; - mdoc->sec_last = sec; + mdoc->lastnamed = sec; return(1); } @@ -268,8 +267,7 @@ post_os(struct mdoc *mdoc) return(mdoc_err(mdoc, "macro parameters too long")); mdoc->meta.os = xstrdup(buf[0] ? buf : "local"); - mdoc->sec_lastn = mdoc->sec_last = SEC_BODY; - mdoc->flags |= MDOC_BODYPARSE; + mdoc->lastnamed = SEC_BODY; return(post_prologue(mdoc)); } diff --git a/mdoc.c b/mdoc.c index 31953ede..473f42b5 100644 --- a/mdoc.c +++ b/mdoc.c @@ -305,8 +305,8 @@ mdoc_parseln(struct mdoc *mdoc, int line, char *buf) mdoc->linetok = 0; if ('.' != *buf) { - if ( ! (MDOC_BODYPARSE & mdoc->flags)) - return(mdoc_perr(mdoc, line, 0, "text disallowed")); + if (SEC_PROLOGUE == mdoc->lastnamed) + return(mdoc_perr(mdoc, line, 0, "text disallowed in document prologue")); if ( ! mdoc_word_alloc(mdoc, line, 0, buf)) return(0); mdoc->next = MDOC_NEXT_SIBLING; @@ -407,9 +407,12 @@ mdoc_macro(struct mdoc *mdoc, int tok, assert(mdoc_macros[tok].fp); - if ( ! (MDOC_PROLOGUE & mdoc_macros[tok].flags) && - ! (MDOC_BODYPARSE & mdoc->flags)) - return(mdoc_perr(mdoc, ln, ppos, "macro disallowed: not in document body")); + if (MDOC_PROLOGUE & mdoc_macros[tok].flags && + SEC_PROLOGUE != mdoc->lastnamed) + return(mdoc_perr(mdoc, ln, ppos, "macro disallowed in document body")); + if ( ! (MDOC_PROLOGUE & mdoc_macros[tok].flags) && + SEC_PROLOGUE == mdoc->lastnamed) + return(mdoc_perr(mdoc, ln, ppos, "macro disallowed in document prologue")); if (1 != ppos && ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) return(mdoc_perr(mdoc, ln, ppos, "macro not callable")); return((*mdoc_macros[tok].fp)(mdoc, tok, ln, ppos, pos, buf)); diff --git a/private.h b/private.h index 1e80043f..498fb1d2 100644 --- a/private.h +++ b/private.h @@ -33,13 +33,11 @@ struct mdoc { int linetok; int flags; #define MDOC_HALT (1 << 0) -#define MDOC_BODYPARSE (1 << 1) enum mdoc_next next; struct mdoc_node *last; struct mdoc_node *first; struct mdoc_meta meta; - enum mdoc_sec sec_lastn; - enum mdoc_sec sec_last; + enum mdoc_sec lastnamed; }; diff --git a/regress/test.name.00 b/regress/test.name.00 new file mode 100644 index 00000000..2d8517bf --- /dev/null +++ b/regress/test.name.00 @@ -0,0 +1,6 @@ +.Dd $Mdocdate$ +.Dt +.Os +.Sh NAME +.Nm name +.Nd description diff --git a/regress/test.name.01 b/regress/test.name.01 new file mode 100644 index 00000000..216188f3 --- /dev/null +++ b/regress/test.name.01 @@ -0,0 +1,6 @@ +.Dd $Mdocdate$ +.Dt +.Os +.Sh NAME +.Nd description +.Nm name diff --git a/regress/test.name.02 b/regress/test.name.02 new file mode 100644 index 00000000..a22e6cff --- /dev/null +++ b/regress/test.name.02 @@ -0,0 +1,5 @@ +.Dd $Mdocdate$ +.Dt +.Os +.Sh NAME +.Nd description diff --git a/regress/test.name.03 b/regress/test.name.03 new file mode 100644 index 00000000..45e46ec9 --- /dev/null +++ b/regress/test.name.03 @@ -0,0 +1,7 @@ +.Dd $Mdocdate$ +.Dt +.Os +.Sh NAME +.Nm name +.Fl +.Nd description diff --git a/regress/test.prologue.05 b/regress/test.prologue.05 index d7fd5b66..b88771dc 100644 --- a/regress/test.prologue.05 +++ b/regress/test.prologue.05 @@ -2,3 +2,5 @@ .Dt .Os .Sh NAME +.Nm name +.Nd description diff --git a/regress/test.prologue.07 b/regress/test.prologue.07 index d326eaaa..2d8517bf 100644 --- a/regress/test.prologue.07 +++ b/regress/test.prologue.07 @@ -2,3 +2,5 @@ .Dt .Os .Sh NAME +.Nm name +.Nd description diff --git a/regress/test.prologue.08 b/regress/test.prologue.08 index e590b07c..b6fb3f2a 100644 --- a/regress/test.prologue.08 +++ b/regress/test.prologue.08 @@ -2,3 +2,5 @@ .Dt .Os .Sh NAME +.Nm name +.Nd description diff --git a/regress/test.prologue.09 b/regress/test.prologue.09 index d1e742fa..4feaa925 100644 --- a/regress/test.prologue.09 +++ b/regress/test.prologue.09 @@ -2,3 +2,5 @@ .Dt .Os .Sh NAME +.Nm name +.Nd description diff --git a/regress/test.prologue.10 b/regress/test.prologue.10 index d326eaaa..2d8517bf 100644 --- a/regress/test.prologue.10 +++ b/regress/test.prologue.10 @@ -2,3 +2,5 @@ .Dt .Os .Sh NAME +.Nm name +.Nd description diff --git a/regress/test.prologue.11 b/regress/test.prologue.11 index def6a5a1..22b57e43 100644 --- a/regress/test.prologue.11 +++ b/regress/test.prologue.11 @@ -2,3 +2,5 @@ .Dt test .Os .Sh NAME +.Nm name +.Nd description diff --git a/regress/test.prologue.12 b/regress/test.prologue.12 index 3a789b0d..af8602eb 100644 --- a/regress/test.prologue.12 +++ b/regress/test.prologue.12 @@ -2,3 +2,5 @@ .Dt test 1 .Os .Sh NAME +.Nm name +.Nd description diff --git a/regress/test.prologue.14 b/regress/test.prologue.14 index 4cdda822..f73384af 100644 --- a/regress/test.prologue.14 +++ b/regress/test.prologue.14 @@ -2,3 +2,5 @@ .Dt test 1 alpha .Os .Sh NAME +.Nm name +.Nd description diff --git a/regress/test.prologue.17 b/regress/test.prologue.17 index 6636c2bf..23c4e8c8 100644 --- a/regress/test.prologue.17 +++ b/regress/test.prologue.17 @@ -2,3 +2,5 @@ .Dt test 1 AMD .Os .Sh NAME +.Nm name +.Nd description diff --git a/regress/test.prologue.20 b/regress/test.prologue.20 index 640d4e32..47e91431 100644 --- a/regress/test.prologue.20 +++ b/regress/test.prologue.20 @@ -2,3 +2,5 @@ .Dt test\ 1 1 AMD .Os .Sh NAME +.Nm name +.Nd description diff --git a/regress/test.prologue.25 b/regress/test.prologue.25 new file mode 100644 index 00000000..2ab5a9df --- /dev/null +++ b/regress/test.prologue.25 @@ -0,0 +1,5 @@ +.Dd $Mdocdate$ +.Dd $Mdocdate$ +.Dt +.Os +.Sh NAME diff --git a/regress/test.prologue.26 b/regress/test.prologue.26 new file mode 100644 index 00000000..3775ba96 --- /dev/null +++ b/regress/test.prologue.26 @@ -0,0 +1,5 @@ +.Dd $Mdocdate$ +.Dt +.Dt +.Os +.Sh NAME diff --git a/regress/test.prologue.27 b/regress/test.prologue.27 new file mode 100644 index 00000000..a9755e36 --- /dev/null +++ b/regress/test.prologue.27 @@ -0,0 +1,5 @@ +.Dd $Mdocdate$ +.Dt +.Os +.Os +.Sh NAME diff --git a/regress/test.prologue.28 b/regress/test.prologue.28 new file mode 100644 index 00000000..c8614046 --- /dev/null +++ b/regress/test.prologue.28 @@ -0,0 +1,3 @@ +.Dd $Mdocdate$ +.Dt +.Sh NAME diff --git a/regress/test.prologue.29 b/regress/test.prologue.29 new file mode 100644 index 00000000..485b6fef --- /dev/null +++ b/regress/test.prologue.29 @@ -0,0 +1,3 @@ +.Dt +.Os +.Sh NAME diff --git a/regress/test.prologue.30 b/regress/test.prologue.30 new file mode 100644 index 00000000..6d73569f --- /dev/null +++ b/regress/test.prologue.30 @@ -0,0 +1 @@ +.Sh NAME diff --git a/regress/test.prologue.31 b/regress/test.prologue.31 new file mode 100644 index 00000000..8f430c33 --- /dev/null +++ b/regress/test.prologue.31 @@ -0,0 +1,5 @@ +.Dd $Mdocdate$ +.Dt +.Sh NAME +.Os +.Sh NAME diff --git a/regress/test.prologue.32 b/regress/test.prologue.32 new file mode 100644 index 00000000..2aec95a2 --- /dev/null +++ b/regress/test.prologue.32 @@ -0,0 +1,4 @@ +.Dd $Mdocdate$ +.Os +.Dt +.Sh NAME diff --git a/regress/test.prologue.33 b/regress/test.prologue.33 new file mode 100644 index 00000000..7622251f --- /dev/null +++ b/regress/test.prologue.33 @@ -0,0 +1,4 @@ +.Dt +.Dd $Mdocdate$ +.Os +.Sh NAME diff --git a/regress/test.sh.00 b/regress/test.sh.00 new file mode 100644 index 00000000..2d8517bf --- /dev/null +++ b/regress/test.sh.00 @@ -0,0 +1,6 @@ +.Dd $Mdocdate$ +.Dt +.Os +.Sh NAME +.Nm name +.Nd description diff --git a/regress/test.sh.01 b/regress/test.sh.01 new file mode 100644 index 00000000..3c88df81 --- /dev/null +++ b/regress/test.sh.01 @@ -0,0 +1,4 @@ +.Dd $Mdocdate$ +.Dt +.Os +.Sh "NAME" diff --git a/regress/test.sh.02 b/regress/test.sh.02 new file mode 100644 index 00000000..e27c7284 --- /dev/null +++ b/regress/test.sh.02 @@ -0,0 +1,4 @@ +.Dd $Mdocdate$ +.Dt +.Os +.Sh NAME \ diff --git a/regress/test.sh.03 b/regress/test.sh.03 new file mode 100644 index 00000000..be144b51 --- /dev/null +++ b/regress/test.sh.03 @@ -0,0 +1,5 @@ +.Dd $Mdocdate$ +.Dt +.Os +.Fl +.Sh NAME diff --git a/validate.c b/validate.c index 6ed8b6f8..8841b738 100644 --- a/validate.c +++ b/validate.c @@ -91,6 +91,8 @@ static int bwarn_ge1(struct mdoc *); static int ewarn_ge1(struct mdoc *); static int ebool(struct mdoc *); static int post_sh(struct mdoc *); +static int post_sh_body(struct mdoc *); +static int post_sh_head(struct mdoc *); static int post_bl(struct mdoc *); static int post_it(struct mdoc *); static int post_ex(struct mdoc *); @@ -717,7 +719,7 @@ static int pre_prologue(struct mdoc *mdoc, struct mdoc_node *node) { - if (SEC_PROLOGUE != mdoc->sec_lastn) + if (SEC_PROLOGUE != mdoc->lastnamed) return(mdoc_nerr(mdoc, node, "macro may only be invoked in the prologue")); assert(MDOC_ELEM == node->type); @@ -1060,39 +1062,78 @@ static int post_root(struct mdoc *mdoc) { - if (NULL == mdoc->last->child) + if (NULL == mdoc->first->child) return(mdoc_err(mdoc, "document has no data")); - if (NULL == mdoc->meta.title) - return(mdoc_err(mdoc, "document has incomplete prologue")); - if (NULL == mdoc->meta.os) - return(mdoc_err(mdoc, "document has incomplete prologue")); - if (0 == mdoc->meta.date) + if (SEC_PROLOGUE == mdoc->lastnamed) return(mdoc_err(mdoc, "document has incomplete prologue")); + if (MDOC_BLOCK != mdoc->first->child->type) + return(mdoc_err(mdoc, "document expects `%s' macro after prologue", mdoc_macronames[MDOC_Sh])); + if (MDOC_Sh != mdoc->first->child->tok) + return(mdoc_err(mdoc, "document expects `%s' macro after prologue", mdoc_macronames[MDOC_Sh])); return(1); } -/* Warn if conventional sections are out of order. */ static int post_sh(struct mdoc *mdoc) +{ + + if (MDOC_HEAD == mdoc->last->type) + return(post_sh_head(mdoc)); + if (MDOC_BODY == mdoc->last->type) + return(post_sh_body(mdoc)); + return(1); +} + + +static int +post_sh_body(struct mdoc *mdoc) +{ + struct mdoc_node *n; + + assert(MDOC_Sh == mdoc->last->tok); + if (SEC_NAME != mdoc->lastnamed) + return(1); + + if (NULL == (n = mdoc->last->child)) + return(mdoc_err(mdoc, "section NAME must contain %s as the first body child", mdoc_macronames[MDOC_Nm])); + if (MDOC_ELEM != n->type || MDOC_Nm != n->tok) + return(mdoc_err(mdoc, "section NAME must contain %s as the first body child", mdoc_macronames[MDOC_Nm])); + if (NULL == (n = n->next)) + return(mdoc_err(mdoc, "section NAME must contain %s as the second body child", mdoc_macronames[MDOC_Nd])); + if (MDOC_ELEM != n->type || MDOC_Nd != n->tok) + return(mdoc_err(mdoc, "section NAME must contain %s as the second body child", mdoc_macronames[MDOC_Nd])); + if (NULL == (n = n->next)) + return(1); + + return(mdoc_warn(mdoc, WARN_SYNTAX, "section NAME usually limited to %s and %s body children", + mdoc_macronames[MDOC_Nm], mdoc_macronames[MDOC_Nd])); +} + + +static int +post_sh_head(struct mdoc *mdoc) { char buf[64]; enum mdoc_sec sec; - if (MDOC_HEAD != mdoc->last->type) - return(1); assert(MDOC_Sh == mdoc->last->tok); if ( ! xstrlcats(buf, mdoc->last->child, 64)) return(mdoc_err(mdoc, "macro parameters too long")); - if (SEC_CUSTOM == (sec = mdoc_atosec(buf))) - return(1); - if (sec > mdoc->sec_lastn) + sec = mdoc_atosec(buf); + + if (SEC_BODY == mdoc->lastnamed && SEC_NAME != sec) + return(mdoc_err(mdoc, "section NAME must be first")); + if (SEC_CUSTOM == sec) return(1); - if (sec == mdoc->sec_lastn) + if (sec == mdoc->lastnamed) return(mdoc_warn(mdoc, WARN_SYNTAX, "section repeated")); - return(mdoc_warn(mdoc, WARN_SYNTAX, "section out of conventional order")); + if (sec < mdoc->lastnamed) + return(mdoc_warn(mdoc, WARN_SYNTAX, "section out of conventional order")); + + return(1); } -- cgit