+int
+mdoc_valid_pre(struct mdoc *mdoc,
+ const struct mdoc_node *node)
+{
+ v_pre *p;
+ int line, pos;
+ const char *tp;
+
+ if (MDOC_TEXT == node->type) {
+ tp = node->string;
+ line = node->line;
+ pos = node->pos;
+ return(check_text(mdoc, line, pos, tp));
+ }
+
+ if ( ! check_args(mdoc, node))
+ return(0);
+ if (NULL == mdoc_valids[node->tok].pre)
+ return(1);
+ for (p = mdoc_valids[node->tok].pre; *p; p++)
+ if ( ! (*p)(mdoc, node))
+ return(0);
+ return(1);
+}
+
+
+int
+mdoc_valid_post(struct mdoc *mdoc)
+{
+ v_post *p;
+
+ /*
+ * This check occurs after the macro's children have been filled
+ * in: postfix validation. Since this happens when we're
+ * rewinding the scope tree, it's possible to have multiple
+ * invocations (as by design, for now), we set bit MDOC_VALID to
+ * indicate that we've validated.
+ */
+
+ if (MDOC_VALID & mdoc->last->flags)
+ return(1);
+ mdoc->last->flags |= MDOC_VALID;
+
+ if (MDOC_TEXT == mdoc->last->type)
+ return(1);
+ if (MDOC_ROOT == mdoc->last->type)
+ return(post_root(mdoc));
+
+ if (NULL == mdoc_valids[mdoc->last->tok].post)
+ return(1);
+ for (p = mdoc_valids[mdoc->last->tok].post; *p; p++)
+ if ( ! (*p)(mdoc))
+ return(0);
+
+ return(1);
+}
+
+
+#define merr(m, t) nerr((m), (m)->last, (t))
+static int
+nerr(struct mdoc *m, const struct mdoc_node *n, enum merr type)
+{
+ char *p;
+
+ p = NULL;
+
+ switch (type) {
+ case (ENESTDISP):
+ p = "displays may not be nested";
+ break;
+ case (EBOOL):
+ p = "expected boolean value";
+ break;
+ case (EARGREP):
+ p = "argument repeated";
+ break;
+ case (EMULTIDISP):
+ p = "multiple display types specified";
+ break;
+ case (EMULTILIST):
+ p = "multiple list types specified";
+ break;
+ case (ELISTTYPE):
+ p = "missing list type";
+ break;
+ case (EDISPTYPE):
+ p = "missing display type";
+ break;
+ case (ELINE):
+ p = "expected line arguments";
+ break;
+ case (ENOPROLOGUE):
+ p = "document has no prologue";
+ break;
+ case (ENODATA):
+ p = "document has no data";
+ break;
+ case (EATT):
+ p = "expected valid AT&T symbol";
+ break;
+ case (ENAME):
+ p = "default name not yet set";
+ break;
+ }
+
+ assert(p);
+ return(mdoc_nerr(m, n, p));
+}
+
+
+#define mwarn(m, t) nwarn((m), (m)->last, (t))
+static int
+nwarn(struct mdoc *m, const struct mdoc_node *n, enum mwarn type)
+{
+ char *p;
+ enum mdoc_warn c;
+
+ c = WARN_SYNTAX;
+ p = NULL;
+
+ switch (type) {
+ case (WBADMSEC):
+ p = "inappropriate manual section";
+ c = WARN_COMPAT;
+ break;
+ case (WBADSEC):
+ p = "inappropriate document section";
+ c = WARN_COMPAT;
+ break;
+ case (WARGVAL):
+ p = "argument value suggested";
+ c = WARN_COMPAT;
+ break;
+ case (WPROLREP):
+ p = "prologue macros repeated";
+ c = WARN_COMPAT;
+ break;
+ case (WPROLOOO):
+ p = "prologue macros out-of-order";
+ c = WARN_COMPAT;
+ break;
+ case (WNOLINE):
+ p = "suggested no line arguments";
+ break;
+ case (WLINE):
+ p = "suggested line arguments";
+ break;
+ case (WMULTILINE):
+ p = "suggested multi-line arguments";
+ break;
+ case (WNOMULTILINE):
+ p = "suggested no multi-line arguments";
+ break;
+ case (WWRONGMSEC):
+ p = "document section in wrong manual section";
+ c = WARN_COMPAT;
+ break;
+ case (WSECOOO):
+ p = "document section out of conventional order";
+ break;
+ case (WSECREP):
+ p = "document section repeated";
+ break;
+ case (WBADSTAND):
+ p = "unknown standard";
+ break;
+ case (WNAMESECINC):
+ p = "NAME section contents incomplete/badly-ordered";
+ break;
+ }
+ assert(p);
+ return(mdoc_nwarn(m, n, c, p));
+}
+
+
+