-/* $Id: libmdocml.c,v 1.2 2008/11/22 18:34:06 kristaps Exp $ */
+/* $Id: libmdocml.c,v 1.9 2008/11/24 14:24:55 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
#include <unistd.h>
#include "libmdocml.h"
+#include "private.h"
-#define BUFFER_LINE BUFSIZ
+#define BUFFER_LINE BUFSIZ /* Default line-buffer size. */
-typedef int (*md_line) (struct md_mbuf *, const struct md_rbuf *,
- const char *, size_t);
+static int md_run_enter(const struct md_args *,
+ struct md_mbuf *, struct md_rbuf *, void *);
+static int md_run_leave(const struct md_args *, struct md_mbuf *,
+ struct md_rbuf *, int, void *);
-static int md_line_dummy(struct md_mbuf *,
- const struct md_rbuf *,
- const char *, size_t);
-static ssize_t md_buf_fill(struct md_rbuf *);
-static int md_buf_flush(struct md_mbuf *);
-static int md_buf_putchar(struct md_mbuf *, char);
-static int md_buf_puts(struct md_mbuf *,
- const char *, size_t);
+static ssize_t md_buf_fill(struct md_rbuf *);
+static int md_buf_flush(struct md_mbuf *);
-ssize_t
+static ssize_t
md_buf_fill(struct md_rbuf *in)
{
ssize_t ssz;
}
-int
+static int
md_buf_flush(struct md_mbuf *buf)
{
ssize_t sz;
}
+int
+md_buf_putstring(struct md_mbuf *buf, const char *p)
+{
+ return(md_buf_puts(buf, p, strlen(p)));
+}
+
+
int
md_buf_puts(struct md_mbuf *buf, const char *p, size_t sz)
{
}
-int
-md_run(enum md_type type, struct md_mbuf *out, struct md_rbuf *in)
+static int
+md_run_leave(const struct md_args *args, struct md_mbuf *mbuf,
+ struct md_rbuf *rbuf, int c, void *data)
+{
+ assert(args);
+ assert(mbuf);
+ assert(rbuf);
+
+ /* Run exiters. */
+ switch (args->type) {
+ case (MD_HTML4_STRICT):
+ if ( ! md_exit_html4_strict(data, -1 == c ? 0 : 1))
+ c = -1;
+ break;
+ default:
+ if ( ! md_exit_dummy(data, -1 == c ? 0 : 1))
+ c = -1;
+ break;
+ }
+
+ /* Make final flush of buffer. */
+ if ( ! md_buf_flush(mbuf))
+ return(-1);
+
+ return(c);
+}
+
+
+static int
+md_run_enter(const struct md_args *args, struct md_mbuf *mbuf,
+ struct md_rbuf *rbuf, void *p)
{
ssize_t sz, i;
char line[BUFFER_LINE];
size_t pos;
- md_line func;
-
- assert(in);
- assert(out);
-
- out->pos = 0;
- in->line = 1;
+ md_line fp;
+
+ assert(args);
+ assert(mbuf);
+ assert(rbuf);
+
+ /* Function ptrs to line-parsers. */
+ switch (args->type) {
+ case (MD_HTML4_STRICT):
+ fp = md_line_html4_strict;
+ break;
+ default:
+ fp = md_line_dummy;
+ break;
+ }
- assert(MD_DUMMY == type);
- func = md_line_dummy;
+ pos = 0;
- /* LINTED */
- for (pos = 0; ; ) {
- if (-1 == (sz = md_buf_fill(in)))
- return(1);
- else if (0 == sz)
- break;
-
- for (i = 0; i < sz; i++) {
- if ('\n' == in->buf[i]) {
- if ((*func)(out, in, line, pos))
- return(1);
- in->line++;
- pos = 0;
- continue;
- }
+again:
+ if (-1 == (sz = md_buf_fill(rbuf))) {
+ return(md_run_leave(args, mbuf, rbuf, -1, p));
+ } else if (0 == sz && 0 != pos) {
+ warnx("%s: no newline at end of file", rbuf->name);
+ return(md_run_leave(args, mbuf, rbuf, -1, p));
+ } else if (0 == sz)
+ return(md_run_leave(args, mbuf, rbuf, 0, p));
+ for (i = 0; i < sz; i++) {
+ if ('\n' != rbuf->buf[i]) {
if (pos < BUFFER_LINE) {
/* LINTED */
- line[pos++] = in->buf[i];
+ line[pos++] = rbuf->buf[i];
continue;
}
-
warnx("%s: line %zu too long",
- in->name, in->line);
- return(1);
+ rbuf->name, rbuf->line);
+ return(md_run_leave(args, mbuf, rbuf, -1, p));
}
- }
- if (0 != pos && (*func)(out, in, line, pos))
- return(1);
+ line[pos] = 0;
+ if ( ! (*fp)(p, line, pos))
+ return(md_run_leave(args, mbuf, rbuf, -1, p));
+ rbuf->line++;
+ pos = 0;
+ }
- return(md_buf_flush(out) ? 0 : 1);
+ goto again;
+ /* NOTREACHED */
}
-static int
-md_line_dummy(struct md_mbuf *out, const struct md_rbuf *in,
- const char *buf, size_t sz)
+int
+md_run(const struct md_args *args,
+ const struct md_buf *out, const struct md_buf *in)
{
+ struct md_mbuf mbuf;
+ struct md_rbuf rbuf;
+ void *data;
- assert(buf);
- assert(out);
+ assert(args);
assert(in);
+ assert(out);
- if ( ! md_buf_puts(out, buf, sz))
- return(1);
- if ( ! md_buf_putchar(out, '\n'))
- return(1);
+ (void)memcpy(&mbuf, out, sizeof(struct md_buf));
+ (void)memcpy(&rbuf, in, sizeof(struct md_buf));
+
+ mbuf.pos = 0;
+ rbuf.line = 1;
+
+ /* Run initialisers. */
+ switch (args->type) {
+ case (MD_HTML4_STRICT):
+ data = md_init_html4_strict
+ (args, &mbuf, &rbuf);
+ break;
+ default:
+ data = md_init_dummy
+ (args, &mbuf, &rbuf);
+ break;
+ }
- return(0);
+ /* Go into mainline. */
+ return(md_run_enter(args, &mbuf, &rbuf, data));
}
-
-