diff options
-rw-r--r-- | Makefile | 175 | ||||
-rw-r--r-- | compat.c | 1 | ||||
-rw-r--r-- | hash.c | 126 | ||||
-rw-r--r-- | html.c | 1085 | ||||
-rw-r--r-- | html.h | 86 | ||||
-rw-r--r-- | index.7 | 156 | ||||
-rw-r--r-- | libmdocml.c | 261 | ||||
-rw-r--r-- | libmdocml.h | 67 | ||||
-rw-r--r-- | literals.c | 615 | ||||
-rw-r--r-- | macro.c | 292 | ||||
-rw-r--r-- | mdoc.c | 734 | ||||
-rw-r--r-- | mdoc.h | 289 | ||||
-rw-r--r-- | mdocml.c | 461 | ||||
-rw-r--r-- | mdocml.css | 58 | ||||
-rw-r--r-- | ml.c | 261 | ||||
-rw-r--r-- | ml.h | 93 | ||||
-rw-r--r-- | mlg.c | 868 | ||||
-rw-r--r-- | noop.c | 294 | ||||
-rw-r--r-- | private.h | 405 | ||||
-rw-r--r-- | tags.c | 188 | ||||
-rw-r--r-- | tokens.c | 193 | ||||
-rw-r--r-- | xml.c | 235 |
22 files changed, 1771 insertions, 5172 deletions
@@ -1,174 +1,57 @@ -VERSION = 1.0.3 +VERSION = 1.1.0 -# FIXME -CFLAGS += -W -Wall -Wno-unused-parameter -g -DDEBUG +CFLAGS += -W -Wall -Wno-unused-parameter -g -LNS = mdocml.ln html.ln xml.ln libmdocml.ln roff.ln ml.ln mlg.ln \ - compat.ln tokens.ln literals.ln tags.ln noop.ln +LNS = macro.ln mdoc.ln mdocml.ln hash.ln -LLNS = llib-lmdocml.ln +LLNS = llib-llibmdoc.ln llib-lmdocml.ln -LIBS = libmdocml.a +LIBS = libmdoc.a -OBJS = mdocml.o html.o xml.o libmdocml.o roff.o ml.o mlg.o \ - compat.o tokens.o literals.o tags.o noop.o +OBJS = macro.o mdoc.o mdocml.o hash.o -SRCS = mdocml.c html.c xml.c libmdocml.c roff.c ml.c mlg.c \ - compat.c tokens.c literals.c tags.c noop.c +SRCS = macro.c mdoc.c mdocml.c hash.c -HEADS = libmdocml.h private.h ml.h roff.h html.h +HEADS = mdoc.h -MANS = mdocml.1 index.7 +BINS = mdocml -HTML = index.html mdocml.html +CLEAN = $(BINS) $(LNS) $(LLNS) $(LIBS) $(OBJS) -XML = index.xml +all: $(BINS) -TEXT = index.txt +lint: $(LLNS) -CLEAN = mdocml $(LLNS) $(LNS) $(OBJS) $(LIBS) $(HTML) $(XML) $(TEXT) \ - mdocml-$(VERSION).tar.gz mdocml-port-$(VERSION).tar.gz - -INSTALL = Makefile $(HEADS) $(SRCS) $(MANS) mdocml.css - -FAIL = test.0 test.1 test.2 test.3 test.4 test.5 test.6 \ - test.15 test.20 test.22 test.24 test.26 test.27 test.30 \ - test.36 test.37 test.40 test.50 test.61 test.64 test.65 \ - test.66 test.69 test.70 - -SUCCEED = test.7 test.8 test.9 test.10 test.11 test.12 test.13 \ - test.14 test.16 test.17 test.18 test.19 test.21 test.23 \ - test.25 test.28 test.29 test.31 test.32 test.33 test.34 \ - test.35 test.38 test.39 test.41 test.42 test.43 test.44 \ - test.45 test.46 test.47 test.48 test.49 test.51 test.52 \ - test.54 test.55 test.56 test.57 test.58 test.59 test.60 \ - test.62 test.63 test.67 test.68 test.71 test.72 test.73 - -all: mdocml - -lint: llib-lmdocml.ln - -dist: mdocml-$(VERSION).tar.gz mdocml-port-$(VERSION).tar.gz - -www: all $(HTML) $(XML) $(TEXT) - -regress: mdocml - @for f in $(FAIL); do \ - echo "./mdocml $$f" ; \ - ./mdocml -v $$f 1>/dev/null 2>/dev/null || continue ; \ - done - @for f in $(SUCCEED); do \ - echo "./mdocml $$f" ; \ - ./mdocml -v $$f 1>/dev/null || exit 1 ; \ - done - -mdocml: mdocml.o libmdocml.a - $(CC) $(CFLAGS) -o $@ mdocml.o libmdocml.a +mdocml: mdocml.o libmdoc.a + $(CC) $(CFLAGS) -o $@ mdocml.o libmdoc.a clean: rm -f $(CLEAN) -index.html: index.7 mdocml.css - ./mdocml -fhtml -Wall -e -o $@ index.7 - -index.xml: index.7 mdocml.css - ./mdocml -fxml -Wall -o $@ index.7 - -index.txt: index.7 - cp -f index.7 index.txt - -mdocml.html: mdocml.1 mdocml.css - ./mdocml -Wall -fhtml -e -o $@ mdocml.1 - -install: - mkdir -p $(PREFIX)/bin/ - install -m 0755 mdocml $(PREFIX)/bin/ - mkdir -p $(PREFIX)/man/man1/ - install -m 0444 mdocml.1 $(PREFIX)/man/man1/ - mkdir -p $(PREFIX)/share/mdocml/ - install -m 0444 mdocml.css $(PREFIX)/share/mdocml/ - -uninstall: - rm -f $(PREFIX)/bin/mdocml - rm -f $(PREFIX)/man/man1/mdocml.1 - rm -f $(PREFIX)/share/mdocml/mdocml.css - -install-www: www dist - install -m 0644 mdocml-$(VERSION).tar.gz $(PREFIX)/ - install -m 0644 mdocml-$(VERSION).tar.gz $(PREFIX)/mdocml.tar.gz - install -m 0644 mdocml-port-$(VERSION).tar.gz $(PREFIX)/ - install -m 0644 mdocml-port-$(VERSION).tar.gz $(PREFIX)/mdocml-port.tar.gz - install -m 0644 $(HTML) $(XML) $(TEXT) $(PREFIX)/ - -mdocml-$(VERSION).tar.gz: $(INSTALL) - mkdir -p .dist/mdocml/mdocml-$(VERSION)/ - install -m 0644 $(INSTALL) .dist/mdocml/mdocml-$(VERSION)/ - ( cd .dist/mdocml/ && tar zcf ../../$@ mdocml-$(VERSION)/ ) - rm -rf .dist/ - -mdocml-port-$(VERSION).tar.gz: $(INSTALL) - mkdir -p .dist/mdocml/pkg - sed -e "s!@VERSION@!$(VERSION)!" Makefile.port > .dist/mdocml/Makefile - md5 mdocml-$(VERSION).tar.gz > .dist/mdocml/distinfo - rmd160 mdocml-$(VERSION).tar.gz >> .dist/mdocml/distinfo - sha1 mdocml-$(VERSION).tar.gz >> .dist/mdocml/distinfo - install -m 0644 DESCR .dist/mdocml/pkg/DESCR - echo @comment $$OpenBSD$$ > .dist/mdocml/pkg/PLIST - echo bin/mdocml >> .dist/mdocml/pkg/PLIST - echo share/mdocml/mdocml.css >> .dist/mdocml/pkg/PLIST - echo @man man/man1/mdocml.1 >> .dist/mdocml/pkg/PLIST - ( cd .dist/ && tar zcf ../$@ mdocml/ ) - rm -rf .dist/ - -llib-lmdocml.ln: mdocml.ln libmdocml.ln html.ln xml.ln roff.ln ml.ln mlg.ln compat.ln tokens.ln literals.ln tags.ln noop.ln - $(LINT) $(LINTFLAGS) -Cmdocml mdocml.ln libmdocml.ln html.ln xml.ln roff.ln ml.ln mlg.ln compat.ln tokens.ln literals.ln tags.ln noop.ln - -mdocml.ln: mdocml.c libmdocml.h - -mdocml.o: mdocml.c libmdocml.h - -libmdocml.a: libmdocml.o html.o xml.o roff.o ml.o mlg.o compat.o tokens.o literals.o tags.o noop.o - $(AR) rs $@ libmdocml.o html.o xml.o roff.o ml.o mlg.o compat.o tokens.o literals.o tags.o noop.o - -xml.ln: xml.c ml.h - -xml.o: xml.c ml.h - -html.ln: html.c private.h - -html.o: html.c private.h - -tags.ln: tags.c html.h - -tags.o: tags.c html.h - -roff.ln: roff.c private.h - -roff.o: roff.c private.h - -libmdocml.ln: libmdocml.c private.h - -libmdocml.o: libmdocml.c private.h +llib-llibmdoc.ln: macro.ln mdoc.ln hash.ln + $(LINT) $(LINTFLAGS) -Cllibmdoc mdoc.ln macro.ln hash.ln -ml.ln: ml.c ml.h +llib-llmdocml.ln: mdocml.ln llib-llibmdoc.ln + $(LINT) $(LINTFLAGS) -Cllibmdoc mdocml.ln llib-llibmdoc.ln -ml.o: ml.c ml.h +macro.ln: macro.c private.h -mlg.ln: mlg.c ml.h +macro.o: macro.c private.h -mlg.o: mlg.c ml.h +hash.ln: hash.c private.h -compat.ln: compat.c +hash.o: hash.c private.h -compat.o: compat.c +mdoc.ln: mdoc.c private.h -noop.ln: noop.c private.h +mdoc.o: mdoc.c private.h -noop.o: noop.c private.h +mdocml.ln: mdocml.c mdoc.h -html.h: ml.h +mdocml.o: mdocml.c mdoc.h -ml.h: private.h +private.h: mdoc.h -private.h: libmdocml.h +libmdoc.a: macro.o mdoc.o hash.o + $(AR) rs $@ macro.o mdoc.o hash.o @@ -87,4 +87,5 @@ strlcpy(char *dst, const char *src, size_t siz) return(s - src - 1); /* count does not include NUL */ } + #endif /*__linux__*/ @@ -0,0 +1,126 @@ +/* $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 "private.h" + + +void +mdoc_hash_free(void *htab) +{ + + free(htab); +} + + +void * +mdoc_hash_alloc(void) +{ + int i, major, minor, index; + const void **htab; + + htab = calloc(27 * 26, sizeof(struct mdoc_macro *)); + if (NULL == htab) + err(1, "calloc"); + + for (i = 1; i < MDOC_MAX; i++) { + major = mdoc_macronames[i][0]; + assert((major >= 65 && major <= 90) || + major == 37); + + if (major == 37) + major = 0; + else + major -= 64; + + minor = mdoc_macronames[i][1]; + assert((minor >= 65 && minor <= 90) || + (minor == 49) || + (minor >= 97 && minor <= 122)); + + if (minor == 49) + minor = 0; + else if (minor <= 90) + minor -= 65; + else + minor -= 97; + + assert(major >= 0 && major < 27); + assert(minor >= 0 && minor < 26); + + index = (major * 27) + minor; + + assert(NULL == htab[index]); + htab[index] = &mdoc_macros[i]; + } + + return((void *)htab); +} + + +int +mdoc_hash_find(const void *arg, const char *tmp) +{ + int major, minor, index, slot; + const void **htab; + + htab = (const void **)arg; + + if (0 == tmp[0] || 0 == tmp[1]) + return(MDOC_MAX); + + if ( ! (tmp[0] == 37 || (tmp[0] >= 65 && tmp[0] <= 90))) + return(MDOC_MAX); + + if ( ! ((tmp[1] >= 65 && tmp[1] <= 90) || + (tmp[1] == 49) || + (tmp[1] >= 97 && tmp[1] <= 122))) + return(MDOC_MAX); + + if (tmp[0] == 37) + major = 0; + else + major = tmp[0] - 64; + + if (tmp[1] == 49) + minor = 0; + else if (tmp[1] <= 90) + minor = tmp[1] - 65; + else + minor = tmp[1] - 97; + + index = (major * 27) + minor; + + if (NULL == htab[index]) + return(MDOC_MAX); + + slot = htab[index] - (void *)mdoc_macros; + assert(0 == slot % sizeof(struct mdoc_macro)); + slot /= sizeof(struct mdoc_macro); + + if (0 != strcmp(mdoc_macronames[slot], tmp)) + return(MDOC_MAX); + return(slot); +} + diff --git a/html.c b/html.c deleted file mode 100644 index 6d34045f..00000000 --- a/html.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* $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 <sys/param.h> -#include <sys/stat.h> - -#include <assert.h> -#include <err.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -#include "html.h" -#include "ml.h" - -/* TODO: allow head/tail-less invocations (just "div" start). */ - -struct htmlnode { - int tok; - enum md_ns ns; - int argc[ROFF_MAXLINEARG]; - char *argv[ROFF_MAXLINEARG]; - struct htmlnode *parent; -}; - -struct htmlq { - struct htmlnode *last; -}; - - -static int html_loadcss(struct md_mbuf *, - const char *); -static int html_alloc(void **); -static void html_free(void *); -static ssize_t html_endtag(struct ml_args *, - enum md_ns, int); -static ssize_t html_beginstring(struct ml_args *, - const char *, size_t); -static ssize_t html_endstring(struct ml_args *, - const char *, size_t); -static ssize_t html_begintag(struct ml_args *, - enum md_ns, int, - const int *, const char **); -static int html_begin(struct ml_args *, - const struct tm *, - const char *, const char *, - enum roffmsec, enum roffvol); -static int html_end(struct ml_args *, - const struct tm *, - const char *, const char *, - enum roffmsec, enum roffvol); -static int html_printargs(struct md_mbuf *, int, - const char *, const int *, - const char **, size_t *); -static ssize_t html_beginhttp(struct md_mbuf *, - const struct md_args *, - const char *, size_t); -static ssize_t html_endhttp(struct md_mbuf *, - const struct md_args *, - const char *, size_t); -static int html_blocktagname(struct md_mbuf *, - const struct md_args *, int, - struct htmlq *, const int *, - const char **, size_t *); -static int html_blocktagargs(struct md_mbuf *, - const struct md_args *, int, - const int *, const char **, size_t *); -static int html_headtagname(struct md_mbuf *, - const struct md_args *, int, - struct htmlq *, const int *, - const char **, size_t *); -static int html_headtagargs(struct md_mbuf *, - const struct md_args *, int, - const int *, const char **, size_t *); -static int html_bodytagname(struct md_mbuf *, - const struct md_args *, - int, struct htmlq *, const int *, - const char **, size_t *); -static int html_bodytagargs(struct md_mbuf *, - const struct md_args *, int, - const int *, const char **, size_t *); -static int html_inlinetagname(struct md_mbuf *, - const struct md_args *, int, size_t *); -static int html_inlinetagargs(struct md_mbuf *, - const struct md_args *, int, - const int *, const char **, size_t *); -static int html_Bl_bodytagname(struct md_mbuf *, - struct htmlq *, const int *, - const char **, size_t *); -static int html_It_blocktagname(struct md_mbuf *, - struct htmlq *, const int *, - const char **, size_t *); -static int html_It_headtagname(struct md_mbuf *, - struct htmlq *, const int *, - const char **, size_t *); -static int html_It_bodytagname(struct md_mbuf *, - struct htmlq *, const int *, - const char **, size_t *); -static int html_tputln(struct md_mbuf *, - enum ml_scope, int, enum html_tag); -static int html_aputln(struct md_mbuf *, enum ml_scope, - int, enum html_tag, - int, const struct html_pair *); - - -/* ARGSUSED */ -static int -html_It_headtagname(struct md_mbuf *mbuf, struct htmlq *q, - const int *argc, const char **argv, size_t *res) -{ - struct htmlnode *n; - int i; - struct html_pair attr[2]; - - for (n = q->last; n; n = n->parent) - if (n->tok == ROFF_Bl) - break; - - assert(n); - - /* LINTED */ - for (i = 0; ROFF_ARGMAX != n->argc[i] && - i < ROFF_MAXLINEARG; i++) { - switch (n->argc[i]) { - case (ROFF_Ohang): - return(html_stput(mbuf, HTML_TAG_DIV, res)); - case (ROFF_Tag): - attr[0].attr = HTML_ATTR_VALIGN; - attr[0].val = "top"; - attr[1].attr = HTML_ATTR_NOWRAP; - attr[1].val = "true"; - return(html_saput(mbuf, HTML_TAG_TD, - res, 2, attr)); - case (ROFF_Column): - attr[0].attr = HTML_ATTR_VALIGN; - attr[0].val = "top"; - return(html_saput(mbuf, HTML_TAG_TD, - res, 1, attr)); - default: - break; - } - } - - return(0); -} - - -/* ARGSUSED */ -static int -html_It_bodytagname(struct md_mbuf *mbuf, struct htmlq *q, - const int *argc, const char **argv, size_t *res) -{ - struct htmlnode *n; - int i; - struct html_pair attr[1]; - - for (n = q->last; n; n = n->parent) - if (n->tok == ROFF_Bl) - break; - - assert(n); - - /* LINTED */ - for (i = 0; ROFF_ARGMAX != n->argc[i] && - i < ROFF_MAXLINEARG; i++) { - switch (n->argc[i]) { - case (ROFF_Enum): - /* FALLTHROUGH */ - case (ROFF_Bullet): - /* FALLTHROUGH */ - case (ROFF_Dash): - /* FALLTHROUGH */ - case (ROFF_Hyphen): - /* FALLTHROUGH */ - case (ROFF_Item): - /* FALLTHROUGH */ - case (ROFF_Diag): - /* FALLTHROUGH */ - case (ROFF_Hang): - /* FALLTHROUGH */ - case (ROFF_Ohang): - /* FALLTHROUGH */ - case (ROFF_Inset): - return(html_stput(mbuf, HTML_TAG_DIV, res)); - case (ROFF_Tag): - /* FALLTHROUGH */ - case (ROFF_Column): - attr[0].attr = HTML_ATTR_VALIGN; - attr[0].val = "top"; - return(html_saput(mbuf, HTML_TAG_TD, - res, 1, attr)); - default: - break; - } - } - - assert(i != ROFF_MAXLINEARG); - return(0); -} - - -/* ARGSUSED */ -static int -html_Bl_bodytagname(struct md_mbuf *mbuf, struct htmlq *q, - const int *argc, const char **argv, size_t *res) -{ - int i; - - for (i = 0; ROFF_ARGMAX != argc[i] - && i < ROFF_MAXLINEARG; i++) { - switch (argc[i]) { - case (ROFF_Enum): - return(html_stput(mbuf, HTML_TAG_OL, res)); - case (ROFF_Bullet): - /* FALLTHROUGH */ - case (ROFF_Dash): - /* FALLTHROUGH */ - case (ROFF_Hyphen): - /* FALLTHROUGH */ - case (ROFF_Item): - /* FALLTHROUGH */ - case (ROFF_Diag): - /* FALLTHROUGH */ - case (ROFF_Hang): - /* FALLTHROUGH */ - case (ROFF_Ohang): - /* FALLTHROUGH */ - case (ROFF_Inset): - return(html_stput(mbuf, HTML_TAG_UL, res)); - case (ROFF_Tag): - /* FALLTHROUGH */ - case (ROFF_Column): - return(html_stput(mbuf, HTML_TAG_TABLE, res)); - default: - break; - } - } - - assert(i != ROFF_MAXLINEARG); - return(0); -} - - -/* ARGSUSED */ -static int -html_It_blocktagname(struct md_mbuf *mbuf, struct htmlq *q, - const int *argc, const char **argv, size_t *res) -{ - struct htmlnode *n; - int i; - - for (n = q->last; n; n = n->parent) - if (n->tok == ROFF_Bl) - break; - - assert(n); - - /* LINTED */ - for (i = 0; ROFF_ARGMAX != n->argc[i] && - i < ROFF_MAXLINEARG; i++) { - switch (n->argc[i]) { - case (ROFF_Enum): - /* FALLTHROUGH */ - case (ROFF_Bullet): - /* FALLTHROUGH */ - case (ROFF_Dash): - /* FALLTHROUGH */ - case (ROFF_Hyphen): - /* FALLTHROUGH */ - case (ROFF_Item): - /* FALLTHROUGH */ - case (ROFF_Diag): - /* FALLTHROUGH */ - case (ROFF_Hang): - /* FALLTHROUGH */ - case (ROFF_Ohang): - /* FALLTHROUGH */ - case (ROFF_Inset): - return(html_stput(mbuf, HTML_TAG_LI, res)); - case (ROFF_Tag): - /* FALLTHROUGH */ - case (ROFF_Column): - return(html_stput(mbuf, HTML_TAG_TR, res)); - default: - break; - } - } - - assert(i != ROFF_MAXLINEARG); - return(0); -} - - -static int -html_loadcss(struct md_mbuf *mbuf, const char *css) -{ - size_t res, bufsz; - char *buf; - struct stat st; - int fd, c; - ssize_t ssz; - - c = 0; - res = 0; - buf = NULL; - - if (-1 == (fd = open(css, O_RDONLY, 0))) { - warn("%s", css); - return(0); - } - - if (-1 == fstat(fd, &st)) { - warn("%s", css); - goto out; - } - - bufsz = MAX(st.st_blksize, BUFSIZ); - if (NULL == (buf = malloc(bufsz))) { - warn("malloc"); - goto out; - } - - for (;;) { - if (-1 == (ssz = read(fd, buf, bufsz))) { - warn("%s", css); - goto out; - } else if (0 == ssz) - break; - if ( ! ml_nputs(mbuf, buf, (size_t)ssz, &res)) - goto out; - } - - c = 1; - -out: - if (-1 == close(fd)) { - warn("%s", css); - c = 0; - } - - if (buf) - free(buf); - - return(c); -} - - -static int -html_tputln(struct md_mbuf *mbuf, enum ml_scope scope, - int i, enum html_tag tag) -{ - - if ( ! ml_putchars(mbuf, ' ', INDENT(i) * INDENT_SZ, NULL)) - return(0); - if ( ! html_tput(mbuf, scope, tag, NULL)) - return(0); - return(ml_nputs(mbuf, "\n", 1, NULL)); -} - - -static int -html_aputln(struct md_mbuf *mbuf, enum ml_scope scope, int i, - enum html_tag tag, int sz, const struct html_pair *p) -{ - - if ( ! ml_putchars(mbuf, ' ', INDENT(i) * INDENT_SZ, NULL)) - return(0); - if ( ! html_aput(mbuf, scope, tag, NULL, sz, p)) - return(0); - return(ml_nputs(mbuf, "\n", 1, NULL)); -} - - -/* ARGSUSED */ -static int -html_begin(struct ml_args *p, const struct tm *tm, const char *os, - const char *name, enum roffmsec msec, enum roffvol vol) -{ - enum roffvol bvol; - struct html_pair attr[4]; - char ts[32], title[64]; - int i; - - (void)snprintf(ts, sizeof(ts), "%s(%s)", - name, roff_msecname(msec)); - - if (vol >= ROFF_ARCH_START) { - switch (msec) { - case(ROFF_MSEC_1): - /* FALLTHROUGH */ - case(ROFF_MSEC_6): - /* FALLTHROUGH */ - case(ROFF_MSEC_7): - bvol = ROFF_VOL_URM; - break; - case(ROFF_MSEC_2): - /* FALLTHROUGH */ - case(ROFF_MSEC_3): - /* FALLTHROUGH */ - case(ROFF_MSEC_3p): - /* FALLTHROUGH */ - case(ROFF_MSEC_4): - /* FALLTHROUGH */ - case(ROFF_MSEC_5): - bvol = ROFF_VOL_PRM; - break; - case(ROFF_MSEC_8): - bvol = ROFF_VOL_PRM; - break; - case(ROFF_MSEC_9): - bvol = ROFF_VOL_KM; - break; - case(ROFF_MSEC_UNASS): - /* FALLTHROUGH */ - case(ROFF_MSEC_DRAFT): - /* FALLTHROUGH */ - case(ROFF_MSEC_PAPER): - bvol = ROFF_VOL_NONE; - break; - default: - abort(); - /* NOTREACHED */ - } - - (void)snprintf(title, sizeof(title), "%s (%s)", - roff_volname(bvol), roff_volname(vol)); - } else - (void)snprintf(title, sizeof(title), "%s", roff_volname(vol)); - - - i = 0; - - if ( ! html_typeput(p->mbuf, HTML_TYPE_4_01_STRICT, NULL)) - return(0); - if ( ! html_tputln(p->mbuf, ML_OPEN, i, HTML_TAG_HTML)) - return(0); - if ( ! html_tputln(p->mbuf, ML_OPEN, i++, HTML_TAG_HEAD)) - return(0); - - attr[0].attr = HTML_ATTR_HTTP_EQUIV; - attr[0].val = "content-type"; - attr[1].attr = HTML_ATTR_CONTENT; - attr[1].val = "text/html;charset=utf-8"; - - if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_META, 2, attr)) - return(0); - - attr[0].attr = HTML_ATTR_NAME; - attr[0].val = "resource-type"; - attr[1].attr = HTML_ATTR_CONTENT; - attr[1].val = "document"; - - if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_META, 2, attr)) - return(0); - - if ( ! html_tputln(p->mbuf, ML_OPEN, i, HTML_TAG_TITLE)) - return(0); - if ( ! ml_putstring(p->mbuf, ts, NULL)) - return(0); - if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TITLE)) - return(0); - - if (HTML_CSS_EMBED & p->args->params.html.flags) { - attr[0].attr = HTML_ATTR_TYPE; - attr[0].val = "text/css"; - - if ( ! html_aputln(p->mbuf, ML_OPEN, i, - HTML_TAG_STYLE, 1, attr)) - return(0); - if ( ! html_commentput(p->mbuf, ML_OPEN, NULL)) - return(0); - - if ( ! html_loadcss(p->mbuf, p->args->params.html.css)) - return(0); - - if ( ! html_commentput(p->mbuf, ML_CLOSE, NULL)) - return(0); - if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_STYLE)) - return(0); - } else { - attr[0].attr = HTML_ATTR_REL; - attr[0].val = "stylesheet"; - attr[1].attr = HTML_ATTR_TYPE; - attr[1].val = "text/css"; - attr[2].attr = HTML_ATTR_HREF; - attr[2].val = p->args->params.html.css; - - if ( ! html_aputln(p->mbuf, ML_OPEN, i, - HTML_TAG_LINK, 3, attr)) - return(0); - } - - if ( ! html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_HEAD)) - return(0); - if ( ! html_tputln(p->mbuf, ML_OPEN, i, HTML_TAG_BODY)) - return(0); - - attr[0].attr = HTML_ATTR_CLASS; - attr[0].val = "mdoc"; - - if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_DIV, 1, attr)) - return(0); - - attr[0].attr = HTML_ATTR_WIDTH; - attr[0].val = "100%"; - attr[1].attr = HTML_ATTR_CLASS; - attr[1].val = "header-table"; - - if ( ! html_aputln(p->mbuf, ML_OPEN, i++, HTML_TAG_TABLE, 2, attr)) - return(0); - if ( ! html_tputln(p->mbuf, ML_OPEN, i++, HTML_TAG_TR)) - return(0); - - attr[0].attr = HTML_ATTR_ALIGN; - attr[0].val = "left"; - attr[1].attr = HTML_ATTR_CLASS; - attr[1].val = "header-section"; - - if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr)) - return(0); - if ( ! ml_putstring(p->mbuf, ts, NULL)) - return(0); - if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD)) - return(0); - - attr[0].attr = HTML_ATTR_ALIGN; - attr[0].val = "center"; - attr[1].attr = HTML_ATTR_CLASS; - attr[1].val = "header-volume"; - - if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr)) - return(0); - if ( ! ml_putstring(p->mbuf, title, NULL)) - return(0); - if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD)) - return(0); - - attr[0].attr = HTML_ATTR_ALIGN; - attr[0].val = "right"; - attr[1].attr = HTML_ATTR_CLASS; - attr[1].val = "header-section"; - - if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr)) - return(0); - if ( ! ml_putstring(p->mbuf, ts, NULL)) - return(0); - if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD)) - return(0); - - if ( ! html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_TR)) - return(0); - return(html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_TABLE)); -} - - -/* ARGSUSED */ -static int -html_end(struct ml_args *p, const struct tm *tm, const char *os, - const char *name, enum roffmsec msec, enum roffvol vol) -{ - struct html_pair attr[4]; - int i; - char ts[64]; - - if (0 == strftime(ts, sizeof(ts), "%B %d, %Y", tm)) { - warn("strftime"); - return(0); - } - - i = 0; - - attr[0].attr = HTML_ATTR_WIDTH; - attr[0].val = "100%"; - attr[1].attr = HTML_ATTR_CLASS; - attr[1].val = "header-footer"; - - if ( ! html_aputln(p->mbuf, ML_OPEN, i++, HTML_TAG_TABLE, 2, attr)) - return(0); - if ( ! html_tputln(p->mbuf, ML_OPEN, i++, HTML_TAG_TR)) - return(0); - - attr[0].attr = HTML_ATTR_ALIGN; - attr[0].val = "left"; - attr[1].attr = HTML_ATTR_CLASS; - attr[1].val = "footer-os"; - - if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr)) - return(0); - if ( ! ml_putstring(p->mbuf, os, NULL)) - return(0); - if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD)) - return(0); - - attr[0].attr = HTML_ATTR_ALIGN; - attr[0].val = "right"; - attr[1].attr = HTML_ATTR_CLASS; - attr[1].val = "footer-date"; - - if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr)) - return(0); - if ( ! ml_putstring(p->mbuf, ts, NULL)) - return(0); - if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD)) - return(0); - - if ( ! html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_TR)) - return(0); - if ( ! html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_TABLE)) - return(0); - - if ( ! html_tputln(p->mbuf, ML_CLOSE, 0, HTML_TAG_DIV)) - return(0); - if ( ! html_tputln(p->mbuf, ML_CLOSE, 0, HTML_TAG_BODY)) - return(0); - return(html_tputln(p->mbuf, ML_CLOSE, 0, HTML_TAG_HTML)); -} - - -/* ARGSUSED */ -static int -html_bodytagname(struct md_mbuf *mbuf, - const struct md_args *args, int tok, struct htmlq *q, - const int *argc, const char **argv, size_t *res) -{ - - switch (tok) { - case (ROFF_Bl): - return(html_Bl_bodytagname(mbuf, q, argc, argv, res)); - case (ROFF_Fo): - return(html_stput(mbuf, HTML_TAG_SPAN, res)); - case (ROFF_It): - return(html_It_bodytagname(mbuf, q, argc, argv, res)); - case (ROFF_Oo): - return(html_stput(mbuf, HTML_TAG_SPAN, res)); - default: - break; - } - - return(html_stput(mbuf, HTML_TAG_DIV, res)); -} - - -/* ARGSUSED */ -static int -html_headtagname(struct md_mbuf *mbuf, - const struct md_args *args, int tok, struct htmlq *q, - const int *argc, const char **argv, size_t *res) -{ - - switch (tok) { - case (ROFF_It): - return(html_It_headtagname(mbuf, q, argc, argv, res)); - case (ROFF_Fo): - /* FALLTHROUGH */ - case (ROFF_Oo): - return(html_stput(mbuf, HTML_TAG_SPAN, res)); - case (ROFF_Sh): - return(html_stput(mbuf, HTML_TAG_H1, res)); - case (ROFF_Ss): - return(html_stput(mbuf, HTML_TAG_H2, res)); - default: - break; - } - - return(html_stput(mbuf, HTML_TAG_DIV, res)); -} - - -/* ARGSUSED */ -static int -html_blocktagname(struct md_mbuf *mbuf, const struct md_args *args, - int tok, struct htmlq *q, const int *argc, - const char **argv, size_t *res) -{ - - switch (tok) { - case (ROFF_Fo): - /* FALLTHROUGH */ - case (ROFF_Oo): - return(html_stput(mbuf, HTML_TAG_SPAN, res)); - case (ROFF_It): - return(html_It_blocktagname(mbuf, q, argc, argv, res)); - default: - break; - } - - return(html_stput(mbuf, HTML_TAG_DIV, res)); -} - - -/* ARGSUSED */ -static int -html_printargs(struct md_mbuf *mbuf, int tok, const char *ns, - const int *argc, const char **argv, size_t *res) -{ - - /* FIXME: use API in ml.h. */ - - if ( ! ml_puts(mbuf, " class=\"", res)) - return(0); - if ( ! ml_puts(mbuf, ns, res)) - return(0); - if ( ! ml_puts(mbuf, "-", res)) - return(0); - if ( ! ml_puts(mbuf, toknames[tok], res)) - return(0); - return(ml_puts(mbuf, "\"", res)); -} - - -/* ARGSUSED */ -static int -html_headtagargs(struct md_mbuf *mbuf, - const struct md_args *args, int tok, - const int *argc, const char **argv, size_t *res) -{ - - return(html_printargs(mbuf, tok, "head", argc, argv, res)); -} - - -/* ARGSUSED */ -static int -html_bodytagargs(struct md_mbuf *mbuf, - const struct md_args *args, int tok, - const int *argc, const char **argv, size_t *res) -{ - - return(html_printargs(mbuf, tok, "body", argc, argv, res)); -} - - -/* ARGSUSED */ -static int -html_blocktagargs(struct md_mbuf *mbuf, - const struct md_args *args, int tok, - const int *argc, const char **argv, size_t *res) -{ - - return(html_printargs(mbuf, tok, "block", argc, argv, res)); -} - - -/* ARGSUSED */ -static int -html_inlinetagargs(struct md_mbuf *mbuf, - const struct md_args *args, int tok, - const int *argc, const char **argv, size_t *res) -{ - - if ( ! html_printargs(mbuf, tok, "inline", argc, argv, res)) - return(0); - - switch (tok) { - case (ROFF_Sh): - - /* FIXME: use API in ml.h. */ - - assert(*argv); - if ( ! ml_nputs(mbuf, " name=\"", 7, res)) - return(0); - if ( ! ml_putstring(mbuf, *argv++, res)) - return(0); - while (*argv) { - if ( ! ml_putstring(mbuf, "_", res)) - return(0); - if ( ! ml_putstring(mbuf, *argv++, res)) - return(0); - } - if ( ! ml_nputs(mbuf, "\"", 1, res)) - return(0); - break; - - case (ROFF_Sx): - - /* FIXME: use API in ml.h. */ - - assert(*argv); - if ( ! ml_nputs(mbuf, " href=\"#", 8, res)) - return(0); - if ( ! ml_putstring(mbuf, *argv++, res)) - return(0); - while (*argv) { - if ( ! ml_putstring(mbuf, "_", res)) - return(0); - if ( ! ml_putstring(mbuf, *argv++, res)) - return(0); - } - if ( ! ml_nputs(mbuf, "\"", 1, res)) - return(0); - - break; - default: - break; - } - - return(1); -} - - -/* ARGSUSED */ -static int -html_inlinetagname(struct md_mbuf *mbuf, - const struct md_args *args, int tok, size_t *res) -{ - - switch (tok) { - case (ROFF_Dl): - /* FALLTHROUGH */ - case (ROFF_D1): - return(html_stput(mbuf, HTML_TAG_DIV, res)); - case (ROFF_Sh): - return(html_stput(mbuf, HTML_TAG_A, res)); - case (ROFF_Pp): - return(html_stput(mbuf, HTML_TAG_DIV, res)); - case (ROFF_Sx): - return(html_stput(mbuf, HTML_TAG_A, res)); - default: - break; - } - - return(html_stput(mbuf, HTML_TAG_SPAN, res)); -} - - -static ssize_t -html_begintag(struct ml_args *p, enum md_ns ns, - int tok, const int *argc, const char **argv) -{ - size_t res; - struct htmlq *q; - struct htmlnode *node; - int i; - - assert(ns != MD_NS_DEFAULT); - res = 0; - - q = (struct htmlq *)p->data; - - if (NULL == (node = calloc(1, sizeof(struct htmlnode)))) { - warn("calloc"); - return(-1); - } - - node->parent = q->last; - node->tok = tok; - node->ns = ns; - - if (argc) { - /* TODO: argv. */ - - assert(argv); - /* LINTED */ - for (i = 0; ROFF_ARGMAX != argc[i] - && i < ROFF_MAXLINEARG; i++) - node->argc[i] = argc[i]; - assert(i != ROFF_MAXLINEARG); - } - - - q->last = node; - - switch (ns) { - case (MD_NS_BLOCK): - if ( ! html_blocktagname(p->mbuf, p->args, tok, - q, argc, argv, &res)) - return(-1); - if ( ! html_blocktagargs(p->mbuf, p->args, tok, - argc, argv, &res)) - return(-1); - break; - case (MD_NS_BODY): - if ( ! html_bodytagname(p->mbuf, p->args, tok, - q, argc, argv, &res)) - return(-1); - if ( ! html_bodytagargs(p->mbuf, p->args, tok, - argc, argv, &res)) - return(-1); - break; - case (MD_NS_HEAD): - if ( ! html_headtagname(p->mbuf, p->args, tok, q, - argc, argv, &res)) - return(-1); - if ( ! html_headtagargs(p->mbuf, p->args, tok, - argc, argv, &res)) - return(-1); - break; - default: - if ( ! html_inlinetagname(p->mbuf, p->args, tok, &res)) - return(-1); - if ( ! html_inlinetagargs(p->mbuf, p->args, tok, - argc, argv, &res)) - return(-1); - break; - } - - return((ssize_t)res); -} - - -static ssize_t -html_endtag(struct ml_args *p, enum md_ns ns, int tok) -{ - size_t res; - struct htmlq *q; - struct htmlnode *node; - - assert(ns != MD_NS_DEFAULT); - res = 0; - - q = (struct htmlq *)p->data; - node = q->last; - - switch (ns) { - case (MD_NS_BLOCK): - if ( ! html_blocktagname(p->mbuf, p->args, tok, - q, node->argc, - (const char **)node->argv, &res)) - return(-1); - break; - case (MD_NS_BODY): - if ( ! html_bodytagname(p->mbuf, p->args, tok, - q, node->argc, - (const char **)node->argv, &res)) - return(-1); - break; - case (MD_NS_HEAD): - if ( ! html_headtagname(p->mbuf, p->args, tok, - q, node->argc, - (const char **)node->argv, &res)) - return(-1); - break; - default: - if ( ! html_inlinetagname(p->mbuf, p->args, tok, &res)) - return(-1); - break; - } - - q->last = node->parent; - - free(node); - - return((ssize_t)res); -} - - -static int -html_alloc(void **p) -{ - - if (NULL == (*p = calloc(1, sizeof(struct htmlq)))) { - warn("calloc"); - return(0); - } - return(1); -} - - -static void -html_free(void *p) -{ - struct htmlq *q; - struct htmlnode *n; - - assert(p); - q = (struct htmlq *)p; - - /* LINTED */ - while ((n = q->last)) { - q->last = n->parent; - free(n); - } - - free(q); -} - - -/* ARGSUSED */ -static ssize_t -html_beginhttp(struct md_mbuf *mbuf, - const struct md_args *args, - const char *buf, size_t sz) -{ - size_t res; - struct html_pair pair; - - res = 0; - pair.attr = HTML_ATTR_HREF; - pair.val = (char *)buf; - - if ( ! html_aput(mbuf, ML_OPEN, HTML_TAG_A, &res, 1, &pair)) - return(-1); - return((ssize_t)res); -} - - -/* ARGSUSED */ -static ssize_t -html_endhttp(struct md_mbuf *mbuf, - const struct md_args *args, - const char *buf, size_t sz) -{ - size_t res; - - res = 0; - if ( ! html_tput(mbuf, ML_CLOSE, HTML_TAG_A, &res)) - return(-1); - return((ssize_t)res); -} - - -/* ARGSUSED */ -static ssize_t -html_beginstring(struct ml_args *p, const char *buf, size_t sz) -{ - - if (0 == strncmp(buf, "http://", 7)) - return(html_beginhttp(p->mbuf, p->args, buf, sz)); - - return(0); -} - - -/* ARGSUSED */ -static ssize_t -html_endstring(struct ml_args *p, const char *buf, size_t sz) -{ - - if (0 == strncmp(buf, "http://", 7)) - return(html_endhttp(p->mbuf, p->args, buf, sz)); - - return(0); -} - - -int -md_line_html(void *data, char *buf) -{ - - return(mlg_line((struct md_mlg *)data, buf)); -} - - -int -md_exit_html(void *data, int flush) -{ - - return(mlg_exit((struct md_mlg *)data, flush)); -} - - -void * -md_init_html(const struct md_args *args, - struct md_mbuf *mbuf, const struct md_rbuf *rbuf) -{ - struct ml_cbs cbs; - - cbs.ml_alloc = html_alloc; - cbs.ml_free = html_free; - cbs.ml_begintag = html_begintag; - cbs.ml_endtag = html_endtag; - cbs.ml_begin = html_begin; - cbs.ml_end = html_end; - cbs.ml_beginstring = html_beginstring; - cbs.ml_endstring = html_endstring; - - return(mlg_alloc(args, rbuf, mbuf, &cbs)); -} diff --git a/html.h b/html.h deleted file mode 100644 index b73a3a4b..00000000 --- a/html.h +++ /dev/null @@ -1,86 +0,0 @@ -/* $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 HTML_H -#define HTML_H - -#include "ml.h" - -enum html_tag { - HTML_TAG_SPAN = 0, - HTML_TAG_HTML = 1, - HTML_TAG_HEAD = 2, - HTML_TAG_META = 3, - HTML_TAG_TITLE = 4, - HTML_TAG_STYLE = 5, - HTML_TAG_LINK = 6, - HTML_TAG_BODY = 7, - HTML_TAG_DIV = 8, - HTML_TAG_TABLE = 9, - HTML_TAG_TD = 10, - HTML_TAG_TR = 11, - HTML_TAG_OL = 12, - HTML_TAG_UL = 13, - HTML_TAG_LI = 14, - HTML_TAG_H1 = 15, - HTML_TAG_H2 = 16, - HTML_TAG_A = 17 -}; - -enum html_attr { - HTML_ATTR_CLASS = 0, - HTML_ATTR_HTTP_EQUIV = 1, - HTML_ATTR_CONTENT = 2, - HTML_ATTR_NAME = 3, - HTML_ATTR_TYPE = 4, - HTML_ATTR_REL = 5, - HTML_ATTR_HREF = 6, - HTML_ATTR_WIDTH = 7, - HTML_ATTR_ALIGN = 8, - HTML_ATTR_VALIGN = 9, - HTML_ATTR_NOWRAP = 10 -}; - -enum html_type { - HTML_TYPE_4_01_STRICT = 0 -}; - -struct html_pair { - enum html_attr attr; - char *val; -}; - -__BEGIN_DECLS - -int html_typeput(struct md_mbuf *, - enum html_type, size_t *); -int html_commentput(struct md_mbuf *, - enum ml_scope, size_t *); -int html_tput(struct md_mbuf *, - enum ml_scope, enum html_tag, size_t *); -int html_aput(struct md_mbuf *, enum ml_scope, - enum html_tag, size_t *, - int, const struct html_pair *); -int html_stput(struct md_mbuf *, - enum html_tag, size_t *); -int html_saput(struct md_mbuf *, enum html_tag, - size_t *, int, const struct html_pair *); - -__END_DECLS - -#endif /*!HTML_H*/ diff --git a/index.7 b/index.7 deleted file mode 100644 index 6e3dc723..00000000 --- a/index.7 +++ /dev/null @@ -1,156 +0,0 @@ -.\" -.Dd $Mdocdate$ -.Dt index 7 -.Os LOCAL -.\" -.Sh NAME -.Nm mdocml -.Nd compile mdoc macros into mark-up language -.\" -.Sh DESCRIPTION -The -.Nm -utility compiles -.Xr mdoc 7 -macros, such as those inheriting from -.Xr mdoc.samples 7 , -into XML or HTML documents. Unlike other similar utilities such as -.Xr rman 1 -and -.Xr man2html 1 , -.Nm -is a full macro parser operating on source documents, specifically mdoc, -validating input and compiling to HTML and XML output types. -.Pp -Downloads (source and ports) are available in the -.Sx DOWNLOADS -section. -.Pp -The -.Nm -utility is tested specifically on -.Ox -manual sources as compiled and invoked both on -.Ox -and Linux. -.Nm -is -.Ud -.\" -.Ss Validation -In order to operate sanely, -.Nm -fully validates its input. This includes, but is not limited to, the -following checks: -.Pp -.Bl -enum -compact -.It -valid special characters (such as -.Sq \en -and -.Sq \et ) , -.It -sane macro scope (such as -.Sq \&.Sh -macros clobbering a pending -.Sq \&.Bl -scope), -.It -valid predefined characters (such as \\*(>= and \\*q), -.It -correctly-ordered prelude and sections, -.It -sane macro argument values (such as those for -.Sq \&.Dt -or -.Sq \&.Sm ) , -.It -valid manual sections and systems; -.It -and so on. -.El -.\" -.Ss Filtering -When a line of source has been parsed, it's passed to the output -filters, which format and display data. The two available filters are -HTML and XML. -.Pp -The HTML filter has the following features: -.Pp -.Bl -enum -compact -.It -HTML-4.01 strict compliance; -.It -proper rendering of values in UTF-8, such as -.Dq quotes -and \*(>= predefined values; -.It -URI-appearing http://bsd.lv/ strings are correctly enclosed in link tags; -.It -CSS-dictated style with meaningful non-CSS defaults; -.It -and so on. -.El -.Pp -The XML filter creates a correct XML tree with -.Dq block , -.Dq head , -.Dq body , -and -.Dq inline -namespaces corresponding to macro categories. Namespace identifiers -correspond to their definitions. A sample is available at -http://mdocml.bsd.lv/index.xml -.Ns . -.\" -.Sh DOWNLOADS -Download -.Nm -at http://mdocml.bsd.lv/mdocml.tar.gz -.Ns . -.\" - UPDATE ME WITH EVERY RELEASE. ---------------------------------- -The current version is 1.0.3, dated 10/12/2008. -.\" ------------------------------------------------------------------ -.Pp -An OpenBSD port is available at http://mdocml.bsd.lv/mdocml-port.tar.gz -.Ns . -.Pp -Previous versions are archived as mdocml-x.y.z.tar.gz, with the appropriate -versions filled in. -.\" -.Sh DOCUMENTS -The manual for -.Nm -is available at http://mdocml.bsd.lv/mdocml.html -.Ns . -.\" -.Sh EXAMPLES -This page was produced as follows: -.Pp -.D1 % mdocml -fhtml -Wall -e -o index.html index.7 -.Pp -The original mdoc source is at http://mdocml.bsd.lv/index.txt -.Ns . -.\" -.Sh SEE ALSO -.Bl -ohang -.It Xr rman Ns : http://polyglotman.sourceforge.net/rman.html -Accepts either formatted roff output or source and produces HTML output. -.It Xr man2html Ns : http://www.nongnu.org/man2html/ -Accepts formatted -.Xr nroff 1 -text and produces HTML output. -.It Xr man.cgi Ns : http://www.freebsd.org/cgi/man.cgi/source -.Fx -and -.Ox -project CGI for producing HTML from nroff source. -.It Xr roffit Ns : http://daniel.haxx.se/projects/roffit/ -HTML from roff manual source. Dead project? -.El -.\" -.Sh AUTHORS -The -.Nm -utility was written by -.An Kristaps Dzonsons Aq kristaps@kth.se . diff --git a/libmdocml.c b/libmdocml.c deleted file mode 100644 index 33f5ffa7..00000000 --- a/libmdocml.c +++ /dev/null @@ -1,261 +0,0 @@ -/* $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 <fcntl.h> -#include <err.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "private.h" - -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 -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); -} - - -static 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) -{ - - assert(buf); - return(md_buf_puts(buf, &c, 1)); -} - - -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; - - 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); -} - - -static int -md_run_leave(const struct md_args *args, struct md_mbuf *mbuf, - struct md_rbuf *rbuf, int c, void *data) -{ - md_exit fp; - - assert(args); - assert(mbuf); - assert(rbuf); - - /* Run exiters. */ - switch (args->type) { - case (MD_HTML): - fp = md_exit_html; - break; - case (MD_XML): - fp = md_exit_xml; - break; - default: - fp = md_exit_noop; - break; - } - - if ( ! (*fp)(data, -1 == c ? 0 : 1)) - c = -1; - - /* Make final flush of buffer. */ - 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, void *p) -{ - ssize_t sz, i; - size_t pos; - char line[MD_LINE]; - md_line fp; - - assert(args); - assert(mbuf); - assert(rbuf); - - /* Function ptrs to line-parsers. */ - switch (args->type) { - case (MD_HTML): - fp = md_line_html; - break; - case (MD_XML): - fp = md_line_xml; - break; - default: - fp = md_line_noop; - break; - } - - 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 ('\n' != rbuf->buf[i]) { - if (pos < MD_LINE) { - /* LINTED */ - rbuf->linebuf[pos++] = rbuf->buf[i]; - continue; - } - warnx("%s: line %zu too long", - rbuf->name, rbuf->line); - return(md_run_leave(args, mbuf, rbuf, -1, p)); - } - - rbuf->linebuf[(int)pos] = 0; - (void)memcpy(line, rbuf->linebuf, sizeof(line)); - if ( ! (*fp)(p, line)) - return(md_run_leave(args, mbuf, rbuf, -1, p)); - rbuf->line++; - pos = 0; - } - - goto again; - /* NOTREACHED */ -} - - -int -md_run(const struct md_args *args, - const struct md_buf *out, const struct md_buf *in) -{ - md_init fp; - struct md_mbuf mbuf; - struct md_rbuf rbuf; - void *data; - - assert(args); - assert(in); - assert(out); - - (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_HTML): - fp = md_init_html; - break; - case (MD_XML): - fp = md_init_xml; - break; - default: - fp = md_init_noop; - break; - } - - data = (*fp)(args, &mbuf, &rbuf); - - /* Go into mainline. */ - return(md_run_enter(args, &mbuf, &rbuf, data)); -} diff --git a/libmdocml.h b/libmdocml.h deleted file mode 100644 index 93126e85..00000000 --- a/libmdocml.h +++ /dev/null @@ -1,67 +0,0 @@ -/* $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 LIBMDOCML_H -#define LIBMDOCML_H - -#include <sys/types.h> - -struct md_params_html { - char *css; - int flags; -#define HTML_CSS_EMBED (1 << 0) -}; - -union md_params { - struct md_params_html html; -}; - -enum md_type { - MD_XML, /* XML. */ - MD_HTML, /* HTML4.01-strict. */ - MD_NOOP /* Validates only. */ -}; - -struct md_args { - union md_params params;/* Parameters for parser. */ - enum md_type type; /* Type of parser. */ - - int warnings; -#define MD_WARN_ALL (1 << 0) -#define MD_WARN_ERROR (1 << 1) - int verbosity; -}; - -struct md_buf { - int fd; /* Open file descriptor. */ - char *name; /* Name of file/socket/whatever. */ - char *buf; /* Buffer for storing data. */ - size_t bufsz; /* Size of buf. */ -}; - -__BEGIN_DECLS - -/* Run the parser over prepared input and output buffers. Returns -1 on - * failure and 0 on success. - */ -int md_run(const struct md_args *, - const struct md_buf *, const struct md_buf *); - -__END_DECLS - -#endif /*!LIBMDOCML_H*/ diff --git a/literals.c b/literals.c deleted file mode 100644 index 75c24e43..00000000 --- a/literals.c +++ /dev/null @@ -1,615 +0,0 @@ -/* $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 <string.h> -#include <stdlib.h> - -#include "private.h" - -#define ROFF_ATTname_V1 "v1" -#define ROFF_ATTname_V2 "v2" -#define ROFF_ATTname_V3 "v3" -#define ROFF_ATTname_V6 "v6" -#define ROFF_ATTname_V7 "v7" -#define ROFF_ATTname_32V "32v" -#define ROFF_ATTname_V_1 "V.1" -#define ROFF_ATTname_V_4 "V.4" - -#define ROFFSecname_NAME "NAME" -#define ROFFSecname_SYNOP "SYNOPSIS" -#define ROFFSecname_DESC "DESCRIPTION" -#define ROFFSecname_ENV "ENVIRONMENT" -#define ROFFSecname_FILES "FILES" -#define ROFFSecname_EX "EXAMPLES" -#define ROFFSecname_DIAG "DIAGNOSTICS" -#define ROFFSecname_ERRS "ERRORS" -#define ROFFSecname_STAND "STANDARDS" -#define ROFFSecname_HIST "HISTORY" -#define ROFFSecname_AUTH "AUTHORS" -#define ROFFSecname_CAVEATS "CAVEATS" -#define ROFFSecname_BUGS "BUGS" -#define ROFFSecname_RETVAL "RETURN VALUES" -#define ROFFSecname_RETVAL1 "RETURN" -#define ROFFSecname_RETVAL2 "VALUES" -#define ROFFSecname_SEEALSO "SEE ALSO" -#define ROFFSecname_SEEALSO1 "SEE" -#define ROFFSecname_SEEALSO2 "ALSO" - -#define ROFF_MSECname_1 "1" -#define ROFF_MSECname_2 "2" -#define ROFF_MSECname_3 "3" -#define ROFF_MSECname_3p "3p" -#define ROFF_MSECname_4 "4" -#define ROFF_MSECname_5 "5" -#define ROFF_MSECname_6 "6" -#define ROFF_MSECname_7 "7" -#define ROFF_MSECname_8 "8" -#define ROFF_MSECname_9 "9" -#define ROFF_MSECname_UNASS "unass" -#define ROFF_MSECname_DRAFT "draft" -#define ROFF_MSECname_PAPER "paper" - -#define ROFF_VOLname_AMD "AMD" -#define ROFF_VOLname_IND "IND" -#define ROFF_VOLname_KM "KM" -#define ROFF_VOLname_LOCAL "LOCAL" -#define ROFF_VOLname_PRM "PRM" -#define ROFF_VOLname_PS1 "PS1" -#define ROFF_VOLname_SMM "SMM" -#define ROFF_VOLname_URM "URM" -#define ROFF_VOLname_USD "USD" -#define ROFF_ARCHname_ALPHA "alpha" -#define ROFF_ARCHname_AMD64 "amd64" -#define ROFF_ARCHname_AMIGA "amiga" -#define ROFF_ARCHname_ARC "arc" -#define ROFF_ARCHname_ARMISH "armish" -#define ROFF_ARCHname_AVIION "aviion" -#define ROFF_ARCHname_HP300 "hp300" -#define ROFF_ARCHname_HPPA "hppa" -#define ROFF_ARCHname_HPPA64 "hppa64" -#define ROFF_ARCHname_I386 "i386" -#define ROFF_ARCHname_LANDISK "landisk" -#define ROFF_ARCHname_LUNA88K "luna88k" -#define ROFF_ARCHname_MAC68K "mac68k" -#define ROFF_ARCHname_MACPPC "macppc" -#define ROFF_ARCHname_MVME68K "mvme68k" -#define ROFF_ARCHname_MVME88K "mvme88k" -#define ROFF_ARCHname_MVMEPPC "mvmeppc" -#define ROFF_ARCHname_PMAX "pmax" -#define ROFF_ARCHname_SGI "sgi" -#define ROFF_ARCHname_SPARC "sparc" -#define ROFF_ARCHname_SPARC64 "sparc64" -#define ROFF_ARCHname_SUN3 "sun3" -#define ROFF_ARCHname_VAX "vax" -#define ROFF_ARCHname_ZAURUS "zaurus" - -int -roff_sec(const char **p) -{ - - assert(*p); - if (NULL != *(p + 1)) { - if (NULL != *(p + 2)) - return(ROFFSec_OTHER); - if (0 == strcmp(*p, ROFFSecname_RETVAL1) && - 0 == strcmp(*(p + 1), ROFFSecname_RETVAL2)) - return(ROFFSec_RETVAL); - if (0 == strcmp(*p, ROFFSecname_SEEALSO1) && - 0 == strcmp(*(p + 1), ROFFSecname_SEEALSO2)) - return(ROFFSec_SEEALSO); - return(ROFFSec_OTHER); - } - - if (0 == strcmp(*p, ROFFSecname_NAME)) - return(ROFFSec_NAME); - else if (0 == strcmp(*p, ROFFSecname_SYNOP)) - return(ROFFSec_SYNOP); - else if (0 == strcmp(*p, ROFFSecname_DESC)) - return(ROFFSec_DESC); - else if (0 == strcmp(*p, ROFFSecname_ENV)) - return(ROFFSec_ENV); - else if (0 == strcmp(*p, ROFFSecname_FILES)) - return(ROFFSec_FILES); - else if (0 == strcmp(*p, ROFFSecname_EX)) - return(ROFFSec_EX); - else if (0 == strcmp(*p, ROFFSecname_DIAG)) - return(ROFFSec_DIAG); - else if (0 == strcmp(*p, ROFFSecname_ERRS)) - return(ROFFSec_ERRS); - else if (0 == strcmp(*p, ROFFSecname_STAND)) - return(ROFFSec_STAND); - else if (0 == strcmp(*p, ROFFSecname_HIST)) - return(ROFFSec_HIST); - else if (0 == strcmp(*p, ROFFSecname_AUTH)) - return(ROFFSec_AUTH); - else if (0 == strcmp(*p, ROFFSecname_CAVEATS)) - return(ROFFSec_CAVEATS); - else if (0 == strcmp(*p, ROFFSecname_BUGS)) - return(ROFFSec_BUGS); - else if (0 == strcmp(*p, ROFFSecname_RETVAL)) - return(ROFFSec_RETVAL); - else if (0 == strcmp(*p, ROFFSecname_SEEALSO)) - return(ROFFSec_SEEALSO); - - return(ROFFSec_OTHER); -} - - -enum roffmsec -roff_msec(const char *p) -{ - - assert(p); - if (0 == strcmp(p, ROFF_MSECname_1)) - return(ROFF_MSEC_1); - else if (0 == strcmp(p, ROFF_MSECname_2)) - return(ROFF_MSEC_2); - else if (0 == strcmp(p, ROFF_MSECname_3)) - return(ROFF_MSEC_3); - else if (0 == strcmp(p, ROFF_MSECname_3p)) - return(ROFF_MSEC_3p); - else if (0 == strcmp(p, ROFF_MSECname_4)) - return(ROFF_MSEC_4); - else if (0 == strcmp(p, ROFF_MSECname_5)) - return(ROFF_MSEC_5); - else if (0 == strcmp(p, ROFF_MSECname_6)) - return(ROFF_MSEC_6); - else if (0 == strcmp(p, ROFF_MSECname_7)) - return(ROFF_MSEC_7); - else if (0 == strcmp(p, ROFF_MSECname_8)) - return(ROFF_MSEC_8); - else if (0 == strcmp(p, ROFF_MSECname_9)) - return(ROFF_MSEC_9); - else if (0 == strcmp(p, ROFF_MSECname_UNASS)) - return(ROFF_MSEC_UNASS); - else if (0 == strcmp(p, ROFF_MSECname_DRAFT)) - return(ROFF_MSEC_DRAFT); - else if (0 == strcmp(p, ROFF_MSECname_PAPER)) - return(ROFF_MSEC_PAPER); - - return(ROFF_MSEC_MAX); -} - - -char * -roff_msecname(enum roffmsec sec) -{ - - switch (sec) { - case(ROFF_MSEC_1): - return(ROFF_MSECname_1); - case(ROFF_MSEC_2): - return(ROFF_MSECname_2); - case(ROFF_MSEC_3): - return(ROFF_MSECname_3); - case(ROFF_MSEC_3p): - return(ROFF_MSECname_3p); - case(ROFF_MSEC_4): - return(ROFF_MSECname_4); - case(ROFF_MSEC_5): - return(ROFF_MSECname_5); - case(ROFF_MSEC_6): - return(ROFF_MSECname_6); - case(ROFF_MSEC_7): - return(ROFF_MSECname_7); - case(ROFF_MSEC_8): - return(ROFF_MSECname_8); - case(ROFF_MSEC_9): - return(ROFF_MSECname_9); - case(ROFF_MSEC_UNASS): - return(ROFF_MSECname_UNASS); - case(ROFF_MSEC_DRAFT): - return(ROFF_MSECname_DRAFT); - case(ROFF_MSEC_PAPER): - return(ROFF_MSECname_PAPER); - default: - break; - } - - abort(); - /* NOTREACHED */ -} - - -char * -roff_fmtstring(int tok) -{ - - switch (tok) { - case (ROFF_Ex): - return ("The %s utility exits 0 on success, and " - ">0 if an error occurs."); - case (ROFF_Rv): - return ("The %s() function returns the value 0 if " - "successful; otherwise the value -1 " - "is returned and the global variable " - "errno is set to indicate the error."); - case (ROFF_In): - return("#include \\*(Lt%s\\*(Gt"); - default: - break; - } - - abort(); - /* NOTREACHED */ -} - - -char * -roff_literal(int tok, const int *argc, - const char **argv, const char **morep) -{ - - switch (tok) { - case (ROFF_At): - assert(NULL == *argv); - assert(ROFF_ARGMAX == *argc); - if (NULL == *morep) - return("AT&T UNIX"); - - switch (roff_att(*morep)) { - case (ROFF_ATT_V1): - return("Version 1 AT&T UNIX"); - case (ROFF_ATT_V2): - return("Version 2 AT&T UNIX"); - case (ROFF_ATT_V3): - return("Version 3 AT&T UNIX"); - case (ROFF_ATT_V6): - return("Version 6 AT&T UNIX"); - case (ROFF_ATT_V7): - return("Version 7 AT&T UNIX"); - case (ROFF_ATT_32V): - return("Version 32v AT&T UNIX"); - case (ROFF_ATT_V_1): - return("AT&T System V.1 UNIX"); - case (ROFF_ATT_V_4): - return("AT&T System V.4 UNIX"); - default: - break; - } - - abort(); - /* NOTREACHED */ - - case (ROFF_St): - assert(ROFF_ARGMAX != *argc); - assert(NULL == *argv); - switch (*argc) { - case(ROFF_p1003_1_88): - return("IEEE Std 1003.1-1988 " - "(\\*(LqPOSIX\\*(Rq)"); - case(ROFF_p1003_1_90): - return("IEEE Std 1003.1-1990 " - "(\\*(LqPOSIX\\*(Rq)"); - case(ROFF_p1003_1_96): - return("ISO/IEC 9945-1:1996 " - "(\\*(LqPOSIX\\*(Rq)"); - case(ROFF_p1003_1_2001): - return("IEEE Std 1003.1-2001 " - "(\\*(LqPOSIX\\*(Rq)"); - case(ROFF_p1003_1_2004): - return("IEEE Std 1003.1-2004 " - "(\\*(LqPOSIX\\*(Rq)"); - case(ROFF_p1003_1): - return("IEEE Std 1003.1 " - "(\\*(LqPOSIX\\*(Rq)"); - case(ROFF_p1003_1b): - return("IEEE Std 1003.1b " - "(\\*(LqPOSIX\\*(Rq)"); - case(ROFF_p1003_1b_93): - return("IEEE Std 1003.1b-1993 " - "(\\*(LqPOSIX\\*(Rq)"); - case(ROFF_p1003_1c_95): - return("IEEE Std 1003.1c-1995 " - "(\\*(LqPOSIX\\*(Rq)"); - case(ROFF_p1003_1g_2000): - return("IEEE Std 1003.1g-2000 " - "(\\*(LqPOSIX\\*(Rq)"); - case(ROFF_p1003_2_92): - return("IEEE Std 1003.2-1992 " - "(\\*(LqPOSIX.2\\*(Rq)"); - case(ROFF_p1387_2_95): - return("IEEE Std 1387.2-1995 " - "(\\*(LqPOSIX.7.2\\*(Rq)"); - case(ROFF_p1003_2): - return("IEEE Std 1003.2 " - "(\\*(LqPOSIX.2\\*(Rq)"); - case(ROFF_p1387_2): - return("IEEE Std 1387.2 " - "(\\*(LqPOSIX.7.2\\*(Rq)"); - case(ROFF_isoC_90): - return("ISO/IEC 9899:1990 " - "(\\*(LqISO C90\\*(Rq)"); - case(ROFF_isoC_amd1): - return("ISO/IEC 9899/AMD1:1995 " - "(\\*(LqISO C90\\*(Rq)"); - case(ROFF_isoC_tcor1): - return("ISO/IEC 9899/TCOR1:1994 " - "(\\*(LqISO C90\\*(Rq)"); - case(ROFF_isoC_tcor2): - return("ISO/IEC 9899/TCOR2:1995 " - "(\\*(LqISO C90\\*(Rq)"); - case(ROFF_isoC_99): - return("ISO/IEC 9899:1999 " - "(\\*(LqISO C99\\*(Rq)"); - case(ROFF_ansiC): - return("ANSI X3.159-1989 " - "(\\*(LqANSI C\\*(Rq)"); - case(ROFF_ansiC_89): - return("ANSI X3.159-1989 " - "(\\*(LqANSI C\\*(Rq)"); - case(ROFF_ansiC_99): - return("ANSI/ISO/IEC 9899-1999 " - "(\\*(LqANSI C99\\*(Rq)"); - case(ROFF_ieee754): - return("IEEE Std 754-1985"); - case(ROFF_iso8802_3): - return("ISO 8802-3: 1989"); - case(ROFF_xpg3): - return("X/Open Portability Guide Issue 3 " - "(\\*(LqXPG3\\*(Rq)"); - case(ROFF_xpg4): - return("X/Open Portability Guide Issue 4 " - "(\\*(LqXPG4\\*(Rq)"); - case(ROFF_xpg4_2): - return("X/Open Portability Guide Issue 4.2 " - "(\\*(LqXPG4.2\\*(Rq)"); - case(ROFF_xpg4_3): - return("X/Open Portability Guide Issue 4.3 " - "(\\*(LqXPG4.3\\*(Rq)"); - case(ROFF_xbd5): - return("X/Open System Interface Definitions " - "Issue 5 (\\*(LqXBD5\\*(Rq)"); - case(ROFF_xcu5): - return("X/Open Commands and Utilities Issue 5 " - "(\\*(LqXCU5\\*(Rq)"); - case(ROFF_xsh5): - return("X/Open System Interfaces and Headers " - "Issue 5 (\\*(LqXSH5\\*(Rq)"); - case(ROFF_xns5): - return("X/Open Networking Services Issue 5 " - "(\\*(LqXNS5\\*(Rq)"); - case(ROFF_xns5_2d2_0): - return("X/Open Networking Services " - "Issue 5.2 Draft 2.0 " - "(\\*(LqXNS5.2D2.0\\*(Rq)"); - case(ROFF_xcurses4_2): - return("X/Open Curses Issue 4 Version 2 " - "(\\*(LqXCURSES4.2\\*(Rq)"); - case(ROFF_susv2): - return("Version 2 of the Single " - "UNIX Specification"); - case(ROFF_susv3): - return("Version 3 of the Single " - "UNIX Specification"); - case(ROFF_svid4): - return("System V Interface Definition, Fourth " - "Edition (\\*(LqSVID4\\*(Rq)"); - default: - break; - } - abort(); - /* NOTREACHED */ - - case (ROFF_Bt): - return("is currently in beta test."); - case (ROFF_Ud): - return("currently under development."); - case (ROFF_Fx): - return("FreeBSD"); - case (ROFF_Nx): - return("NetBSD"); - case (ROFF_Ox): - return("OpenBSD"); - case (ROFF_Ux): - return("UNIX"); - case (ROFF_Bx): - return("BSD"); - case (ROFF_Bsx): - return("BSDI BSD/OS"); - default: - break; - } - - abort(); - /* NOTREACHED */ -} - - -enum roffatt -roff_att(const char *p) -{ - - assert(p); - if (0 == strcmp(p, ROFF_ATTname_V1)) - return(ROFF_ATT_V1); - else if (0 == strcmp(p, ROFF_ATTname_V2)) - return(ROFF_ATT_V2); - else if (0 == strcmp(p, ROFF_ATTname_V3)) - return(ROFF_ATT_V3); - else if (0 == strcmp(p, ROFF_ATTname_V6)) - return(ROFF_ATT_V6); - else if (0 == strcmp(p, ROFF_ATTname_V7)) - return(ROFF_ATT_V7); - else if (0 == strcmp(p, ROFF_ATTname_32V)) - return(ROFF_ATT_32V); - else if (0 == strcmp(p, ROFF_ATTname_V_1)) - return(ROFF_ATT_V_1); - else if (0 == strcmp(p, ROFF_ATTname_V_4)) - return(ROFF_ATT_V_4); - - return(ROFF_ATT_MAX); -} - - -enum roffvol -roff_vol(const char *p) -{ - - if (0 == strcmp(p, ROFF_VOLname_AMD)) - return(ROFF_VOL_AMD); - else if (0 == strcmp(p, ROFF_VOLname_IND)) - return(ROFF_VOL_IND); - else if (0 == strcmp(p, ROFF_VOLname_KM)) - return(ROFF_VOL_KM); - else if (0 == strcmp(p, ROFF_VOLname_LOCAL)) - return(ROFF_VOL_LOCAL); - else if (0 == strcmp(p, ROFF_VOLname_PRM)) - return(ROFF_VOL_PRM); - else if (0 == strcmp(p, ROFF_VOLname_PS1)) - return(ROFF_VOL_PS1); - else if (0 == strcmp(p, ROFF_VOLname_SMM)) - return(ROFF_VOL_SMM); - else if (0 == strcmp(p, ROFF_VOLname_URM)) - return(ROFF_VOL_URM); - else if (0 == strcmp(p, ROFF_VOLname_USD)) - return(ROFF_VOL_USD); - else if (0 == strcmp(p, ROFF_ARCHname_ALPHA)) - return(ROFF_ARCH_ALPHA); - else if (0 == strcmp(p, ROFF_ARCHname_AMD64)) - return(ROFF_ARCH_AMD64); - else if (0 == strcmp(p, ROFF_ARCHname_AMIGA)) - return(ROFF_ARCH_AMIGA); - else if (0 == strcmp(p, ROFF_ARCHname_ARC)) - return(ROFF_ARCH_ARC); - else if (0 == strcmp(p, ROFF_ARCHname_ARMISH)) - return(ROFF_ARCH_ARMISH); - else if (0 == strcmp(p, ROFF_ARCHname_AVIION)) - return(ROFF_ARCH_AVIION); - else if (0 == strcmp(p, ROFF_ARCHname_HP300)) - return(ROFF_ARCH_HP300); - else if (0 == strcmp(p, ROFF_ARCHname_HPPA)) - return(ROFF_ARCH_HPPA); - else if (0 == strcmp(p, ROFF_ARCHname_HPPA64)) - return(ROFF_ARCH_HPPA64); - else if (0 == strcmp(p, ROFF_ARCHname_I386)) - return(ROFF_ARCH_I386); - else if (0 == strcmp(p, ROFF_ARCHname_LANDISK)) - return(ROFF_ARCH_LANDISK); - else if (0 == strcmp(p, ROFF_ARCHname_LUNA88K)) - return(ROFF_ARCH_LUNA88K); - else if (0 == strcmp(p, ROFF_ARCHname_MAC68K)) - return(ROFF_ARCH_MAC68K); - else if (0 == strcmp(p, ROFF_ARCHname_MACPPC)) - return(ROFF_ARCH_MACPPC); - else if (0 == strcmp(p, ROFF_ARCHname_MVME68K)) - return(ROFF_ARCH_MVME68K); - else if (0 == strcmp(p, ROFF_ARCHname_MVME88K)) - return(ROFF_ARCH_MVME88K); - else if (0 == strcmp(p, ROFF_ARCHname_MVMEPPC)) - return(ROFF_ARCH_MVMEPPC); - else if (0 == strcmp(p, ROFF_ARCHname_PMAX)) - return(ROFF_ARCH_PMAX); - else if (0 == strcmp(p, ROFF_ARCHname_SGI)) - return(ROFF_ARCH_SGI); - else if (0 == strcmp(p, ROFF_ARCHname_SPARC)) - return(ROFF_ARCH_SPARC); - else if (0 == strcmp(p, ROFF_ARCHname_SPARC64)) - return(ROFF_ARCH_SPARC64); - else if (0 == strcmp(p, ROFF_ARCHname_SUN3)) - return(ROFF_ARCH_SUN3); - else if (0 == strcmp(p, ROFF_ARCHname_VAX)) - return(ROFF_ARCH_VAX); - else if (0 == strcmp(p, ROFF_ARCHname_ZAURUS)) - return(ROFF_ARCH_ZAURUS); - - return(ROFF_VOL_MAX); -} - - -char * -roff_volname(enum roffvol vol) -{ - - /* FIXME: is OpenBSD specific! */ - - switch (vol) { - case(ROFF_VOL_AMD): - return("OpenBSD Ancestral Manual Documents"); - case(ROFF_VOL_IND): - return("OpenBSD Manual Master Index"); - case(ROFF_VOL_KM): - return("OpenBSD Kernel Manual"); - case(ROFF_VOL_LOCAL): - return("OpenBSD Local Manual"); - case(ROFF_VOL_PRM): - return("OpenBSD Programmer's Manual"); - case(ROFF_VOL_PS1): - return("OpenBSD Programmer's Supplementary Documents"); - case(ROFF_VOL_SMM): - return("OpenBSD System Manager's Manual"); - case(ROFF_VOL_URM): - return("OpenBSD Reference Manual"); - case(ROFF_VOL_USD): - return("OpenBSD User's Supplementary Documents"); - case(ROFF_ARCH_ALPHA): - return("Alpha"); - case(ROFF_ARCH_AMD64): - return("AMD64"); - case(ROFF_ARCH_AMIGA): - return("Amiga"); - case(ROFF_ARCH_ARC): - return("ARC"); - case(ROFF_ARCH_ARMISH): - return("ARMISH"); - case(ROFF_ARCH_AVIION): - return("AVIION"); - case(ROFF_ARCH_HP300): - return("HP300"); - case(ROFF_ARCH_HPPA): - return("HPPA"); - case(ROFF_ARCH_HPPA64): - return("HPPA64"); - case(ROFF_ARCH_I386): - return("i386"); - case(ROFF_ARCH_LANDISK): - return("LANDISK"); - case(ROFF_ARCH_LUNA88K): - return("Luna88K"); - case(ROFF_ARCH_MAC68K): - return("Mac68K"); - case(ROFF_ARCH_MACPPC): - return("MacPPC"); - case(ROFF_ARCH_MVME68K): - return("MVME68K"); - case(ROFF_ARCH_MVME88K): - return("MVME88K"); - case(ROFF_ARCH_MVMEPPC): - return("MVMEPPC"); - case(ROFF_ARCH_PMAX): - return("PMAX"); - case(ROFF_ARCH_SGI): - return("SGI"); - case(ROFF_ARCH_SPARC): - return("SPARC"); - case(ROFF_ARCH_SPARC64): - return("SPARC64"); - case(ROFF_ARCH_SUN3): - return("Sun3"); - case(ROFF_ARCH_VAX): - return("Vax"); - case(ROFF_ARCH_ZAURUS): - return("Zaurus"); - default: - break; - } - - abort(); - /* NOTREACHED */ -} @@ -16,90 +16,294 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ +#include <assert.h> +#include <ctype.h> #include <stdlib.h> +#include <stdio.h> + +#include "private.h" + +#define _C(p) ((const char **)p) + +static int isdelim(const char *); +static int args_next(struct mdoc *, int, int *, char *, char **); +static int append_text(struct mdoc *, int, int, int, char *[]); +static int append_scoped(struct mdoc *, int, int, int, char *[]); + + +static int +isdelim(const char *p) +{ + + if (0 == *p) + return(0); + if (0 != *(p + 1)) + return(0); + + switch (*p) { + case('{'): + /* FALLTHROUGH */ + case('.'): + /* FALLTHROUGH */ + case(','): + /* FALLTHROUGH */ + case(';'): + /* FALLTHROUGH */ + case(':'): + /* FALLTHROUGH */ + case('?'): + /* FALLTHROUGH */ + case('!'): + /* FALLTHROUGH */ + case('('): + /* FALLTHROUGH */ + case(')'): + /* FALLTHROUGH */ + case('['): + /* FALLTHROUGH */ + case(']'): + /* FALLTHROUGH */ + case('}'): + return(1); + default: + break; + } + + return(0); +} -#include "roff.h" static int -macro_args_next(struct rofftree *tree, int *pos, char *buf, char **v) +args_next(struct mdoc *mdoc, int tok, + int *pos, char *buf, char **v) { - int i; if (0 == buf[*pos]) return(0); + assert( ! isspace(buf[*pos])); + if ('\"' == buf[*pos]) { - /* Syntax error: quotation marks not allowed. */ + (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_QUOTE); return(-1); } *v = &buf[*pos]; + /* Scan ahead to end of token. */ + while (buf[*pos] && ! isspace(buf[*pos])) (*pos)++; - if (buf[*pos + 1] && '\\' == buf[*pos]) { - /* Syntax error: escaped whitespace not allowed. */ + if (buf[*pos] && buf[*pos + 1] && '\\' == buf[*pos]) { + (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_WS); return(-1); } - buf[i] = 0; + if (0 == buf[*pos]) + return(1); + + /* Scan ahead over trailing whitespace. */ + + buf[(*pos)++] = 0; + while (buf[*pos] && isspace(buf[*pos])) + (*pos)++; + + if (0 == buf[*pos]) + if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_WS_EOLN)) + return(-1); + return(1); } -/* - * Parses the following: - * - * .Xx foo bar baz ; foo "bar baz" ; ; - * ^---------- ^---------- - */ + static int -macro_fl(struct rofftree *tree, int tok, int *pos, char *buf) +append_scoped(struct mdoc *mdoc, int tok, int pos, int sz, char *args[]) { - int i, j, c, first; - char *args[ROFF_MAXLINEARG]; - first = *pos == 0; + args[sz] = NULL; + mdoc_block_alloc(mdoc, pos, tok, 0, NULL); + mdoc_head_alloc(mdoc, pos, tok, sz, _C(args)); + mdoc_body_alloc(mdoc, pos, tok); + return(1); +} - for (j = 0; ; ) { - i = *pos; - c = macro_args_next(tree, *i, buf, args[j]); - if (-1 == c) + +static int +append_text(struct mdoc *mdoc, int tok, int pos, int sz, char *args[]) +{ + + args[sz] = NULL; + + switch (tok) { + /* ======= ADD MORE MACRO ARGUMENT-LIMITS BELOW. ======= */ + + case (MDOC_Ft): + /* FALLTHROUGH */ + case (MDOC_Li): + /* FALLTHROUGH */ + case (MDOC_Ms): + /* FALLTHROUGH */ + case (MDOC_Pa): + /* FALLTHROUGH */ + case (MDOC_Tn): + if (0 == sz && ! mdoc_warn(mdoc, tok, pos, WARN_ARGS_GE1)) return(0); - if (0 == c) - break; + mdoc_elem_alloc(mdoc, pos, tok, 0, NULL, sz, _C(args)); + return(1); - /* Break at the next command. */ + case (MDOC_Ar): + /* FALLTHROUGH */ + case (MDOC_Cm): + /* FALLTHROUGH */ + case (MDOC_Fl): + mdoc_elem_alloc(mdoc, pos, tok, 0, NULL, sz, _C(args)); + return(1); - if (ROFF_MAX != (c = rofffindcallable(args[pos]))) { - if ( ! macro(tree, tok, argc, argv, i, p)) - return(0); - if ( ! parse(tree, c, pos, args)) + case (MDOC_Ad): + /* FALLTHROUGH */ + case (MDOC_Em): + /* FALLTHROUGH */ + case (MDOC_Er): + /* FALLTHROUGH */ + case (MDOC_Ev): + /* FALLTHROUGH */ + case (MDOC_Fa): + /* FALLTHROUGH */ + case (MDOC_Dv): + /* FALLTHROUGH */ + case (MDOC_Ic): + /* FALLTHROUGH */ + case (MDOC_Va): + /* FALLTHROUGH */ + case (MDOC_Vt): + if (0 == sz) + return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1)); + mdoc_elem_alloc(mdoc, pos, tok, 0, NULL, sz, _C(args)); + return(1); + + /* ======= ADD MORE MACRO ARGUMENT-LIMITS ABOVE. ======= */ + default: + break; + } + + abort(); + /* NOTREACHED */ +} + + +int +macro_text(struct mdoc *mdoc, int tok, int ppos, int *pos, char *buf) +{ + int lastarg, j, c, lasttok, lastpunct; + char *args[MDOC_LINEARG_MAX], *p; + + lasttok = ppos; + lastpunct = 0; + j = 0; + +again: + + lastarg = *pos; + c = args_next(mdoc, tok, pos, buf, &args[j]); + + if (-1 == c) + return(0); + if (0 == c && ! lastpunct) + return(append_text(mdoc, tok, lasttok, j, args)); + else if (0 == c) + return(1); + + /* Command found. */ + + if (MDOC_MAX != (c = mdoc_find(mdoc, args[j]))) { + if ( ! lastpunct) + if ( ! append_text(mdoc, tok, lasttok, j, args)) return(0); - break; - } + return(mdoc_macro(mdoc, c, lastarg, pos, buf)); + } - /* Continue if we're just words. */ + /* Word found. */ - if ( ! roffispunct(args[pos])) { - i++; - continue; - } + if ( ! isdelim(args[j])) { + j++; + goto again; + } + + /* Punctuation found. */ + + p = args[j]; /* Save argument (NULL-ified in append). */ + + if ( ! lastpunct) + if ( ! append_text(mdoc, tok, lasttok, j, args)) + return(0); + + args[j] = p; - /* Break if there's only remaining punctuation. */ + mdoc_word_alloc(mdoc, lastarg, args[j]); + lastpunct = 1; + j = 0; - if (args[pos + 1] && roffispunct(args[pos + 1])) + goto again; + + /* NOTREACHED */ +} + + +int +macro_scoped_implicit(struct mdoc *mdoc, + int tok, int ppos, int *pos, char *buf) +{ + int j, c, lastarg, t; + char *args[MDOC_LINEARG_MAX]; + struct mdoc_node *n; + + /* + * Look for an implicit parent. + */ + + assert( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)); + + for (n = mdoc->last; n; n = n->parent) { + if (MDOC_BLOCK != n->type) + continue; + if (tok == (t = n->data.block.tok)) break; + if ( ! (MDOC_EXPLICIT & mdoc_macros[t].flags)) + continue; + return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK)); + } - /* If there are remaining words, start anew. */ + if (n) { + mdoc->last = n; + mdoc_msg(mdoc, ppos, "scope: rewound `%s'", + mdoc_macronames[tok]); + } else + mdoc_msg(mdoc, ppos, "scope: new `%s'", + mdoc_macronames[tok]); - if ( ! macro(tree, tok, argc, argv, i, p)) - return(0); + j = 0; + +again: + + lastarg = *pos; + c = args_next(mdoc, tok, pos, buf, &args[j]); + + if (-1 == c) + return(0); + if (0 == c) + return(append_scoped(mdoc, tok, ppos, j, args)); - /* Spit out the punctuation. */ + /* Command found. */ - if ( ! word(tree, tok, *args++)) + if (MDOC_MAX != (c = mdoc_find(mdoc, args[j]))) + if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_MACLIKE)) return(0); - i++; - } + + /* Word found. */ + + j++; + goto again; + + /* NOTREACHED */ } @@ -0,0 +1,734 @@ +/* $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 <stdarg.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "private.h" + +extern int macro_text(struct mdoc *, int, int, int *, char *); +extern int macro_scoped_implicit(struct mdoc *, + int, int, int *, char *); + +const char *const __mdoc_macronames[MDOC_MAX] = { + "\\\"", "Dd", "Dt", "Os", + "Sh", "Ss", "Pp", "D1", + "Dl", "Bd", "Ed", "Bl", + "El", "It", "Ad", "An", + "Ar", "Cd", "Cm", "Dv", + "Er", "Ev", "Ex", "Fa", + "Fd", "Fl", "Fn", "Ft", + "Ic", "In", "Li", "Nd", + "Nm", "Op", "Ot", "Pa", + "Rv", "St", "Va", "Vt", + /* LINTED */ + "Xr", "\%A", "\%B", "\%D", + /* LINTED */ + "\%I", "\%J", "\%N", "\%O", + /* LINTED */ + "\%P", "\%R", "\%T", "\%V", + "Ac", "Ao", "Aq", "At", + "Bc", "Bf", "Bo", "Bq", + "Bsx", "Bx", "Db", "Dc", + "Do", "Dq", "Ec", "Ef", + "Em", "Eo", "Fx", "Ms", + "No", "Ns", "Nx", "Ox", + "Pc", "Pf", "Po", "Pq", + "Qc", "Ql", "Qo", "Qq", + "Re", "Rs", "Sc", "So", + "Sq", "Sm", "Sx", "Sy", + "Tn", "Ux", "Xc", "Xo", + "Fo", "Fc", "Oo", "Oc", + "Bk", "Ek", "Bt", "Hf", + "Fr", "Ud", + }; + +const char *const __mdoc_argnames[MDOC_ARG_MAX] = { + "split", "nosplit", "ragged", + "unfilled", "literal", "file", + "offset", "bullet", "dash", + "hyphen", "item", "enum", + "tag", "diag", "hang", + "ohang", "inset", "column", + "width", "compact", "std", + "p1003.1-88", "p1003.1-90", "p1003.1-96", + "p1003.1-2001", "p1003.1-2004", "p1003.1", + "p1003.1b", "p1003.1b-93", "p1003.1c-95", + "p1003.1g-2000", "p1003.2-92", "p1387.2-95", + "p1003.2", "p1387.2", "isoC-90", + "isoC-amd1", "isoC-tcor1", "isoC-tcor2", + "isoC-99", "ansiC", "ansiC-89", + "ansiC-99", "ieee754", "iso8802-3", + "xpg3", "xpg4", "xpg4.2", + "xpg4.3", "xbd5", "xcu5", + "xsh5", "xns5", "xns5.2d2.0", + "xcurses4.2", "susv2", "susv3", + "svid4", "filled", "words", + }; + +const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { + { NULL, 0 }, /* \" */ + { NULL, 0 }, /* Dd */ + { NULL, 0 }, /* Dt */ + { NULL, 0 }, /* Os */ + { macro_scoped_implicit, 0 }, /* Sh */ + { macro_scoped_implicit, 0 }, /* Ss */ + { NULL, 0 }, /* Pp */ + { NULL, 0 }, /* D1 */ + { NULL, 0 }, /* Dl */ + { NULL, 0 }, /* Bd */ + { NULL, 0 }, /* Ed */ + { NULL, 0 }, /* Bl */ + { NULL, 0 }, /* El */ + { NULL, 0 }, /* It */ + { macro_text, MDOC_CALLABLE }, /* Ad */ + { NULL, 0 }, /* An */ + { macro_text, MDOC_CALLABLE }, /* Ar */ + { NULL, 0 }, /* Cd */ + { macro_text, MDOC_CALLABLE }, /* Cm */ + { macro_text, MDOC_CALLABLE }, /* Dv */ + { macro_text, MDOC_CALLABLE }, /* Er */ + { macro_text, MDOC_CALLABLE }, /* Ev */ + { NULL, 0 }, /* Ex */ + { macro_text, MDOC_CALLABLE }, /* Fa */ + { NULL, 0 }, /* Fd */ + { macro_text, MDOC_CALLABLE }, /* Fl */ + { NULL, 0 }, /* Fn */ + { macro_text, 0 }, /* Ft */ + { macro_text, MDOC_CALLABLE }, /* Ic */ + { NULL, 0 }, /* In */ + { macro_text, MDOC_CALLABLE }, /* Li */ + { NULL, 0 }, /* Nd */ + { NULL, 0 }, /* Nm */ + { NULL, 0 }, /* Op */ + { NULL, 0 }, /* Ot */ + { macro_text, MDOC_CALLABLE }, /* Pa */ + { NULL, 0 }, /* Rv */ + { NULL, 0 }, /* St */ + { macro_text, MDOC_CALLABLE }, /* Va */ + { macro_text, MDOC_CALLABLE }, /* Vt */ + { NULL, 0 }, /* Xr */ + { NULL, 0 }, /* %A */ + { NULL, 0 }, /* %B */ + { NULL, 0 }, /* %D */ + { NULL, 0 }, /* %I */ + { NULL, 0 }, /* %J */ + { NULL, 0 }, /* %N */ + { NULL, 0 }, /* %O */ + { NULL, 0 }, /* %P */ + { NULL, 0 }, /* %R */ + { NULL, 0 }, /* %T */ + { NULL, 0 }, /* %V */ + { NULL, 0 }, /* Ac */ + { NULL, 0 }, /* Ao */ + { NULL, 0 }, /* Aq */ + { NULL, 0 }, /* At */ + { NULL, 0 }, /* Bc */ + { NULL, 0 }, /* Bf */ + { NULL, 0 }, /* Bo */ + { NULL, 0 }, /* Bq */ + { NULL, 0 }, /* Bsx */ + { NULL, 0 }, /* Bx */ + { NULL, 0 }, /* Db */ + { NULL, 0 }, /* Dc */ + { NULL, 0 }, /* Do */ + { NULL, 0 }, /* Dq */ + { NULL, 0 }, /* Ec */ + { NULL, 0 }, /* Ef */ + { macro_text, MDOC_CALLABLE }, /* Em */ + { NULL, 0 }, /* Eo */ + { NULL, 0 }, /* Fx */ + { macro_text, 0 }, /* Ms */ + { NULL, 0 }, /* No */ + { NULL, 0 }, /* Ns */ + { NULL, 0 }, /* Nx */ + { NULL, 0 }, /* Ox */ + { NULL, 0 }, /* Pc */ + { NULL, 0 }, /* Pf */ + { NULL, 0 }, /* Po */ + { NULL, 0 }, /* Pq */ + { NULL, 0 }, /* Qc */ + { NULL, 0 }, /* Ql */ + { NULL, 0 }, /* Qo */ + { NULL, 0 }, /* Qq */ + { NULL, 0 }, /* Re */ + { NULL, 0 }, /* Rs */ + { NULL, 0 }, /* Sc */ + { NULL, 0 }, /* So */ + { NULL, 0 }, /* Sq */ + { NULL, 0 }, /* Sm */ + { NULL, 0 }, /* Sx */ + { NULL, 0 }, /* Sy */ + { macro_text, MDOC_CALLABLE }, /* Tn */ + { NULL, 0 }, /* Ux */ + { NULL, 0 }, /* Xc */ + { NULL, 0 }, /* Xo */ + { NULL, 0 }, /* Fo */ + { NULL, 0 }, /* Fc */ + { NULL, 0 }, /* Oo */ + { NULL, 0 }, /* Oc */ + { NULL, 0 }, /* Bk */ + { NULL, 0 }, /* Ek */ + { NULL, 0 }, /* Bt */ + { NULL, 0 }, /* Hf */ + { NULL, 0 }, /* Fr */ + { NULL, 0 }, /* Ud */ +}; + +const char * const *mdoc_macronames = __mdoc_macronames; +const char * const *mdoc_argnames = __mdoc_argnames; +const struct mdoc_macro * const mdoc_macros = __mdoc_macros; + + +static void *xcalloc(size_t, size_t); +static char *xstrdup(const char *); + +static struct mdoc_arg *argdup(size_t, const struct mdoc_arg *); +static void argfree(size_t, struct mdoc_arg *); +static void argcpy(struct mdoc_arg *, + const struct mdoc_arg *); +static char **paramdup(size_t, const char **); +static void paramfree(size_t, char **); + +static void mdoc_node_freelist(struct mdoc_node *); +static void mdoc_node_append(struct mdoc *, int, + struct mdoc_node *); +static void mdoc_elem_free(struct mdoc_elem *); +static void mdoc_text_free(struct mdoc_text *); + + +const struct mdoc_node * +mdoc_result(struct mdoc *mdoc) +{ + + return(mdoc->first); +} + + +void +mdoc_free(struct mdoc *mdoc) +{ + + if (mdoc->first) + mdoc_node_freelist(mdoc->first); + if (mdoc->htab) + mdoc_hash_free(mdoc->htab); + + free(mdoc); +} + + +struct mdoc * +mdoc_alloc(void *data, const struct mdoc_cb *cb) +{ + struct mdoc *p; + + p = xcalloc(1, sizeof(struct mdoc)); + + p->data = data; + (void)memcpy(&p->cb, cb, sizeof(struct mdoc_cb)); + + p->htab = mdoc_hash_alloc(); + return(p); +} + + +static void * +xcalloc(size_t num, size_t sz) +{ + void *p; + + if (NULL == (p = calloc(num, sz))) + err(EXIT_FAILURE, "calloc"); + return(p); +} + + +static char * +xstrdup(const char *p) +{ + char *pp; + + if (NULL == (pp = strdup(p))) + err(EXIT_FAILURE, "strdup"); + return(pp); +} + + +int +mdoc_parseln(struct mdoc *mdoc, char *buf) +{ + int c, i; + char tmp[5]; + + if ('.' != *buf) { + /* TODO. */ + return(1); + } + + if (buf[1] && '\\' == buf[1]) + if (buf[2] && '\"' == buf[2]) + return(1); + + i = 1; + while (buf[i] && ! isspace(buf[i]) && i < (int)sizeof(tmp)) + i++; + + if (i == (int)sizeof(tmp)) + return(mdoc_err(mdoc, -1, 1, ERR_MACRO_NOTSUP)); + else if (i <= 2) + return(mdoc_err(mdoc, -1, 1, ERR_MACRO_NOTSUP)); + + i--; + + (void)memcpy(tmp, buf + 1, i); + tmp[i++] = 0; + + if (MDOC_MAX == (c = mdoc_find(mdoc, tmp))) + return(mdoc_err(mdoc, c, 1, ERR_MACRO_NOTSUP)); + + while (buf[i] && isspace(buf[i])) + i++; + + if (NULL == (mdoc_macros[c].fp)) { + (void)mdoc_err(mdoc, c, 1, ERR_MACRO_NOTSUP); + return(0); + } + + return((*mdoc_macros[c].fp)(mdoc, c, 1, &i, buf)); +} + + +void +mdoc_msg(struct mdoc *mdoc, int pos, const char *fmt, ...) +{ + va_list ap; + char buf[256]; + + if (NULL == mdoc->cb.mdoc_msg) + return; + + va_start(ap, fmt); + (void)vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + (*mdoc->cb.mdoc_msg)(mdoc->data, pos, buf); +} + + +int +mdoc_err(struct mdoc *mdoc, int tok, int pos, enum mdoc_err type) +{ + + if (NULL == mdoc->cb.mdoc_err) + return(0); + return((*mdoc->cb.mdoc_err)(mdoc->data, tok, pos, type)); +} + + +int +mdoc_warn(struct mdoc *mdoc, int tok, int pos, enum mdoc_warn type) +{ + + if (NULL == mdoc->cb.mdoc_warn) + return(0); + return((*mdoc->cb.mdoc_warn)(mdoc->data, tok, pos, type)); +} + + +int +mdoc_macro(struct mdoc *mdoc, int tok, int ppos, int *pos, char *buf) +{ + + if (NULL == (mdoc_macros[tok].fp)) { + (void)mdoc_err(mdoc, tok, ppos, ERR_MACRO_NOTSUP); + return(0); + } else if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) { + (void)mdoc_err(mdoc, tok, ppos, ERR_MACRO_NOTCALL); + return(0); + } + + return((*mdoc_macros[tok].fp)(mdoc, tok, ppos, pos, buf)); +} + + +static void +mdoc_node_append(struct mdoc *mdoc, int pos, struct mdoc_node *p) +{ + const char *nn, *on, *nt, *ot, *act; + + switch (p->type) { + case (MDOC_TEXT): + nn = "<text>"; + nt = "text"; + break; + case (MDOC_BODY): + nn = mdoc_macronames[p->data.body.tok]; + nt = "body"; + break; + case (MDOC_ELEM): + nn = mdoc_macronames[p->data.elem.tok]; + nt = "elem"; + break; + case (MDOC_HEAD): + nn = mdoc_macronames[p->data.head.tok]; + nt = "head"; + break; + case (MDOC_BLOCK): + nn = mdoc_macronames[p->data.block.tok]; + nt = "block"; + break; + } + + if (NULL == mdoc->first) { + assert(NULL == mdoc->last); + mdoc->first = p; + mdoc->last = p; + mdoc_msg(mdoc, pos, "parse: root %s `%s'", nt, nn); + return; + } + + switch (mdoc->last->type) { + case (MDOC_TEXT): + on = "<text>"; + ot = "text"; + break; + case (MDOC_BODY): + on = mdoc_macronames[mdoc->last->data.body.tok]; + ot = "body"; + break; + case (MDOC_ELEM): + on = mdoc_macronames[mdoc->last->data.elem.tok]; + ot = "elem"; + break; + case (MDOC_HEAD): + on = mdoc_macronames[mdoc->last->data.head.tok]; + ot = "head"; + break; + case (MDOC_BLOCK): + on = mdoc_macronames[mdoc->last->data.block.tok]; + ot = "block"; + break; + } + + switch (p->type) { + case (MDOC_BODY): + switch (mdoc->last->type) { + case (MDOC_BLOCK): + p->parent = mdoc->last; + mdoc->last->child = p; + act = "child"; + break; + case (MDOC_HEAD): + p->parent = mdoc->last->parent; + mdoc->last->next = p; + act = "sibling"; + break; + default: + abort(); + /* NOTREACHED */ + } + break; + case (MDOC_HEAD): + assert(mdoc->last->type == MDOC_BLOCK); + p->parent = mdoc->last; + mdoc->last->child = p; + act = "child"; + break; + default: + switch (mdoc->last->type) { + case (MDOC_BODY): + /* FALLTHROUGH */ + case (MDOC_HEAD): + p->parent = mdoc->last->parent; + mdoc->last->child = p; + act = "child"; + break; + default: + p->parent = mdoc->last->parent; + mdoc->last->next = p; + act = "sibling"; + break; + } + break; + } + + mdoc_msg(mdoc, pos, "parse: %s `%s' %s %s `%s'", + nt, nn, act, ot, on); + mdoc->last = p; +} + + +void +mdoc_head_alloc(struct mdoc *mdoc, int pos, int tok, + size_t paramsz, const char **params) +{ + struct mdoc_node *p; + + assert(mdoc->first); + assert(mdoc->last); + assert(mdoc->last->type == MDOC_BLOCK); + assert(mdoc->last->data.block.tok == tok); + + p = xcalloc(1, sizeof(struct mdoc_node)); + p->type = MDOC_HEAD; + p->data.head.tok = tok; + p->data.head.sz = paramsz; + p->data.head.args = paramdup(paramsz, params); + + mdoc_node_append(mdoc, pos, p); +} + + +void +mdoc_body_alloc(struct mdoc *mdoc, int pos, int tok) +{ + struct mdoc_node *p; + + assert(mdoc->first); + assert(mdoc->last); + assert((mdoc->last->type == MDOC_BLOCK) || + (mdoc->last->type == MDOC_HEAD)); + if (mdoc->last->type == MDOC_BLOCK) + assert(mdoc->last->data.block.tok == tok); + else + assert(mdoc->last->data.head.tok == tok); + + p = xcalloc(1, sizeof(struct mdoc_node)); + + p->type = MDOC_BODY; + p->data.body.tok = tok; + + mdoc_node_append(mdoc, pos, p); +} + + +void +mdoc_block_alloc(struct mdoc *mdoc, int pos, int tok, + size_t argsz, const struct mdoc_arg *args) +{ + struct mdoc_node *p; + + p = xcalloc(1, sizeof(struct mdoc_node)); + + p->type = MDOC_BLOCK; + p->data.block.tok = tok; + p->data.block.argc = argsz; + p->data.block.argv = argdup(argsz, args); + + mdoc_node_append(mdoc, pos, p); +} + + +void +mdoc_elem_alloc(struct mdoc *mdoc, int pos, int tok, + size_t argsz, const struct mdoc_arg *args, + size_t paramsz, const char **params) +{ + struct mdoc_node *p; + + p = xcalloc(1, sizeof(struct mdoc_node)); + p->type = MDOC_ELEM; + p->data.elem.tok = tok; + p->data.elem.sz = paramsz; + p->data.elem.args = paramdup(paramsz, params); + p->data.elem.argc = argsz; + p->data.elem.argv = argdup(argsz, args); + + mdoc_node_append(mdoc, pos, p); +} + + +void +mdoc_word_alloc(struct mdoc *mdoc, int pos, const char *word) +{ + struct mdoc_node *p; + + p = xcalloc(1, sizeof(struct mdoc_node)); + p->type = MDOC_TEXT; + p->data.text.string = xstrdup(word); + + mdoc_node_append(mdoc, pos, p); +} + + +static void +argfree(size_t sz, struct mdoc_arg *p) +{ + size_t i, j; + + if (0 == sz) + return; + + assert(p); + for (i = 0; i < sz; i++) + if (p[i].sz > 0) { + assert(p[i].value); + for (j = 0; j < p[i].sz; j++) + free(p[i].value[j]); + } + free(p); +} + + +static void +mdoc_elem_free(struct mdoc_elem *p) +{ + + paramfree(p->sz, p->args); + argfree(p->argc, p->argv); +} + + +static void +mdoc_block_free(struct mdoc_block *p) +{ + + argfree(p->argc, p->argv); +} + + +static void +mdoc_text_free(struct mdoc_text *p) +{ + + if (p->string) + free(p->string); +} + + +static void +mdoc_head_free(struct mdoc_head *p) +{ + + paramfree(p->sz, p->args); +} + + +void +mdoc_node_free(struct mdoc_node *p) +{ + + switch (p->type) { + case (MDOC_TEXT): + mdoc_text_free(&p->data.text); + break; + case (MDOC_ELEM): + mdoc_elem_free(&p->data.elem); + break; + case (MDOC_BLOCK): + mdoc_block_free(&p->data.block); + break; + case (MDOC_HEAD): + mdoc_head_free(&p->data.head); + break; + default: + break; + } + + free(p); +} + + +static void +mdoc_node_freelist(struct mdoc_node *p) +{ + + if (p->child) + mdoc_node_freelist(p->child); + if (p->next) + mdoc_node_freelist(p->next); + + mdoc_node_free(p); +} + + +int +mdoc_find(const struct mdoc *mdoc, const char *key) +{ + + return(mdoc_hash_find(mdoc->htab, key)); +} + + +static void +argcpy(struct mdoc_arg *dst, const struct mdoc_arg *src) +{ + size_t i; + + dst->arg = src->arg; + if (0 == (dst->sz = src->sz)) + return; + dst->value = xcalloc(dst->sz, sizeof(char *)); + for (i = 0; i < dst->sz; i++) + dst->value[i] = xstrdup(src->value[i]); +} + + +static struct mdoc_arg * +argdup(size_t argsz, const struct mdoc_arg *args) +{ + struct mdoc_arg *pp; + size_t i; + + if (0 == argsz) + return(NULL); + + pp = xcalloc((size_t)argsz, sizeof(struct mdoc_arg)); + for (i = 0; i < argsz; i++) + argcpy(&pp[i], &args[i]); + + return(pp); +} + + +static void +paramfree(size_t sz, char **p) +{ + size_t i; + + if (0 == sz) + return; + + assert(p); + for (i = 0; i < sz; i++) + free(p[i]); + free(p); +} + + +static char ** +paramdup(size_t sz, const char **p) +{ + char **pp; + size_t i; + + if (0 == sz) + return(NULL); + + pp = xcalloc(sz, sizeof(char *)); + for (i = 0; i < sz; i++) + pp[i] = xstrdup(p[i]); + + return(pp); +} @@ -0,0 +1,289 @@ +/* $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 MDOC_H +#define MDOC_H + +#define MDOC_LINEARG_MAX 9 + +#define MDOC___ 0 +#define MDOC_Dd 1 +#define MDOC_Dt 2 +#define MDOC_Os 3 +#define MDOC_Sh 4 +#define MDOC_Ss 5 +#define MDOC_Pp 6 +#define MDOC_D1 7 +#define MDOC_Dl 8 +#define MDOC_Bd 9 +#define MDOC_Ed 10 +#define MDOC_Bl 11 +#define MDOC_El 12 +#define MDOC_It 13 +#define MDOC_Ad 14 +#define MDOC_An 15 +#define MDOC_Ar 16 +#define MDOC_Cd 17 +#define MDOC_Cm 18 +#define MDOC_Dv 19 +#define MDOC_Er 20 +#define MDOC_Ev 21 +#define MDOC_Ex 22 +#define MDOC_Fa 23 +#define MDOC_Fd 24 +#define MDOC_Fl 25 +#define MDOC_Fn 26 +#define MDOC_Ft 27 +#define MDOC_Ic 28 +#define MDOC_In 29 +#define MDOC_Li 30 +#define MDOC_Nd 31 +#define MDOC_Nm 32 +#define MDOC_Op 33 +#define MDOC_Ot 34 +#define MDOC_Pa 35 +#define MDOC_Rv 36 +#define MDOC_St 37 +#define MDOC_Va 38 +#define MDOC_Vt 39 +#define MDOC_Xr 40 +#define MDOC__A 41 +#define MDOC__B 42 +#define MDOC__D 43 +#define MDOC__I 44 +#define MDOC__J 45 +#define MDOC__N 46 +#define MDOC__O 47 +#define MDOC__P 48 +#define MDOC__R 49 +#define MDOC__T 50 +#define MDOC__V 51 +#define MDOC_Ac 52 +#define MDOC_Ao 53 +#define MDOC_Aq 54 +#define MDOC_At 55 +#define MDOC_Bc 56 +#define MDOC_Bf 57 +#define MDOC_Bo 58 +#define MDOC_Bq 59 +#define MDOC_Bsx 60 +#define MDOC_Bx 61 +#define MDOC_Db 62 +#define MDOC_Dc 63 +#define MDOC_Do 64 +#define MDOC_Dq 65 +#define MDOC_Ec 66 +#define MDOC_Ef 67 +#define MDOC_Em 68 +#define MDOC_Eo 69 +#define MDOC_Fx 70 +#define MDOC_Ms 71 +#define MDOC_No 72 +#define MDOC_Ns 73 +#define MDOC_Nx 74 +#define MDOC_Ox 75 +#define MDOC_Pc 76 +#define MDOC_Pf 77 +#define MDOC_Po 78 +#define MDOC_Pq 79 +#define MDOC_Qc 80 +#define MDOC_Ql 81 +#define MDOC_Qo 82 +#define MDOC_Qq 83 +#define MDOC_Re 84 +#define MDOC_Rs 85 +#define MDOC_Sc 86 +#define MDOC_So 87 +#define MDOC_Sq 88 +#define MDOC_Sm 89 +#define MDOC_Sx 90 +#define MDOC_Sy 91 +#define MDOC_Tn 92 +#define MDOC_Ux 93 +#define MDOC_Xc 94 +#define MDOC_Xo 95 +#define MDOC_Fo 96 +#define MDOC_Fc 97 +#define MDOC_Oo 98 +#define MDOC_Oc 99 +#define MDOC_Bk 100 +#define MDOC_Ek 101 +#define MDOC_Bt 102 +#define MDOC_Hf 103 +#define MDOC_Fr 104 +#define MDOC_Ud 105 +#define MDOC_MAX 106 + +#define MDOC_Split 0 +#define MDOC_Nosplit 1 +#define MDOC_Ragged 2 +#define MDOC_Unfilled 3 +#define MDOC_Literal 4 +#define MDOC_File 5 +#define MDOC_Offset 6 +#define MDOC_Bullet 7 +#define MDOC_Dash 8 +#define MDOC_Hyphen 9 +#define MDOC_Item 10 +#define MDOC_Enum 11 +#define MDOC_Tag 12 +#define MDOC_Diag 13 +#define MDOC_Hang 14 +#define MDOC_Ohang 15 +#define MDOC_Inset 16 +#define MDOC_Column 17 +#define MDOC_Width 18 +#define MDOC_Compact 19 +#define MDOC_Std 20 +#define MDOC_p1003_1_88 21 +#define MDOC_p1003_1_90 22 +#define MDOC_p1003_1_96 23 +#define MDOC_p1003_1_2001 24 +#define MDOC_p1003_1_2004 25 +#define MDOC_p1003_1 26 +#define MDOC_p1003_1b 27 +#define MDOC_p1003_1b_93 28 +#define MDOC_p1003_1c_95 29 +#define MDOC_p1003_1g_2000 30 +#define MDOC_p1003_2_92 31 +#define MDOC_p1387_2_95 32 +#define MDOC_p1003_2 33 +#define MDOC_p1387_2 34 +#define MDOC_isoC_90 35 +#define MDOC_isoC_amd1 36 +#define MDOC_isoC_tcor1 37 +#define MDOC_isoC_tcor2 38 +#define MDOC_isoC_99 39 +#define MDOC_ansiC 40 +#define MDOC_ansiC_89 41 +#define MDOC_ansiC_99 42 +#define MDOC_ieee754 43 +#define MDOC_iso8802_3 44 +#define MDOC_xpg3 45 +#define MDOC_xpg4 46 +#define MDOC_xpg4_2 47 +#define MDOC_xpg4_3 48 +#define MDOC_xbd5 49 +#define MDOC_xcu5 50 +#define MDOC_xsh5 51 +#define MDOC_xns5 52 +#define MDOC_xns5_2d2_0 53 +#define MDOC_xcurses4_2 54 +#define MDOC_susv2 55 +#define MDOC_susv3 56 +#define MDOC_svid4 57 +#define MDOC_Filled 58 +#define MDOC_Words 59 +#define MDOC_ARG_MAX 60 + +enum mdoc_err { + ERR_SYNTAX_QUOTE, + ERR_SYNTAX_WS, + ERR_MACRO_NOTSUP, + ERR_MACRO_NOTCALL, + ERR_SCOPE_BREAK, + ERR_ARGS_GE1 +}; + +enum mdoc_warn { + WARN_SYNTAX_WS_EOLN, + WARN_SYNTAX_MACLIKE, + WARN_ARGS_GE1 +}; + +struct mdoc_arg { + int arg; + size_t sz; + char **value; +}; + +enum mdoc_type { + MDOC_TEXT, + MDOC_ELEM, + MDOC_HEAD, + MDOC_BODY, + MDOC_BLOCK +}; + +struct mdoc_text { + char *string; +}; + +struct mdoc_block { + int tok; + size_t argc; + struct mdoc_arg *argv; +}; + +struct mdoc_head { + size_t sz; + char **args; + int tok; +}; + +struct mdoc_body { + int tok; +}; + +struct mdoc_elem { + size_t sz; + char **args; + int tok; + size_t argc; + struct mdoc_arg *argv; +}; + +union mdoc_data { + struct mdoc_text text; + struct mdoc_elem elem; + struct mdoc_body body; + struct mdoc_head head; + struct mdoc_block block; +}; + +struct mdoc_node { + struct mdoc_node *parent; + struct mdoc_node *child; + struct mdoc_node *next; + enum mdoc_type type; + union mdoc_data data; +}; + +struct mdoc_cb { + int (*mdoc_err)(void *, int, int, enum mdoc_err); + int (*mdoc_warn)(void *, int, int, enum mdoc_warn); + void (*mdoc_msg)(void *, int, const char *); +}; + +extern const char *const *mdoc_macronames; +extern const char *const *mdoc_argnames; + +__BEGIN_DECLS + +struct mdoc; + +void mdoc_free(struct mdoc *); +struct mdoc *mdoc_alloc(void *data, const struct mdoc_cb *); +int mdoc_parseln(struct mdoc *, char *buf); + +const struct mdoc_node + *mdoc_result(struct mdoc *); + +__END_DECLS + +#endif /*!MDOC_H*/ @@ -16,39 +16,48 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ -#include <sys/param.h> #include <sys/stat.h> +#include <sys/param.h> #include <assert.h> -#include <err.h> #include <fcntl.h> +#include <err.h> #include <getopt.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include "libmdocml.h" +#include "mdoc.h" -#define BUFFER_IN_DEF BUFSIZ /* See begin_bufs. */ -#define BUFFER_OUT_DEF BUFSIZ /* See begin_bufs. */ +#define MD_LINE_SZ (256) -#ifdef DEBUG -#define CSS "mdocml.css" -#else -#define CSS "/usr/local/share/mdocml/mdocml.css" -#endif +struct md_parse { + int warn; +#define MD_WARN_ALL (1 << 0) +#define MD_WARN_ERR (1 << 1) + int dbg; + struct mdoc *mdoc; + char *buf; + u_long bufsz; + char *name; + int fd; + int lnn; + char *line; +}; static void usage(void); -static int begin_io(const struct md_args *, - char *, char *); -static int leave_io(const struct md_buf *, - const struct md_buf *, int); -static int begin_bufs(const struct md_args *, - struct md_buf *, struct md_buf *); -static int leave_bufs(const struct md_buf *, - const struct md_buf *, int); +static int parse_begin(struct md_parse *); +static int parse_leave(struct md_parse *, int); +static int io_begin(struct md_parse *); +static int io_leave(struct md_parse *, int); +static int buf_begin(struct md_parse *); +static int buf_leave(struct md_parse *, int); + +static int msg_err(void *, int, int, enum mdoc_err); +static int msg_warn(void *, int, int, enum mdoc_warn); +static void msg_msg(void *, int, const char *); #ifdef __linux__ extern int getsubopt(char **, char *const *, char **); @@ -58,8 +67,8 @@ int main(int argc, char *argv[]) { int c; - char *out, *in, *opts, *v; - struct md_args args; + struct md_parse parser; + char *opts, *v; #define ALL 0 #define ERROR 1 char *toks[] = { "all", "error", NULL }; @@ -67,49 +76,22 @@ main(int argc, char *argv[]) extern char *optarg; extern int optind; - out = in = NULL; + (void)memset(&parser, 0, sizeof(struct md_parse)); - (void)memset(&args, 0, sizeof(struct md_args)); - - args.type = MD_NOOP; - - while (-1 != (c = getopt(argc, argv, "c:ef:o:vW:"))) + while (-1 != (c = getopt(argc, argv, "vW:"))) switch (c) { - case ('c'): - if (args.type != MD_HTML) - errx(1, "-c only valid for -fhtml"); - args.params.html.css = optarg; - break; - case ('e'): - if (args.type != MD_HTML) - errx(1, "-e only valid for -fhtml"); - args.params.html.flags |= HTML_CSS_EMBED; - break; - case ('f'): - if (0 == strcmp(optarg, "html")) - args.type = MD_HTML; - else if (0 == strcmp(optarg, "xml")) - args.type = MD_XML; - else if (0 == strcmp(optarg, "noop")) - args.type = MD_NOOP; - else - errx(1, "invalid filter type"); - break; - case ('o'): - out = optarg; - break; case ('v'): - args.verbosity++; + parser.dbg++; break; case ('W'): opts = optarg; while (*opts) switch (getsubopt(&opts, toks, &v)) { case (ALL): - args.warnings |= MD_WARN_ALL; + parser.warn |= MD_WARN_ALL; break; case (ERROR): - args.warnings |= MD_WARN_ERROR; + parser.warn |= MD_WARN_ERR; break; default: usage(); @@ -121,148 +103,324 @@ main(int argc, char *argv[]) return(1); } - if (MD_HTML == args.type) - if (NULL == args.params.html.css) - args.params.html.css = CSS; - argv += optind; argc -= optind; + parser.name = "-"; if (1 == argc) - in = *argv++; + parser.name = *argv++; + + if ( ! io_begin(&parser)) + return(EXIT_FAILURE); - return(begin_io(&args, out ? out : "-", in ? in : "-")); + return(EXIT_SUCCESS); } -/* - * Close out file descriptors opened in begin_io. If the descriptor - * refers to stdin/stdout, then do nothing. - */ static int -leave_io(const struct md_buf *out, - const struct md_buf *in, int c) +io_leave(struct md_parse *p, int code) { - assert(out); - assert(in); - if (-1 != in->fd && -1 == close(in->fd)) { - assert(in->name); - warn("%s", in->name); - c = 1; - } - if (-1 != out->fd && STDOUT_FILENO != out->fd && - -1 == close(out->fd)) { - assert(out->name); - warn("%s", out->name); - c = 1; + if (-1 == p->fd || STDIN_FILENO == p->fd) + return(code); + + if (-1 == close(p->fd)) { + warn("%s", p->name); + code = 0; } - if (1 == c && STDOUT_FILENO != out->fd) - if (-1 == unlink(out->name)) - warn("%s", out->name); + return(code); +} + + +static int +io_begin(struct md_parse *p) +{ + + p->fd = STDIN_FILENO; + if (0 != strncmp(p->name, "-", 1)) + if (-1 == (p->fd = open(p->name, O_RDONLY, 0))) { + warn("%s", p->name); + return(io_leave(p, 0)); + } - return(c); + return(io_leave(p, buf_begin(p))); } -/* - * Open file descriptors or assign stdin/stdout, if dictated by the "-" - * token instead of a filename. - */ static int -begin_io(const struct md_args *args, char *out, char *in) +buf_leave(struct md_parse *p, int code) { - struct md_buf fi; - struct md_buf fo; -#define FI_FL O_RDONLY -#define FO_FL O_WRONLY|O_CREAT|O_TRUNC + if (p->buf) + free(p->buf); + return(code); +} - assert(args); - assert(out); - assert(in); - bzero(&fi, sizeof(struct md_buf)); - bzero(&fo, sizeof(struct md_buf)); +static int +buf_begin(struct md_parse *p) +{ + struct stat st; - fi.fd = STDIN_FILENO; - fo.fd = STDOUT_FILENO; + if (-1 == fstat(p->fd, &st)) { + warn("%s", p->name); + return(1); + } - fi.name = in; - fo.name = out; + p->bufsz = MAX(st.st_blksize, BUFSIZ); - if (0 != strncmp(fi.name, "-", 1)) - if (-1 == (fi.fd = open(fi.name, FI_FL, 0))) { - warn("%s", fi.name); - return(leave_io(&fo, &fi, 1)); - } + if (NULL == (p->buf = malloc(p->bufsz))) { + warn("malloc"); + return(buf_leave(p, 0)); + } + + return(buf_leave(p, parse_begin(p))); +} + + +static void +print_node(const struct mdoc_node *n, int indent) +{ + const char *p, *t; + int i; + + switch (n->type) { + case (MDOC_TEXT): + assert(NULL == n->child); + p = "<text>"; + t = "text"; + break; + case (MDOC_BODY): + p = mdoc_macronames[n->data.body.tok]; + t = "block-body"; + break; + case (MDOC_HEAD): + p = mdoc_macronames[n->data.head.tok]; + t = "block-head"; + break; + case (MDOC_ELEM): + assert(NULL == n->child); + p = mdoc_macronames[n->data.elem.tok]; + t = "element"; + break; + case (MDOC_BLOCK): + p = mdoc_macronames[n->data.block.tok]; + t = "block"; + break; + } + + for (i = 0; i < indent; i++) + (void)printf(" "); + (void)printf("%s (%s)\n", p, t); + + if (n->child) + print_node(n->child, indent + 1); + if (n->next) + print_node(n->next, indent); +} + + +static int +parse_leave(struct md_parse *p, int code) +{ + const struct mdoc_node *n; - if (0 != strncmp(fo.name, "-", 1)) - if (-1 == (fo.fd = open(fo.name, FO_FL, 0644))) { - warn("%s", fo.name); - return(leave_io(&fo, &fi, 1)); + if (p->mdoc) { + if ((n = mdoc_result(p->mdoc))) + print_node(n, 0); + mdoc_free(p->mdoc); + } + return(code); +} + + +static int +parse_begin(struct md_parse *p) +{ + ssize_t sz, i; + size_t pos; + char line[256], sv[256]; + struct mdoc_cb cb; + + cb.mdoc_err = msg_err; + cb.mdoc_warn = msg_warn; + cb.mdoc_msg = msg_msg; + + if (NULL == (p->mdoc = mdoc_alloc(p, &cb))) + return(parse_leave(p, 0)); + + p->lnn = 1; + p->line = sv; + + for (pos = 0; ; ) { + if (-1 == (sz = read(p->fd, p->buf, p->bufsz))) { + warn("%s", p->name); + return(parse_leave(p, 0)); + } else if (0 == sz) + break; + + for (i = 0; i < sz; i++) { + if ('\n' != p->buf[i]) { + if (pos < sizeof(line)) { + /* LINTED */ + sv[pos] = p->buf[i]; + line[pos++] = p->buf[i]; + continue; + } + warnx("%s: line %d too long", + p->name, p->lnn); + return(parse_leave(p, 0)); + } + + line[(int)pos] = sv[(int)pos] = 0; + if ( ! mdoc_parseln(p->mdoc, line)) + return(parse_leave(p, 0)); + + p->lnn++; + pos = 0; } + } - return(leave_io(&fo, &fi, begin_bufs(args, &fo, &fi))); + return(parse_leave(p, 1)); } -/* - * Free buffers allocated in begin_bufs. - */ static int -leave_bufs(const struct md_buf *out, - const struct md_buf *in, int c) +msg_err(void *arg, int tok, int col, enum mdoc_err type) +{ + char *fmt, *lit; + struct md_parse *p; + int i; + + p = (struct md_parse *)arg; + + fmt = lit = NULL; + + switch (type) { + case (ERR_SYNTAX_QUOTE): + lit = "syntax: unterminated quotation"; + break; + case (ERR_SYNTAX_WS): + lit = "syntax: whitespace in argument"; + break; + case (ERR_SCOPE_BREAK): + /* Which scope is broken? */ + fmt = "macro `%s' breaks prior explicit scope"; + break; + case (ERR_MACRO_NOTSUP): + fmt = "macro `%s' not supported"; + break; + case (ERR_MACRO_NOTCALL): + fmt = "macro `%s' not callable"; + break; + case (ERR_ARGS_GE1): + fmt = "macro `%s' expects one or more arguments"; + break; + default: + abort(); + /* NOTREACHED */ + } + + if (fmt) { + (void)fprintf(stderr, "%s:%d: error: ", + p->name, p->lnn); + (void)fprintf(stderr, fmt, mdoc_macronames[tok]); + } else + (void)fprintf(stderr, "%s:%d: error: %s", + p->name, p->lnn, lit); + + if (p->dbg < 1) { + (void)fprintf(stderr, " (column %d)\n", col); + return(0); + } + + (void)fprintf(stderr, "\nFrom: %s\n ", p->line); + for (i = 0; i < col; i++) + (void)fprintf(stderr, " "); + (void)fprintf(stderr, "^\n"); + + return(0); +} + + +static void +msg_msg(void *arg, int col, const char *msg) { - assert(out); - assert(in); - if (out->buf) - free(out->buf); - if (in->buf) - free(in->buf); - return(c); + struct md_parse *p; + int i; + + p = (struct md_parse *)arg; + + if (p->dbg < 2) + return; + + (void)printf("%s:%d: %s", p->name, p->lnn, msg); + + if (p->dbg < 3) { + (void)printf(" (column %d)\n", col); + return; + } + + (void)printf("\nFrom: %s\n ", p->line); + for (i = 0; i < col; i++) + (void)printf(" "); + (void)printf("^\n"); } -/* - * Allocate buffers to the maximum of either the input file's blocksize - * or BUFFER_IN_DEF/BUFFER_OUT_DEF, which should be around BUFSIZE. - */ static int -begin_bufs(const struct md_args *args, - struct md_buf *out, struct md_buf *in) +msg_warn(void *arg, int tok, int col, enum mdoc_warn type) { - struct stat stin, stout; - int c; + char *fmt, *lit; + struct md_parse *p; + int i; + extern char *__progname; - assert(args); - assert(in); - assert(out); + p = (struct md_parse *)arg; - if (-1 == fstat(in->fd, &stin)) { - warn("%s", in->name); - return(1); - } else if (STDIN_FILENO != in->fd && 0 == stin.st_size) { - warnx("%s: empty file", in->name); + if ( ! (p->warn & MD_WARN_ALL)) return(1); - } else if (-1 == fstat(out->fd, &stout)) { - warn("%s", out->name); - return(1); - } - in->bufsz = MAX(stin.st_blksize, BUFFER_IN_DEF); - out->bufsz = MAX(stout.st_blksize, BUFFER_OUT_DEF); + fmt = lit = NULL; + + switch (type) { + case (WARN_SYNTAX_WS_EOLN): + lit = "syntax: whitespace at end-of-line"; + break; + case (WARN_SYNTAX_MACLIKE): + lit = "syntax: macro-like argument"; + break; + case (WARN_ARGS_GE1): + fmt = "macro `%s' suggests one or more arguments"; + break; + default: + abort(); + /* NOTREACHED */ + } - if (NULL == (in->buf = malloc(in->bufsz))) { - warn("malloc"); - return(leave_bufs(out, in, 1)); - } else if (NULL == (out->buf = malloc(out->bufsz))) { - warn("malloc"); - return(leave_bufs(out, in, 1)); + if (fmt) { + (void)fprintf(stderr, "%s:%d: warning: ", + p->name, p->lnn); + (void)fprintf(stderr, fmt, mdoc_macronames[tok]); + } else + (void)fprintf(stderr, "%s:%d: warning: %s", + p->name, p->lnn, lit); + + if (p->dbg >= 1) { + (void)fprintf(stderr, "\nFrom: %s\n ", p->line); + for (i = 0; i < col; i++) + (void)fprintf(stderr, " "); + (void)fprintf(stderr, "^\n"); + } else + (void)fprintf(stderr, " (column %d)\n", col); + + if (p->warn & MD_WARN_ERR) { + (void)fprintf(stderr, "%s: considering warnings as " + "errors\n", __progname); + return(0); } - c = md_run(args, out, in); - return(leave_bufs(out, in, -1 == c ? 1 : 0)); + return(1); } @@ -271,8 +429,7 @@ usage(void) { extern char *__progname; - (void)fprintf(stderr, "usage: %s [-v] [-Wwarn...] " - "[-f filter] [-o outfile] [infile]\n", + (void)fprintf(stderr, "usage: %s [-v] [-Wwarn...] [infile]\n", __progname); } diff --git a/mdocml.css b/mdocml.css deleted file mode 100644 index 05f7906a..00000000 --- a/mdocml.css +++ /dev/null @@ -1,58 +0,0 @@ - body { margin: 10px; - font-family: Tahoma, sans-serif; - font-size: small; } - h1 { font-size: small; } - h2 { font-size: small; } - div.mdoc { width: 600px; } - div.block-Sh { margin-bottom: 20px; } - div.head-Ss { font-weight: bold; - margin-top: 10px; - text-align: justify; } - div.body-Sh { margin-left: 20px; - margin-top: 10px; - text-align: justify; } - table.header-table { margin-bottom: 10px; } - td.header-section { text-transform: uppercase; } - span.inline-Nd:before { content: ' \2014 '; } - span.inline-Fl:before { content: '-'; } - span.inline-Fl { font-weight: bolder; } - span.inline-Cm { font-weight: bolder; } - span.inline-Cd { font-weight: bolder; } - span.inline-Nm { font-weight: bolder; } - span.inline-An { text-decoration: underline; } - span.inline-Ar { text-decoration: underline; } - span.inline-Pa { text-decoration: underline; } - div.block-Bl { margin-top: 10px; - margin-left: 20px; } - div.inline-Pp { margin-bottom: 10px; } - span.inline-Sy { font-weight: bolder; } - span.inline-Tn { font-variant: small-caps; } - div.inline-D1 { margin-left: 20px; } - div.inline-Dl { margin-left: 20px; } - span.head-Fo { font-weight: bolder; } - span.body-Fo:before { content: '('; } - span.body-Fo:after { content: ')'; } - span.body-Oo:before { content: '['; } - span.body-Oo:after { content: ']'; } - span.inline-Va { text-decoration: underline; } - span.inline-Vt { text-decoration: underline; } - span.inline-Em { font-style: italic; } - span.inline-Ft { text-decoration: underline; } - span.inline-Fd { font-weight: bolder; } - span.inline-Ic { font-weight: bolder; } - span.inline-Op:before { content: '['; } - span.inline-Op:after { content: ']'; } - span.inline-Qq:before { content: '\"'; } - span.inline-Qq:after { content: '\"'; } - span.inline-Aq:before { content: '\3c'; } - span.inline-Aq:after { content: '\3e'; } - span.inline-Bq:before { content: '['; } - span.inline-Bq:after { content: ']'; } - span.inline-Dq:before { content: '\201c'; } - span.inline-Dq:after { content: '\201d'; } - span.inline-Pq:before { content: '('; } - span.inline-Pq:after { content: ')'; } - span.inline-Ql:before { content: '\2018'; } - span.inline-Ql:after { content: '\2019'; } - span.inline-Sq:before { content: '\2018'; } - span.inline-Sq:after { content: '\2019'; } @@ -1,261 +0,0 @@ -/* $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 <stdlib.h> -#include <string.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 - - -int -ml_putstring(struct md_mbuf *p, const char *buf, size_t *pos) -{ - - return(ml_nputstring(p, buf, strlen(buf), pos)); -} - - -int -ml_nputstring(struct md_mbuf *p, - const char *buf, size_t sz, size_t *pos) -{ - int i, v; - const char *seq; - size_t ssz; - - for (i = 0; i < (int)sz; i++) { - switch (buf[i]) { - - /* Escaped value. */ - case ('\\'): - if (-1 == (v = rofftok_scan(buf, &i))) - return(0); - - switch (v) { - case (ROFFTok_Sp_A): - seq = "\\a"; - ssz = 2; - break; - case (ROFFTok_Sp_B): - seq = "\\b"; - ssz = 2; - break; - case (ROFFTok_Sp_F): - seq = "\\f"; - ssz = 2; - break; - case (ROFFTok_Sp_N): - seq = "\\n"; - ssz = 2; - break; - case (ROFFTok_Sp_R): - seq = "\\r"; - ssz = 2; - break; - case (ROFFTok_Sp_T): - seq = "\\t"; - ssz = 2; - break; - case (ROFFTok_Sp_V): - seq = "\\v"; - ssz = 2; - break; - case (ROFFTok_Sp_0): - seq = "\\0"; - ssz = 2; - break; - case (ROFFTok_Space): - seq = " "; - ssz = 6; - break; - case (ROFFTok_Hyphen): - seq = "‐"; - ssz = 7; - break; - case (ROFFTok_Em): - seq = "—"; - ssz = 7; - break; - case (ROFFTok_En): - seq = "–"; - ssz = 7; - break; - case (ROFFTok_Ge): - seq = "≥"; - ssz = 7; - break; - case (ROFFTok_Le): - seq = "≤"; - ssz = 7; - break; - case (ROFFTok_Rquote): - seq = "”"; - ssz = 7; - break; - case (ROFFTok_Lquote): - seq = "“"; - ssz = 7; - break; - case (ROFFTok_Uparrow): - seq = "↑"; - ssz = 7; - break; - case (ROFFTok_Acute): - seq = "´"; - ssz = 6; - break; - case (ROFFTok_Grave): - seq = "`"; - ssz = 5; - break; - case (ROFFTok_Pi): - seq = "π"; - ssz = 6; - break; - case (ROFFTok_Ne): - seq = "≠"; - ssz = 7; - break; - case (ROFFTok_Lt): - seq = "<"; - ssz = 4; - break; - case (ROFFTok_Gt): - seq = ">"; - ssz = 4; - break; - case (ROFFTok_Plusmin): - seq = "±"; - ssz = 6; - break; - case (ROFFTok_Infty): - seq = "∞"; - ssz = 7; - break; - case (ROFFTok_Bar): - seq = "|"; - ssz = 6; - break; - case (ROFFTok_Nan): - seq = "Nan"; - ssz = 3; - break; - case (ROFFTok_Quote): - seq = """; - ssz = 6; - break; - case (ROFFTok_Slash): - seq = "\\"; - ssz = 1; - break; - case (ROFFTok_Null): - seq = ""; - ssz = 0; - break; - default: - return(0); - } - break; - - /* Ampersand ml-escape. */ - case ('&'): - seq = "&"; - ssz = 5; - break; - - /* Quotation ml-escape. */ - case ('"'): - seq = """; - ssz = 6; - break; - - /* Lt ml-escape. */ - case ('<'): - seq = "<"; - ssz = 4; - break; - - /* Gt ml-escape. */ - case ('>'): - seq = ">"; - ssz = 4; - break; - - default: - seq = &buf[i]; - ssz = 1; - break; - } - - if (ssz > 0 && ! ml_nputs(p, seq, ssz, pos)) - return(-1); - } - return(1); -} - - -int -ml_nputs(struct md_mbuf *p, const char *buf, size_t sz, size_t *pos) -{ - - if (0 == sz) - return(1); - - if ( ! md_buf_puts(p, buf, sz)) - return(0); - - if (pos) - *pos += sz; - return(1); -} - - -int -ml_puts(struct md_mbuf *p, const char *buf, size_t *pos) -{ - size_t sz; - - if (0 == (sz = strlen(buf))) - return(1); - - if ( ! md_buf_puts(p, buf, sz)) - return(0); - - if (pos) - *pos += sz; - return(1); -} - - -int -ml_putchars(struct md_mbuf *p, char buf, size_t count, size_t *pos) -{ - size_t i; - - for (i = 0; i < count; i++) - if ( ! ml_nputs(p, &buf, 1, pos)) - return(0); - - return(1); -} @@ -1,93 +0,0 @@ -/* $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 - -#include "private.h" - -#define COLUMNS 72 -#define INDENT_SZ 4 -#define INDENT(x) ((x) > MAXINDENT ? MAXINDENT : (x)) -#define MAXINDENT 10 - -struct md_mlg; - -enum md_ns { - MD_NS_BLOCK, - MD_NS_HEAD, - MD_NS_BODY, - MD_NS_INLINE, - MD_NS_DEFAULT -}; - -enum ml_scope { - ML_OPEN, - ML_CLOSE -}; - -struct ml_args { - const struct md_args *args; - const struct md_rbuf *rbuf; - struct md_mbuf *mbuf; - int section; - void *data; -}; - -struct ml_cbs { - int (*ml_begin)(struct ml_args *, const struct tm *, - const char *, const char *, - enum roffmsec, enum roffvol); - int (*ml_end)(struct ml_args *, const struct tm *, - const char *, const char *, - enum roffmsec, enum roffvol); - ssize_t (*ml_beginstring)(struct ml_args *, - const char *, size_t); - ssize_t (*ml_endstring)(struct ml_args *, - const char *, size_t); - ssize_t (*ml_endtag)(struct ml_args *, enum md_ns, int); - ssize_t (*ml_begintag)(struct ml_args *, enum md_ns, int, - const int *, const char **); - int (*ml_alloc)(void **); - void (*ml_free)(void *); -}; - -__BEGIN_DECLS - -int ml_putstring(struct md_mbuf *, - const char *, size_t *); -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_puts(struct md_mbuf *, const char *, 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 *, - const struct ml_cbs *); -int mlg_exit(struct md_mlg *, int); -int mlg_line(struct md_mlg *, char *); - -int ml_tagput(struct md_mbuf *, - enum ml_scope, const char *, size_t *); - -__END_DECLS - -#endif /*!ML_H*/ @@ -1,868 +0,0 @@ -/* $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 <stdarg.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "ml.h" - -/* TODO: literal tokens. */ - -enum md_tok { - MD_TEXT, - MD_INLINE_IN, - MD_INLINE_OUT, - MD_BLK_IN, - MD_BLK_OUT -}; - -struct md_mlg { - struct ml_args args; - struct rofftree *tree; - size_t indent; - size_t pos; - enum md_tok last; - void *arg; - struct ml_cbs cbs; - int flags; -#define ML_OVERRIDE_ONE (1 << 0) -#define ML_OVERRIDE_ALL (1 << 1) -}; - -static int mlg_roffmsg(void *arg, - enum roffmsg, const char *, - const char *, const char *); -static int mlg_roffhead(void *, const struct tm *, - const char *, const char *, - enum roffmsec, enum roffvol); -static int mlg_rofftail(void *, const struct tm *, - const char *, const char *, - enum roffmsec, enum roffvol); -static int mlg_roffin(void *, int, - int *, const char **); -static int mlg_roffdata(void *, int, - const char *, const char *); -static int mlg_roffout(void *, int); -static int mlg_roffblkin(void *, int, int *, - const char **); -static int mlg_roffblkout(void *, int); -static int mlg_roffspecial(void *, int, - const char *, const int *, - const char **, const char **); -static int mlg_roffblkheadin(void *, int, - int *, const char **); -static int mlg_roffblkheadout(void *, int); -static int mlg_roffblkbodyin(void *, int, - int *, const char **); -static int mlg_roffblkbodyout(void *, int); - -static int mlg_ref_special(struct md_mlg *, int, - const char *, const char **); -static int mlg_formatted_special(struct md_mlg *, - int, const char *, const int *, - const char **, const char **); -static int mlg_literal_special(struct md_mlg *, - int, const char *, const int *, - const char **, const char **); -static int mlg_function_special(struct md_mlg *, - const char *, const char **); -static int mlg_atom_special(struct md_mlg *, int, - const char *, const char **); -static int mlg_link_special(struct md_mlg *, int, - const char *, const char **); -static int mlg_anchor_special(struct md_mlg *, - int, const char **); - -static int mlg_begintag(struct md_mlg *, enum md_ns, - int, int *, const 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_nstring(struct md_mlg *, - const char *, const char *, size_t); -static int mlg_string(struct md_mlg *, - const char *, const char *); -static int mlg_data(struct md_mlg *, int, - const char *, const char *); -static int mlg_err(struct md_mlg *, const char *, - const char *, const char *, ...); -static int mlg_msg(struct md_mlg *, - enum roffmsg, const char *, - const char *, const char *); -static int mlg_vmsg(struct md_mlg *, enum roffmsg, - const char *, const char *, - const char *, va_list); - -#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, const char **argv) -{ - ssize_t res; - - assert(MD_NS_DEFAULT != ns); - - switch (ns) { - case (MD_NS_INLINE): - 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->args.mbuf, " ", 1, &p->pos)) - return(0); - if (0 == p->pos && ! mlg_indent(p)) - return(0); - mlg_mode(p, MD_INLINE_IN); - break; - default: - 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); - break; - } - - if ( ! ml_nputs(p->args.mbuf, "<", 1, &p->pos)) - return(0); - - res = (*p->cbs.ml_begintag)(&p->args, ns, tok, argc, argv); - if (-1 == res) - return(0); - - assert(res >= 0); - p->pos += (size_t)res; - - if ( ! ml_nputs(p->args.mbuf, ">", 1, &p->pos)) - return(0); - - switch (ns) { - case (MD_NS_INLINE): - break; - default: - if ( ! mlg_newline(p)) - return(0); - break; - } - - return(1); -} - - -static int -mlg_endtag(struct md_mlg *p, enum md_ns ns, int tok) -{ - ssize_t res; - - assert(MD_NS_DEFAULT != ns); - - switch (ns) { - case (MD_NS_INLINE): - break; - default: - 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); - break; - } - - if ( ! ml_nputs(p->args.mbuf, "</", 2, &p->pos)) - return(0); - - res = (*p->cbs.ml_endtag)(&p->args, ns, tok); - if (-1 == res) - return(0); - - assert(res >= 0); - p->pos += (size_t)res; - - if ( ! ml_nputs(p->args.mbuf, ">", 1, &p->pos)) - return(0); - - switch (ns) { - case (MD_NS_INLINE): - mlg_mode(p, MD_INLINE_OUT); - break; - default: - mlg_mode(p, MD_BLK_OUT); - break; - } - - return(1); -} - - -static int -mlg_indent(struct md_mlg *p) -{ - - assert(0 == p->pos); - return(ml_putchars(p->args.mbuf, ' ', INDENT_SZ * - INDENT(p->indent), &p->pos)); -} - - -static int -mlg_newline(struct md_mlg *p) -{ - - p->pos = 0; - return(ml_nputs(p->args.mbuf, "\n", 1, NULL)); -} - - -static void -mlg_mode(struct md_mlg *p, enum md_tok ns) -{ - - p->flags &= ~ML_OVERRIDE_ONE; - p->last = ns; -} - - -static int -mlg_string(struct md_mlg *p, const char *start, const char *buf) -{ - - return(mlg_nstring(p, start, buf, strlen(buf))); -} - - -static int -mlg_nstring(struct md_mlg *p, const char *start, - const char *buf, size_t sz) -{ - int c; - ssize_t res; - - assert(p->args.mbuf); - assert(0 != p->indent); - - res = (*p->cbs.ml_beginstring)(&p->args, buf, sz); - if (-1 == res) - return(0); - - if (0 == (c = ml_nputstring(p->args.mbuf, buf, sz, &p->pos))) - return(mlg_err(p, start, buf, "bad string " - "encoding: `%s'", buf)); - else if (-1 == c) - return(0); - - res = (*p->cbs.ml_endstring)(&p->args, buf, sz); - if (-1 == res) - return(0); - - return(1); -} - - -static int -mlg_data(struct md_mlg *p, int space, - const char *start, const char *buf) -{ - size_t sz; - - assert(p->args.mbuf); - assert(0 != p->indent); - - if (ML_OVERRIDE_ONE & p->flags || - ML_OVERRIDE_ALL & p->flags) - space = 0; - - sz = strlen(buf); - - if (0 == p->pos) { - if ( ! mlg_indent(p)) - return(0); - if ( ! mlg_nstring(p, start, buf, sz)) - return(0); - - if (INDENT(p->indent) * INDENT_SZ + sz >= COLUMNS) - if ( ! mlg_newline(p)) - return(0); - - return(1); - } - - 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->args.mbuf, " ", 1, &p->pos)) - return(0); - } - - return(mlg_nstring(p, start, buf, sz)); -} - - -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); - (*p->cbs.ml_free)(p->args.data); - - free(p); - - return(c); -} - - -struct md_mlg * -mlg_alloc(const struct md_args *args, - const struct md_rbuf *rbuf, - struct md_mbuf *mbuf, - const struct ml_cbs *cbs) -{ - 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.roffblkheadin = mlg_roffblkheadin; - cb.roffblkheadout = mlg_roffblkheadout; - cb.roffblkbodyin = mlg_roffblkbodyin; - cb.roffblkbodyout = mlg_roffblkbodyout; - 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 = args; - p->args.mbuf = mbuf; - p->args.rbuf = rbuf; - - (void)memcpy(&p->cbs, cbs, sizeof(struct ml_cbs)); - - if (NULL == (p->tree = roff_alloc(&cb, p))) - free(p); - else if ( ! (*p->cbs.ml_alloc)(&p->args.data)) - free(p); - else - return(p); - - return(NULL); -} - - -static int -mlg_roffhead(void *arg, const struct tm *tm, const char *os, - const char *title, enum roffmsec sec, enum roffvol vol) -{ - struct md_mlg *p; - - assert(arg); - p = (struct md_mlg *)arg; - - mlg_mode(p, MD_BLK_IN); - - if ( ! (*p->cbs.ml_begin)(&p->args, tm, os, title, sec, vol)) - return(0); - - p->indent++; - return(mlg_newline(p)); -} - - -static int -mlg_rofftail(void *arg, const struct tm *tm, const char *os, - const char *title, enum roffmsec sec, enum roffvol vol) -{ - struct md_mlg *p; - - assert(arg); - p = (struct md_mlg *)arg; - - if (0 != p->pos) - if ( ! mlg_newline(p)) - return(0); - - if ( ! (*p->cbs.ml_end)(&p->args, tm, os, title, sec, vol)) - return(0); - - mlg_mode(p, MD_BLK_OUT); - return(mlg_newline(p)); -} - - -static int -mlg_literal_special(struct md_mlg *p, int tok, const char *start, - const int *argc, const char **argv, const char **more) -{ - char *lit; - - if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more)) - return(0); - - lit = roff_literal(tok, argc, argv, more); - assert(lit); - - if ( ! mlg_string(p, start, lit)) - return(0); - - while (*more) { - if ( ! ml_nputs(p->args.mbuf, " ", 1, &p->pos)) - return(0); - if ( ! mlg_string(p, start, *more++)) - return(0); - } - - return(mlg_endtag(p, MD_NS_INLINE, tok)); -} - - -static int -mlg_ref_special(struct md_mlg *p, int tok, - const char *start, const char **more) -{ - - if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more)) - return(0); - - assert(*more); - if ( ! ml_puts(p->args.mbuf, *more++, &p->pos)) - return(0); - - if (*more) { - if ( ! ml_nputs(p->args.mbuf, "(", 1, &p->pos)) - return(0); - if ( ! mlg_string(p, start, *more++)) - return(0); - if ( ! ml_nputs(p->args.mbuf, ")", 1, &p->pos)) - return(0); - } - - assert(NULL == *more); - return(mlg_endtag(p, MD_NS_INLINE, tok)); -} - - -/* ARGSUSED */ -static int -mlg_formatted_special(struct md_mlg *p, int tok, const char *start, - const int *argc, const char **argv, const char **more) -{ - char buf[256], *lit; - - if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more)) - return(0); - - lit = roff_fmtstring(tok); - - assert(lit); - assert(*more); - (void)snprintf(buf, sizeof(buf), lit, *more++); - assert(NULL == *more); - - if ( ! mlg_string(p, start, buf)) - return(0); - - return(mlg_endtag(p, MD_NS_INLINE, tok)); -} - - -static int -mlg_atom_special(struct md_mlg *p, int tok, - const char *start, const char **more) -{ - - if (ROFFSec_SYNOP == p->args.section) { - if ( ! mlg_begintag(p, MD_NS_INLINE, ROFF_Pp, NULL, more)) - return(0); - if ( ! mlg_endtag(p, MD_NS_INLINE, ROFF_Pp)) - return(0); - } - - if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more)) - return(0); - - assert(*more); - if ( ! mlg_string(p, start, *more++)) - return(0); - - return(mlg_endtag(p, MD_NS_INLINE, tok)); -} - - -static int -mlg_function_special(struct md_mlg *p, - const char *start, const char **more) -{ - - assert(*more); - - if ( ! mlg_begintag(p, MD_NS_INLINE, ROFF_Fn, NULL, more)) - return(0); - if ( ! mlg_string(p, start, *more++)) - return(0); - if ( ! mlg_endtag(p, MD_NS_INLINE, ROFF_Fn)) - return(0); - - if (NULL == *more) - return(1); - - if ( ! ml_nputs(p->args.mbuf, "(", 1, &p->pos)) - return(0); - - p->flags |= ML_OVERRIDE_ONE; - - if ( ! mlg_begintag(p, MD_NS_INLINE, ROFF_Fa, NULL, more)) - return(0); - if ( ! mlg_string(p, start, *more++)) - return(0); - if ( ! mlg_endtag(p, MD_NS_INLINE, ROFF_Fa)) - return(0); - - while (*more) { - if ( ! ml_nputs(p->args.mbuf, ", ", 2, &p->pos)) - return(0); - if ( ! mlg_begintag(p, MD_NS_INLINE, ROFF_Fa, NULL, more)) - return(0); - if ( ! mlg_string(p, start, *more++)) - return(0); - if ( ! mlg_endtag(p, MD_NS_INLINE, ROFF_Fa)) - return(0); - } - - return(ml_nputs(p->args.mbuf, ")", 1, &p->pos)); -} - - -static int -mlg_anchor_special(struct md_mlg *p, int tok, const char **more) -{ - if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more)) - return(0); - return(mlg_endtag(p, MD_NS_INLINE, tok)); -} - - -static int -mlg_link_special(struct md_mlg *p, int tok, - const char *start, const char **more) -{ - - if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more)) - return(0); - if ( ! mlg_string(p, start, *more++)) - return(0); - while (*more) { - if ( ! mlg_string(p, start, " ")) - return(0); - if ( ! mlg_string(p, start, *more++)) - return(0); - } - return(mlg_endtag(p, MD_NS_INLINE, tok)); -} - - -/* ARGSUSED */ -static int -mlg_roffspecial(void *arg, int tok, const char *start, - const int *argc, const char **argv, const char **more) -{ - struct md_mlg *p; - - assert(arg); - p = (struct md_mlg *)arg; - - switch (tok) { - case (ROFF_Ns): - p->flags |= ML_OVERRIDE_ONE; - return(1); - - case (ROFF_Sm): - assert(*more); - if (0 == strcmp(*more, "on")) - p->flags |= ML_OVERRIDE_ALL; - else - p->flags &= ~ML_OVERRIDE_ALL; - return(1); - - case (ROFF_Fn): - return(mlg_function_special(p, start, more)); - - case (ROFF_Xr): - return(mlg_ref_special(p, tok, start, more)); - - case (ROFF_Sh): - p->args.section = roff_sec(more); - return(mlg_anchor_special(p, tok, more)); - - case (ROFF_Sx): - return(mlg_link_special(p, tok, start, more)); - - case (ROFF_Nm): - return(mlg_atom_special(p, tok, start, more)); - - case (ROFF_In): - /* NOTREACHED */ - case (ROFF_Ex): - /* NOTREACHED */ - case (ROFF_Rv): - return(mlg_formatted_special(p, tok, start, - argc, argv, more)); - - case (ROFF_At): - /* FALLTHROUGH */ - case (ROFF_Bt): - /* FALLTHROUGH */ - case (ROFF_Ud): - /* FALLTHROUGH */ - case (ROFF_Ux): - /* FALLTHROUGH */ - case (ROFF_Bx): - /* FALLTHROUGH */ - case (ROFF_Bsx): - /* FALLTHROUGH */ - case (ROFF_Fx): - /* FALLTHROUGH */ - case (ROFF_Nx): - /* FALLTHROUGH */ - case (ROFF_St): - /* FALLTHROUGH */ - case (ROFF_Ox): - return(mlg_literal_special(p, tok, start, - argc, argv, more)); - default: - break; - } - - return(mlg_err(p, start, start, "`%s' not yet supported", - toknames[tok])); -} - - -static int -mlg_roffblkin(void *arg, int tok, - int *argc, const char **argv) -{ - - return(mlg_begintag((struct md_mlg *)arg, - MD_NS_BLOCK, tok, argc, argv)); -} - - -static int -mlg_roffblkout(void *arg, int tok) -{ - - return(mlg_endtag((struct md_mlg *)arg, MD_NS_BLOCK, tok)); -} - - -static int -mlg_roffblkbodyin(void *arg, int tok, - int *argc, const char **argv) -{ - - return(mlg_begintag((struct md_mlg *)arg, - MD_NS_BODY, tok, argc, argv)); -} - - -static int -mlg_roffblkbodyout(void *arg, int tok) -{ - - return(mlg_endtag((struct md_mlg *)arg, MD_NS_BODY, tok)); -} - - -static int -mlg_roffblkheadin(void *arg, int tok, - int *argc, const char **argv) -{ - - return(mlg_begintag((struct md_mlg *)arg, - MD_NS_HEAD, tok, argc, argv)); -} - - -static int -mlg_roffblkheadout(void *arg, int tok) -{ - - return(mlg_endtag((struct md_mlg *)arg, MD_NS_HEAD, tok)); -} - - -static int -mlg_roffin(void *arg, int tok, int *argc, const char **argv) -{ - - return(mlg_begintag((struct md_mlg *)arg, - MD_NS_INLINE, tok, argc, argv)); -} - - -static int -mlg_roffout(void *arg, int tok) -{ - - return(mlg_endtag((struct md_mlg *)arg, MD_NS_INLINE, tok)); -} - - -static int -mlg_roffmsg(void *arg, enum roffmsg lvl, const char *buf, - const char *pos, const char *msg) -{ - - return(mlg_msg((struct md_mlg *)arg, lvl, buf, pos, msg)); -} - - -static int -mlg_roffdata(void *arg, int space, - const char *start, const char *buf) -{ - struct md_mlg *p; - - assert(arg); - p = (struct md_mlg *)arg; - - if ( ! mlg_data(p, space, start, buf)) - return(0); - - mlg_mode(p, MD_TEXT); - return(1); -} - - -static int -mlg_vmsg(struct md_mlg *p, enum roffmsg lvl, const char *start, - const char *pos, const char *fmt, va_list ap) -{ - char buf[128]; - - (void)vsnprintf(buf, sizeof(buf), fmt, ap); - return(mlg_msg(p, lvl, start, pos, buf)); -} - - -static int -mlg_err(struct md_mlg *p, const char *start, - const char *pos, const char *fmt, ...) -{ - va_list ap; - int c; - - va_start(ap, fmt); - c = mlg_vmsg(p, ROFF_ERROR, start, pos, fmt, ap); - va_end(ap); - return(c); -} - - -static int -mlg_msg(struct md_mlg *p, enum roffmsg lvl, - const char *buf, const char *pos, const char *msg) -{ - char *level, b[256]; - size_t sz; - int i; - - sz = sizeof(b); - - switch (lvl) { - case (ROFF_WARN): - level = "warning"; - if ( ! (MD_WARN_ALL & p->args.args->warnings)) - return(1); - break; - case (ROFF_ERROR): - level = "error"; - break; - default: - abort(); - /* NOTREACHED */ - } - - if (pos) { - assert(pos >= buf); - if (0 < p->args.args->verbosity) { - (void)snprintf(b, sz, "%s:%zu: %s: %s\n", - p->args.rbuf->name, - p->args.rbuf->line, - level, msg); - - (void)strlcat(b, "Error at: ", sz); - (void)strlcat(b, p->args.rbuf->linebuf, sz); - (void)strlcat(b, "\n ", sz); - - for (i = 0; i < pos - buf; i++) - (void)strlcat(b, " ", sz); - - (void)strlcat(b, "^", sz); - } else - (void)snprintf(b, sz, "%s:%zu: %s: %s (%zu)", - p->args.rbuf->name, - p->args.rbuf->line, - level, msg, pos - buf); - } else - (void)snprintf(b, sz, "%s: %s: %s", - p->args.rbuf->name, level, msg); - - (void)fprintf(stderr, "%s\n", b); - return(lvl == ROFF_WARN ? 1 : 0); -} - diff --git a/noop.c b/noop.c deleted file mode 100644 index 520bd797..00000000 --- a/noop.c +++ /dev/null @@ -1,294 +0,0 @@ -/* $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 <err.h> -#include <stdlib.h> -#include <string.h> - -#include "private.h" - - -struct md_noop { - const struct md_args *args; - const struct md_rbuf *rbuf; - struct rofftree *tree; -}; - - -static int noop_roffmsg(void *arg, - enum roffmsg, const char *, - const char *, const char *); -static int noop_roffhead(void *, const struct tm *, - const char *, const char *, - enum roffmsec, enum roffvol); -static int noop_rofftail(void *, const struct tm *, - const char *, const char *, - enum roffmsec, enum roffvol); -static int noop_roffin(void *, int, - int *, const char **); -static int noop_roffdata(void *, int, - const char *, const char *); -static int noop_roffout(void *, int); -static int noop_roffblkin(void *, int, int *, - const char **); -static int noop_roffblkout(void *, int); -static int noop_roffspecial(void *, int, - const char *, const int *, - const char **, const char **); -static int noop_roffblkheadin(void *, int, - int *, const char **); -static int noop_roffblkheadout(void *, int); -static int noop_roffblkbodyin(void *, int, - int *, const char **); -static int noop_roffblkbodyout(void *, int); - -#ifdef __linux__ -extern size_t strlcat(char *, const char *, size_t); -extern size_t strlcpy(char *, const char *, size_t); -#endif - - -int -md_exit_noop(void *data, int flush) -{ - struct md_noop *noop; - int c; - - noop = (struct md_noop *)data; - c = roff_free(noop->tree, flush); - free(noop); - return(c); -} - - -int -md_line_noop(void *data, char *buf) -{ - struct md_noop *noop; - - noop = (struct md_noop *)data; - return(roff_engine(noop->tree, buf)); -} - - -/* ARGSUSED */ -void * -md_init_noop(const struct md_args *args, - struct md_mbuf *mbuf, const struct md_rbuf *rbuf) -{ - struct roffcb cb; - struct md_noop *noop; - - if (NULL == (noop = calloc(1, sizeof(struct md_noop)))) - err(1, "calloc"); - - noop->args = args; - noop->rbuf = rbuf; - - cb.roffhead = noop_roffhead; - cb.rofftail = noop_rofftail; - cb.roffin = noop_roffin; - cb.roffout = noop_roffout; - cb.roffblkin = noop_roffblkin; - cb.roffblkheadin = noop_roffblkheadin; - cb.roffblkheadout = noop_roffblkheadout; - cb.roffblkbodyin = noop_roffblkbodyin; - cb.roffblkbodyout = noop_roffblkbodyout; - cb.roffblkout = noop_roffblkout; - cb.roffspecial = noop_roffspecial; - cb.roffmsg = noop_roffmsg; - cb.roffdata = noop_roffdata; - - if (NULL == (noop->tree = roff_alloc(&cb, noop))) { - free(noop); - return(NULL); - } - return(noop); -} - - -/* ARGSUSED */ -static int -noop_roffhead(void *arg, const struct tm *tm, const char *os, - const char *title, enum roffmsec sec, enum roffvol vol) -{ - - return(1); -} - - -/* ARGSUSED */ -static int -noop_rofftail(void *arg, const struct tm *tm, const char *os, - const char *title, enum roffmsec sec, enum roffvol vol) -{ - - return(1); -} - - -/* ARGSUSED */ -static int -noop_roffspecial(void *arg, int tok, const char *start, - const int *argc, const char **argv, const char **more) -{ - - return(1); -} - - -/* ARGSUSED */ -static int -noop_roffblkin(void *arg, int tok, - int *argc, const char **argv) -{ - - return(1); -} - - -/* ARGSUSED */ -static int -noop_roffblkout(void *arg, int tok) -{ - - return(1); -} - - -/* ARGSUSED */ -static int -noop_roffblkbodyin(void *arg, int tok, - int *argc, const char **argv) -{ - - return(1); -} - - -/* ARGSUSED */ -static int -noop_roffblkbodyout(void *arg, int tok) -{ - - return(1); -} - - -/* ARGSUSED */ -static int -noop_roffblkheadin(void *arg, int tok, - int *argc, const char **argv) -{ - - return(1); -} - - -/* ARGSUSED */ -static int -noop_roffblkheadout(void *arg, int tok) -{ - - return(1); -} - - -/* ARGSUSED */ -static int -noop_roffin(void *arg, int tok, int *argc, const char **argv) -{ - - return(1); -} - - -/* ARGSUSED */ -static int -noop_roffout(void *arg, int tok) -{ - - return(1); -} - - -/* ARGSUSED */ -static int -noop_roffdata(void *arg, int tok, - const char *start, const char *buf) -{ - - return(1); -} - - -static int -noop_roffmsg(void *arg, enum roffmsg lvl, - const char *buf, const char *pos, const char *msg) -{ - struct md_noop *p; - char *level; - char b[256]; - int i; - - p = (struct md_noop *)arg; - assert(p); - - switch (lvl) { - case (ROFF_WARN): - level = "warning"; - if ( ! (MD_WARN_ALL & p->args->warnings)) - return(1); - break; - case (ROFF_ERROR): - level = "error"; - break; - default: - abort(); - /* NOTREACHED */ - } - - if (pos) { - assert(pos >= buf); - if (0 < p->args->verbosity) { - (void)snprintf(b, sizeof(b), - "%s:%zu: %s: %s\n", - p->rbuf->name, p->rbuf->line, - level, msg); - (void)strlcat(b, "Error at: ", sizeof(b)); - (void)strlcat(b, p->rbuf->linebuf, sizeof(b)); - - (void)strlcat(b, "\n ", sizeof(b)); - for (i = 0; i < pos - buf; i++) - (void)strlcat(b, " ", sizeof(b)); - (void)strlcat(b, "^", sizeof(b)); - - } else - (void)snprintf(b, sizeof(b), - "%s:%zu: %s: %s (%zu)", - p->rbuf->name, p->rbuf->line, - level, msg, pos - buf); - } else - (void)snprintf(b, sizeof(b), "%s: %s: %s", - p->rbuf->name, level, msg); - - (void)fprintf(stderr, "%s\n", b); - return(lvl == ROFF_WARN ? 1 : 0); -} - @@ -19,387 +19,52 @@ #ifndef PRIVATE_H #define PRIVATE_H -#include <stdio.h> -#include <time.h> - -#include "libmdocml.h" - -struct md_rbuf { - int fd; /* Open descriptor. */ - char *name; /* Name of file. */ - char *buf; /* Buffer. */ - size_t bufsz; /* Size of buffer. */ - size_t line; /* Current line number. */ -#define MD_LINE (BUFSIZ) - char linebuf[MD_LINE]; -}; - -struct md_mbuf { - int fd; /* Open descriptor. */ - char *name; /* Name of file. */ - char *buf; /* Buffer. */ - size_t bufsz; /* Size of buffer. */ - size_t pos; /* Position in buffer. */ -}; - -#define ROFFTok_Sp_A 0 -#define ROFFTok_Sp_B 1 -#define ROFFTok_Sp_F 2 -#define ROFFTok_Sp_N 3 -#define ROFFTok_Sp_R 4 -#define ROFFTok_Sp_T 5 -#define ROFFTok_Sp_V 6 -#define ROFFTok_Space 7 -#define ROFFTok_Null 8 -#define ROFFTok_Hyphen 9 -#define ROFFTok_Em 10 -#define ROFFTok_En 11 -#define ROFFTok_Ge 12 -#define ROFFTok_Le 13 -#define ROFFTok_Rquote 14 -#define ROFFTok_Lquote 15 -#define ROFFTok_Uparrow 16 -#define ROFFTok_Acute 17 -#define ROFFTok_Grave 18 -#define ROFFTok_Pi 19 -#define ROFFTok_Ne 20 -#define ROFFTok_Lt 21 -#define ROFFTok_Gt 22 -#define ROFFTok_Plusmin 23 -#define ROFFTok_Infty 24 -#define ROFFTok_Bar 25 -#define ROFFTok_Nan 26 -#define ROFFTok_Quote 27 -#define ROFFTok_Sp_0 28 -#define ROFFTok_Slash 29 -#define ROFFTok_MAX 30 - -#define ROFF___ 0 -#define ROFF_Dd 1 -#define ROFF_Dt 2 -#define ROFF_Os 3 -#define ROFF_Sh 4 -#define ROFF_Ss 5 -#define ROFF_Pp 6 -#define ROFF_D1 7 -#define ROFF_Dl 8 -#define ROFF_Bd 9 -#define ROFF_Ed 10 -#define ROFF_Bl 11 -#define ROFF_El 12 -#define ROFF_It 13 -#define ROFF_Ad 14 -#define ROFF_An 15 -#define ROFF_Ar 16 -#define ROFF_Cd 17 -#define ROFF_Cm 18 -#define ROFF_Dv 19 -#define ROFF_Er 20 -#define ROFF_Ev 21 -#define ROFF_Ex 22 -#define ROFF_Fa 23 -#define ROFF_Fd 24 -#define ROFF_Fl 25 -#define ROFF_Fn 26 -#define ROFF_Ft 27 -#define ROFF_Ic 28 -#define ROFF_In 29 -#define ROFF_Li 30 -#define ROFF_Nd 31 -#define ROFF_Nm 32 -#define ROFF_Op 33 -#define ROFF_Ot 34 -#define ROFF_Pa 35 -#define ROFF_Rv 36 -#define ROFF_St 37 -#define ROFF_Va 38 -#define ROFF_Vt 39 -#define ROFF_Xr 40 -#define ROFF__A 41 -#define ROFF__B 42 -#define ROFF__D 43 -#define ROFF__I 44 -#define ROFF__J 45 -#define ROFF__N 46 -#define ROFF__O 47 -#define ROFF__P 48 -#define ROFF__R 49 -#define ROFF__T 50 -#define ROFF__V 51 -#define ROFF_Ac 52 -#define ROFF_Ao 53 -#define ROFF_Aq 54 -#define ROFF_At 55 -#define ROFF_Bc 56 -#define ROFF_Bf 57 -#define ROFF_Bo 58 -#define ROFF_Bq 59 -#define ROFF_Bsx 60 -#define ROFF_Bx 61 -#define ROFF_Db 62 -#define ROFF_Dc 63 -#define ROFF_Do 64 -#define ROFF_Dq 65 -#define ROFF_Ec 66 -#define ROFF_Ef 67 -#define ROFF_Em 68 -#define ROFF_Eo 69 -#define ROFF_Fx 70 -#define ROFF_Ms 71 -#define ROFF_No 72 -#define ROFF_Ns 73 -#define ROFF_Nx 74 -#define ROFF_Ox 75 -#define ROFF_Pc 76 -#define ROFF_Pf 77 -#define ROFF_Po 78 -#define ROFF_Pq 79 -#define ROFF_Qc 80 -#define ROFF_Ql 81 -#define ROFF_Qo 82 -#define ROFF_Qq 83 -#define ROFF_Re 84 -#define ROFF_Rs 85 -#define ROFF_Sc 86 -#define ROFF_So 87 -#define ROFF_Sq 88 -#define ROFF_Sm 89 -#define ROFF_Sx 90 -#define ROFF_Sy 91 -#define ROFF_Tn 92 -#define ROFF_Ux 93 -#define ROFF_Xc 94 -#define ROFF_Xo 95 -#define ROFF_Fo 96 -#define ROFF_Fc 97 -#define ROFF_Oo 98 -#define ROFF_Oc 99 -#define ROFF_Bk 100 -#define ROFF_Ek 101 -#define ROFF_Bt 102 -#define ROFF_Hf 103 -#define ROFF_Fr 104 -#define ROFF_Ud 105 -#define ROFF_MAX 106 - -#define ROFF_Split 0 -#define ROFF_Nosplit 1 -#define ROFF_Ragged 2 -#define ROFF_Unfilled 3 -#define ROFF_Literal 4 -#define ROFF_File 5 -#define ROFF_Offset 6 -#define ROFF_Bullet 7 -#define ROFF_Dash 8 -#define ROFF_Hyphen 9 -#define ROFF_Item 10 -#define ROFF_Enum 11 -#define ROFF_Tag 12 -#define ROFF_Diag 13 -#define ROFF_Hang 14 -#define ROFF_Ohang 15 -#define ROFF_Inset 16 -#define ROFF_Column 17 -#define ROFF_Width 18 -#define ROFF_Compact 19 -#define ROFF_Std 20 -#define ROFF_p1003_1_88 21 -#define ROFF_p1003_1_90 22 -#define ROFF_p1003_1_96 23 -#define ROFF_p1003_1_2001 24 -#define ROFF_p1003_1_2004 25 -#define ROFF_p1003_1 26 -#define ROFF_p1003_1b 27 -#define ROFF_p1003_1b_93 28 -#define ROFF_p1003_1c_95 29 -#define ROFF_p1003_1g_2000 30 -#define ROFF_p1003_2_92 31 -#define ROFF_p1387_2_95 32 -#define ROFF_p1003_2 33 -#define ROFF_p1387_2 34 -#define ROFF_isoC_90 35 -#define ROFF_isoC_amd1 36 -#define ROFF_isoC_tcor1 37 -#define ROFF_isoC_tcor2 38 -#define ROFF_isoC_99 39 -#define ROFF_ansiC 40 -#define ROFF_ansiC_89 41 -#define ROFF_ansiC_99 42 -#define ROFF_ieee754 43 -#define ROFF_iso8802_3 44 -#define ROFF_xpg3 45 -#define ROFF_xpg4 46 -#define ROFF_xpg4_2 47 -#define ROFF_xpg4_3 48 -#define ROFF_xbd5 49 -#define ROFF_xcu5 50 -#define ROFF_xsh5 51 -#define ROFF_xns5 52 -#define ROFF_xns5_2d2_0 53 -#define ROFF_xcurses4_2 54 -#define ROFF_susv2 55 -#define ROFF_susv3 56 -#define ROFF_svid4 57 -#define ROFF_Filled 58 -#define ROFF_Words 59 -#define ROFF_ARGMAX 60 - -#define ROFF_MAXLINEARG 32 - -extern const char *const *toknames; -extern const char *const *tokargnames; - -enum roffmsg { - ROFF_WARN, - ROFF_ERROR +#include "mdoc.h" + +struct mdoc { + void *data; + struct mdoc_cb cb; + void *htab; + struct mdoc_node *last; + struct mdoc_node *first; }; -enum roffmsec { - ROFF_MSEC_1, - ROFF_MSEC_2, - ROFF_MSEC_3, - ROFF_MSEC_3p, - ROFF_MSEC_4, - ROFF_MSEC_5, - ROFF_MSEC_6, - ROFF_MSEC_7, - ROFF_MSEC_8, - ROFF_MSEC_9, - ROFF_MSEC_UNASS, - ROFF_MSEC_DRAFT, - ROFF_MSEC_PAPER, - ROFF_MSEC_MAX +struct mdoc_macro { + int (*fp)(struct mdoc *, int, int, int *, char *); + int flags; +#define MDOC_CALLABLE (1 << 0) +#define MDOC_EXPLICIT (1 << 1) }; -enum roffatt { - ROFF_ATT_V1, - ROFF_ATT_V2, - ROFF_ATT_V3, - ROFF_ATT_V6, - ROFF_ATT_V7, - ROFF_ATT_32V, - ROFF_ATT_V_1, - ROFF_ATT_V_4, - ROFF_ATT_MAX -}; +extern const struct mdoc_macro *const mdoc_macros; -enum roffvol { - ROFF_VOL_NONE, - ROFF_VOL_AMD, - ROFF_VOL_IND, - ROFF_VOL_KM, - ROFF_VOL_LOCAL, - ROFF_VOL_PRM, - ROFF_VOL_PS1, - ROFF_VOL_SMM, - ROFF_VOL_URM, - ROFF_VOL_USD, -#define ROFF_ARCH_START ROFF_ARCH_ALPHA - ROFF_ARCH_ALPHA, - ROFF_ARCH_AMD64, - ROFF_ARCH_AMIGA, - ROFF_ARCH_ARC, - ROFF_ARCH_ARMISH, - ROFF_ARCH_AVIION, - ROFF_ARCH_HP300, - ROFF_ARCH_HPPA, - ROFF_ARCH_HPPA64, - ROFF_ARCH_I386, - ROFF_ARCH_LANDISK, - ROFF_ARCH_LUNA88K, - ROFF_ARCH_MAC68K, - ROFF_ARCH_MACPPC, - ROFF_ARCH_MVME68K, - ROFF_ARCH_MVME88K, - ROFF_ARCH_MVMEPPC, - ROFF_ARCH_PMAX, - ROFF_ARCH_SGI, - ROFF_ARCH_SPARC, - ROFF_ARCH_SPARC64, - ROFF_ARCH_SUN3, - ROFF_ARCH_VAX, - ROFF_ARCH_ZAURUS, - ROFF_VOL_MAX -}; +__BEGIN_DECLS -#define ROFFSec_NMASK (0x07) +int mdoc_err(struct mdoc *, int, int, enum mdoc_err); +int mdoc_warn(struct mdoc *, int, int, enum mdoc_warn); +void mdoc_msg(struct mdoc *, int, const char *, ...); -#define ROFFSec_PR_Os (1 << 1) -#define ROFFSec_PR_Dt (1 << 2) -#define ROFFSec_PR_Dd (1 << 3) -#define ROFFSec_NAME (1 << 4) -#define ROFFSec_SYNOP (1 << 5) -#define ROFFSec_DESC (1 << 6) -#define ROFFSec_RETVAL (1 << 7) -#define ROFFSec_ENV (1 << 8) -#define ROFFSec_FILES (1 << 9) -#define ROFFSec_EX (1 << 10) -#define ROFFSec_DIAG (1 << 11) -#define ROFFSec_ERRS (1 << 12) -#define ROFFSec_SEEALSO (1 << 13) -#define ROFFSec_STAND (1 << 14) -#define ROFFSec_HIST (1 << 15) -#define ROFFSec_AUTH (1 << 16) -#define ROFFSec_CAVEATS (1 << 17) -#define ROFFSec_BUGS (1 << 18) -#define ROFFSec_OTHER (1 << 19) +int mdoc_macro(struct mdoc *, int, int, int *, char *); +int mdoc_find(const struct mdoc *, const char *); -struct roffcb { - int (*roffmsg)(void *, enum roffmsg, - const char *, const char *, const char *); - int (*roffhead)(void *, const struct tm *, const char *, - const char *, enum roffmsec, enum roffvol); - int (*rofftail)(void *, const struct tm *, const char *, - const char *, enum roffmsec, enum roffvol); - int (*roffdata)(void *, int, const char *, const char *); - int (*roffin)(void *, int, int *, const char **); - int (*roffout)(void *, int); - int (*roffblkin)(void *, int, int *, const char **); - int (*roffblkout)(void *, int); - int (*roffblkheadin)(void *, int, int *, const char **); - int (*roffblkheadout)(void *, int); - int (*roffblkbodyin)(void *, int, int *, const char **); - int (*roffblkbodyout)(void *, int); - int (*roffspecial)(void *, int, const char *, - const int *, const char **, const char **); -}; +void mdoc_word_alloc(struct mdoc *, int, const char *); +void mdoc_elem_alloc(struct mdoc *, int, int, + size_t, const struct mdoc_arg *, + size_t, const char **); +void mdoc_block_alloc(struct mdoc *, int, int, + size_t, const struct mdoc_arg *); +void mdoc_head_alloc(struct mdoc *, + int, int, size_t, const char **); +void mdoc_body_alloc(struct mdoc *, int, int); -struct rofftree; +void mdoc_node_free(struct mdoc_node *); -__BEGIN_DECLS +void mdoc_sibling(struct mdoc *, int, struct mdoc_node **, + struct mdoc_node **, struct mdoc_node *); -typedef void (*(*md_init)(const struct md_args *, - struct md_mbuf *, const struct md_rbuf *)); -typedef int (*md_line)(void *, char *); -typedef int (*md_exit)(void *, int); -void *md_init_html(const struct md_args *, - struct md_mbuf *, const struct md_rbuf *); -int md_line_html(void *, char *); -int md_exit_html(void *, int); -void *md_init_noop(const struct md_args *, - struct md_mbuf *, const struct md_rbuf *); -int md_line_noop(void *, char *); -int md_exit_noop(void *, int); -void *md_init_xml(const struct md_args *, - struct md_mbuf *, const struct md_rbuf *); -int md_line_xml(void *, char *); -int md_exit_xml(void *, int); -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 *roff_alloc(const struct roffcb *, void *); -int roff_engine(struct rofftree *, char *); -int roff_free(struct rofftree *, int); -int rofftok_scan(const char *, int *); -char *roff_literal(int, const int *, - const char **, const char **); -char *roff_fmtstring(int); -char *roff_msecname(enum roffmsec); -enum roffmsec roff_msec(const char *); -int roff_sec(const char **); -enum roffatt roff_att(const char *); -enum roffvol roff_vol(const char *); -char *roff_volname(enum roffvol); +void *mdoc_hash_alloc(void); +int mdoc_hash_find(const void *, const char *); +void mdoc_hash_free(void *); __END_DECLS diff --git a/tags.c b/tags.c deleted file mode 100644 index cbc498a3..00000000 --- a/tags.c +++ /dev/null @@ -1,188 +0,0 @@ -/* $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 <stdarg.h> -#include <stdlib.h> - -#include "html.h" - -static int html_tstart(struct md_mbuf *, enum ml_scope, - enum html_tag, size_t *); -static int html_tclose(struct md_mbuf *, size_t *); - -static const char * const tagnames[] = { - "span", "html", "head", "meta", - "title", "style", "link", "body", - "div", "table", "td", "tr", - "ol", "ul", "li", "h1", - "h2", "a", - }; - -static const char * const attrnames[] = { - "class", "http-equiv", "content", "name", - "type", "rel", "href", "width", - "align", "valign", "nowrap", - }; - -static const char * const typenames[] = { - "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"" - "\"http://www.w3.org/TR/html4/strict.dtd\">", - }; - - -/* FIXME: move into ml.c. */ -static int -html_tstart(struct md_mbuf *mbuf, enum ml_scope scope, - enum html_tag tag, size_t *res) -{ - - switch (scope) { - case (ML_OPEN): - if ( ! ml_nputs(mbuf, "<", 1, res)) - return(0); - break; - case (ML_CLOSE): - if ( ! ml_nputs(mbuf, "</", 2, res)) - return(0); - break; - default: - abort(); - /* NOTREACHED */ - } - - return(ml_puts(mbuf, tagnames[tag], res)); -} - - -/* FIXME: move into ml.c. */ -static int -html_tclose(struct md_mbuf *mbuf, size_t *res) -{ - - return(ml_nputs(mbuf, ">", 1, res)); -} - - - -int -html_stput(struct md_mbuf *mbuf, enum html_tag tag, size_t *res) -{ - - return(ml_puts(mbuf, tagnames[tag], res)); -} - - -int -html_saput(struct md_mbuf *mbuf, enum html_tag tag, - size_t *res, int sz, const struct html_pair *p) -{ - int i; - - if ( ! ml_puts(mbuf, tagnames[tag], res)) - return(0); - - assert(sz >= 0); - for (i = 0; i < sz; i++) { - - /* FIXME: move into ml.c. */ - - if ( ! ml_nputs(mbuf, " ", 1, res)) - return(0); - if ( ! ml_puts(mbuf, attrnames[p[i].attr], res)) - return(0); - if ( ! ml_nputs(mbuf, "=\"", 2, res)) - return(0); - if ( ! ml_putstring(mbuf, p[i].val, res)) - return(0); - if ( ! ml_nputs(mbuf, "\"", 1, res)) - return(0); - } - - return(1); -} - - -int -html_tput(struct md_mbuf *mbuf, enum ml_scope scope, - enum html_tag tag, size_t *res) -{ - - if ( ! html_tstart(mbuf, scope, tag, res)) - return(0); - return(html_tclose(mbuf, res)); -} - - -int -html_aput(struct md_mbuf *mbuf, enum ml_scope scope, - enum html_tag tag, size_t *res, - int sz, const struct html_pair *p) -{ - int i; - - if ( ! html_tstart(mbuf, scope, tag, res)) - return(0); - - assert(sz >= 0); - for (i = 0; i < sz; i++) { - - /* FIXME: move into ml.c. */ - - if ( ! ml_nputs(mbuf, " ", 1, res)) - return(0); - if ( ! ml_puts(mbuf, attrnames[p[i].attr], res)) - return(0); - if ( ! ml_nputs(mbuf, "=\"", 2, res)) - return(0); - if ( ! ml_putstring(mbuf, p[i].val, res)) - return(0); - if ( ! ml_nputs(mbuf, "\"", 1, res)) - return(0); - } - - return(html_tclose(mbuf, res)); -} - - -int -html_typeput(struct md_mbuf *mbuf, - enum html_type type, size_t *res) -{ - - return(ml_puts(mbuf, typenames[type], res)); -} - - -int -html_commentput(struct md_mbuf *mbuf, - enum ml_scope scope, size_t *res) -{ - - switch (scope) { - case (ML_OPEN): - return(ml_nputs(mbuf, "<!--", 4, res)); - case (ML_CLOSE): - return(ml_nputs(mbuf, "-->", 3, res)); - default: - break; - } - - abort(); - /* NOTREACHED */ -} diff --git a/tokens.c b/tokens.c deleted file mode 100644 index ce46d335..00000000 --- a/tokens.c +++ /dev/null @@ -1,193 +0,0 @@ -/* $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 <stdlib.h> -#include <string.h> - -#include "private.h" - - -static int rofftok_dashes(const char *, int *); -static int rofftok_special(const char *, int *); -static int rofftok_predef(const char *, int *); -static int rofftok_defined(const char *, int *); - - -static int -rofftok_defined(const char *buf, int *i) -{ - const char *p; - - if (0 == buf[*i]) - return(-1); - if (0 == buf[*i + 1]) - return(-1); - - (*i)++; - p = &buf[(*i)++]; - - if (0 == memcmp(p, ">=", 2)) - return(ROFFTok_Ge); - else if (0 == memcmp(p, "<=", 2)) - return(ROFFTok_Le); - else if (0 == memcmp(p, "Rq", 2)) - return(ROFFTok_Rquote); - else if (0 == memcmp(p, "Lq", 2)) - return(ROFFTok_Lquote); - else if (0 == memcmp(p, "ua", 2)) - return(ROFFTok_Uparrow); - else if (0 == memcmp(p, "aa", 2)) - return(ROFFTok_Acute); - else if (0 == memcmp(p, "ga", 2)) - return(ROFFTok_Grave); - else if (0 == memcmp(p, "Pi", 2)) - return(ROFFTok_Pi); - else if (0 == memcmp(p, "Ne", 2)) - return(ROFFTok_Ne); - else if (0 == memcmp(p, "Le", 2)) - return(ROFFTok_Le); - else if (0 == memcmp(p, "Ge", 2)) - return(ROFFTok_Ge); - else if (0 == memcmp(p, "Lt", 2)) - return(ROFFTok_Lt); - else if (0 == memcmp(p, "Gt", 2)) - return(ROFFTok_Gt); - else if (0 == memcmp(p, "Pm", 2)) - return(ROFFTok_Plusmin); - else if (0 == memcmp(p, "If", 2)) - return(ROFFTok_Infty); - else if (0 == memcmp(p, "Na", 2)) - return(ROFFTok_Nan); - else if (0 == memcmp(p, "Ba", 2)) - return(ROFFTok_Bar); - - return(-1); -} - - -static int -rofftok_predef(const char *buf, int *i) -{ - if (0 == buf[*i]) - return(-1); - if ('(' == buf[*i]) - return(rofftok_defined(buf, i)); - - switch (buf[*i]) { - case ('q'): - return(ROFFTok_Quote); - default: - break; - } - - return(-1); -} - - -static int -rofftok_dashes(const char *buf, int *i) -{ - - if (0 == buf[*i]) - return(-1); - else if (buf[(*i)++] != 'e') - return(-1); - if (0 == buf[*i]) - return(-1); - - switch (buf[*i]) { - case ('m'): - return(ROFFTok_Em); - case ('n'): - return(ROFFTok_En); - default: - break; - } - return(-1); -} - - -static int -rofftok_special(const char *buf, int *i) -{ - - if (0 == buf[*i]) - return(ROFFTok_Slash); - - switch (buf[*i]) { - case ('a'): - return(ROFFTok_Sp_A); - case ('b'): - return(ROFFTok_Sp_B); - case ('f'): - return(ROFFTok_Sp_F); - case ('n'): - return(ROFFTok_Sp_N); - case ('r'): - return(ROFFTok_Sp_R); - case ('t'): - return(ROFFTok_Sp_T); - case ('v'): - return(ROFFTok_Sp_V); - case ('0'): - return(ROFFTok_Sp_0); - default: - break; - } - return(-1); -} - - -int -rofftok_scan(const char *buf, int *i) -{ - - assert(*buf); - assert(buf[*i] == '\\'); - - (*i)++; - - for ( ; buf[*i]; (*i)++) { - switch (buf[*i]) { - case ('e'): - (*i)++; - return(rofftok_special(buf, i)); - case ('('): - (*i)++; - return(rofftok_dashes(buf, i)); - case (' '): - return(ROFFTok_Space); - case ('&'): - return(ROFFTok_Null); - case ('-'): - return(ROFFTok_Hyphen); - case ('*'): - (*i)++; - return(rofftok_predef(buf, i)); - case ('\\'): - return(ROFFTok_Slash); - default: - break; - } - } - - return(-1); -} - - @@ -1,235 +0,0 @@ -/* $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 <stdlib.h> -#include <string.h> - -#include "private.h" -#include "ml.h" - - -static int xml_alloc(void **); -static void xml_free(void *); -static ssize_t xml_beginstring(struct ml_args *, - const char *, size_t); -static ssize_t xml_endstring(struct ml_args *, - const char *, size_t); -static int xml_begin(struct ml_args *, const struct tm *, - const char *, const char *, - enum roffmsec, enum roffvol); -static int xml_end(struct ml_args *, const struct tm *, - const char *, const char *, - enum roffmsec, enum roffvol); -static ssize_t xml_printtagname(struct ml_args *, - enum md_ns, int); -static ssize_t xml_printtagargs(struct ml_args *, - const int *, const char **); -static ssize_t xml_endtag(struct ml_args *, enum md_ns, int); -static ssize_t xml_begintag(struct ml_args *, enum md_ns, int, - const int *, const char **); - - -static ssize_t -xml_printtagargs(struct ml_args *p, const int *argc, const char **argv) -{ - int i, c; - size_t res; - - if (NULL == argc || NULL == argv) - return(0); - assert(argc && argv); - - /* LINTED */ - for (res = 0, i = 0; ROFF_ARGMAX != (c = argc[i]); i++) { - if ( ! ml_nputs(p->mbuf, " ", 1, &res)) - return(-1); - - /* FIXME: should puke on some, no? */ - - if ( ! ml_puts(p->mbuf, tokargnames[c], &res)) - return(-1); - if ( ! ml_nputs(p->mbuf, "=\"", 2, &res)) - return(-1); - if (argv[i]) { - if ( ! ml_putstring(p->mbuf, argv[i], &res)) - return(-1); - } else if ( ! ml_nputs(p->mbuf, "true", 4, &res)) - return(-1); - if ( ! ml_nputs(p->mbuf, "\"", 1, &res)) - return(-1); - } - - return((ssize_t)res); -} - - -static ssize_t -xml_printtagname(struct ml_args *p, enum md_ns ns, int tok) -{ - size_t res; - - res = 0; - switch (ns) { - case (MD_NS_BLOCK): - if ( ! ml_nputs(p->mbuf, "block:", 6, &res)) - return(-1); - break; - case (MD_NS_INLINE): - if ( ! ml_nputs(p->mbuf, "inline:", 7, &res)) - return(-1); - break; - case (MD_NS_BODY): - if ( ! ml_nputs(p->mbuf, "body:", 5, &res)) - return(-1); - break; - case (MD_NS_HEAD): - if ( ! ml_nputs(p->mbuf, "head:", 5, &res)) - return(-1); - break; - default: - break; - } - - if ( ! ml_puts(p->mbuf, toknames[tok], &res)) - return(-1); - return((ssize_t)res); -} - - -/* ARGSUSED */ -static int -xml_begin(struct ml_args *p, const struct tm *tm, const char *os, - const char *title, enum roffmsec sec, enum roffvol vol) -{ - - if ( ! ml_puts(p->mbuf, "<?xml version=\"1.0\" " - "encoding=\"UTF-8\"?>\n", NULL)) - return(0); - return(ml_puts(p->mbuf, "<mdoc xmlns:block=\"block\" " - "xmlns:body=\"body\" " - "xmlns:head=\"head\" " - "xmlns:inline=\"inline\">", NULL)); -} - - -/* ARGSUSED */ -static int -xml_end(struct ml_args *p, const struct tm *tm, const char *os, - const char *title, enum roffmsec sec, enum roffvol vol) -{ - - return(ml_puts(p->mbuf, "</mdoc>", NULL)); -} - - -/* ARGSUSED */ -static ssize_t -xml_beginstring(struct ml_args *p, const char *buf, size_t sz) -{ - - return(0); -} - - -/* ARGSUSED */ -static ssize_t -xml_endstring(struct ml_args *p, const char *buf, size_t sz) -{ - - return(0); -} - - -/* ARGSUSED */ -static ssize_t -xml_begintag(struct ml_args *p, enum md_ns ns, - int tok, const int *argc, const char **argv) -{ - ssize_t res, sz; - - if (-1 == (res = xml_printtagname(p, ns, tok))) - return(-1); - if (-1 == (sz = xml_printtagargs(p, argc, argv))) - return(-1); - return(res + sz); -} - - -/* ARGSUSED */ -static ssize_t -xml_endtag(struct ml_args *p, enum md_ns ns, int tok) -{ - - return(xml_printtagname(p, ns, tok)); -} - - -/* ARGSUSED */ -int -xml_alloc(void **p) -{ - - *p = NULL; - return(1); -} - - -/* ARGSUSED */ -void -xml_free(void *p) -{ - - /* Do nothing. */ -} - - -int -md_line_xml(void *data, char *buf) -{ - - return(mlg_line((struct md_mlg *)data, buf)); -} - - -int -md_exit_xml(void *data, int flush) -{ - - return(mlg_exit((struct md_mlg *)data, flush)); -} - - -void * -md_init_xml(const struct md_args *args, - struct md_mbuf *mbuf, const struct md_rbuf *rbuf) -{ - struct ml_cbs cbs; - - cbs.ml_alloc = xml_alloc; - cbs.ml_free = xml_free; - cbs.ml_begintag = xml_begintag; - cbs.ml_endtag = xml_endtag; - cbs.ml_begin = xml_begin; - cbs.ml_end = xml_end; - cbs.ml_beginstring = xml_beginstring; - cbs.ml_endstring = xml_endstring; - - return(mlg_alloc(args, rbuf, mbuf, &cbs)); -} - |