summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2010-10-11 13:24:33 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2010-10-11 13:24:33 +0000
commite117e698fc50edcb592d1cba182bd5ceb8f6d151 (patch)
tree5ad521673cd7c281ef745ea4925ffd57e622130a
parent3d378740b04b9c699a76ada1be91544f7cbb44fa (diff)
downloadmandoc-e117e698fc50edcb592d1cba182bd5ceb8f6d151.tar.gz
Initial commit of cleaned-up validation code for -mdoc. Remove those
ugly CPP macros in favour of real functions. Enumerate areas of short- term future cleanup, too.
-rw-r--r--mdoc_validate.c204
1 files changed, 123 insertions, 81 deletions
diff --git a/mdoc_validate.c b/mdoc_validate.c
index 8ec87e3e..97c239f7 100644
--- a/mdoc_validate.c
+++ b/mdoc_validate.c
@@ -36,6 +36,18 @@
#define PRE_ARGS struct mdoc *mdoc, struct mdoc_node *n
#define POST_ARGS struct mdoc *mdoc
+enum check_ineq {
+ CHECK_LT,
+ CHECK_GT,
+ CHECK_EQ
+};
+
+enum check_lvl {
+ CHECK_WARN,
+ CHECK_ERROR,
+ CHECK_FATAL
+};
+
typedef int (*v_pre)(PRE_ARGS);
typedef int (*v_post)(POST_ARGS);
@@ -44,26 +56,19 @@ struct valids {
v_post *post;
};
+static int check_count(struct mdoc *, enum mdoc_type,
+ enum check_lvl, enum check_ineq, int);
static int check_parent(PRE_ARGS, enum mdoct, enum mdoc_type);
static int check_stdarg(PRE_ARGS);
static int check_text(struct mdoc *, int, int, char *);
static int check_argv(struct mdoc *,
struct mdoc_node *, struct mdoc_argv *);
static int check_args(struct mdoc *, struct mdoc_node *);
-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);
-static int warn_child_eq(struct mdoc *, const char *, int);
-static int warn_count(struct mdoc *, const char *,
- int, const char *, int);
-static int err_count(struct mdoc *, const char *,
- int, const char *, int);
+static int ebool(POST_ARGS);
static int berr_ge1(POST_ARGS);
static int bwarn_ge1(POST_ARGS);
-static int ebool(POST_ARGS);
+static int eerr_eq0(POST_ARGS);
static int eerr_eq1(POST_ARGS);
static int eerr_ge1(POST_ARGS);
static int eerr_le1(POST_ARGS);
@@ -71,8 +76,8 @@ static int ewarn_eq0(POST_ARGS);
static int ewarn_ge1(POST_ARGS);
static int herr_eq0(POST_ARGS);
static int herr_ge1(POST_ARGS);
-static int hwarn_eq1(POST_ARGS);
static int hwarn_eq0(POST_ARGS);
+static int hwarn_eq1(POST_ARGS);
static int hwarn_le1(POST_ARGS);
static int post_an(POST_ARGS);
@@ -319,91 +324,124 @@ mdoc_valid_post(struct mdoc *mdoc)
return(1);
}
+static int
+check_count(struct mdoc *m, enum mdoc_type type,
+ enum check_lvl lvl, enum check_ineq ineq, int val)
+{
+ const char *p;
+
+ if (m->last->type != type)
+ return(1);
+
+ switch (ineq) {
+ case (CHECK_LT):
+ p = "less than ";
+ if (m->last->nchild < val)
+ return(1);
+ break;
+ case (CHECK_GT):
+ p = "greater than ";
+ if (m->last->nchild > val)
+ return(1);
+ break;
+ case (CHECK_EQ):
+ p = "";
+ if (val == m->last->nchild)
+ return(1);
+ break;
+ }
+
+ if (CHECK_WARN == lvl) {
+ return(mdoc_vmsg(m, MANDOCERR_ARGCOUNT,
+ m->last->line, m->last->pos,
+ "want %s%d children (have %d)",
+ p, val, m->last->nchild));
+ }
+
+ return(mdoc_vmsg(m, MANDOCERR_ARGCOUNT,
+ m->last->line, m->last->pos,
+ "require %s%d children (have %d)",
+ p, val, m->last->nchild));
+}
-static inline int
-warn_count(struct mdoc *m, const char *k,
- int want, const char *v, int has)
+static int
+berr_ge1(POST_ARGS)
{
- return(mdoc_vmsg(m, MANDOCERR_ARGCOUNT,
- m->last->line, m->last->pos,
- "%s %s %d (have %d)", v, k, want, has));
+ return(check_count(mdoc, MDOC_BODY, CHECK_FATAL, CHECK_GT, 0));
}
+static int
+bwarn_ge1(POST_ARGS)
+{
+ return(check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0));
+}
-static inline int
-err_count(struct mdoc *m, const char *k,
- int want, const char *v, int has)
+static int
+eerr_eq0(POST_ARGS)
{
+ return(check_count(mdoc, MDOC_ELEM, CHECK_FATAL, CHECK_EQ, 0));
+}
- mdoc_vmsg(m, MANDOCERR_SYNTARGCOUNT,
- m->last->line, m->last->pos,
- "%s %s %d (have %d)",
- v, k, want, has);
- return(0);
+static int
+eerr_eq1(POST_ARGS)
+{
+ return(check_count(mdoc, MDOC_ELEM, CHECK_FATAL, CHECK_EQ, 1));
}
+static int
+eerr_ge1(POST_ARGS)
+{
+ return(check_count(mdoc, MDOC_ELEM, CHECK_FATAL, CHECK_GT, 0));
+}
-/*
- * Build these up with macros because they're basically the same check
- * for different inequalities. Yes, this could be done with functions,
- * but this is reasonable for now.
- */
+static int
+eerr_le1(POST_ARGS)
+{
+ return(check_count(mdoc, MDOC_ELEM, CHECK_FATAL, CHECK_LT, 2));
+}
+
+static int
+ewarn_eq0(POST_ARGS)
+{
+ return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 0));
+}
-#define CHECK_CHILD_DEFN(lvl, name, ineq) \
-static int \
-lvl##_child_##name(struct mdoc *mdoc, const char *p, int sz) \
-{ \
- if (mdoc->last->nchild ineq sz) \
- return(1); \
- return(lvl##_count(mdoc, #ineq, sz, p, mdoc->last->nchild)); \
+static int
+ewarn_ge1(POST_ARGS)
+{
+ return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0));
}
-#define CHECK_BODY_DEFN(name, lvl, func, num) \
-static int \
-b##lvl##_##name(POST_ARGS) \
-{ \
- if (MDOC_BODY != mdoc->last->type) \
- return(1); \
- return(func(mdoc, "multi-line arguments", (num))); \
+static int
+herr_eq0(POST_ARGS)
+{
+ return(check_count(mdoc, MDOC_HEAD, CHECK_FATAL, CHECK_EQ, 0));
}
-#define CHECK_ELEM_DEFN(name, lvl, func, num) \
-static int \
-e##lvl##_##name(POST_ARGS) \
-{ \
- assert(MDOC_ELEM == mdoc->last->type); \
- return(func(mdoc, "line arguments", (num))); \
+static int
+herr_ge1(POST_ARGS)
+{
+ return(check_count(mdoc, MDOC_HEAD, CHECK_FATAL, CHECK_GT, 0));
}
-#define CHECK_HEAD_DEFN(name, lvl, func, num) \
-static int \
-h##lvl##_##name(POST_ARGS) \
-{ \
- if (MDOC_HEAD != mdoc->last->type) \
- return(1); \
- return(func(mdoc, "line arguments", (num))); \
+static int
+hwarn_eq0(POST_ARGS)
+{
+ return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0));
}
+static int
+hwarn_eq1(POST_ARGS)
+{
+ return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 1));
+}
-CHECK_CHILD_DEFN(warn, gt, >) /* warn_child_gt() */
-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_BODY_DEFN(ge1, err, err_child_gt, 0) /* berr_ge1() */
-CHECK_ELEM_DEFN(eq0, warn, warn_child_eq, 0) /* ewarn_eq0() */
-CHECK_ELEM_DEFN(ge1, warn, warn_child_gt, 0) /* ewarn_ge1() */
-CHECK_ELEM_DEFN(eq1, err, err_child_eq, 1) /* eerr_eq1() */
-CHECK_ELEM_DEFN(le1, err, err_child_lt, 2) /* eerr_le1() */
-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, 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() */
-CHECK_HEAD_DEFN(eq0, warn, warn_child_eq, 0) /* hwarn_eq0() */
+static int
+hwarn_le1(POST_ARGS)
+{
+ return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_LT, 2));
+}
static int
@@ -862,6 +900,8 @@ pre_an(PRE_ARGS)
if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_ARGCOUNT))
return(0);
+ /* FIXME: this should use a different error message. */
+
if (MDOC_Split == n->args->argv[0].arg)
n->data.An.auth = AUTH_split;
else if (MDOC_Nosplit == n->args->argv[0].arg)
@@ -1094,7 +1134,11 @@ post_an(POST_ARGS)
np = mdoc->last;
if (AUTH__NONE != np->data.An.auth && np->child)
- return(mdoc_nmsg(mdoc, np, MANDOCERR_ARGCOUNT));
+ return(eerr_eq0(mdoc));
+ /*
+ * FIXME: make this ewarn and make sure that the front-ends
+ * don't print the arguments.
+ */
if (AUTH__NONE != np->data.An.auth || np->child)
return(1);
return(mdoc_nmsg(mdoc, np, MANDOCERR_NOARGS));
@@ -1191,7 +1235,6 @@ post_it(POST_ARGS)
static int
post_bl_head(POST_ARGS)
{
- int i;
struct mdoc_node *n;
assert(mdoc->last->parent);
@@ -1205,9 +1248,8 @@ post_bl_head(POST_ARGS)
return(1);
}
- if (0 == (i = mdoc->last->nchild))
- return(1);
- return(warn_count(mdoc, "==", 0, "line arguments", i));
+ /* FIXME: should be ERROR class. */
+ return(hwarn_eq0(mdoc));
}