diff options
-rw-r--r-- | Makefile | 23 | ||||
-rw-r--r-- | libman.h | 4 | ||||
-rw-r--r-- | main.c | 41 | ||||
-rw-r--r-- | man.c | 43 | ||||
-rw-r--r-- | man.h | 8 | ||||
-rw-r--r-- | man_macro.c | 9 | ||||
-rw-r--r-- | man_validate.c | 134 | ||||
-rw-r--r-- | mdoc_validate.c (renamed from validate.c) | 0 |
8 files changed, 238 insertions, 24 deletions
@@ -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 @@ -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 @@ -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); +} @@ -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)); +} + + @@ -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 |