diff options
-rw-r--r-- | Makefile | 120 | ||||
-rw-r--r-- | action.c | 11 | ||||
-rw-r--r-- | arch.c | 2 | ||||
-rw-r--r-- | argv.c | 17 | ||||
-rw-r--r-- | att.c | 2 | ||||
-rw-r--r-- | lib.c | 2 | ||||
-rw-r--r-- | libman.h | 66 | ||||
-rw-r--r-- | libmdoc.h (renamed from private.h) | 14 | ||||
-rw-r--r-- | main.c | 190 | ||||
-rw-r--r-- | man.c | 368 | ||||
-rw-r--r-- | man.h | 97 | ||||
-rw-r--r-- | man_hash.c | 58 | ||||
-rw-r--r-- | man_macro.c | 96 | ||||
-rw-r--r-- | mdoc.7 | 5 | ||||
-rw-r--r-- | mdoc.c | 48 | ||||
-rw-r--r-- | mdoc.h | 2 | ||||
-rw-r--r-- | mdoc_hash.c (renamed from hash.c) | 2 | ||||
-rw-r--r-- | mdoc_macro.c (renamed from macro.c) | 2 | ||||
-rw-r--r-- | msec.c | 2 | ||||
-rw-r--r-- | st.c | 2 | ||||
-rw-r--r-- | strings.c | 2 | ||||
-rw-r--r-- | term.h | 2 | ||||
-rw-r--r-- | validate.c | 2 | ||||
-rw-r--r-- | vol.c | 2 | ||||
-rw-r--r-- | xstd.c | 11 |
25 files changed, 902 insertions, 223 deletions
@@ -17,30 +17,29 @@ CFLAGS += -W -Wall -Wstrict-prototypes -Wno-unused-parameter -g LINTFLAGS += $(VFLAGS) CFLAGS += $(VFLAGS) -# If you want to strip `Xo/Xc' macro pairs, enable this. Really, only -# OpenBSD should be doing this while it kicks its cruft. -#CFLAGS += -DSTRIP_XO -#LINTFLAGS += -DSTRIP_XO - -LIBLNS = macro.ln mdoc.ln hash.ln strings.ln xstd.ln argv.ln \ - validate.ln action.ln lib.ln att.ln arch.ln vol.ln \ - msec.ln st.ln -LIBOBJS = macro.o mdoc.o hash.o strings.o xstd.o argv.o validate.o \ - action.o lib.o att.o arch.o vol.o msec.o st.o -LIBSRCS = macro.c mdoc.c hash.c strings.c xstd.c argv.c validate.c \ - action.c lib.c att.c arch.c vol.c msec.c st.c +MDOCLNS = mdoc_macro.ln mdoc.ln mdoc_hash.ln strings.ln xstd.ln \ + argv.ln validate.ln action.ln lib.ln att.ln arch.ln \ + vol.ln msec.ln st.ln +MDOCOBJS = mdoc_macro.o mdoc.o mdoc_hash.o strings.o xstd.o argv.o \ + validate.o action.o lib.o att.o arch.o vol.o msec.o st.o +MDOCSRCS = mdoc_macro.c mdoc.c mdoc_hash.c strings.c xstd.c argv.c \ + validate.c action.c lib.c att.c arch.c vol.c msec.c st.c + +MANLNS = man_macro.ln man.ln man_hash.ln +MANOBJS = man_macro.o man.o man_hash.o +MANSRCS = man_macro.c man.c man_hash.c MAINLNS = main.ln term.ln ascii.ln terminal.ln tree.ln compat.ln MAINOBJS = main.o term.o ascii.o terminal.o tree.o compat.o MAINSRCS = main.c term.c ascii.c terminal.c tree.c compat.c -LLNS = llib-llibmdoc.ln llib-lmandoc.ln -LNS = $(MAINLNS) $(LIBLNS) -LIBS = libmdoc.a -OBJS = $(LIBOBJS) $(MAINOBJS) -SRCS = $(LIBSRCS) $(MAINSRCS) +LLNS = llib-llibmdoc.ln llib-llibman.ln llib-lmandoc.ln +LNS = $(MAINLNS) $(MDOCLNS) +LIBS = libmdoc.a libman.a +OBJS = $(MDOCOBJS) $(MAINOBJS) +SRCS = $(MDOCSRCS) $(MAINSRCS) DATAS = arch.in att.in lib.in msec.in st.in vol.in ascii.in -HEADS = mdoc.h private.h term.h +HEADS = mdoc.h libmdoc.h man.h libman.h term.h SGMLS = index.sgml HTMLS = index.html STATICS = style.css external.png @@ -91,41 +90,50 @@ uninstall: rm -f $(MANDIR)/man1/mandoc.1 rm -f $(MANDIR)/man7/mdoc.7 -lib.ln: lib.c lib.in private.h -lib.o: lib.c lib.in private.h +man_macro.ln: man_macro.c libman.h +man_macro.o: man_macro.c libman.h -att.ln: att.c att.in private.h -att.o: att.c att.in private.h +lib.ln: lib.c lib.in libmdoc.h +lib.o: lib.c lib.in libmdoc.h -arch.ln: arch.c arch.in private.h -arch.o: arch.c arch.in private.h +att.ln: att.c att.in libmdoc.h +att.o: att.c att.in libmdoc.h -vol.ln: vol.c vol.in private.h -vol.o: vol.c vol.in private.h +arch.ln: arch.c arch.in libmdoc.h +arch.o: arch.c arch.in libmdoc.h + +vol.ln: vol.c vol.in libmdoc.h +vol.o: vol.c vol.in libmdoc.h ascii.ln: ascii.c ascii.in term.h ascii.o: ascii.c ascii.in term.h -msec.ln: msec.c msec.in private.h -msec.o: msec.c msec.in private.h +msec.ln: msec.c msec.in libmdoc.h +msec.o: msec.c msec.in libmdoc.h -st.ln: st.c st.in private.h -st.o: st.c st.in private.h +st.ln: st.c st.in libmdoc.h +st.o: st.c st.in libmdoc.h -macro.ln: macro.c private.h -macro.o: macro.c private.h +mdoc_macro.ln: mdoc_macro.c libmdoc.h +mdoc_macro.o: mdoc_macro.c libmdoc.h term.ln: term.c term.h term.o: term.c term.h -strings.ln: strings.c private.h -strings.o: strings.c private.h +strings.ln: strings.c libmdoc.h +strings.o: strings.c libmdoc.h + +man_hash.ln: man_hash.c libman.h +man_hash.o: man_hash.c libman.h + +mdoc_hash.ln: mdoc_hash.c libmdoc.h +mdoc_hash.o: mdoc_hash.c libmdoc.h -hash.ln: hash.c private.h -hash.o: hash.c private.h +mdoc.ln: mdoc.c libmdoc.h +mdoc.o: mdoc.c libmdoc.h -mdoc.ln: mdoc.c private.h -mdoc.o: mdoc.c private.h +man.ln: man.c libman.h +man.o: man.c libman.h main.ln: main.c mdoc.h main.o: main.c mdoc.h @@ -133,19 +141,19 @@ main.o: main.c mdoc.h terminal.ln: terminal.c term.h terminal.o: terminal.c term.h -xstd.ln: xstd.c private.h -xstd.o: xstd.c private.h +xstd.ln: xstd.c libmdoc.h +xstd.o: xstd.c libmdoc.h -argv.ln: argv.c private.h -argv.o: argv.c private.h +argv.ln: argv.c libmdoc.h +argv.o: argv.c libmdoc.h -validate.ln: validate.c private.h -validate.o: validate.c private.h +validate.ln: validate.c libmdoc.h +validate.o: validate.c libmdoc.h -action.ln: action.c private.h -action.o: action.c private.h +action.ln: action.c libmdoc.h +action.o: action.c libmdoc.h -private.h: mdoc.h +libmdoc.h: mdoc.h term.h: mdoc.h @@ -185,17 +193,23 @@ mdocml-$(VERSION).tar.gz: $(INSTALL) ( cd .dist/mdocml/ && tar zcf ../../$@ mdocml-$(VERSION)/ ) rm -rf .dist/ -llib-llibmdoc.ln: $(LIBLNS) - $(LINT) $(LINTFLAGS) -Clibmdoc $(LIBLNS) +llib-llibmdoc.ln: $(MDOCLNS) + $(LINT) $(LINTFLAGS) -Clibmdoc $(MDOCLNS) + +llib-llibman.ln: $(MANLNS) + $(LINT) $(LINTFLAGS) -Clibman $(MANLNS) llib-lmandoc.ln: $(MAINLNS) llib-llibmdoc.ln $(LINT) $(LINTFLAGS) -Cmandoc $(MAINLNS) llib-llibmdoc.ln -libmdoc.a: $(LIBOBJS) - $(AR) rs $@ $(LIBOBJS) +libmdoc.a: $(MDOCOBJS) + $(AR) rs $@ $(MDOCOBJS) + +libman.a: $(MANOBJS) + $(AR) rs $@ $(MANOBJS) -mandoc: $(MAINOBJS) libmdoc.a - $(CC) $(CFLAGS) -o $@ $(MAINOBJS) libmdoc.a +mandoc: $(MAINOBJS) libmdoc.a libman.a + $(CC) $(CFLAGS) -o $@ $(MAINOBJS) libmdoc.a libman.a .sgml.html: validate $< @@ -24,7 +24,7 @@ #include <stdlib.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" /* * Actions are executed on macros after they've been post-validated: in @@ -272,7 +272,10 @@ post_std(POST_ARGS) assert(m->meta.name); - m->last->args->argv[0].value = xcalloc(1, sizeof(char *)); + m->last->args->argv[0].value = calloc(1, sizeof(char *)); + if (NULL == m->last->args->argv[0].value) + err(1, "calloc"); + m->last->args->argv[0].sz = 1; m->last->args->argv[0].value[0] = xstrdup(m->meta.name); return(1); @@ -493,7 +496,9 @@ post_bl_tagwidth(struct mdoc *m) n->args->argv[n->args->argc - 1].line = m->last->line; n->args->argv[n->args->argc - 1].pos = m->last->pos; n->args->argv[n->args->argc - 1].sz = 1; - n->args->argv[n->args->argc - 1].value = xcalloc(1, sizeof(char *)); + n->args->argv[n->args->argc - 1].value = calloc(1, sizeof(char *)); + if (NULL == n->args->argv[n->args->argc - 1].value) + err(1, "calloc"); n->args->argv[n->args->argc - 1].value[0] = xstrdup(buf); return(1); @@ -19,7 +19,7 @@ #include <stdlib.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" #define LINE(x, y) \ if (0 == strcmp(p, x)) return(y); @@ -25,7 +25,7 @@ #include <stdio.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" /* * Routines to parse arguments of macros. Arguments follow the syntax @@ -294,7 +294,8 @@ mdoc_argv(struct mdoc *mdoc, int line, int tok, return(ARGV_ERROR); if (NULL == (arg = *v)) { - *v = xcalloc(1, sizeof(struct mdoc_arg)); + if (NULL == (*v = calloc(1, sizeof(struct mdoc_arg)))) + err(1, "calloc"); arg = *v; } @@ -792,8 +793,10 @@ argv_opt_single(struct mdoc *mdoc, int line, return(1); v->sz = 1; - v->value = xcalloc(1, sizeof(char *)); - v->value[0] = xstrdup(p); + if (NULL == (v->value = calloc(1, sizeof(char *)))) + err(1, "calloc"); + if (NULL == (v->value[0] = strdup(p))) + err(1, "strdup"); return(1); } @@ -817,8 +820,10 @@ argv_single(struct mdoc *mdoc, int line, return(perr(mdoc, line, ppos, EARGVAL)); v->sz = 1; - v->value = xcalloc(1, sizeof(char *)); - v->value[0] = xstrdup(p); + if (NULL == (v->value = calloc(1, sizeof(char *)))) + err(1, "calloc"); + if (NULL == (v->value[0] = strdup(p))) + err(1, "strdup"); return(1); } @@ -19,7 +19,7 @@ #include <stdlib.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" #define LINE(x, y) \ if (0 == strcmp(p, x)) return(y); @@ -19,7 +19,7 @@ #include <stdlib.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" #define LINE(x, y) \ if (0 == strcmp(p, x)) return(y); diff --git a/libman.h b/libman.h new file mode 100644 index 00000000..e4aa9d5e --- /dev/null +++ b/libman.h @@ -0,0 +1,66 @@ +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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 LIBMAN_H +#define LIBMAN_H + +#include "man.h" + +enum man_next { + MAN_NEXT_SIBLING = 0, + MAN_NEXT_CHILD +}; + +struct man { + void *htab; + int flags; +#define MAN_LITERAL (1 << 1) + enum man_next next; + struct man_node *last; + struct man_node *first; + struct man_meta meta; +}; + + +#define MACRO_PROT_ARGS struct man *man, int tok, int line, \ + int ppos, int *pos, char *buf + +struct man_macro { + int (*fp)(MACRO_PROT_ARGS); + int flags; +#define MDOC_PROLOGUE (1 << 0) +}; + +extern const struct man_macro *const man_macros; + +__BEGIN_DECLS + +int man_word_alloc(struct man *, int, int, const char *); +int man_elem_alloc(struct man *, int, int, int); +int man_block_alloc(struct man *, int, int, int); +int man_head_alloc(struct man *, int, int, int); +int man_body_alloc(struct man *, int, int, int); +void man_node_free(struct man_node *); +void man_node_freelist(struct man_node *); +void *man_hash_alloc(void); +int man_hash_find(const void *, const char *); +void man_hash_free(void *); + +__END_DECLS + +#endif /*!LIBMAN_H*/ @@ -1,6 +1,6 @@ /* $Id$ */ /* - * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the @@ -16,8 +16,8 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ -#ifndef PRIVATE_H -#define PRIVATE_H +#ifndef LIBMDOC_H +#define LIBMDOC_H #include "mdoc.h" @@ -30,7 +30,6 @@ struct mdoc { void *data; struct mdoc_cb cb; void *htab; - int linetok; int flags; #define MDOC_HALT (1 << 0) #define MDOC_LITERAL (1 << 1) @@ -107,7 +106,6 @@ int mdoc_elem_alloc(struct mdoc *, int, int, int, struct mdoc_arg *); int mdoc_block_alloc(struct mdoc *, int, int, int, struct mdoc_arg *); -int mdoc_root_alloc(struct mdoc *); int mdoc_head_alloc(struct mdoc *, int, int, int); int mdoc_tail_alloc(struct mdoc *, int, int, int); int mdoc_body_alloc(struct mdoc *, int, int, int); @@ -121,6 +119,7 @@ int mdoc_isdelim(const char *); size_t mdoc_isescape(const char *); enum mdoc_sec mdoc_atosec(const char *); time_t mdoc_atotime(const char *); + size_t mdoc_macro2len(int); const char *mdoc_a2arch(const char *); const char *mdoc_a2vol(const char *); @@ -146,15 +145,16 @@ int mdoc_args(struct mdoc *, int, #define ARGS_PUNCT (2) #define ARGS_QWORD (3) #define ARGS_PHRASE (4) + +/* FIXME: get rid of these. */ int xstrlcpys(char *, const struct mdoc_node *, size_t); int xstrlcat(char *, const char *, size_t); int xstrlcpy(char *, const char *, size_t); int xstrcmp(const char *, const char *); -void *xcalloc(size_t, size_t); void *xrealloc(void *, size_t); char *xstrdup(const char *); int macro_end(struct mdoc *); __END_DECLS -#endif /*!PRIVATE_H*/ +#endif /*!LIBMDOC_H*/ @@ -27,12 +27,17 @@ #include <unistd.h> #include "mdoc.h" +#include "man.h" #ifdef __linux__ extern int getsubopt(char **, char * const *, char **); # ifndef __dead # define __dead __attribute__((__noreturn__)) # endif +#elif defined(__FreeBSD__) +# ifndef __dead +# define __dead __dead2 +# endif #endif struct buf { @@ -49,8 +54,13 @@ struct curparse { #define WARN_WERR (1 << 2) /* Warnings->errors. */ }; -enum outt { - OUTT_ASCII, +enum intt { + INTT_MDOC = 0, + INTT_MAN +}; + +enum outt { + OUTT_ASCII = 0, OUTT_LATIN1, OUTT_UTF8, OUTT_TREE, @@ -69,18 +79,22 @@ extern int terminal_run(void *, const struct mdoc *); extern int tree_run(void *, const struct mdoc *); extern void terminal_free(void *); -__dead static void version(void); -__dead static void usage(void); static int foptions(int *, char *); static int toptions(enum outt *, char *); +static int moptions(enum intt *, char *); static int woptions(int *, char *); static int merr(void *, int, int, const char *); static int mwarn(void *, int, int, enum mdoc_warn, const char *); -static int file(struct buf *, struct buf *, - const char *, struct mdoc *); +static int file(struct buf *, struct buf *, + const char *, + struct man *, struct mdoc *); static int fdesc(struct buf *, struct buf *, - const char *, int, struct mdoc *); + const char *, int, + struct man *, struct mdoc *); + +__dead static void version(void); +__dead static void usage(void); int @@ -88,9 +102,11 @@ main(int argc, char *argv[]) { int c, rc, fflags; struct mdoc_cb cb; + struct man *man; struct mdoc *mdoc; void *outdata; enum outt outtype; + enum intt inttype; struct buf ln, blk; out_run outrun; out_free outfree; @@ -98,16 +114,21 @@ main(int argc, char *argv[]) fflags = 0; outtype = OUTT_ASCII; + inttype = INTT_MDOC; bzero(&curp, sizeof(struct curparse)); /* LINTED */ - while (-1 != (c = getopt(argc, argv, "f:VW:T:"))) + while (-1 != (c = getopt(argc, argv, "f:m:VW:T:"))) switch (c) { case ('f'): if ( ! foptions(&fflags, optarg)) return(0); break; + case ('m'): + if ( ! moptions(&inttype, optarg)) + return(0); + break; case ('T'): if ( ! toptions(&outtype, optarg)) return(0); @@ -174,7 +195,17 @@ main(int argc, char *argv[]) bzero(&ln, sizeof(struct buf)); bzero(&blk, sizeof(struct buf)); - mdoc = mdoc_alloc(&curp, fflags, &cb); + man = NULL; + mdoc = NULL; + + switch (inttype) { + case (INTT_MAN): + man = man_alloc(); + break; + default: + mdoc = mdoc_alloc(&curp, fflags, &cb); + break; + } /* * Loop around available files. @@ -182,22 +213,31 @@ main(int argc, char *argv[]) if (NULL == *argv) { curp.file = "<stdin>"; - c = fdesc(&blk, &ln, "stdin", STDIN_FILENO, mdoc); rc = 0; + c = fdesc(&blk, &ln, "stdin", + STDIN_FILENO, man, mdoc); + if (c && NULL == outrun) rc = 1; +#if 0 else if (c && outrun && (*outrun)(outdata, mdoc)) rc = 1; +#endif } else { while (*argv) { curp.file = *argv; - c = file(&blk, &ln, *argv, mdoc); + c = file(&blk, &ln, *argv, man, mdoc); if ( ! c) break; +#if 0 if (outrun && ! (*outrun)(outdata, mdoc)) break; - /* Reset the parser for another file. */ - mdoc_reset(mdoc); +#endif + if (man) + man_reset(man); + if (mdoc) + mdoc_reset(mdoc); + argv++; } rc = NULL == *argv; @@ -209,8 +249,10 @@ main(int argc, char *argv[]) free(ln.buf); if (outfree) (*outfree)(outdata); - - mdoc_free(mdoc); + if (mdoc) + mdoc_free(mdoc); + if (man) + man_free(man); return(rc ? EXIT_SUCCESS : EXIT_FAILURE); } @@ -237,8 +279,8 @@ usage(void) static int -file(struct buf *blk, struct buf *ln, - const char *file, struct mdoc *mdoc) +file(struct buf *blk, struct buf *ln, const char *file, + struct man *man, struct mdoc *mdoc) { int fd, c; @@ -247,7 +289,7 @@ file(struct buf *blk, struct buf *ln, return(0); } - c = fdesc(blk, ln, file, fd, mdoc); + c = fdesc(blk, ln, file, fd, man, mdoc); if (-1 == close(fd)) warn("%s", file); @@ -258,15 +300,15 @@ file(struct buf *blk, struct buf *ln, static int fdesc(struct buf *blk, struct buf *ln, - const char *f, int fd, struct mdoc *mdoc) + const char *f, int fd, + struct man *man, struct mdoc *mdoc) { size_t sz; ssize_t ssz; struct stat st; int j, i, pos, lnn; -#ifdef STRIP_XO - int macro, xo, xeoln; -#endif + + assert( ! (man && mdoc)); /* * Two buffers: ln and buf. buf is the input buffer, optimised @@ -291,9 +333,6 @@ fdesc(struct buf *blk, struct buf *ln, /* * Fill buf with file blocksize and parse newlines into ln. */ -#ifdef STRIP_XO - macro = xo = xeoln = 0; -#endif for (lnn = 1, pos = 0; ; ) { if (-1 == (ssz = read(fd, blk->buf, sz))) { @@ -311,66 +350,6 @@ fdesc(struct buf *blk, struct buf *ln, } if ('\n' != blk->buf[i]) { - /* - * Ugly of uglies. Here we handle the - * dreaded `Xo/Xc' scoping. Cover the - * eyes of any nearby children. This - * makes `Xo/Xc' enclosures look like - * one huge line. - */ -#ifdef STRIP_XO - /* - * First, note whether we're in a macro - * line. - */ - if (0 == pos && '.' == blk->buf[i]) - macro = 1; - - /* - * If we're in an `Xo' context and just - * nixed a newline, remove the control - * character for new macro lines: - * they're going to show up as all part - * of the same line. - */ - if (xo && xeoln && '.' == blk->buf[i]) { - xeoln = 0; - continue; - } - xeoln = 0; - - /* - * If we've parsed `Xo', enter an xo - * context. `Xo' must be in a parsable - * state. This is the ugly part. IT IS - * NOT SMART ENOUGH TO HANDLE ESCAPED - * WHITESPACE. - */ - if (macro && pos && 'o' == blk->buf[i]) { - if (xo && 'X' == ln->buf[pos - 1]) { - if (' ' == ln->buf[pos - 2]) - xo++; - } else if ('X' == ln->buf[pos - 1]) { - if (2 == pos && '.' == ln->buf[pos - 2]) - xo++; - else if (' ' == ln->buf[pos - 2]) - xo++; - } - } - - /* - * If we're parsed `Xc', leave an xo - * context if one's already pending. - * `Xc' must be in a parsable state. - * THIS IS NOT SMART ENOUGH TO HANDLE - * ESCAPED WHITESPACE. - */ - if (macro && pos && 'c' == blk->buf[i]) - if (xo && 'X' == ln->buf[pos - 1]) - if (' ' == ln->buf[pos - 2]) - xo--; -#endif /* STRIP_XO */ - ln->buf[pos++] = blk->buf[i]; continue; } @@ -389,30 +368,37 @@ fdesc(struct buf *blk, struct buf *ln, } } -#ifdef STRIP_XO - /* - * If we're in an xo context, put a space in - * place of the newline and continue parsing. - * Mark that we just did a newline. - */ - if (xo) { - xeoln = 1; - ln->buf[pos++] = ' '; - lnn++; - continue; - } - macro = 0; -#endif /* STRIP_XO */ - ln->buf[pos] = 0; - if ( ! mdoc_parseln(mdoc, lnn, ln->buf)) + if (mdoc && ! mdoc_parseln(mdoc, lnn, ln->buf)) + return(0); + if (man && ! man_parseln(man, lnn, ln->buf)) return(0); lnn++; pos = 0; } } - return(mdoc_endparse(mdoc)); + if (mdoc) + return(mdoc_endparse(mdoc)); + + return(man_endparse(man)); +} + + +static int +moptions(enum intt *tflags, char *arg) +{ + + if (0 == strcmp(arg, "mdoc")) + *tflags = INTT_MDOC; + else if (0 == strcmp(arg, "man")) + *tflags = INTT_MAN; + else { + warnx("bad argument: -m%s", arg); + return(0); + } + + return(1); } @@ -0,0 +1,368 @@ +/* $Id$ */ +/* + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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 "libman.h" + +const char *const __man_macronames[MAN_MAX] = { + "\\\"", "TH", "SH", "SS", + "TP", "LP", "PP", "P", + "IP", "HP", "SM", "SB", + "BI", "IB", "BR", "RB", + "R", "B", "I" + }; + +const char * const *man_macronames = __man_macronames; + +static struct man_node *man_node_alloc(int, int, enum man_type); +static int man_node_append(struct man *, + struct man_node *); +static int man_ptext(struct man *, int, char *); +static int man_pmacro(struct man *, int, char *); + + +const struct man_node * +man_node(const struct man *man) +{ + + return(man->first); +} + + +const struct man_meta * +man_meta(const struct man *man) +{ + + return(&man->meta); +} + + +void +man_reset(struct man *man) +{ + + if (man->first) + man_node_freelist(man->first); + if (man->meta.title) + free(man->meta.title); + if (man->meta.os) + free(man->meta.os); + if (man->meta.vol) + free(man->meta.vol); + + bzero(&man->meta, sizeof(struct man_meta)); + man->flags = 0; + if (NULL == (man->last = calloc(1, sizeof(struct man_node)))) + err(1, "malloc"); + man->first = man->last; + man->last->type = MAN_ROOT; + man->next = MAN_NEXT_CHILD; +} + + +void +man_free(struct man *man) +{ + + if (man->first) + man_node_freelist(man->first); + if (man->meta.title) + free(man->meta.title); + if (man->meta.os) + free(man->meta.os); + if (man->meta.vol) + free(man->meta.vol); + if (man->htab) + man_hash_free(man->htab); + free(man); +} + + +struct man * +man_alloc(void) +{ + struct man *p; + + if (NULL == (p = calloc(1, sizeof(struct man)))) + err(1, "malloc"); + if (NULL == (p->last = calloc(1, sizeof(struct man_node)))) + err(1, "malloc"); + + p->first = p->last; + p->last->type = MAN_ROOT; + p->next = MAN_NEXT_CHILD; + p->htab = man_hash_alloc(); + return(p); +} + + +int +man_endparse(struct man *m) +{ + + return(1); +} + + +int +man_parseln(struct man *m, int ln, char *buf) +{ + + return('.' == *buf ? + man_pmacro(m, ln, buf) : + man_ptext(m, ln, buf)); +} + + +static int +man_node_append(struct man *man, struct man_node *p) +{ + + assert(man->last); + assert(man->first); + assert(MAN_ROOT != p->type); + + switch (man->next) { + case (MAN_NEXT_SIBLING): + man->last->next = p; + p->prev = man->last; + p->parent = man->last->parent; + break; + case (MAN_NEXT_CHILD): + man->last->child = p; + p->parent = man->last; + break; + default: + abort(); + /* NOTREACHED */ + } + +#if 0 + if ( ! man_valid_pre(man, p)) + return(0); + if ( ! man_action_pre(man, p)) + return(0); +#endif + + switch (p->type) { + case (MAN_HEAD): + assert(MAN_BLOCK == p->parent->type); + p->parent->head = p; + break; + case (MAN_BODY): + assert(MAN_BLOCK == p->parent->type); + p->parent->body = p; + break; + default: + break; + } + + man->last = p; + return(1); +} + + +static struct man_node * +man_node_alloc(int line, int pos, enum man_type type) +{ + struct man_node *p; + + if (NULL == (p = calloc(1, sizeof(struct man_node)))) + err(1, "malloc"); + p->line = line; + p->pos = pos; + p->type = type; + + return(p); +} + + +int +man_head_alloc(struct man *man, int line, int pos, int tok) +{ + struct man_node *p; + + p = man_node_alloc(line, pos, MAN_HEAD); + p->tok = tok; + + return(man_node_append(man, p)); +} + + +int +man_body_alloc(struct man *man, int line, int pos, int tok) +{ + struct man_node *p; + + p = man_node_alloc(line, pos, MAN_BODY); + p->tok = tok; + + return(man_node_append(man, p)); +} + + +int +man_block_alloc(struct man *man, int line, int pos, int tok) +{ + struct man_node *p; + + p = man_node_alloc(line, pos, MAN_BLOCK); + p->tok = tok; + + return(man_node_append(man, p)); +} + + +int +man_elem_alloc(struct man *man, int line, int pos, int tok) +{ + struct man_node *p; + + p = man_node_alloc(line, pos, MAN_ELEM); + p->tok = tok; + + return(man_node_append(man, p)); +} + + +int +man_word_alloc(struct man *man, + int line, int pos, const char *word) +{ + struct man_node *p; + + p = man_node_alloc(line, pos, MAN_TEXT); + if (NULL == (p->string = strdup(word))) + err(1, "strdup"); + + return(man_node_append(man, p)); +} + + +void +man_node_free(struct man_node *p) +{ + + if (p->string) + free(p->string); + free(p); +} + + +void +man_node_freelist(struct man_node *p) +{ + + if (p->child) + man_node_freelist(p->child); + if (p->next) + man_node_freelist(p->next); + + man_node_free(p); +} + + +static int +man_ptext(struct man *m, int line, char *buf) +{ + + if (0 == buf[0]) { + warnx("blank line!"); + return(1); + } + + if ( ! man_word_alloc(m, line, 0, buf)) + return(0); + + m->next = MAN_NEXT_SIBLING; + return(1); +} + + +int +man_pmacro(struct man *m, int ln, char *buf) +{ + int i, c; + char mac[5]; + + /* Comments and empties are quickly ignored. */ + + if (0 == buf[1]) + return(1); + + if (' ' == buf[1]) { + i = 2; + while (buf[i] && ' ' == buf[i]) + i++; + if (0 == buf[i]) + return(1); + warnx("invalid syntax"); + return(0); + } + + if (buf[1] && '\\' == buf[1]) + if (buf[2] && '\"' == buf[2]) + return(1); + + /* Copy the first word into a nil-terminated buffer. */ + + for (i = 1; i < 5; i++) { + if (0 == (mac[i - 1] = buf[i])) + break; + else if (' ' == buf[i]) + break; + } + + mac[i - 1] = 0; + + if (i == 5 || i <= 1) { + warnx("unknown macro: %s", mac); + goto err; + } + + if (MAN_MAX == (c = man_hash_find(m->htab, mac))) { + warnx("unknown macro: %s", mac); + goto err; + } + + /* The macro is sane. Jump to the next word. */ + + while (buf[i] && ' ' == buf[i]) + i++; + + /* Begin recursive parse sequence. */ + + if ( ! (*man_macros[c].fp)(m, c, ln, 1, &i, buf)) + goto err; + + return(1); + +err: /* Error out. */ + +#if 0 + m->flags |= MDOC_HALT; +#endif + return(0); +} @@ -0,0 +1,97 @@ +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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 MAN_H +#define MAN_H + +#include <time.h> + +#define MAN___ 0 +#define MAN_TH 1 +#define MAN_SH 2 +#define MAN_SS 3 +#define MAN_TP 4 +#define MAN_LP 5 +#define MAN_PP 6 +#define MAN_P 7 +#define MAN_IP 8 +#define MAN_HP 9 +#define MAN_SM 10 +#define MAN_SB 11 +#define MAN_BI 12 +#define MAN_IB 13 +#define MAN_BR 14 +#define MAN_RB 15 +#define MAN_R 16 +#define MAN_B 17 +#define MAN_I 18 +#define MAN_MAX 19 + +enum man_type { + MAN_TEXT, + MAN_ELEM, + MAN_HEAD, + MAN_BODY, + MAN_BLOCK, + MAN_ROOT +}; + +struct man_meta { + int msec; + char *vol; + time_t date; + char *title; + char *os; +}; + +struct man_node { + struct man_node *parent; + struct man_node *child; + struct man_node *next; + struct man_node *prev; + int line; + int pos; + int tok; + int flags; +#define MAN_VALID (1 << 0) +#define MAN_ACTED (1 << 1) + enum man_type type; + + struct man_node *head; + struct man_node *body; + char *string; +}; + +extern const char *const *man_macronames; + +__BEGIN_DECLS + +struct man; + +void man_free(struct man *); +struct man *man_alloc(void); +void man_reset(struct man *); +int man_parseln(struct man *, int, char *buf); +int man_endparse(struct man *); + +const struct man_node *man_node(const struct man *); +const struct man_meta *man_meta(const struct man *); + +__END_DECLS + +#endif /*!MAN_H*/ diff --git a/man_hash.c b/man_hash.c new file mode 100644 index 00000000..418c0b83 --- /dev/null +++ b/man_hash.c @@ -0,0 +1,58 @@ +/* $Id$ */ +/* + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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 "libman.h" + +/* ARGUSED */ +void +man_hash_free(void *htab) +{ + + /* Do nothing. */ +} + + +/* ARGUSED */ +void * +man_hash_alloc(void) +{ + + /* Do nothing. */ + return(NULL); +} + + +int +man_hash_find(const void *arg, const char *tmp) +{ + int i; + + for (i = 0; i < MAN_MAX; i++) + if (0 == strcasecmp(tmp, man_macronames[i])) + return(i); + + return(MAN_MAX); +} + diff --git a/man_macro.c b/man_macro.c new file mode 100644 index 00000000..915c29e6 --- /dev/null +++ b/man_macro.c @@ -0,0 +1,96 @@ +/* $Id$ */ +/* + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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 <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "libman.h" + +static int in_line_eoln(MACRO_PROT_ARGS); + +const struct man_macro __man_macros[MAN_MAX] = { + { in_line_eoln, NULL }, /* MAN___ */ + { in_line_eoln, NULL }, /* MAN_TH */ + { in_line_eoln, NULL }, /* MAN_SH */ + { in_line_eoln, NULL }, /* MAN_SS */ + { in_line_eoln, NULL }, /* MAN_TP */ + { in_line_eoln, NULL }, /* MAN_LP */ + { in_line_eoln, NULL }, /* MAN_PP */ + { in_line_eoln, NULL }, /* MAN_P */ + { in_line_eoln, NULL }, /* MAN_IP */ + { in_line_eoln, NULL }, /* MAN_HP */ + { in_line_eoln, NULL }, /* MAN_SM */ + { in_line_eoln, NULL }, /* MAN_SB */ + { in_line_eoln, NULL }, /* MAN_BI */ + { in_line_eoln, NULL }, /* MAN_IB */ + { in_line_eoln, NULL }, /* MAN_BR */ + { in_line_eoln, NULL }, /* MAN_RB */ + { in_line_eoln, NULL }, /* MAN_R */ + { in_line_eoln, NULL }, /* MAN_B */ + { in_line_eoln, NULL }, /* MAN_I */ +}; + +const struct man_macro * const man_macros = __man_macros; + + +/* + * In-line macro that spans an entire line. May be callable, but has no + * subsequent parsed arguments. + */ +static int +in_line_eoln(MACRO_PROT_ARGS) +{ +#if 0 + int c, w, la; + char *p; + + if ( ! man_elem_alloc(man, line, ppos, tok, arg)) + return(0); + man->next = MDOC_NEXT_SIBLING; + + for (;;) { + la = *pos; + w = man_args(man, line, pos, buf, tok, &p); + + if (ARGS_ERROR == w) + return(0); + if (ARGS_EOLN == w) + break; + + c = ARGS_QWORD == w ? MAN_MAX : + lookup(man, line, la, tok, p); + + if (MDOC_MAX != c && -1 != c) { + if ( ! rew_elem(mdoc, tok)) + return(0); + return(mdoc_macro(mdoc, c, line, la, pos, buf)); + } else if (-1 == c) + return(0); + + if ( ! mdoc_word_alloc(mdoc, line, la, p)) + return(0); + } + + return(rew_elem(mdoc, tok)); +#endif + return(1); +} + @@ -1016,4 +1016,9 @@ should be provided for Linux (\(`a la .Sq \&Ox , .Sq \&Nx etc.). +.\" LIST-ITEM +.It +There's no way to refer to references in +.Sq \&Rs/Re +blocks. .El @@ -24,7 +24,7 @@ #include <stdio.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" /* * Main caller in the libmdoc library. This begins the parsing routine, @@ -32,6 +32,7 @@ * in macro.c, validate.c and action.c. */ +/* FIXME: have this accept line/pos/tok. */ static struct mdoc_node *mdoc_node_alloc(const struct mdoc *); static int mdoc_node_append(struct mdoc *, struct mdoc_node *); @@ -121,8 +122,9 @@ mdoc_meta(const struct mdoc *mdoc) /* - * Free up all resources contributed by a parse: the node tree, meta-data and - * so on. Then reallocate the root node for another parse. + * Free up all resources contributed by a parse: the node tree, + * meta-data and so on. Then reallocate the root node for another + * parse. */ void mdoc_reset(struct mdoc *mdoc) @@ -144,9 +146,10 @@ mdoc_reset(struct mdoc *mdoc) bzero(&mdoc->meta, sizeof(struct mdoc_meta)); mdoc->flags = 0; mdoc->lastnamed = mdoc->lastsec = 0; - - mdoc->first = mdoc->last = - xcalloc(1, sizeof(struct mdoc_node)); + mdoc->last = calloc(1, sizeof(struct mdoc_node)); + if (NULL == mdoc->last) + err(1, "calloc"); + mdoc->first = mdoc->last; mdoc->last->type = MDOC_ROOT; mdoc->next = MDOC_NEXT_CHILD; } @@ -184,14 +187,16 @@ mdoc_alloc(void *data, int pflags, const struct mdoc_cb *cb) { struct mdoc *p; - p = xcalloc(1, sizeof(struct mdoc)); + if (NULL == (p = calloc(1, sizeof(struct mdoc)))) + err(1, "calloc"); p->data = data; if (cb) (void)memcpy(&p->cb, cb, sizeof(struct mdoc_cb)); - p->last = p->first = - xcalloc(1, sizeof(struct mdoc_node)); + if (NULL == (p->first = calloc(1, sizeof(struct mdoc_node)))) + err(1, "calloc"); + p->last = p->first; p->last->type = MDOC_ROOT; p->pflags = pflags; p->next = MDOC_NEXT_CHILD; @@ -370,7 +375,8 @@ mdoc_node_alloc(const struct mdoc *mdoc) { struct mdoc_node *p; - p = xcalloc(1, sizeof(struct mdoc_node)); + if (NULL == (p = calloc(1, sizeof(struct mdoc_node)))) + err(1, "calloc"); p->sec = mdoc->lastsec; return(p); @@ -435,19 +441,6 @@ mdoc_body_alloc(struct mdoc *mdoc, int line, int pos, int tok) int -mdoc_root_alloc(struct mdoc *mdoc) -{ - struct mdoc_node *p; - - p = mdoc_node_alloc(mdoc); - - p->type = MDOC_ROOT; - - return(mdoc_node_append(mdoc, p)); -} - - -int mdoc_block_alloc(struct mdoc *mdoc, int line, int pos, int tok, struct mdoc_arg *args) { @@ -500,7 +493,8 @@ mdoc_word_alloc(struct mdoc *mdoc, p->line = line; p->pos = pos; p->type = MDOC_TEXT; - p->string = xstrdup(word); + if (NULL == (p->string = strdup(word))) + err(1, "strdup"); return(mdoc_node_append(mdoc, p)); } @@ -629,12 +623,6 @@ parsemacro(struct mdoc *m, int ln, char *buf) if ( ! mdoc_macro(m, c, ln, 1, &i, buf)) goto err; - /* - * If we're in literal mode, then add a newline to the end of - * macro lines. Our frontends will interpret this correctly - * (it's documented in mdoc.3). - */ - return(1); err: /* Error out. */ @@ -1,6 +1,6 @@ /* $Id$ */ /* - * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the @@ -23,7 +23,7 @@ #include <stdio.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" /* * Routines for the perfect-hash hashtable used by the parser to look up @@ -22,7 +22,7 @@ #include <stdio.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" /* * This has scanning/parsing routines, each of which extract a macro and @@ -19,7 +19,7 @@ #include <stdlib.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" #define LINE(x, y) \ if (0 == strcmp(p, x)) return(y); @@ -19,7 +19,7 @@ #include <stdlib.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" #define LINE(x, y) \ if (0 == strcmp(p, x)) return(y); @@ -24,7 +24,7 @@ #include <stdio.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" /* * Various string-literal operations: converting scalars to and from @@ -1,6 +1,6 @@ /* $Id$ */ /* - * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the @@ -23,7 +23,7 @@ #include <stdarg.h> #include <stdlib.h> -#include "private.h" +#include "libmdoc.h" /* FIXME: .Bl -diag can't have non-text children in HEAD. */ /* TODO: ignoring Pp (it's superfluous in some invocations). */ @@ -19,7 +19,7 @@ #include <stdlib.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" #define LINE(x, y) \ if (0 == strcmp(p, x)) return(y); @@ -21,7 +21,7 @@ #include <stdlib.h> #include <string.h> -#include "private.h" +#include "libmdoc.h" #ifdef __linux__ extern size_t strlcpy(char *, const char *, size_t); @@ -64,15 +64,6 @@ xrealloc(void *ptr, size_t sz) return(p); } -void * -xcalloc(size_t num, size_t sz) -{ - void *p; - - if (NULL == (p = calloc(num, sz))) - err(EXIT_FAILURE, "calloc"); - return(p); -} char * xstrdup(const char *p) |