]> git.cameronkatri.com Git - mandoc.git/blobdiff - validate.c
All "low-hanging" macros implemented in term.c.
[mandoc.git] / validate.c
index cbc02554e83d13dd9c9bea636590522347d1de45..7b109965e04da5039ae874eb2a15738dd90126b6 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: validate.c,v 1.55 2009/02/24 12:20:52 kristaps Exp $ */
+/* $Id: validate.c,v 1.59 2009/02/25 11:37:05 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -17,6 +17,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 #include <assert.h>
+#include <ctype.h>
 #include <stdlib.h>
 
 #include "private.h"
@@ -38,7 +39,6 @@ typedef       int     (*v_post)(POST_ARGS);
 /* FIXME: some sections should only occur in specific msecs. */
 /* FIXME: ignoring Pp. */
 /* FIXME: math symbols. */
-/* FIXME: .Fd only in synopsis section. */
 
 struct valids {
        v_pre   *pre;
@@ -55,6 +55,7 @@ static        int     check_text(struct mdoc *,
                        size_t, size_t, const char *);
 
 static int     err_child_lt(struct mdoc *, const char *, int);
+static int     warn_child_lt(struct mdoc *, const char *, int);
 static int     err_child_gt(struct mdoc *, const char *, int);
 static int     warn_child_gt(struct mdoc *, const char *, int);
 static int     err_child_eq(struct mdoc *, const char *, int);
@@ -89,7 +90,7 @@ static        int     pre_prologue(PRE_ARGS);
 /* Specific post-child-parse routines. */
 
 static int     herr_ge1(POST_ARGS);
-static int     herr_le1(POST_ARGS);
+static int     hwarn_le1(POST_ARGS);
 static int     herr_eq0(POST_ARGS);
 static int     eerr_eq0(POST_ARGS);
 static int     eerr_le1(POST_ARGS);
@@ -99,12 +100,14 @@ static     int     eerr_ge1(POST_ARGS);
 static int     ewarn_eq0(POST_ARGS);
 static int     ewarn_eq1(POST_ARGS);
 static int     bwarn_ge1(POST_ARGS);
+static int     hwarn_eq1(POST_ARGS);
 static int     ewarn_ge1(POST_ARGS);
 static int     ebool(POST_ARGS);
 
 static int     post_sh(POST_ARGS);
 static int     post_sh_body(POST_ARGS);
 static int     post_sh_head(POST_ARGS);
+static int     post_fd(POST_ARGS);
 static int     post_bl(POST_ARGS);
 static int     post_it(POST_ARGS);
 static int     post_ex(POST_ARGS);
@@ -151,10 +154,11 @@ static    v_post  posts_an[] = { post_an, NULL };
 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_bf[] = { hwarn_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_fo[] = { hwarn_eq1, bwarn_ge1, NULL };
 static v_post  posts_bk[] = { herr_eq0, bwarn_ge1, NULL };
+static v_post  posts_fd[] = { ewarn_ge1, post_fd, NULL };
 
 /* Per-macro pre- and post-child-check routine collections. */
 
@@ -183,7 +187,7 @@ const       struct valids mdoc_valids[MDOC_MAX] = {
        { NULL, posts_text },                   /* Ev */ 
        { pres_ex, posts_ex },                  /* Ex */ 
        { NULL, posts_text },                   /* Fa */ 
-       { NULL, posts_wtext },                  /* Fd */
+       { NULL, posts_fd },                     /* Fd */
        { NULL, NULL },                         /* Fl */
        { NULL, posts_text },                   /* Fn */ 
        { NULL, posts_wtext },                  /* Ft */ 
@@ -268,14 +272,93 @@ const     struct valids mdoc_valids[MDOC_MAX] = {
 };
 
 
+int
+mdoc_valid_pre(struct mdoc *mdoc, 
+               const struct mdoc_node *node)
+{
+       v_pre           *p;
+       struct mdoc_arg *argv;
+       size_t           argc, i, j, line, pos;
+       const char      *tp;
+
+       if (MDOC_TEXT == node->type) {
+               tp = node->data.text.string;
+               line = node->line;
+               pos = node->pos;
+               return(check_text(mdoc, line, pos, tp));
+       }
+
+       if (MDOC_BLOCK == node->type || MDOC_ELEM == node->type) {
+               argv = MDOC_BLOCK == node->type ?
+                       node->data.block.argv :
+                       node->data.elem.argv;
+               argc = MDOC_BLOCK == node->type ?
+                       node->data.block.argc :
+                       node->data.elem.argc;
+
+               for (i = 0; i < argc; i++) {
+                       if (0 == argv[i].sz)
+                               continue;
+                       for (j = 0; j < argv[i].sz; j++) {
+                               tp = argv[i].value[j];
+                               line = argv[i].line;
+                               pos = argv[i].pos;
+                               if ( ! check_text(mdoc, line, pos, tp))
+                                       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);
+}
+
+
+
 static inline int
 warn_count(struct mdoc *m, const char *k, 
                int want, const char *v, int has)
 {
 
        return(mdoc_warn(m, WARN_SYNTAX, 
-                               "suggests %s %d %s (has %d)", 
-                               v, want, k, has));
+                               "suggests %s %s %d (has %d)", 
+                               v, k, want, has));
 }
 
 
@@ -284,8 +367,8 @@ err_count(struct mdoc *m, const char *k,
                int want, const char *v, int has)
 {
 
-       return(mdoc_err(m, "requires %s %d %s (has %d)",
-                               v, want, k, has));
+       return(mdoc_err(m, "requires %s %s %d (has %d)",
+                               v, k, want, has));
 }
 
 
@@ -341,7 +424,7 @@ h##lvl##_##name(POST_ARGS)                                  \
 {                                                              \
        if (MDOC_HEAD != mdoc->last->type)                      \
                return(1);                                      \
-       return(func(mdoc, "multiline parameters", (num)));      \
+       return(func(mdoc, "line parameters", (num)));           \
 }
 
 
@@ -350,6 +433,7 @@ CHECK_CHILD_DEFN(err, gt, >)                        /* err_child_gt() */
 CHECK_CHILD_DEFN(warn, eq, ==)                 /* warn_child_eq() */
 CHECK_CHILD_DEFN(err, eq, ==)                  /* err_child_eq() */
 CHECK_CHILD_DEFN(err, lt, <)                   /* err_child_lt() */
+CHECK_CHILD_DEFN(warn, lt, <)                  /* warn_child_lt() */
 CHECK_BODY_DEFN(ge1, warn, warn_child_gt, 0)   /* bwarn_ge1() */
 CHECK_ELEM_DEFN(eq1, warn, warn_child_eq, 1)   /* ewarn_eq1() */
 CHECK_ELEM_DEFN(eq0, warn, warn_child_eq, 0)   /* ewarn_eq0() */
@@ -360,8 +444,9 @@ CHECK_ELEM_DEFN(le1, err, err_child_lt, 2)  /* eerr_le1() */
 CHECK_ELEM_DEFN(eq0, err, err_child_eq, 0)     /* eerr_eq0() */
 CHECK_ELEM_DEFN(ge1, err, err_child_gt, 0)     /* eerr_ge1() */
 CHECK_HEAD_DEFN(eq0, err, err_child_eq, 0)     /* herr_eq0() */
-CHECK_HEAD_DEFN(le1, err, err_child_lt, 2)     /* herr_le1() */
+CHECK_HEAD_DEFN(le1, warn, warn_child_lt, 2)   /* hwarn_le1() */
 CHECK_HEAD_DEFN(ge1, err, err_child_gt, 0)     /* herr_ge1() */
+CHECK_HEAD_DEFN(eq1, warn, warn_child_eq, 1)   /* hwarn_eq1() */
 
 
 static int
@@ -396,6 +481,9 @@ check_text(struct mdoc *mdoc, size_t line, size_t pos, const char *p)
        size_t           c;
 
        for ( ; *p; p++) {
+               if ( ! isprint(*p) && '\t' != *p)
+                       return(mdoc_perr(mdoc, line, pos,
+                                       "invalid characters"));
                if ('\\' != *p)
                        continue;
                if ((c = mdoc_isescape(p))) {
@@ -403,7 +491,7 @@ check_text(struct mdoc *mdoc, size_t line, size_t pos, const char *p)
                        continue;
                }
                return(mdoc_perr(mdoc, line, pos,
-                               "invalid escape sequence"));
+                                       "invalid escape sequence"));
        }
 
        return(1);
@@ -1062,80 +1150,12 @@ post_sh_head(POST_ARGS)
 }
 
 
-int
-mdoc_valid_pre(struct mdoc *mdoc, 
-               const struct mdoc_node *node)
-{
-       v_pre           *p;
-       struct mdoc_arg *argv;
-       size_t           argc, i, j, line, pos;
-       const char      *tp;
-
-       if (MDOC_TEXT == node->type) {
-               tp = node->data.text.string;
-               line = node->line;
-               pos = node->pos;
-               return(check_text(mdoc, line, pos, tp));
-       }
-
-       if (MDOC_BLOCK == node->type || MDOC_ELEM == node->type) {
-               argv = MDOC_BLOCK == node->type ?
-                       node->data.block.argv :
-                       node->data.elem.argv;
-               argc = MDOC_BLOCK == node->type ?
-                       node->data.block.argc :
-                       node->data.elem.argc;
-
-               for (i = 0; i < argc; i++) {
-                       if (0 == argv[i].sz)
-                               continue;
-                       for (j = 0; j < argv[i].sz; j++) {
-                               tp = argv[i].value[j];
-                               line = argv[i].line;
-                               pos = argv[i].pos;
-                               if ( ! check_text(mdoc, line, pos, tp))
-                                       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)
+static int
+post_fd(POST_ARGS)
 {
-       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)
+       if (SEC_SYNOPSIS == mdoc->last->sec)
                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);
+       return(mdoc_warn(mdoc, WARN_COMPAT, 
+                       "suggested only in section SYNOPSIS"));
 }
-