-/* $Id: libmdocml.c,v 1.3 2008/11/22 20:15:34 kristaps Exp $ */
+/* $Id: libmdocml.c,v 1.18 2008/12/03 14:39:59 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
+#include <ctype.h>
#include <fcntl.h>
#include <err.h>
#include <stdio.h>
#include <unistd.h>
#include "libmdocml.h"
+#include "private.h"
-#define BUFFER_LINE BUFSIZ
-
-struct md_rbuf {
- int fd;
- char *name;
- char *buf;
- size_t bufsz;
- size_t line;
-};
-
-struct md_mbuf {
- int fd;
- char *name;
- char *buf;
- size_t bufsz;
- size_t pos;
-};
-
-typedef int (*md_line) (const struct md_args *, struct md_mbuf *,
- const struct md_rbuf *,
- const char *, size_t);
-typedef int (*md_init) (const struct md_args *, struct md_mbuf *);
-typedef int (*md_exit) (const struct md_args *, struct md_mbuf *);
-
-static int md_line_dummy(const struct md_args *,
- struct md_mbuf *,
- const struct md_rbuf *,
- const char *, size_t);
-
-static int md_line_html4_strict(const struct md_args *,
- struct md_mbuf *,
- const struct md_rbuf *,
- const char *, size_t);
-static int md_init_html4_strict(const struct md_args *,
- struct md_mbuf *);
-static int md_exit_html4_strict(const struct md_args *,
- struct md_mbuf *);
-
-static int md_run_enter(const struct md_args *,
- struct md_mbuf *, struct md_rbuf *);
-static int md_run_leave(const struct md_args *,
- struct md_mbuf *,
- struct md_rbuf *, int);
-
-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);
+#define BUFFER_LINE BUFSIZ /* Default line-buffer size. */
+
+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 ssize_t md_buf_fill(struct md_rbuf *);
+static int md_buf_flush(struct md_mbuf *);
static ssize_t
}
-static int
-md_buf_flush(struct md_mbuf *buf)
+static int md_buf_flush(struct md_mbuf *buf)
{
ssize_t sz;
}
-static int
+int
md_buf_putchar(struct md_mbuf *buf, char c)
{
+
+ assert(buf);
return(md_buf_puts(buf, &c, 1));
}
-static int
+int
+md_buf_putstring(struct md_mbuf *buf, const char *p)
+{
+
+ assert(buf);
+ return(md_buf_puts(buf, p, strlen(p)));
+}
+
+
+int
md_buf_puts(struct md_mbuf *buf, const char *p, size_t sz)
{
size_t ssz;
static int
-md_run_leave(const struct md_args *args,
- struct md_mbuf *mbuf, struct md_rbuf *rbuf, int c)
+md_run_leave(const struct md_args *args, struct md_mbuf *mbuf,
+ struct md_rbuf *rbuf, int c, void *data)
{
assert(args);
assert(mbuf);
/* Run exiters. */
switch (args->type) {
- case (MD_HTML4_STRICT):
- if ( ! md_exit_html4_strict(args, mbuf))
- return(-1);
- break;
- case (MD_DUMMY):
+ case (MD_HTML):
+ if ( ! md_exit_html(data, -1 == c ? 0 : 1))
+ c = -1;
break;
default:
- abort();
+ if ( ! md_exit_xml(data, -1 == c ? 0 : 1))
+ c = -1;
+ break;
}
/* Make final flush of buffer. */
- if ( ! md_buf_flush(mbuf))
+ if (-1 != c && ! 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)
+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];
/* Function ptrs to line-parsers. */
switch (args->type) {
- case (MD_HTML4_STRICT):
- fp = md_line_html4_strict;
- break;
- case (MD_DUMMY):
- fp = md_line_dummy;
+ case (MD_HTML):
+ fp = md_line_html;
break;
default:
- abort();
+ fp = md_line_xml;
+ break;
}
- /* LINTED */
- for (pos = 0; ; ) {
- if (-1 == (sz = md_buf_fill(rbuf)))
- return(-1);
- else if (0 == sz)
- break;
-
- for (i = 0; i < sz; i++) {
- if ('\n' == rbuf->buf[i]) {
- if ( ! (*fp)(args, mbuf, rbuf, line, pos))
- return(-1);
- rbuf->line++;
- pos = 0;
- continue;
- }
-
+ pos = 0;
+
+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 ( ! isascii(rbuf->buf[i])) {
+ warnx("%s: non-ascii char (line %zu, col %zu)",
+ rbuf->name, rbuf->line, pos);
+ return(md_run_leave(args, mbuf, rbuf, -1, p));
+ }
+ */
+ if ('\n' != rbuf->buf[i]) {
if (pos < BUFFER_LINE) {
/* LINTED */
line[pos++] = rbuf->buf[i];
continue;
}
-
warnx("%s: line %zu too long",
rbuf->name, rbuf->line);
- return(-1);
+ return(md_run_leave(args, mbuf, rbuf, -1, p));
}
- }
- if (0 != pos && ! (*fp)(args, mbuf, rbuf, line, pos))
- return(-1);
+ line[(int)pos] = 0;
+ if ( ! (*fp)(p, line))
+ return(md_run_leave(args, mbuf, rbuf, -1, p));
+ rbuf->line++;
+ pos = 0;
+ }
- return(md_run_leave(args, mbuf, rbuf, 0));
+ goto again;
+ /* NOTREACHED */
}
{
struct md_mbuf mbuf;
struct md_rbuf rbuf;
+ void *data;
assert(args);
assert(in);
/* Run initialisers. */
switch (args->type) {
- case (MD_HTML4_STRICT):
- if ( ! md_init_html4_strict(args, &mbuf))
- return(-1);
- break;
- case (MD_DUMMY):
+ case (MD_HTML):
+ data = md_init_html(args, &mbuf, &rbuf);
break;
default:
- abort();
+ data = md_init_xml(args, &mbuf, &rbuf);
+ break;
}
/* Go into mainline. */
- return(md_run_enter(args, &mbuf, &rbuf));
-}
-
-
-static int
-md_line_dummy(const struct md_args *args, struct md_mbuf *out,
- const struct md_rbuf *in, const char *buf, size_t sz)
-{
-
- assert(buf);
- assert(out);
- assert(in);
- assert(args);
-
- if ( ! md_buf_puts(out, buf, sz))
- return(0);
- if ( ! md_buf_putchar(out, '\n'))
- return(0);
-
- return(1);
-}
-
-
-static int
-md_exit_html4_strict(const struct md_args *args, struct md_mbuf *p)
-{
-
- assert(p);
- assert(args);
- return(1);
-}
-
-
-static int
-md_init_html4_strict(const struct md_args *args, struct md_mbuf *p)
-{
-
- assert(p);
- assert(args);
- return(1);
-}
-
-
-static int
-md_line_html4_strict(const struct md_args *args, struct md_mbuf *out,
- const struct md_rbuf *in, const char *buf, size_t sz)
-{
-
- assert(args);
- assert(buf);
- assert(out);
- assert(in);
- (void)sz;
-
- return(1);
+ return(md_run_enter(args, &mbuf, &rbuf, data));
}