diff options
-rw-r--r-- | Makefile | 34 | ||||
-rw-r--r-- | compat.c | 90 | ||||
-rw-r--r-- | html.c (renamed from html4_strict.c) | 6 | ||||
-rw-r--r-- | libmdocml.c | 13 | ||||
-rw-r--r-- | libmdocml.h | 6 | ||||
-rw-r--r-- | ml.c | 162 | ||||
-rw-r--r-- | ml.h | 54 | ||||
-rw-r--r-- | mlg.c | 496 | ||||
-rw-r--r-- | private.h | 19 | ||||
-rw-r--r-- | xml.c | 608 |
10 files changed, 756 insertions, 732 deletions
@@ -2,15 +2,15 @@ CFLAGS += -W -Wall -Wno-unused-parameter -g LINTFLAGS += -c -e -f -u -LNS = mdocml.ln html4_strict.ln xml.ln libmdocml.ln roff.ln ml.ln +LNS = mdocml.ln html.ln xml.ln libmdocml.ln roff.ln ml.ln mlg.ln compat.ln LLNS = llib-lmdocml.ln LIBS = libmdocml.a -OBJS = mdocml.o html4_strict.o xml.o libmdocml.o roff.o ml.o +OBJS = mdocml.o html.o xml.o libmdocml.o roff.o ml.o mlg.o compat.o -SRCS = mdocml.c html4_strict.c xml.c libmdocml.c roff.c ml.c +SRCS = mdocml.c html.c xml.c libmdocml.c roff.c ml.c mlg.c compat.c HEADS = libmdocml.h private.h @@ -52,23 +52,23 @@ mdocml.tgz: $(INSTALL) ( cd .dist/ && tar zcf ../mdocml.tgz mdocml/ ) rm -rf .dist/ -llib-lmdocml.ln: mdocml.ln libmdocml.ln html4_strict.ln xml.ln roff.ln ml.ln - $(LINT) $(LINTFLAGS) -Cmdocml mdocml.ln libmdocml.ln html4_strict.ln xml.ln roff.ln ml.ln +llib-lmdocml.ln: mdocml.ln libmdocml.ln html.ln xml.ln roff.ln ml.ln mlg.ln compat.ln + $(LINT) $(LINTFLAGS) -Cmdocml mdocml.ln libmdocml.ln html.ln xml.ln roff.ln ml.ln mlg.ln compat.ln mdocml.ln: mdocml.c libmdocml.h mdocml.o: mdocml.c libmdocml.h -libmdocml.a: libmdocml.o html4_strict.o xml.o roff.o ml.o - $(AR) rs $@ libmdocml.o html4_strict.o xml.o roff.o ml.o +libmdocml.a: libmdocml.o html.o xml.o roff.o ml.o mlg.o compat.o + $(AR) rs $@ libmdocml.o html.o xml.o roff.o ml.o mlg.o compat.o -xml.ln: xml.c private.h libmdocml.h +xml.ln: xml.c private.h libmdocml.h ml.h -xml.o: xml.c private.h libmdocml.h +xml.o: xml.c private.h libmdocml.h ml.h -html4_strict.ln: html4_strict.c private.h libmdocml.h +html.ln: html.c private.h libmdocml.h -html4_strict.o: html4_strict.c private.h libmdocml.h +html.o: html.c private.h libmdocml.h roff.ln: roff.c private.h libmdocml.h @@ -78,6 +78,14 @@ libmdocml.ln: libmdocml.c private.h libmdocml.h libmdocml.o: libmdocml.c private.h libmdocml.h -ml.ln: ml.c private.h libmdocml.h +ml.ln: ml.c private.h libmdocml.h ml.h -ml.o: ml.c private.h libmdocml.h +ml.o: ml.c private.h libmdocml.h ml.h + +mlg.ln: mlg.c private.h libmdocml.h ml.h + +mlg.o: mlg.c private.h libmdocml.h ml.h + +compat.ln: compat.c + +compat.o: compat.c diff --git a/compat.c b/compat.c new file mode 100644 index 00000000..bb1972a3 --- /dev/null +++ b/compat.c @@ -0,0 +1,90 @@ +/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * + * 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/types.h> +#include <string.h> + +#ifdef __linux__ + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} + + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} +#endif /*__linux__*/ @@ -25,7 +25,7 @@ /* ARGSUSED */ int -md_line_html4_strict(void *data, char *buf) +md_line_html(void *data, char *buf) { return(1); @@ -34,7 +34,7 @@ md_line_html4_strict(void *data, char *buf) /* ARGSUSED */ int -md_exit_html4_strict(void *data, int flush) +md_exit_html(void *data, int flush) { return(1); @@ -43,7 +43,7 @@ md_exit_html4_strict(void *data, int flush) /* ARGSUSED */ void * -md_init_html4_strict(const struct md_args *args, +md_init_html(const struct md_args *args, struct md_mbuf *mbuf, const struct md_rbuf *rbuf) { diff --git a/libmdocml.c b/libmdocml.c index 7cf6c079..ba4e850f 100644 --- a/libmdocml.c +++ b/libmdocml.c @@ -139,8 +139,8 @@ md_run_leave(const struct md_args *args, struct md_mbuf *mbuf, /* Run exiters. */ switch (args->type) { - case (MD_HTML4_STRICT): - if ( ! md_exit_html4_strict(data, -1 == c ? 0 : 1)) + case (MD_HTML): + if ( ! md_exit_html(data, -1 == c ? 0 : 1)) c = -1; break; default: @@ -172,8 +172,8 @@ md_run_enter(const struct md_args *args, struct md_mbuf *mbuf, /* Function ptrs to line-parsers. */ switch (args->type) { - case (MD_HTML4_STRICT): - fp = md_line_html4_strict; + case (MD_HTML): + fp = md_line_html; break; default: fp = md_line_xml; @@ -242,9 +242,8 @@ md_run(const struct md_args *args, /* Run initialisers. */ switch (args->type) { - case (MD_HTML4_STRICT): - data = md_init_html4_strict - (args, &mbuf, &rbuf); + case (MD_HTML): + data = md_init_html(args, &mbuf, &rbuf); break; default: data = md_init_xml(args, &mbuf, &rbuf); diff --git a/libmdocml.h b/libmdocml.h index 74174e5f..098b7026 100644 --- a/libmdocml.h +++ b/libmdocml.h @@ -25,18 +25,18 @@ struct md_params_xml { int dummy; }; -struct md_params_html4_strict { +struct md_params_html { int dummy; }; union md_params { struct md_params_xml xml; - struct md_params_html4_strict html4_strict; + struct md_params_html html; }; enum md_type { MD_XML, /* XML. */ - MD_HTML4_STRICT /* HTML4.01-strict. */ + MD_HTML /* HTML4.01-strict. */ }; struct md_args { @@ -21,164 +21,68 @@ #include "libmdocml.h" #include "private.h" +#include "ml.h" +#ifdef __linux__ +extern size_t strlcat(char *, const char *, size_t); +extern size_t strlcpy(char *, const char *, size_t); +#endif -#define MAXINDENT 8 -static ssize_t ml_puts(struct md_mbuf *, const char *); -static ssize_t ml_putchar(struct md_mbuf *, char); -static ssize_t ml_putstring(struct md_mbuf *, const char *); - - -static ssize_t -ml_puts(struct md_mbuf *p, const char *buf) -{ - - return(ml_nputs(p, buf, strlen(buf))); -} - - -static ssize_t -ml_putchar(struct md_mbuf *p, char buf) -{ - - return(ml_nputs(p, &buf, 1)); -} - - -static ssize_t -ml_putstring(struct md_mbuf *p, const char *buf) -{ - - return(ml_nputstring(p, buf, strlen(buf))); -} - - -ssize_t -ml_begintag(struct md_mbuf *p, const char *name, - int *argc, char **argv) -{ - int i; - ssize_t res, sz; - - res = 0; - - if (-1 == (sz = ml_nputs(p, "<", 1))) - return(-1); - res += sz; - - if (-1 == (sz = ml_puts(p, name))) - return(-1); - res += sz; - - for (i = 0; ROFF_ARGMAX != argc[i]; i++) { - if (-1 == (sz = ml_nputs(p, " ", 1))) - return(-1); - res += sz; - - if (-1 == (sz = ml_puts(p, tokargnames[argc[i]]))) - return(-1); - res += sz; - - if (-1 == (sz = ml_nputs(p, "=\"", 2))) - return(-1); - res += sz; - - if (-1 == (sz = ml_putstring(p, argv[i] ? - argv[i] : "true"))) - return(-1); - res += sz; - - if (-1 == (sz = ml_nputs(p, "\"", 1))) - return(-1); - res += sz; - } - - if (-1 == (sz = ml_nputs(p, ">", 1))) - return(-1); - - return(res + sz); -} - - -ssize_t -ml_endtag(struct md_mbuf *p, const char *tag) -{ - ssize_t res, sz; - - res = 0; - - if (-1 == (sz = ml_nputs(p, "</", 2))) - return(-1); - res += sz; - - if (-1 == (sz = ml_puts(p, tag))) - return(-1); - res += sz; - - if (-1 == (sz = ml_nputs(p, ">", 1))) - return(-1); - - return(res + sz); -} - - -ssize_t -ml_nputstring(struct md_mbuf *p, const char *buf, size_t bufsz) +int +ml_nputstring(struct md_mbuf *p, + const char *buf, size_t sz, size_t *pos) { int i; - ssize_t res, sz; - res = 0; - - for (i = 0; i < (int)bufsz; i++) { + for (i = 0; i < (int)sz; i++) { switch (buf[i]) { case ('&'): - if (-1 == (sz = ml_nputs(p, "&", 5))) - return(-1); + if ( ! ml_nputs(p, "&", 5, pos)) + return(0); break; case ('"'): - if (-1 == (sz = ml_nputs(p, """, 6))) - return(-1); + if ( ! ml_nputs(p, """, 6, pos)) + return(0); break; case ('<'): - if (-1 == (sz = ml_nputs(p, "<", 4))) - return(-1); + if ( ! ml_nputs(p, "<", 4, pos)) + return(0); break; case ('>'): - if (-1 == (sz = ml_nputs(p, ">", 4))) - return(-1); + if ( ! ml_nputs(p, ">", 4, pos)) + return(0); break; default: - if (-1 == (sz = ml_putchar(p, buf[i]))) - return(-1); + if ( ! ml_nputs(p, &buf[i], 1, pos)) + return(0); break; } - res += sz; } - return(res); + return(1); } -ssize_t -ml_nputs(struct md_mbuf *p, const char *buf, size_t sz) +int +ml_nputs(struct md_mbuf *p, const char *buf, size_t sz, size_t *pos) { - return(0 == md_buf_puts(p, buf, sz) ? -1 : (ssize_t)sz); + if ( ! md_buf_puts(p, buf, sz)) + return(0); + + *pos += sz; + return(1); } -ssize_t -ml_indent(struct md_mbuf *p, int indent) +int +ml_putchars(struct md_mbuf *p, char buf, size_t count, size_t *pos) { size_t i; - ssize_t res, sz; - res = sz 0; + for (i = 0; i < count; i++) + if ( ! ml_nputs(p, &buf, 1, pos)) + return(0); - /* LINTED */ - for (i = 0; i < MIN(indent, MAXINDENT); i++, res += sz) - if (-1 == (sz = ml_nputs(p, " ", 4))) - return(-1); - return(res); + return(1); } @@ -0,0 +1,54 @@ +/* $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. + */ +#ifndef ML_H +#define ML_H + +struct md_mlg; + +enum md_ns { + MD_NS_BLOCK, + MD_NS_INLINE, + MD_NS_DEFAULT, +}; + +typedef ssize_t (*ml_endtag)(struct md_mbuf *, + const struct md_args *, enum md_ns, int); +typedef ssize_t (*ml_begintag)(struct md_mbuf *, + const struct md_args *, enum md_ns, int, + const int *, const char **); + + +__BEGIN_DECLS + +int ml_nputstring(struct md_mbuf *, + const char *, size_t, size_t *); +int ml_nputs(struct md_mbuf *, + const char *, size_t, size_t *); +int ml_putchars(struct md_mbuf *, + char, size_t, size_t *); + +struct md_mlg *mlg_alloc(const struct md_args *, + const struct md_rbuf *, struct md_mbuf *, + ml_begintag, ml_endtag); +int mlg_exit(struct md_mlg *, int); +int mlg_line(struct md_mlg *, char *); + +__END_DECLS + +#endif /*!ML_H*/ @@ -0,0 +1,496 @@ +/* $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 <assert.h> +#include <ctype.h> +#include <err.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "libmdocml.h" +#include "private.h" +#include "ml.h" + +/* TODO: literal tokens. */ + +#define COLUMNS 72 +#define INDENT 4 +#define MAXINDENT 8 + +enum md_tok { + MD_TEXT, + MD_INLINE_IN, + MD_INLINE_OUT, + MD_BLK_IN, + MD_BLK_OUT, +}; + +struct md_mlg { + const struct md_args *args; + const struct md_rbuf *rbuf; + + struct md_mbuf *mbuf; + struct rofftree *tree; + size_t indent; + size_t pos; + enum md_tok last; + void *arg; + ml_begintag begintag; + ml_endtag endtag; + int flags; +#define ML_OVERRIDE_ONE (1 << 0) +#define ML_OVERRIDE_ALL (1 << 1) +}; + + +static void mlg_roffmsg(void *arg, enum roffmsg, + const char *, const char *, char *); +static int mlg_roffhead(void *); +static int mlg_rofftail(void *); +static int mlg_roffin(void *, int, int *, char **); +static int mlg_roffdata(void *, int, char *); +static int mlg_roffout(void *, int); +static int mlg_roffblkin(void *, int, int *, char **); +static int mlg_roffblkout(void *, int); +static int mlg_roffspecial(void *, int, int *, char **, char **); +static int mlg_begintag(struct md_mlg *, enum md_ns, + int, int *, char **); +static int mlg_endtag(struct md_mlg *, enum md_ns, int); +static int mlg_indent(struct md_mlg *); +static int mlg_newline(struct md_mlg *); +static void mlg_mode(struct md_mlg *, enum md_tok); +static int mlg_data(struct md_mlg *, int, char *); + +#ifdef __linux__ +extern size_t strlcat(char *, const char *, size_t); +extern size_t strlcpy(char *, const char *, size_t); +#endif + + +static int +mlg_begintag(struct md_mlg *p, enum md_ns ns, int tok, + int *argc, char **argv) +{ + ssize_t res; + + /* TODO: extra rules for block/inline. */ + + if ( ! ml_nputs(p->mbuf, "<", 1, &p->pos)) + return(0); + + res = (*p->begintag)(p->mbuf, p->args, ns, tok, + argc, (const char **)argv); + if (-1 == res) + return(0); + + assert(res >= 0); + p->pos += (size_t)res; + + /* TODO: extra rules for block/inline. */ + + return(ml_nputs(p->mbuf, ">", 1, &p->pos)); +} + + +static int +mlg_endtag(struct md_mlg *p, enum md_ns ns, int tok) +{ + ssize_t res; + + /* TODO: extra rules for block/inline. */ + + if ( ! ml_nputs(p->mbuf, "</", 2, &p->pos)) + return(0); + + res = (*p->endtag)(p->mbuf, p->args, ns, tok); + if (-1 == res) + return(0); + + assert(res >= 0); + p->pos += (size_t)res; + + /* TODO: extra rules for block/inline. */ + + return(ml_nputs(p->mbuf, ">", 1, &p->pos)); +} + + +static int +mlg_indent(struct md_mlg *p) +{ + size_t count; + + count = p->indent > MAXINDENT ? MAXINDENT : p->indent; + count *= INDENT; + + assert(0 == p->pos); + return(ml_putchars(p->mbuf, ' ', count, &p->pos)); +} + + +static int +mlg_newline(struct md_mlg *p) +{ + size_t dummy; + + if ( ! ml_nputs(p->mbuf, "\n", 1, &dummy)) + return(0); + p->pos = 0; + return(1); +} + + +static void +mlg_mode(struct md_mlg *p, enum md_tok ns) +{ + p->flags &= ~ML_OVERRIDE_ONE; + p->last = ns; +} + + +static int +mlg_data(struct md_mlg *p, int space, char *buf) +{ + size_t sz; + char *bufp; + + assert(p->mbuf); + assert(0 != p->indent); + + if (ML_OVERRIDE_ONE & p->flags || + ML_OVERRIDE_ALL & p->flags) + space = 0; + + while (*buf) { + while (*buf && isspace(*buf)) + buf++; + + if (0 == *buf) + break; + + bufp = buf; + while (*buf && ! isspace(*buf)) + buf++; + + if (0 != *buf) + *buf++ = 0; + + sz = strlen(bufp); + + if (0 == p->pos) { + if ( ! mlg_indent(p)) + return(0); + if ( ! ml_nputstring(p->mbuf, bufp, + sz, &p->pos)) + return(0); + if (p->indent * MAXINDENT + sz >= COLUMNS) + if ( ! mlg_newline(p)) + return(0); + if ( ! (ML_OVERRIDE_ALL & p->flags)) + space = 1; + continue; + } + + if (space && sz + p->pos >= COLUMNS) { + if ( ! mlg_newline(p)) + return(0); + if ( ! mlg_indent(p)) + return(0); + } else if (space) { + if ( ! ml_nputs(p->mbuf, " ", 1, &p->pos)) + return(0); + } + + if ( ! ml_nputstring(p->mbuf, bufp, sz, &p->pos)) + return(0); + + if ( ! (ML_OVERRIDE_ALL & p->flags)) + space = 1; + } + + return(1); +} + + +int +mlg_line(struct md_mlg *p, char *buf) +{ + + return(roff_engine(p->tree, buf)); +} + + +int +mlg_exit(struct md_mlg *p, int flush) +{ + int c; + + c = roff_free(p->tree, flush); + free(p); + return(c); +} + + +struct md_mlg * +mlg_alloc(const struct md_args *args, + const struct md_rbuf *rbuf, + struct md_mbuf *mbuf, + ml_begintag begintag, ml_endtag endtag) +{ + struct roffcb cb; + struct md_mlg *p; + + cb.roffhead = mlg_roffhead; + cb.rofftail = mlg_rofftail; + cb.roffin = mlg_roffin; + cb.roffout = mlg_roffout; + cb.roffblkin = mlg_roffblkin; + cb.roffblkout = mlg_roffblkout; + cb.roffspecial = mlg_roffspecial; + cb.roffmsg = mlg_roffmsg; + cb.roffdata = mlg_roffdata; + + if (NULL == (p = calloc(1, sizeof(struct md_mlg)))) + err(1, "calloc"); + + p->args = args; + p->mbuf = mbuf; + p->rbuf = rbuf; + p->begintag = begintag; + p->endtag = endtag; + + if (NULL == (p->tree = roff_alloc(&cb, p))) { + free(p); + return(NULL); + } + + return(p); +} + + +static int +mlg_roffhead(void *arg) +{ + struct md_mlg *p; + + assert(arg); + p = (struct md_mlg *)arg; + + mlg_mode(p, MD_BLK_IN); + if ( ! mlg_begintag(p, MD_NS_DEFAULT, -1, NULL, NULL)) + return(0); + + p->indent++; + return(mlg_newline(p)); +} + + +static int +mlg_rofftail(void *arg) +{ + struct md_mlg *p; + + assert(arg); + p = (struct md_mlg *)arg; + + if (0 != p->pos && ! mlg_newline(p)) + return(0); + + mlg_mode(p, MD_BLK_OUT); + if ( ! mlg_endtag(p, -1, MD_NS_DEFAULT)) + return(0); + + return(mlg_newline(p)); +} + + +/* ARGSUSED */ +static int +mlg_roffspecial(void *arg, int tok, int *argc, char **argv, char **more) +{ + struct md_mlg *p; + + assert(arg); + p = (struct md_mlg *)arg; + + switch (tok) { + case (ROFF_Ns): + p->flags |= ML_OVERRIDE_ONE; + break; + case (ROFF_Sm): + assert(*more); + if (0 == strcmp(*more, "on")) + p->flags |= ML_OVERRIDE_ALL; + else + p->flags &= ~ML_OVERRIDE_ALL; + break; + default: + break; + } + + return(1); +} + + +static int +mlg_roffblkin(void *arg, int tok, int *argc, char **argv) +{ + struct md_mlg *p; + + assert(arg); + p = (struct md_mlg *)arg; + + if (0 != p->pos) { + if ( ! mlg_newline(p)) + return(0); + if ( ! mlg_indent(p)) + return(0); + } else if ( ! mlg_indent(p)) + return(0); + + p->indent++; + mlg_mode(p, MD_BLK_IN); + + if ( ! mlg_begintag(p, MD_NS_BLOCK, tok, argc, argv)) + return(0); + return(mlg_newline(p)); +} + + +static int +mlg_roffblkout(void *arg, int tok) +{ + struct md_mlg *p; + + assert(arg); + p = (struct md_mlg *)arg; + + p->indent--; + + if (0 != p->pos) { + if ( ! mlg_newline(p)) + return(0); + if ( ! mlg_indent(p)) + return(0); + } else if ( ! mlg_indent(p)) + return(0); + + mlg_mode(p, MD_BLK_OUT); + if ( ! mlg_endtag(p, MD_NS_BLOCK, tok)) + return(0); + return(mlg_newline(p)); +} + + +static int +mlg_roffin(void *arg, int tok, int *argc, char **argv) +{ + struct md_mlg *p; + + assert(arg); + p = (struct md_mlg *)arg; + + /* FIXME: this part. */ + + if ( ! (ML_OVERRIDE_ONE & p->flags) && + ! (ML_OVERRIDE_ALL & p->flags) && + p->pos + 11 > COLUMNS) + if ( ! mlg_newline(p)) + return(0); + + if (0 != p->pos && (MD_TEXT == p->last || + MD_INLINE_OUT == p->last) + && ! (ML_OVERRIDE_ONE & p->flags) + && ! (ML_OVERRIDE_ALL & p->flags)) + if ( ! ml_nputs(p->mbuf, " ", 1, &p->pos)) + return(0); + + if (0 == p->pos && ! mlg_indent(p)) + return(0); + + mlg_mode(p, MD_INLINE_IN); + return(mlg_begintag(p, MD_NS_INLINE, tok, argc, argv)); +} + + +static int +mlg_roffout(void *arg, int tok) +{ + struct md_mlg *p; + + assert(arg); + p = (struct md_mlg *)arg; + + if (0 == p->pos && ! mlg_indent(p)) + return(0); + + mlg_mode(p, MD_INLINE_OUT); + return(mlg_endtag(p, MD_NS_INLINE, tok)); +} + + +static void +mlg_roffmsg(void *arg, enum roffmsg lvl, + const char *buf, const char *pos, char *msg) +{ + char *level; + struct md_mlg *p; + + assert(arg); + p = (struct md_mlg *)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 (column %zu)\n", + p->rbuf->name, p->rbuf->line, level, + msg, pos - buf); + else + (void)fprintf(stderr, "%s: %s: %s\n", + p->rbuf->name, level, msg); + +} + + +static int +mlg_roffdata(void *arg, int space, char *buf) +{ + struct md_mlg *p; + + assert(arg); + p = (struct md_mlg *)arg; + + if ( ! mlg_data(p, space, buf)) + return(0); + + mlg_mode(p, MD_TEXT); + return(1); +} + @@ -19,7 +19,6 @@ #ifndef PRIVATE_H #define PRIVATE_H -/* Input buffer (input read into buffer, then filled when empty). */ struct md_rbuf { int fd; /* Open descriptor. */ char *name; /* Name of file. */ @@ -28,7 +27,6 @@ struct md_rbuf { size_t line; /* Current line number. */ }; -/* Output buffer (output buffered until full, then flushed). */ struct md_mbuf { int fd; /* Open descriptor. */ char *name; /* Name of file. */ @@ -225,6 +223,8 @@ struct roffcb { int (*roffspecial)(void *, int, int *, char **, char **); }; +struct rofftree; + __BEGIN_DECLS typedef void (*(*md_init)(const struct md_args *, @@ -232,10 +232,10 @@ typedef void (*(*md_init)(const struct md_args *, typedef int (*md_line)(void *, char *); typedef int (*md_exit)(void *, int); -void *md_init_html4_strict(const struct md_args *, +void *md_init_html(const struct md_args *, struct md_mbuf *, const struct md_rbuf *); -int md_line_html4_strict(void *, char *); -int md_exit_html4_strict(void *, int); +int md_line_html(void *, char *); +int md_exit_html(void *, int); void *md_init_xml(const struct md_args *, struct md_mbuf *, const struct md_rbuf *); @@ -246,19 +246,10 @@ int md_buf_puts(struct md_mbuf *, const char *, size_t); int md_buf_putchar(struct md_mbuf *, char); 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 *); int roff_free(struct rofftree *, int); -ssize_t ml_begintag(struct md_mbuf *, const char *, - int *, char **); -ssize_t ml_endtag(struct md_mbuf *, const char *); -ssize_t ml_nputstring(struct md_mbuf *, const char *, size_t); -ssize_t ml_nputs(struct md_mbuf *, const char *, size_t); -ssize_t ml_indent(struct md_mbuf *, int); - __END_DECLS #endif /*!PRIVATE_H*/ @@ -16,295 +16,98 @@ * 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" +#include "ml.h" -#define COLUMNS 72 - -enum md_ns { - MD_NS_BLOCK, - MD_NS_INLINE, - MD_NS_DEFAULT -}; - -enum md_tok { - MD_BLKIN, /* Controls spacing. */ - MD_BLKOUT, - MD_IN, - MD_OUT, - MD_TEXT -}; - -struct md_xml { - const struct md_args *args; - const struct md_rbuf *rbuf; - - struct md_mbuf *mbuf; - struct rofftree *tree; - size_t indent; - size_t pos; - enum md_tok last; - int flags; -#define MD_LITERAL (1 << 0) /* TODO */ -#define MD_OVERRIDE_ONE (1 << 1) -#define MD_OVERRIDE_ALL (1 << 2) -}; - -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 *, int, char *); -static int roffout(void *, int); -static int roffblkin(void *, int, int *, char **); -static int roffblkout(void *, int); -static int roffspecial(void *, int, int *, char **, char **); - -static void mbuf_mode(struct md_xml *, enum md_ns); -static int mbuf_newline(struct md_xml *); -static int xml_indent(struct md_xml *); -static int mbuf_data(struct md_xml *, int, char *); -static int xml_nputstring(struct md_xml *, - const char *, size_t); -static int xml_puts(struct md_xml *, const char *); -static int xml_nputs(struct md_xml *, - const char *, size_t); -static int xml_begintag(struct md_xml *, const char *, - enum md_ns, int *, char **); -static int xml_endtag(struct md_xml *, - const char *, enum md_ns); - -#ifdef __linux__ /* FIXME: remove */ -static size_t strlcat(char *, const char *, size_t); -static size_t strlcpy(char *, const char *, size_t); -#endif - - -static void -mbuf_mode(struct md_xml *p, enum md_ns ns) -{ - p->flags &= ~MD_OVERRIDE_ONE; - p->last = ns; -} +static ssize_t xml_endtag(struct md_mbuf *, + const struct md_args *, + enum md_ns, int); +static ssize_t xml_begintag(struct md_mbuf *, + const struct md_args *, + enum md_ns, int, + const int *, const char **); -static int -xml_begintag(struct md_xml *p, const char *name, enum md_ns ns, - int *argc, char **argv) +static ssize_t +xml_begintag(struct md_mbuf *mbuf, const struct md_args *args, + enum md_ns ns, int tok, + const int *argc, const char **argv) { - char buf[64]; - ssize_t sz; size_t res; + res = 0; + switch (ns) { case (MD_NS_BLOCK): - res = strlcpy(buf, "block:", sizeof(buf)); - assert(res < sizeof(buf)); + if ( ! ml_nputs(mbuf, "block:", 6, &res)) + return(-1); break; case (MD_NS_INLINE): - res = strlcpy(buf, "inline:", sizeof(buf)); - assert(res < sizeof(buf)); + if ( ! ml_nputs(mbuf, "inline:", 7, &res)) + return(-1); break; default: - *buf = 0; - break; + if ( ! ml_nputs(mbuf, "mbuf", 4, &res)) + return(-1); + return((ssize_t)res); } - res = strlcat(buf, name, sizeof(buf)); - assert(res < sizeof(buf)); - - if (-1 == (sz = ml_begintag(p->mbuf, buf, argc, argv))) - return(0); + if ( ! ml_nputs(mbuf, toknames[tok], + strlen(toknames[tok]), &res)) + return(-1); - p->pos += sz; - return(1); + return((ssize_t)res); } -static int -xml_endtag(struct md_xml *p, const char *name, enum md_ns ns) +static ssize_t +xml_endtag(struct md_mbuf *mbuf, const struct md_args *args, + enum md_ns ns, int tok) { - char buf[64]; - ssize_t sz; size_t res; + res = 0; + switch (ns) { case (MD_NS_BLOCK): - res = strlcpy(buf, "block:", sizeof(buf)); - assert(res < sizeof(buf)); + if ( ! ml_nputs(mbuf, "block:", 6, &res)) + return(-1); break; case (MD_NS_INLINE): - res = strlcpy(buf, "inline:", sizeof(buf)); - assert(res < sizeof(buf)); + if ( ! ml_nputs(mbuf, "inline:", 7, &res)) + return(-1); break; default: - *buf = 0; - break; + if ( ! ml_nputs(mbuf, "mbuf", 4, &res)) + return(-1); + return((ssize_t)res); } - res = strlcat(buf, name, sizeof(buf)); - assert(res < sizeof(buf)); - - if (-1 == (sz = ml_endtag(p->mbuf, buf))) - return(0); - - p->pos += sz; - return(1); -} - - -static int -xml_nputstring(struct md_xml *p, const char *buf, size_t sz) -{ - ssize_t res; - - if (-1 == (res = ml_nputstring(p->mbuf, buf, sz))) - return(0); - p->pos += res; - return(1); -} - - -static int -xml_nputs(struct md_xml *p, const char *buf, size_t sz) -{ - ssize_t res; - - if (-1 == (res = ml_nputs(p->mbuf, buf, sz))) - return(0); - p->pos += res; - return(1); -} - - -static int -xml_puts(struct md_xml *p, const char *buf) -{ - - return(xml_nputs(p, buf, strlen(buf))); -} - - -static int -xml_indent(struct md_xml *p) -{ - ssize_t res; - - if (-1 == (res = ml_indent(p->mbuf, p->indent))) - return(0); - p->pos += res; - return(1); -} - - -static int -mbuf_newline(struct md_xml *p) -{ - - if ( ! md_buf_putchar(p->mbuf, '\n')) - return(0); - - p->pos = 0; - return(1); -} - - -static int -mbuf_data(struct md_xml *p, int space, char *buf) -{ - size_t sz; - char *bufp; - - assert(p->mbuf); - assert(0 != p->indent); - - if (MD_OVERRIDE_ONE & p->flags || MD_OVERRIDE_ALL & p->flags) - space = 0; - - if (MD_LITERAL & p->flags) - return(xml_nputstring(p, buf, sizeof(buf))); - - while (*buf) { - while (*buf && isspace(*buf)) - buf++; - - if (0 == *buf) - break; - - bufp = buf; - while (*buf && ! isspace(*buf)) - buf++; - - if (0 != *buf) - *buf++ = 0; - - sz = strlen(bufp); + if ( ! ml_nputs(mbuf, toknames[tok], + strlen(toknames[tok]), &res)) + return(-1); - if (0 == p->pos) { - if ( ! xml_indent(p)) - return(0); - if ( ! xml_nputstring(p, bufp, sz)) - return(0); - if (p->indent * MAXINDENT + sz >= COLUMNS) - if ( ! mbuf_newline(p)) - return(0); - if ( ! (MD_OVERRIDE_ALL & p->flags)) - space = 1; - continue; - } - - if (space && sz + p->pos >= COLUMNS) { - if ( ! mbuf_newline(p)) - return(0); - if ( ! xml_indent(p)) - return(0); - } else if (space) { - if ( ! xml_nputs(p, " ", 1)) - return(0); - } - - if ( ! xml_nputstring(p, bufp, sz)) - return(0); - - if ( ! (MD_OVERRIDE_ALL & p->flags)) - space = 1; - } - - return(1); + return((ssize_t)res); } int -md_line_xml(void *arg, char *buf) +md_line_xml(void *data, char *buf) { - struct md_xml *p; - p = (struct md_xml *)arg; - return(roff_engine(p->tree, buf)); + return(mlg_line((struct md_mlg *)data, buf)); } int md_exit_xml(void *data, int flush) { - int c; - struct md_xml *p; - - p = (struct md_xml *)data; - c = roff_free(p->tree, flush); - free(p); - return(c); + return(mlg_exit((struct md_mlg *)data, flush)); } @@ -312,328 +115,7 @@ void * md_init_xml(const struct md_args *args, struct md_mbuf *mbuf, const struct md_rbuf *rbuf) { - struct roffcb cb; - struct md_xml *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_xml)))) - 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) -{ - struct md_xml *p; - - assert(arg); - p = (struct md_xml *)arg; - - if (-1 == xml_puts(p, "<?xml version=\"1.0\" " - "encoding=\"UTF-8\"?>\n")) - return(0); - if (-1 == xml_puts(p, "<mdoc xmlns:block=\"block\" " - "xmlns:special=\"special\" " - "xmlns:inline=\"inline\">")) - return(0); - - p->indent++; - mbuf_mode(p, MD_BLKIN); - return(mbuf_newline(p)); -} - - -static int -rofftail(void *arg) -{ - struct md_xml *p; - - assert(arg); - p = (struct md_xml *)arg; - - if (0 != p->pos && ! mbuf_newline(p)) - return(0); - - mbuf_mode(p, MD_BLKOUT); - if ( ! xml_endtag(p, "mdoc", MD_NS_DEFAULT)) - return(0); - return(mbuf_newline(p)); + return(mlg_alloc(args, rbuf, mbuf, xml_begintag, xml_endtag)); } - -/* ARGSUSED */ -static int -roffspecial(void *arg, int tok, int *argc, char **argv, char **more) -{ - struct md_xml *p; - - assert(arg); - p = (struct md_xml *)arg; - - /* FIXME: this is completely ad hoc. */ - - switch (tok) { - case (ROFF_Ns): - p->flags |= MD_OVERRIDE_ONE; - break; - case (ROFF_Sm): - assert(*more); - if (0 == strcmp(*more, "on")) - p->flags |= MD_OVERRIDE_ALL; - else - p->flags &= ~MD_OVERRIDE_ALL; - break; - default: - break; - } - - return(1); -} - - -static int -roffblkin(void *arg, int tok, int *argc, char **argv) -{ - struct md_xml *p; - - assert(arg); - p = (struct md_xml *)arg; - - if (0 != p->pos) { - if ( ! mbuf_newline(p)) - return(0); - if ( ! xml_indent(p)) - return(0); - } else if ( ! xml_indent(p)) - return(0); - - /* FIXME: xml won't like standards args (e.g., p1003.1-90). */ - - p->indent++; - mbuf_mode(p, MD_BLKIN); - - if ( ! xml_begintag(p, toknames[tok], MD_NS_BLOCK, - argc, argv)) - return(0); - return(mbuf_newline(p)); -} - - -static int -roffblkout(void *arg, int tok) -{ - struct md_xml *p; - - assert(arg); - p = (struct md_xml *)arg; - - p->indent--; - - if (0 != p->pos) { - if ( ! mbuf_newline(p)) - return(0); - if ( ! xml_indent(p)) - return(0); - } else if ( ! xml_indent(p)) - return(0); - - mbuf_mode(p, MD_BLKOUT); - if ( ! xml_endtag(p, toknames[tok], MD_NS_BLOCK)) - return(0); - return(mbuf_newline(p)); -} - - -static int -roffin(void *arg, int tok, int *argc, char **argv) -{ - struct md_xml *p; - - assert(arg); - p = (struct md_xml *)arg; - - if ( ! (MD_OVERRIDE_ONE & p->flags) && - ! (MD_OVERRIDE_ALL & p->flags) && - p->pos + 11 > COLUMNS) - if ( ! mbuf_newline(p)) - return(0); - - if (0 != p->pos && (MD_TEXT == p->last || MD_OUT == p->last) - && ! (MD_OVERRIDE_ONE & p->flags) - && ! (MD_OVERRIDE_ALL & p->flags)) - if ( ! xml_nputs(p, " ", 1)) - return(0); - - if (0 == p->pos && ! xml_indent(p)) - return(0); - - mbuf_mode(p, MD_IN); - return(xml_begintag(p, toknames[tok], - MD_NS_INLINE, argc, argv)); -} - - -static int -roffout(void *arg, int tok) -{ - struct md_xml *p; - - assert(arg); - p = (struct md_xml *)arg; - - if (0 == p->pos && ! xml_indent(p)) - return(0); - - mbuf_mode(p, MD_OUT); - return(xml_endtag(p, toknames[tok], MD_NS_INLINE)); -} - - -static void -roffmsg(void *arg, enum roffmsg lvl, - const char *buf, const char *pos, char *msg) -{ - char *level; - struct md_xml *p; - - assert(arg); - p = (struct md_xml *)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 (column %zu)\n", - p->rbuf->name, p->rbuf->line, level, - msg, pos - buf); - else - (void)fprintf(stderr, "%s: %s: %s\n", - p->rbuf->name, level, msg); - -} - - -static int -roffdata(void *arg, int space, char *buf) -{ - struct md_xml *p; - - assert(arg); - p = (struct md_xml *)arg; - if ( ! mbuf_data(p, space, buf)) - return(0); - - mbuf_mode(p, MD_TEXT); - return(1); -} - - -#ifdef __linux /* FIXME: remove. */ -/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - * - * 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. - */ -static size_t -strlcat(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past - * end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ -} - - -static size_t -strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0) { - while (--n != 0) { - if ((*d++ = *s++) == '\0') - break; - } - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} -#endif /*__linux__*/ |