=================================================================== RCS file: /cvs/mandoc/Attic/validate.c,v retrieving revision 1.43 retrieving revision 1.48 diff -u -p -r1.43 -r1.48 --- mandoc/Attic/validate.c 2009/01/20 12:51:28 1.43 +++ mandoc/Attic/validate.c 2009/02/21 14:56:58 1.48 @@ -1,4 +1,4 @@ -/* $Id: validate.c,v 1.43 2009/01/20 12:51:28 kristaps Exp $ */ +/* $Id: validate.c,v 1.48 2009/02/21 14:56:58 kristaps Exp $ */ /* * Copyright (c) 2008 Kristaps Dzonsons * @@ -21,6 +21,14 @@ #include "private.h" +/* + * Pre- and post-validate macros as they're parsed. Pre-validation + * occurs when the macro has been detected and its arguments parsed. + * Post-validation occurs when all child macros have also been parsed. + * In the ELEMENT case, this is simply the parameters of the macro; in + * the BLOCK case, this is the HEAD, BODY, TAIL and so on. + */ + typedef int (*v_pre)(struct mdoc *, struct mdoc_node *); typedef int (*v_post)(struct mdoc *); @@ -83,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 *); @@ -129,6 +139,9 @@ static v_post posts_at[] = { post_at, NULL }; static v_post posts_xr[] = { eerr_ge1, eerr_le2, post_xr, NULL }; static v_post posts_nm[] = { post_nm, NULL }; static v_post posts_bf[] = { herr_le1, post_bf, NULL }; +static v_post posts_rs[] = { herr_eq0, bwarn_ge1, NULL }; +static v_post posts_fo[] = { bwarn_ge1, NULL }; +static v_post posts_bk[] = { herr_eq0, bwarn_ge1, NULL }; /* Per-macro pre- and post-child-check routine collections. */ @@ -137,7 +150,6 @@ const struct valids mdoc_valids[MDOC_MAX] = { { pres_prologue, posts_text }, /* Dd */ { pres_prologue, NULL }, /* Dt */ { pres_prologue, NULL }, /* Os */ - /* FIXME: NAME section internal ordering. */ { pres_sh, posts_sh }, /* Sh */ { pres_ss, posts_ss }, /* Ss */ { NULL, posts_pp }, /* Pp */ @@ -220,7 +232,7 @@ const struct valids mdoc_valids[MDOC_MAX] = { { NULL, NULL }, /* Qo */ { NULL, posts_wline }, /* Qq */ { NULL, NULL }, /* Re */ - { NULL, NULL }, /* Rs */ + { NULL, posts_rs }, /* Rs */ { NULL, NULL }, /* Sc */ { NULL, NULL }, /* So */ { NULL, posts_wline }, /* Sq */ @@ -231,11 +243,11 @@ const struct valids mdoc_valids[MDOC_MAX] = { { NULL, NULL }, /* Ux */ { NULL, NULL }, /* Xc */ { NULL, NULL }, /* Xo */ - { NULL, NULL }, /* Fo */ + { NULL, posts_fo }, /* Fo */ { NULL, NULL }, /* Fc */ { NULL, NULL }, /* Oo */ { NULL, NULL }, /* Oc */ - { NULL, NULL }, /* Bk */ + { NULL, posts_bk }, /* Bk */ { NULL, NULL }, /* Ek */ { NULL, posts_notext }, /* Bt */ { NULL, NULL }, /* Hf */ @@ -696,6 +708,8 @@ static int pre_it(struct mdoc *mdoc, struct mdoc_node *node) { + /* TODO: -width attribute must be specified for -tag. */ + if (MDOC_BLOCK != node->type) return(1); return(pre_check_parent(mdoc, node, MDOC_Bl, MDOC_BODY)); @@ -706,7 +720,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); @@ -892,6 +906,7 @@ post_it(struct mdoc *mdoc) #define TYPE_NONE (0) #define TYPE_BODY (1) #define TYPE_HEAD (2) +#define TYPE_OHEAD (3) size_t i, argc; struct mdoc_node *n; @@ -938,20 +953,23 @@ post_it(struct mdoc *mdoc) case (MDOC_Hyphen): /* FALLTHROUGH */ case (MDOC_Item): - /* FALLTHROUGH */ - case (MDOC_Column): type = TYPE_BODY; sv = n->data.block.argv[(int)i].arg; break; + case (MDOC_Column): + type = TYPE_OHEAD; + sv = n->data.block.argv[(int)i].arg; + break; default: break; } assert(TYPE_NONE != type); + n = mdoc->last->data.block.head; + assert(n); + if (TYPE_HEAD == type) { - n = mdoc->last->data.block.head; - assert(n); if (NULL == n->child) if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests line parameters")) return(0); @@ -962,26 +980,29 @@ post_it(struct mdoc *mdoc) if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests body children")) return(0); - return(1); + } else if (TYPE_BODY == type) { + if (n->child) + if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests no line parameters")) + return(0); + + n = mdoc->last->data.block.body; + assert(n); + if (NULL == n->child) + if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests body children")) + return(0); + } else { + if (NULL == n->child) + if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests line parameters")) + return(0); + + n = mdoc->last->data.block.body; + assert(n); + if (n->child) + if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests no body children")) + return(0); } - assert(TYPE_BODY == type); - assert(mdoc->last->data.block.head); - - n = mdoc->last->data.block.head; - assert(n); - if (n->child) - if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests no line parameters")) - return(0); - - n = mdoc->last->data.block.body; - assert(n); - if (NULL == n->child) - if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests body children")) - return(0); - - assert(-1 != sv); - if (MDOC_Column != sv) + if (MDOC_Column != sv) return(1); /* Make sure the number of columns is sane. */ @@ -998,6 +1019,7 @@ post_it(struct mdoc *mdoc) #undef TYPE_NONE #undef TYPE_BODY #undef TYPE_HEAD +#undef TYPE_OHEAD } @@ -1049,39 +1071,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) + if (SEC_PROLOGUE == mdoc->lastnamed) 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) - 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))) + 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) - 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); }