Return to libmdocml.c CVS log | Up to [cvsweb.bsd.lv] / mandoc |
version 1.2, 2008/11/22 18:34:06 | version 1.11, 2008/11/27 16:54:58 | ||
---|---|---|---|
|
|
||
* PERFORMANCE OF THIS SOFTWARE. | * PERFORMANCE OF THIS SOFTWARE. | ||
*/ | */ | ||
#include <assert.h> | #include <assert.h> | ||
#include <ctype.h> | |||
#include <fcntl.h> | #include <fcntl.h> | ||
#include <err.h> | #include <err.h> | ||
#include <stdio.h> | #include <stdio.h> | ||
|
|
||
#include <unistd.h> | #include <unistd.h> | ||
#include "libmdocml.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 *, | static int md_run_enter(const struct md_args *, | ||
const char *, size_t); | 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 *, | static ssize_t md_buf_fill(struct md_rbuf *); | ||
const struct md_rbuf *, | static int md_buf_flush(struct md_mbuf *); | ||
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); | |||
ssize_t | static ssize_t | ||
md_buf_fill(struct md_rbuf *in) | md_buf_fill(struct md_rbuf *in) | ||
{ | { | ||
ssize_t ssz; | ssize_t ssz; | ||
|
|
||
} | } | ||
int | static int | ||
md_buf_flush(struct md_mbuf *buf) | md_buf_flush(struct md_mbuf *buf) | ||
{ | { | ||
ssize_t sz; | ssize_t sz; | ||
|
|
||
int | 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) | md_buf_puts(struct md_mbuf *buf, const char *p, size_t sz) | ||
{ | { | ||
size_t ssz; | size_t ssz; | ||
|
|
||
} | } | ||
int | static int | ||
md_run(enum md_type type, struct md_mbuf *out, struct md_rbuf *in) | 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; | ssize_t sz, i; | ||
char line[BUFFER_LINE]; | char line[BUFFER_LINE]; | ||
size_t pos; | size_t pos; | ||
md_line func; | md_line fp; | ||
assert(in); | assert(args); | ||
assert(out); | assert(mbuf); | ||
assert(rbuf); | |||
out->pos = 0; | /* Function ptrs to line-parsers. */ | ||
in->line = 1; | switch (args->type) { | ||
case (MD_HTML4_STRICT): | |||
fp = md_line_html4_strict; | |||
break; | |||
default: | |||
fp = md_line_dummy; | |||
break; | |||
} | |||
assert(MD_DUMMY == type); | pos = 0; | ||
func = md_line_dummy; | |||
/* LINTED */ | again: | ||
for (pos = 0; ; ) { | if (-1 == (sz = md_buf_fill(rbuf))) { | ||
if (-1 == (sz = md_buf_fill(in))) | return(md_run_leave(args, mbuf, rbuf, -1, p)); | ||
return(1); | } else if (0 == sz && 0 != pos) { | ||
else if (0 == sz) | warnx("%s: no newline at end of file", rbuf->name); | ||
break; | 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++) { | for (i = 0; i < sz; i++) { | ||
if ('\n' == in->buf[i]) { | /* | ||
if ((*func)(out, in, line, pos)) | if ( ! isascii(rbuf->buf[i])) { | ||
return(1); | warnx("%s: non-ascii char (line %zu, col %zu)", | ||
in->line++; | rbuf->name, rbuf->line, pos); | ||
pos = 0; | return(md_run_leave(args, mbuf, rbuf, -1, p)); | ||
continue; | } | ||
} | */ | ||
if ('\n' != rbuf->buf[i]) { | |||
if (pos < BUFFER_LINE) { | if (pos < BUFFER_LINE) { | ||
/* LINTED */ | /* LINTED */ | ||
line[pos++] = in->buf[i]; | line[pos++] = rbuf->buf[i]; | ||
continue; | continue; | ||
} | } | ||
warnx("%s: line %zu too long", | warnx("%s: line %zu too long", | ||
in->name, in->line); | rbuf->name, rbuf->line); | ||
return(1); | return(md_run_leave(args, mbuf, rbuf, -1, p)); | ||
} | } | ||
line[pos] = 0; | |||
if ( ! (*fp)(p, line, pos)) | |||
return(md_run_leave(args, mbuf, rbuf, -1, p)); | |||
rbuf->line++; | |||
pos = 0; | |||
} | } | ||
if (0 != pos && (*func)(out, in, line, pos)) | goto again; | ||
return(1); | /* NOTREACHED */ | ||
return(md_buf_flush(out) ? 0 : 1); | |||
} | } | ||
static int | int | ||
md_line_dummy(struct md_mbuf *out, const struct md_rbuf *in, | md_run(const struct md_args *args, | ||
const char *buf, size_t sz) | const struct md_buf *out, const struct md_buf *in) | ||
{ | { | ||
struct md_mbuf mbuf; | |||
struct md_rbuf rbuf; | |||
void *data; | |||
assert(buf); | assert(args); | ||
assert(out); | |||
assert(in); | assert(in); | ||
assert(out); | |||
if ( ! md_buf_puts(out, buf, sz)) | (void)memcpy(&mbuf, out, sizeof(struct md_buf)); | ||
return(1); | (void)memcpy(&rbuf, in, sizeof(struct md_buf)); | ||
if ( ! md_buf_putchar(out, '\n')) | |||
return(1); | |||
return(0); | 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; | |||
} | |||
/* Go into mainline. */ | |||
return(md_run_enter(args, &mbuf, &rbuf, data)); | |||
} |