summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2009-03-25 15:17:49 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2009-03-25 15:17:49 +0000
commit12bf2f26f8d476960eba07e14e64fd26661da3b3 (patch)
treeb759d2d2e7467b1cffc89fb98e9d6e4ccb5bdbed
parent4b4e799e741ce5040d46930f13430debab688774 (diff)
downloadmandoc-12bf2f26f8d476960eba07e14e64fd26661da3b3.tar.gz
Added man validator, renamed mdoc validator.
-rw-r--r--Makefile23
-rw-r--r--libman.h4
-rw-r--r--main.c41
-rw-r--r--man.c43
-rw-r--r--man.h8
-rw-r--r--man_macro.c9
-rw-r--r--man_validate.c134
-rw-r--r--mdoc_validate.c (renamed from validate.c)0
8 files changed, 238 insertions, 24 deletions
diff --git a/Makefile b/Makefile
index 498c9e76..d6e3a04d 100644
--- a/Makefile
+++ b/Makefile
@@ -18,16 +18,18 @@ LINTFLAGS += $(VFLAGS)
CFLAGS += $(VFLAGS)
MDOCLNS = mdoc_macro.ln mdoc.ln mdoc_hash.ln strings.ln xstd.ln \
- argv.ln validate.ln action.ln lib.ln att.ln arch.ln \
- vol.ln msec.ln st.ln
+ argv.ln mdoc_validate.ln action.ln lib.ln att.ln \
+ arch.ln vol.ln msec.ln st.ln
MDOCOBJS = mdoc_macro.o mdoc.o mdoc_hash.o strings.o xstd.o argv.o \
- validate.o action.o lib.o att.o arch.o vol.o msec.o st.o
+ mdoc_validate.o action.o lib.o att.o arch.o vol.o \
+ msec.o st.o
MDOCSRCS = mdoc_macro.c mdoc.c mdoc_hash.c strings.c xstd.c argv.c \
- validate.c action.c lib.c att.c arch.c vol.c msec.c st.c
+ mdoc_validate.c action.c lib.c att.c arch.c vol.c \
+ msec.c st.c
-MANLNS = man_macro.ln man.ln man_hash.ln
-MANOBJS = man_macro.o man.o man_hash.o
-MANSRCS = man_macro.c man.c man_hash.c
+MANLNS = man_macro.ln man.ln man_hash.ln man_validate.ln
+MANOBJS = man_macro.o man.o man_hash.o man_validate.o
+MANSRCS = man_macro.c man.c man_hash.c man_validate.c
MAINLNS = main.ln term.ln ascii.ln terminal.ln tree.ln compat.ln
MAINOBJS = main.o term.o ascii.o terminal.o tree.o compat.o
@@ -154,8 +156,11 @@ xstd.o: xstd.c libmdoc.h
argv.ln: argv.c libmdoc.h
argv.o: argv.c libmdoc.h
-validate.ln: validate.c libmdoc.h
-validate.o: validate.c libmdoc.h
+man_validate.ln: man_validate.c libman.h
+man_validate.o: man_validate.c libman.h
+
+mdoc_validate.ln: mdoc_validate.c libmdoc.h
+mdoc_validate.o: mdoc_validate.c libmdoc.h
action.ln: action.c libmdoc.h
action.o: action.c libmdoc.h
diff --git a/libman.h b/libman.h
index 101ea093..91effa0f 100644
--- a/libman.h
+++ b/libman.h
@@ -27,6 +27,8 @@ enum man_next {
};
struct man {
+ void *data;
+ struct man_cb cb;
void *htab;
int flags;
#define MAN_HALT (1 << 0)
@@ -48,6 +50,8 @@ int man_macro(struct man *, int,
int man_hash_find(const void *, const char *);
void man_hash_free(void *);
int man_macroend(struct man *);
+int man_vwarn(struct man *, int, int, const char *, ...);
+int man_verr(struct man *, int, int, const char *, ...);
__END_DECLS
diff --git a/main.c b/main.c
index 62e44a6e..81b67b29 100644
--- a/main.c
+++ b/main.c
@@ -87,7 +87,8 @@ static int toptions(enum outt *, char *);
static int moptions(enum intt *, char *);
static int woptions(int *, char *);
static int merr(void *, int, int, const char *);
-static int mwarn(void *, int, int,
+static int manwarn(void *, int, int, const char *);
+static int mdocwarn(void *, int, int,
enum mdoc_warn, const char *);
static int file(struct buf *, struct buf *,
const char *,
@@ -104,7 +105,8 @@ int
main(int argc, char *argv[])
{
int c, rc, fflags;
- struct mdoc_cb cb;
+ struct mdoc_cb mdoccb;
+ struct man_cb mancb;
struct man *man;
struct mdoc *mdoc;
void *outdata;
@@ -191,9 +193,12 @@ main(int argc, char *argv[])
* screen. XXX - for now, no path for debugging messages.
*/
- cb.mdoc_msg = NULL;
- cb.mdoc_err = merr;
- cb.mdoc_warn = mwarn;
+ mdoccb.mdoc_msg = NULL;
+ mdoccb.mdoc_err = merr;
+ mdoccb.mdoc_warn = mdocwarn;
+
+ mancb.man_err = merr;
+ mancb.man_warn = manwarn;
bzero(&ln, sizeof(struct buf));
bzero(&blk, sizeof(struct buf));
@@ -203,10 +208,10 @@ main(int argc, char *argv[])
switch (inttype) {
case (INTT_MAN):
- man = man_alloc();
+ man = man_alloc(&curp, &mancb);
break;
default:
- mdoc = mdoc_alloc(&curp, fflags, &cb);
+ mdoc = mdoc_alloc(&curp, fflags, &mdoccb);
break;
}
@@ -515,7 +520,7 @@ merr(void *arg, int line, int col, const char *msg)
static int
-mwarn(void *arg, int line, int col,
+mdocwarn(void *arg, int line, int col,
enum mdoc_warn type, const char *msg)
{
struct curparse *curp;
@@ -550,3 +555,23 @@ mwarn(void *arg, int line, int col,
}
+static int
+manwarn(void *arg, int line, int col, const char *msg)
+{
+ struct curparse *curp;
+
+ curp = (struct curparse *)arg;
+
+ if ( ! (curp->wflags & WARN_WSYNTAX))
+ return(1);
+
+ warnx("%s:%d: syntax warning: %s (column %d)",
+ curp->file, line, msg, col);
+
+ if ( ! (curp->wflags & WARN_WERR))
+ return(1);
+
+ warnx("%s: considering warnings as errors",
+ __progname);
+ return(0);
+}
diff --git a/man.c b/man.c
index e66315c6..27976280 100644
--- a/man.c
+++ b/man.c
@@ -83,7 +83,7 @@ man_free(struct man *man)
struct man *
-man_alloc(void)
+man_alloc(void *data, const struct man_cb *cb)
{
struct man *p;
@@ -93,7 +93,11 @@ man_alloc(void)
man_alloc1(p);
+ if (cb)
+ (void)memcpy(&p->cb, cb, sizeof(struct man_cb));
+
p->htab = man_hash_alloc();
+ p->data = data;
return(p);
}
@@ -175,8 +179,6 @@ man_node_append(struct man *man, struct man_node *p)
}
#if 0
- if ( ! man_valid_pre(man, p))
- return(0);
if ( ! man_action_pre(man, p))
return(0);
#endif
@@ -185,9 +187,9 @@ man_node_append(struct man *man, struct man_node *p)
switch (p->type) {
case (MAN_TEXT):
-#if 0
if ( ! man_valid_post(man))
return(0);
+#if 0
if ( ! man_action_post(man))
return(0);
#endif
@@ -339,3 +341,36 @@ err: /* Error out. */
return(0);
}
+
+int
+man_verr(struct man *man, int ln, int pos, const char *fmt, ...)
+{
+ char buf[256];
+ va_list ap;
+
+ if (NULL == man->cb.man_err)
+ return(0);
+
+ va_start(ap, fmt);
+ (void)vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
+ va_end(ap);
+ return((*man->cb.man_err)(man->data, ln, pos, buf));
+}
+
+
+int
+man_vwarn(struct man *man, int ln, int pos, const char *fmt, ...)
+{
+ char buf[256];
+ va_list ap;
+
+ if (NULL == man->cb.man_warn)
+ return(0);
+
+ va_start(ap, fmt);
+ (void)vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
+ va_end(ap);
+ return((*man->cb.man_warn)(man->data, ln, pos, buf));
+}
+
+
diff --git a/man.h b/man.h
index da242898..0fcffe43 100644
--- a/man.h
+++ b/man.h
@@ -74,15 +74,21 @@ struct man_node {
extern const char *const *man_macronames;
+struct man_cb {
+ int (*man_warn)(void *, int, int, const char *);
+ int (*man_err)(void *, int, int, const char *);
+};
+
__BEGIN_DECLS
struct man;
void man_free(struct man *);
-struct man *man_alloc(void);
+struct man *man_alloc(void *, const struct man_cb *);
void man_reset(struct man *);
int man_parseln(struct man *, int, char *buf);
int man_endparse(struct man *);
+int man_valid_post(struct man *);
const struct man_node *man_node(const struct man *);
const struct man_meta *man_meta(const struct man *);
diff --git a/man_macro.c b/man_macro.c
index 05a95d22..651b7503 100644
--- a/man_macro.c
+++ b/man_macro.c
@@ -56,9 +56,14 @@ man_macro(struct man *man, int tok, int line,
man->next = MAN_NEXT_SIBLING;
}
- /* TODO: validate & actions. */
+ for ( ; man->last && man->last != n;
+ man->last = man->last->parent)
+ if ( ! man_valid_post(man))
+ return(0);
- man->last = n;
+ assert(man->last);
+ if ( ! man_valid_post(man))
+ return(0);
man->next = MAN_NEXT_SIBLING;
return(1);
diff --git a/man_validate.c b/man_validate.c
new file mode 100644
index 00000000..357ae37d
--- /dev/null
+++ b/man_validate.c
@@ -0,0 +1,134 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <sys/types.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "libman.h"
+
+/* FIXME: validate text. */
+
+#define POSTARGS struct man *m, const struct man_node *n
+
+typedef int (*v_post)(POSTARGS);
+
+struct man_valid {
+ v_post *posts;
+};
+
+static int count(POSTARGS);
+static int check_eq0(POSTARGS);
+static int check_ge1(POSTARGS);
+static int check_ge2(POSTARGS);
+static int check_le1(POSTARGS);
+static int check_le2(POSTARGS);
+static int check_le5(POSTARGS);
+
+static v_post posts_le1[] = { check_le1, NULL };
+static v_post posts_le2[] = { check_le2, NULL };
+static v_post posts_ge1[] = { check_ge1, NULL };
+static v_post posts_eq0[] = { check_eq0, NULL };
+static v_post posts_ge2_le5[] = { check_ge2, check_le5, NULL };
+
+static const struct man_valid man_valids[MAN_MAX] = {
+ { NULL }, /* __ */
+ { posts_ge2_le5 }, /* TH */
+ { posts_ge1 }, /* SH */
+ { posts_ge1 }, /* SS */
+ { posts_le1 }, /* TP */
+ { posts_eq0 }, /* LP */
+ { posts_eq0 }, /* PP */
+ { posts_eq0 }, /* P */
+ { posts_le2 }, /* IP */
+ { posts_le1 }, /* HP */
+ { NULL }, /* SM */
+ { NULL }, /* SB */
+ { NULL }, /* BI */
+ { NULL }, /* IB */
+ { NULL }, /* BR */
+ { NULL }, /* RB */
+ { NULL }, /* R */
+ { NULL }, /* B */
+ { NULL }, /* I */
+ { NULL }, /* IR */
+};
+
+
+int
+man_valid_post(struct man *m)
+{
+ v_post *cp;
+
+ if (MAN_VALID & m->last->flags)
+ return(1);
+
+ m->last->flags |= MAN_VALID;
+
+ switch (m->last->type) {
+ case (MAN_TEXT):
+ /* FALLTHROUGH */
+ case (MAN_ROOT):
+ return(1);
+ default:
+ break;
+ }
+
+ if (NULL == (cp = man_valids[m->last->tok].posts))
+ return(1);
+ for ( ; *cp; cp++)
+ if ( ! (*cp)(m, m->last))
+ return(0);
+
+ return(1);
+}
+
+
+static inline int
+count(POSTARGS)
+{
+ int i;
+
+ for (i = 0; n; n = n->next, i++)
+ /* Loop. */ ;
+ return(i);
+}
+
+
+#define INEQ_DEFINE(x, ineq, name) \
+static int \
+check_##name(POSTARGS) \
+{ \
+ int c; \
+ if ((c = count(m, n->child)) ineq (x)) \
+ return(1); \
+ return(man_vwarn(m, n->line, n->pos, \
+ "expected line arguments %s %d, have %d", \
+ #ineq, (x), c)); \
+}
+
+INEQ_DEFINE(0, ==, eq0)
+INEQ_DEFINE(1, >=, ge1)
+INEQ_DEFINE(2, >=, ge2)
+INEQ_DEFINE(1, <=, le1)
+INEQ_DEFINE(2, <=, le2)
+INEQ_DEFINE(5, <=, le5)
+
diff --git a/validate.c b/mdoc_validate.c
index 09b88f45..09b88f45 100644
--- a/validate.c
+++ b/mdoc_validate.c