summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--html4_strict.c2
-rw-r--r--libmdocml.c6
-rw-r--r--private.h10
-rw-r--r--roff.c38
-rw-r--r--validate.c365
5 files changed, 397 insertions, 24 deletions
diff --git a/html4_strict.c b/html4_strict.c
index 68a02730..5f94930a 100644
--- a/html4_strict.c
+++ b/html4_strict.c
@@ -25,7 +25,7 @@
/* ARGSUSED */
int
-md_line_html4_strict(void *data, char *buf, size_t sz)
+md_line_html4_strict(void *data, char *buf)
{
return(1);
diff --git a/libmdocml.c b/libmdocml.c
index 3b7b67f2..06c9266c 100644
--- a/libmdocml.c
+++ b/libmdocml.c
@@ -85,6 +85,8 @@ static int md_buf_flush(struct md_mbuf *buf)
int
md_buf_putchar(struct md_mbuf *buf, char c)
{
+
+ assert(buf);
return(md_buf_puts(buf, &c, 1));
}
@@ -92,6 +94,8 @@ md_buf_putchar(struct md_mbuf *buf, char c)
int
md_buf_putstring(struct md_mbuf *buf, const char *p)
{
+
+ assert(buf);
return(md_buf_puts(buf, p, strlen(p)));
}
@@ -207,7 +211,7 @@ again:
}
line[pos] = 0;
- if ( ! (*fp)(p, line, pos))
+ if ( ! (*fp)(p, line))
return(md_run_leave(args, mbuf, rbuf, -1, p));
rbuf->line++;
pos = 0;
diff --git a/private.h b/private.h
index 173f9273..60fcc5aa 100644
--- a/private.h
+++ b/private.h
@@ -214,7 +214,7 @@ struct roffcb {
int (*roffhead)(void *);
int (*rofftail)(void *);
int (*roffin)(void *, int, int *, char **);
- int (*roffdata)(void *, const char *);
+ int (*roffdata)(void *, char *);
int (*roffout)(void *, int);
int (*roffblkin)(void *, int);
int (*roffblkout)(void *, int);
@@ -225,17 +225,17 @@ __BEGIN_DECLS
typedef void (*(*md_init)(const struct md_args *,
struct md_mbuf *, const struct md_rbuf *));
-typedef int (*md_line)(void *, char *, size_t);
+typedef int (*md_line)(void *, char *);
typedef int (*md_exit)(void *, int);
void *md_init_html4_strict(const struct md_args *,
struct md_mbuf *, const struct md_rbuf *);
-int md_line_html4_strict(void *, char *, size_t);
+int md_line_html4_strict(void *, char *);
int md_exit_html4_strict(void *, int);
void *md_init_valid(const struct md_args *,
struct md_mbuf *, const struct md_rbuf *);
-int md_line_valid(void *, char *, size_t);
+int md_line_valid(void *, char *);
int md_exit_valid(void *, int);
int md_buf_puts(struct md_mbuf *, const char *, size_t);
@@ -245,7 +245,7 @@ int md_buf_putstring(struct md_mbuf *, const char *);
struct rofftree;
struct rofftree *roff_alloc(const struct roffcb *, void *);
-int roff_engine(struct rofftree *, char *, size_t);
+int roff_engine(struct rofftree *, char *);
int roff_free(struct rofftree *, int);
__END_DECLS
diff --git a/roff.c b/roff.c
index 7b834d8a..8df96968 100644
--- a/roff.c
+++ b/roff.c
@@ -130,9 +130,8 @@ static int roffargs(const struct rofftree *,
static int roffargok(int, int);
static int roffnextopt(const struct rofftree *,
int, const char ***, char **);
-static int roffparse(struct rofftree *, char *, size_t);
-static int textparse(const struct rofftree *,
- const char *, size_t);
+static int roffparse(struct rofftree *, char *);
+static int textparse(const struct rofftree *, char *);
static const int roffarg_An[] = { ROFF_Split, ROFF_Nosplit,
@@ -360,6 +359,8 @@ roff_free(struct rofftree *tree, int flush)
int error, t;
struct roffnode *n;
+ error = 0;
+
if ( ! flush)
goto end;
@@ -372,7 +373,7 @@ roff_free(struct rofftree *tree, int flush)
for (n = tree->last; n->parent; n = n->parent) {
if (0 != tokens[n->tok].ctx)
- break;
+ continue;
roff_warn(tree, NULL, "closing explicit scope `%s'",
toknames[n->tok]);
goto end;
@@ -384,7 +385,7 @@ roff_free(struct rofftree *tree, int flush)
goto end;
}
- if ( ! (*tree->cb.roffhead)(tree->arg))
+ if ( ! (*tree->cb.rofftail)(tree->arg))
goto end;
error = 0;
@@ -395,6 +396,7 @@ end:
roffnode_free(tree);
free(tree);
+
return(error ? 0 : 1);
}
@@ -404,6 +406,9 @@ roff_alloc(const struct roffcb *cb, void *args)
{
struct rofftree *tree;
+ assert(args);
+ assert(cb);
+
if (NULL == (tree = calloc(1, sizeof(struct rofftree))))
err(1, "calloc");
@@ -422,27 +427,27 @@ roff_alloc(const struct roffcb *cb, void *args)
int
-roff_engine(struct rofftree *tree, char *buf, size_t sz)
+roff_engine(struct rofftree *tree, char *buf)
{
- tree->cur = NULL;
+ tree->cur = buf;
+ assert(buf);
- if (0 == sz) {
+ if (0 == *buf) {
roff_warn(tree, buf, "blank line");
return(0);
} else if ('.' != *buf)
- return(textparse(tree, buf, sz));
+ return(textparse(tree, buf));
- return(roffparse(tree, buf, sz));
+ return(roffparse(tree, buf));
}
static int
-textparse(const struct rofftree *tree, const char *buf, size_t sz)
+textparse(const struct rofftree *tree, char *buf)
{
-
- /* Print text. */
- return(1);
+
+ return((*tree->cb.roffdata)(tree->arg, buf));
}
@@ -512,15 +517,13 @@ roffscan(int tok, const int *tokv)
static int
-roffparse(struct rofftree *tree, char *buf, size_t sz)
+roffparse(struct rofftree *tree, char *buf)
{
int tok, t;
struct roffnode *n;
char *argv[ROFF_MAXARG];
const char **argvp;
- assert(sz > 0);
-
if (ROFF_MAX == (tok = rofffindtok(buf + 1))) {
roff_err(tree, buf + 1, "bogus line macro");
return(0);
@@ -959,6 +962,7 @@ roff_layout(ROFFCALL_ARGS)
break;
}
+ assert(tree->arg);
if ( ! (*tree->cb.roffdata)(tree->arg, *argv++))
return(0);
}
diff --git a/validate.c b/validate.c
new file mode 100644
index 00000000..922776d3
--- /dev/null
+++ b/validate.c
@@ -0,0 +1,365 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
+ *
+ * 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/param.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libmdocml.h"
+#include "private.h"
+
+#ifdef __linux__ /* FIXME */
+#define strlcat strncat
+#endif
+
+struct md_valid {
+ const struct md_args *args;
+ const struct md_rbuf *rbuf;
+ struct md_mbuf *mbuf;
+ struct rofftree *tree;
+
+ size_t indent;
+ size_t pos;
+
+ int flags;
+#define MD_LITERAL (1 << 0)
+};
+
+static void roffmsg(void *arg, enum roffmsg,
+ const char *, const char *, char *);
+static int roffhead(void *);
+static int rofftail(void *);
+static int roffin(void *, int, int *, char **);
+static int roffdata(void *, char *);
+static int roffout(void *, int);
+static int roffblkin(void *, int);
+static int roffblkout(void *, int);
+static int roffspecial(void *, int);
+
+static int mbuf_newline(struct md_valid *);
+static int mbuf_indent(struct md_valid *);
+static int mbuf_data(struct md_valid *, char *);
+
+
+static int
+mbuf_indent(struct md_valid *p)
+{
+ size_t i;
+
+ assert(0 == p->pos);
+
+ for (i = 0; i < MIN(p->indent, 4); i++)
+ if ( ! md_buf_putstring(p->mbuf, " "))
+ return(0);
+
+ p->pos = i * 4;
+ return(1);
+}
+
+
+static int
+mbuf_atnewline(struct md_valid *p)
+{
+
+ return(p->pos == MIN(4, p->indent));
+}
+
+
+static int
+mbuf_newline(struct md_valid *p)
+{
+
+ if (mbuf_atnewline(p))
+ return(1);
+ if ( ! md_buf_putchar(p->mbuf, '\n'))
+ return(0);
+
+ p->pos = 0;
+ return(mbuf_indent(p));
+}
+
+
+static int
+mbuf_data(struct md_valid *p, char *buf)
+{
+ size_t sz;
+ char *bufp;
+
+ assert(p->mbuf);
+ assert(0 != p->indent);
+
+ if (MD_LITERAL & p->flags)
+ return(md_buf_putstring(p->mbuf, buf));
+
+ if (0 == p->pos)
+ mbuf_indent(p);
+
+ /*
+ * Indent if we're at the beginning of a line. Don't indent
+ * more than 16 or so characters.
+ */
+
+ while (*buf) {
+ while (*buf && isspace(*buf))
+ buf++;
+
+ if (0 == *buf)
+ break;
+
+ bufp = buf;
+ while (*buf && ! isspace(*buf))
+ buf++;
+
+ if (0 != *buf)
+ *buf++ = 0;
+
+ /* Process word. */
+
+ sz = strlen(bufp);
+
+ if (sz + p->pos < 72) {
+ if ( ! md_buf_putstring(p->mbuf, bufp))
+ return(0);
+
+ /* FIXME: check punctuation. */
+
+ if ( ! md_buf_putchar(p->mbuf, ' '))
+ return(0);
+ p->pos += sz + 1;
+ continue;
+ }
+
+ if ( ! mbuf_newline(p))
+ return(0);
+
+ if ( ! md_buf_putstring(p->mbuf, bufp))
+ return(0);
+
+ /* FIXME: check punctuation. */
+
+ if ( ! md_buf_putchar(p->mbuf, ' '))
+ return(0);
+ p->pos += sz + 1;
+ }
+
+ return(1);
+}
+
+
+int
+md_line_valid(void *arg, char *buf)
+{
+ struct md_valid *p;
+
+ p = (struct md_valid *)arg;
+ return(roff_engine(p->tree, buf));
+}
+
+
+int
+md_exit_valid(void *data, int flush)
+{
+ int c;
+ struct md_valid *p;
+
+ p = (struct md_valid *)data;
+ c = roff_free(p->tree, flush);
+ free(p);
+
+ return(c);
+}
+
+
+void *
+md_init_valid(const struct md_args *args,
+ struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
+{
+ struct roffcb cb;
+ struct md_valid *p;
+
+ cb.roffhead = roffhead;
+ cb.rofftail = rofftail;
+ cb.roffin = roffin;
+ cb.roffout = roffout;
+ cb.roffblkin = roffblkin;
+ cb.roffblkout = roffblkout;
+ cb.roffspecial = roffspecial;
+ cb.roffmsg = roffmsg;
+ cb.roffdata = roffdata;
+
+ if (NULL == (p = calloc(1, sizeof(struct md_valid))))
+ err(1, "malloc");
+
+ p->args = args;
+ p->mbuf = mbuf;
+ p->rbuf = rbuf;
+
+ assert(mbuf);
+
+ if (NULL == (p->tree = roff_alloc(&cb, p))) {
+ free(p);
+ return(NULL);
+ }
+
+ return(p);
+}
+
+
+/* ARGSUSED */
+static int
+roffhead(void *arg)
+{
+
+ return(1);
+}
+
+
+static int
+rofftail(void *arg)
+{
+ struct md_valid *p;
+
+ assert(arg);
+ p = (struct md_valid *)arg;
+
+ if (mbuf_atnewline(p))
+ return(1);
+
+ return(md_buf_putchar(p->mbuf, '\n'));
+}
+
+
+static int
+roffspecial(void *arg, int tok)
+{
+
+ return(1);
+}
+
+
+static int
+roffblkin(void *arg, int tok)
+{
+ struct md_valid *p;
+
+ assert(arg);
+ p = (struct md_valid *)arg;
+
+ if ( ! mbuf_atnewline(p)) {
+ if ( ! md_buf_putchar(p->mbuf, '\n'))
+ return(0);
+ p->pos = 0;
+ if ( ! mbuf_indent(p))
+ return(0);
+ }
+
+ if ( ! md_buf_putstring(p->mbuf, toknames[tok]))
+ return(0);
+
+ if ( ! md_buf_putchar(p->mbuf, '\n'))
+ return(0);
+
+ p->pos = 0;
+ p->indent++;
+
+ return(mbuf_indent(p));
+}
+
+
+static int
+roffblkout(void *arg, int tok)
+{
+ struct md_valid *p;
+
+ assert(arg);
+ p = (struct md_valid *)arg;
+
+ if ( ! md_buf_putchar(p->mbuf, '\n'))
+ return(0);
+
+ p->pos = 0;
+ p->indent--;
+
+ return(mbuf_indent(p));
+}
+
+
+static int
+roffin(void *arg, int tok, int *argcp, char **argvp)
+{
+
+ return(1);
+}
+
+
+static int
+roffout(void *arg, int tok)
+{
+
+ return(1);
+}
+
+
+
+static void
+roffmsg(void *arg, enum roffmsg lvl,
+ const char *buf, const char *pos, char *msg)
+{
+ char *level;
+ struct md_valid *p;
+
+ assert(arg);
+ p = (struct md_valid *)arg;
+
+ switch (lvl) {
+ case (ROFF_WARN):
+ if ( ! (MD_WARN_ALL & p->args->warnings))
+ return;
+ level = "warning";
+ break;
+ case (ROFF_ERROR):
+ level = "error";
+ break;
+ default:
+ abort();
+ }
+
+ if (pos)
+ (void)fprintf(stderr, "%s:%zu: %s: %s\n",
+ p->rbuf->name, p->rbuf->line, level, msg);
+ else
+ (void)fprintf(stderr, "%s: %s: %s\n",
+ p->rbuf->name, level, msg);
+
+}
+
+
+static int
+roffdata(void *arg, char *buf)
+{
+ struct md_valid *p;
+
+ assert(arg);
+ p = (struct md_valid *)arg;
+ return(mbuf_data(p, buf));
+}