diff options
author | Kristaps Dzonsons <kristaps@bsd.lv> | 2008-11-22 18:34:06 +0000 |
---|---|---|
committer | Kristaps Dzonsons <kristaps@bsd.lv> | 2008-11-22 18:34:06 +0000 |
commit | b6bd12c3f0303e71b580e5ff0eb8e9adf580d286 (patch) | |
tree | 4cf373cb08d1c35d3d50040c5ff2f5e7fd52b9f6 /libmdocml.c | |
parent | e2f3428b48d38e841c23392993a67bda84aa96ea (diff) | |
download | mandoc-b6bd12c3f0303e71b580e5ff0eb8e9adf580d286.tar.gz |
Putting md_run and friends into libmdocml (needs work to be useful).
Diffstat (limited to 'libmdocml.c')
-rw-r--r-- | libmdocml.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/libmdocml.c b/libmdocml.c index 17dcd525..9e40da80 100644 --- a/libmdocml.c +++ b/libmdocml.c @@ -16,6 +16,178 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ +#include <assert.h> +#include <fcntl.h> +#include <err.h> +#include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <unistd.h> #include "libmdocml.h" + +#define BUFFER_LINE BUFSIZ + +typedef int (*md_line) (struct md_mbuf *, const struct md_rbuf *, + const char *, size_t); + +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); + + +ssize_t +md_buf_fill(struct md_rbuf *in) +{ + ssize_t ssz; + + assert(in); + assert(in->buf); + assert(in->bufsz > 0); + assert(in->name); + + if (-1 == (ssz = read(in->fd, in->buf, in->bufsz))) + warn("%s", in->name); + + return(ssz); +} + + +int +md_buf_flush(struct md_mbuf *buf) +{ + ssize_t sz; + + assert(buf); + assert(buf->buf); + assert(buf->name); + + if (0 == buf->pos) + return(1); + + sz = write(buf->fd, buf->buf, buf->pos); + + if (-1 == sz) { + warn("%s", buf->name); + return(0); + } else if ((size_t)sz != buf->pos) { + warnx("%s: short write", buf->name); + return(0); + } + + buf->pos = 0; + return(1); +} + + +int +md_buf_putchar(struct md_mbuf *buf, char c) +{ + return(md_buf_puts(buf, &c, 1)); +} + + +int +md_buf_puts(struct md_mbuf *buf, const char *p, size_t sz) +{ + size_t ssz; + + assert(p); + assert(buf); + assert(buf->buf); + + /* LINTED */ + while (buf->pos + sz > buf->bufsz) { + ssz = buf->bufsz - buf->pos; + (void)memcpy(/* LINTED */ + buf->buf + buf->pos, p, ssz); + p += (long)ssz; + sz -= ssz; + buf->pos += ssz; + + if ( ! md_buf_flush(buf)) + return(0); + } + + (void)memcpy(/* LINTED */ + buf->buf + buf->pos, p, sz); + buf->pos += sz; + return(1); +} + + +int +md_run(enum md_type type, struct md_mbuf *out, struct md_rbuf *in) +{ + ssize_t sz, i; + char line[BUFFER_LINE]; + size_t pos; + md_line func; + + assert(in); + assert(out); + + out->pos = 0; + in->line = 1; + + assert(MD_DUMMY == type); + func = md_line_dummy; + + /* 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; + } + + if (pos < BUFFER_LINE) { + /* LINTED */ + line[pos++] = in->buf[i]; + continue; + } + + warnx("%s: line %zu too long", + in->name, in->line); + return(1); + } + } + + if (0 != pos && (*func)(out, in, line, pos)) + return(1); + + return(md_buf_flush(out) ? 0 : 1); +} + + +static int +md_line_dummy(struct md_mbuf *out, const struct md_rbuf *in, + const char *buf, size_t sz) +{ + + assert(buf); + assert(out); + assert(in); + + if ( ! md_buf_puts(out, buf, sz)) + return(1); + if ( ! md_buf_putchar(out, '\n')) + return(1); + + return(0); +} + + |