diff options
author | Kristaps Dzonsons <kristaps@bsd.lv> | 2009-02-22 22:58:39 +0000 |
---|---|---|
committer | Kristaps Dzonsons <kristaps@bsd.lv> | 2009-02-22 22:58:39 +0000 |
commit | aa3451385251d0974ed07962c800a38fe4287a2b (patch) | |
tree | 654aaa9e47248d0115f7eda964e659d03791ddbe | |
parent | c9f801d9804d2a25f795302e5db93880df4f4d87 (diff) | |
download | mandoc-aa3451385251d0974ed07962c800a38fe4287a2b.tar.gz |
BROKEN BUILD: migrating to mmain stuff.
-rw-r--r-- | Makefile | 41 | ||||
-rw-r--r-- | mdoc.c | 4 | ||||
-rw-r--r-- | mdoc.h | 4 | ||||
-rw-r--r-- | mdocterm.c | 267 | ||||
-rw-r--r-- | mdoctree.c | 280 | ||||
-rw-r--r-- | mmain.c | 328 | ||||
-rw-r--r-- | mmain.h | 45 |
7 files changed, 445 insertions, 524 deletions
@@ -5,9 +5,9 @@ CFLAGS += -W -Wall -Wstrict-prototypes -Wno-unused-parameter -g LIBLNS = macro.ln mdoc.ln hash.ln strings.ln xstd.ln argv.ln \ validate.ln action.ln -TREELNS = mdoctree.ln tree.ln +TREELNS = mdoctree.ln mmain.ln tree.ln -TERMLNS = mdoctree.ln term.ln termact.ln +TERMLNS = mdoctree.ln mmain.ln term.ln termact.ln LNS = $(LIBLNS) $(TREELNS) $(TERMLNS) @@ -18,16 +18,17 @@ LIBS = libmdoc.a LIBOBJS = macro.o mdoc.o hash.o strings.o xstd.o argv.o \ validate.o action.o -TERMOBJS= mdocterm.o term.o termact.o +TERMOBJS= mdocterm.o mmain.o term.o termact.o -TREEOBJS= mdoctree.o tree.o +TREEOBJS= mdoctree.o mmain.o tree.o OBJS = $(LIBOBJS) $(TERMOBJS) $(TREEOBJS) SRCS = macro.c mdoc.c hash.c strings.c xstd.c argv.c validate.c \ - action.c term.c tree.c termact.c mdoctree.c mdocterm.c + action.c term.c tree.c termact.c mdoctree.c mdocterm.c \ + mmain.c -HEADS = mdoc.h private.h term.h +HEADS = mdoc.h private.h term.h mmain.h MANS = mdoctree.1 mdocterm.1 mdoc.3 @@ -137,59 +138,53 @@ uninstall: rm -f $(PREFIX)/include/mdoc.h macro.ln: macro.c private.h - macro.o: macro.c private.h tree.ln: tree.c mdoc.h - tree.o: tree.c mdoc.h term.ln: term.c term.h - term.o: term.c term.h termact.ln: termact.c term.h - termact.o: termact.c term.h strings.ln: strings.c private.h - strings.o: strings.c private.h hash.ln: hash.c private.h - hash.o: hash.c private.h mdoc.ln: mdoc.c private.h - mdoc.o: mdoc.c private.h -mdocterm.ln: mdocterm.c term.h - -mdocterm.o: mdocterm.c term.h +mdocterm.ln: mdocterm.c mmain.h +mdocterm.o: mdocterm.c mmain.h -mdoctree.ln: mdoctree.c mdoc.h - -mdoctree.o: mdoctree.c mdoc.h +mdoctree.ln: mdoctree.c mmain.h +mdoctree.o: mdoctree.c mmain.h xstd.ln: xstd.c private.h - xstd.o: xstd.c private.h argv.ln: argv.c private.h - argv.o: argv.c private.h validate.ln: validate.c private.h - validate.o: validate.c private.h action.ln: action.c private.h - action.o: action.c private.h +mmain.ln: mmain.c mmain.h +mmain.o: mmain.c mmain.h + private.h: mdoc.h +mmain.h: mdoc.h + +term.h: mdoc.h + mdocml-oport-$(VERSION).tar.gz: Makefile.port DESCR mkdir -p .dist/mdocml/pkg sed -e "s!@VERSION@!$(VERSION)!" Makefile.port > .dist/mdocml/Makefile @@ -221,7 +221,7 @@ static void mdoc_text_free(struct mdoc_text *); const struct mdoc_node * -mdoc_node(struct mdoc *mdoc) +mdoc_node(const struct mdoc *mdoc) { return(mdoc->first); @@ -229,7 +229,7 @@ mdoc_node(struct mdoc *mdoc) const struct mdoc_meta * -mdoc_meta(struct mdoc *mdoc) +mdoc_meta(const struct mdoc *mdoc) { return(&mdoc->meta); @@ -413,10 +413,10 @@ struct mdoc *mdoc_alloc(void *data, const struct mdoc_cb *); int mdoc_parseln(struct mdoc *, int, char *buf); /* Get result first node (after mdoc_endparse!). */ -const struct mdoc_node *mdoc_node(struct mdoc *); +const struct mdoc_node *mdoc_node(const struct mdoc *); /* Get result meta-information (after mdoc_endparse!). */ -const struct mdoc_meta *mdoc_meta(struct mdoc *); +const struct mdoc_meta *mdoc_meta(const struct mdoc *); /* Signal end of parse sequence (boolean retval). */ int mdoc_endparse(struct mdoc *); @@ -16,274 +16,45 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ -#include <sys/stat.h> -#include <sys/param.h> - #include <assert.h> -#include <fcntl.h> #include <err.h> #include <getopt.h> -#include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include "mdoc.h" +#include "mmain.h" #include "term.h" -#define MD_LINE_SZ (256) /* Max input line size. */ - -struct md_parse { - int warn; /* Warning flags. */ -#define MD_WARN_SYNTAX (1 << 0) /* Show syntax warnings. */ -#define MD_WARN_COMPAT (1 << 1) /* Show compat warnings. */ -#define MD_WARN_ALL (0x03) /* Show all warnings. */ -#define MD_WARN_ERR (1 << 2) /* Make warnings->errors. */ - int dbg; /* Debug level. */ - struct mdoc *mdoc; /* Active parser. */ - char *buf; /* Input buffer. */ - u_long bufsz; /* Input buffer size. */ - char *in; /* Input file name. */ - int fdin; /* Input file desc. */ -}; - -extern char *__progname; - -static void usage(void); -static int getsopts(struct md_parse *, char *); -static int parse(struct md_parse *); -static void msg_msg(void *, int, int, const char *); -static int msg_err(void *, int, int, const char *); -static int msg_warn(void *, int, int, - enum mdoc_warn, const char *); - -#ifdef __linux__ -extern int getsubopt(char **, char *const *, char **); -#endif - int main(int argc, char *argv[]) { - struct md_parse p; - struct mdoc_cb cb; - struct stat st; + struct mmain *p; + const struct mdoc *mdoc; int c; - extern char *optarg; - extern int optind; - - (void)memset(&p, 0, sizeof(struct md_parse)); - - while (-1 != (c = getopt(argc, argv, "vW:"))) - switch (c) { - case ('v'): - p.dbg++; - break; - case ('W'): - if ( ! getsopts(&p, optarg)) - return(0); - break; - default: - usage(); - return(0); - } - - argv += optind; - argc -= optind; - - /* Initialise the input file. */ - - p.in = "-"; - p.fdin = STDIN_FILENO; - - if (argc > 0) { - p.in = *argv++; - p.fdin = open(p.in, O_RDONLY, 0); - if (-1 == p.fdin) - err(1, "%s", p.in); - } - - /* Allocate a buffer to be BUFSIZ/block size. */ - if (-1 == fstat(p.fdin, &st)) { - warn("%s", p.in); - p.bufsz = BUFSIZ; - } else - p.bufsz = MAX(st.st_blksize, BUFSIZ); - - p.buf = malloc(p.bufsz); - if (NULL == p.buf) - err(1, "malloc"); - - /* Allocate the parser. */ - - cb.mdoc_err = msg_err; - cb.mdoc_warn = msg_warn; - cb.mdoc_msg = msg_msg; - - p.mdoc = mdoc_alloc(&p, &cb); - - /* Parse the input file. */ - - c = parse(&p); - free(p.buf); - - if (STDIN_FILENO != p.fdin && -1 == close(p.fdin)) - warn("%s", p.in); - - if (0 == c) { - mdoc_free(p.mdoc); - return(EXIT_FAILURE); - } - - /* If the parse succeeded, print it out. */ - - termprint(mdoc_node(p.mdoc), mdoc_meta(p.mdoc)); - mdoc_free(p.mdoc); + extern int optreset; + extern int optind; - return(EXIT_SUCCESS); -} + p = mmain_alloc(); + if ( ! mmain_getopt(p, argc, argv, "")) + mmain_exit(p, 1); -static int -getsopts(struct md_parse *p, char *arg) -{ - char *v; - char *toks[] = { "all", "compat", - "syntax", "error", NULL }; + optreset = optind = 1; - while (*arg) - switch (getsubopt(&arg, toks, &v)) { - case (0): - p->warn |= MD_WARN_ALL; - break; - case (1): - p->warn |= MD_WARN_COMPAT; - break; - case (2): - p->warn |= MD_WARN_SYNTAX; - break; - case (3): - p->warn |= MD_WARN_ERR; - break; + while (-1 != (c = getopt(argc, argv, ""))) + switch (c) { default: - usage(); - return(0); - } - - return(1); -} - - -static int -parse(struct md_parse *p) -{ - ssize_t sz, i; - size_t pos; - char line[MD_LINE_SZ]; - int lnn; - - /* - * This is a little more complicated than fgets. TODO: have - * some benchmarks that show it's faster (note that I want to - * check many, many manuals simultaneously, so speed is - * important). Fill a buffer (sized to the block size) with a - * single read, then parse \n-terminated lines into a line - * buffer, which is passed to the parser. Hard-code the line - * buffer to a particular size -- a reasonable assumption. - */ - - for (lnn = 1, pos = 0; ; ) { - if (-1 == (sz = read(p->fdin, p->buf, p->bufsz))) { - warn("%s", p->in); - return(0); - } else if (0 == sz) - break; - - for (i = 0; i < sz; i++) { - if ('\n' != p->buf[i]) { - if (pos < sizeof(line)) { - line[(int)pos++] = p->buf[(int)i]; - continue; - } - warnx("%s: line %d too long", p->in, lnn); - return(0); - } - - line[(int)pos] = 0; - if ( ! mdoc_parseln(p->mdoc, lnn, line)) - return(0); - - lnn++; - pos = 0; + mmain_usage(""); + mmain_exit(p, 1); + /* NOTREACHED */ } - } - return(mdoc_endparse(p->mdoc)); -} + if (NULL == (mdoc = mmain_mdoc(p))) + mmain_exit(p, 1); - -static int -msg_err(void *arg, int line, int col, const char *msg) -{ - struct md_parse *p; - - p = (struct md_parse *)arg; - - warnx("%s:%d: error: %s (column %d)", - p->in, line, msg, col); - return(0); + termprint(mdoc_node(mdoc), mdoc_meta(mdoc)); + mmain_exit(p, 0); + /* NOTREACHED */ } -static void -msg_msg(void *arg, int line, int col, const char *msg) -{ - struct md_parse *p; - - p = (struct md_parse *)arg; - - if (0 == p->dbg) - return; - - warnx("%s:%d: debug: %s (column %d)", - p->in, line, msg, col); -} - - -static int -msg_warn(void *arg, int line, int col, - enum mdoc_warn type, const char *msg) -{ - struct md_parse *p; - - p = (struct md_parse *)arg; - - switch (type) { - case (WARN_COMPAT): - if (p->warn & MD_WARN_COMPAT) - break; - return(1); - case (WARN_SYNTAX): - if (p->warn & MD_WARN_SYNTAX) - break; - return(1); - } - - warnx("%s:%d: warning: %s (column %d)", - p->in, line, msg, col); - - if ( ! (p->warn & MD_WARN_ERR)) - return(1); - - warnx("%s: considering warnings as errors", __progname); - return(0); -} - - -static void -usage(void) -{ - - warnx("usage: %s [-v] [-Wwarn...] [infile]", __progname); -} - @@ -16,276 +16,58 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ -#include <sys/stat.h> -#include <sys/param.h> - #include <assert.h> -#include <fcntl.h> #include <err.h> #include <getopt.h> -#include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "mdoc.h" - -#define MD_LINE_SZ (256) /* Max input line size. */ - -struct md_parse { - int warn; /* Warning flags. */ -#define MD_WARN_SYNTAX (1 << 0) /* Show syntax warnings. */ -#define MD_WARN_COMPAT (1 << 1) /* Show compat warnings. */ -#define MD_WARN_ALL (0x03) /* Show all warnings. */ -#define MD_WARN_ERR (1 << 2) /* Make warnings->errors. */ - int dbg; /* Debug level. */ - struct mdoc *mdoc; /* Active parser. */ - char *buf; /* Input buffer. */ - u_long bufsz; /* Input buffer size. */ - char *in; /* Input file name. */ - int fdin; /* Input file desc. */ -}; - -extern char *__progname; -static void usage(void); -static int getsopts(struct md_parse *, char *); -static int parse(struct md_parse *); -static void msg_msg(void *, int, int, const char *); -static int msg_err(void *, int, int, const char *); -static int msg_warn(void *, int, int, - enum mdoc_warn, const char *); +#include "mmain.h" -extern void treeprint(const struct mdoc_node *, - const struct mdoc_meta *); - -#ifdef __linux__ -extern int getsubopt(char **, char *const *, char **); -#endif +extern void treeprint(const struct mdoc_node *, + const struct mdoc_meta *); int main(int argc, char *argv[]) { - struct md_parse p; - struct mdoc_cb cb; - struct stat st; + struct mmain *p; + const struct mdoc *mdoc; int c; - extern char *optarg; - extern int optind; - - (void)memset(&p, 0, sizeof(struct md_parse)); - - while (-1 != (c = getopt(argc, argv, "vW:"))) - switch (c) { - case ('v'): - p.dbg++; - break; - case ('W'): - if ( ! getsopts(&p, optarg)) - return(0); - break; - default: - usage(); - return(0); - } - - argv += optind; - argc -= optind; - - /* Initialise the input file. */ - - p.in = "-"; - p.fdin = STDIN_FILENO; - - if (argc > 0) { - p.in = *argv++; - p.fdin = open(p.in, O_RDONLY, 0); - if (-1 == p.fdin) - err(1, "%s", p.in); - } - - /* Allocate a buffer to be BUFSIZ/block size. */ - - if (-1 == fstat(p.fdin, &st)) { - warn("%s", p.in); - p.bufsz = BUFSIZ; - } else - p.bufsz = MAX(st.st_blksize, BUFSIZ); - - p.buf = malloc(p.bufsz); - if (NULL == p.buf) - err(1, "malloc"); - - /* Allocate the parser. */ - - cb.mdoc_err = msg_err; - cb.mdoc_warn = msg_warn; - cb.mdoc_msg = msg_msg; - - p.mdoc = mdoc_alloc(&p, &cb); - - /* Parse the input file. */ - - c = parse(&p); - free(p.buf); - - if (STDIN_FILENO != p.fdin && -1 == close(p.fdin)) - warn("%s", p.in); - - if (0 == c) { - mdoc_free(p.mdoc); - return(EXIT_FAILURE); - } - - /* If the parse succeeded, print it out. */ - - treeprint(mdoc_node(p.mdoc), mdoc_meta(p.mdoc)); - mdoc_free(p.mdoc); - - return(EXIT_SUCCESS); -} - - -static int -getsopts(struct md_parse *p, char *arg) -{ - char *v; - char *toks[] = { "all", "compat", - "syntax", "error", NULL }; - - while (*arg) - switch (getsubopt(&arg, toks, &v)) { - case (0): - p->warn |= MD_WARN_ALL; - break; - case (1): - p->warn |= MD_WARN_COMPAT; - break; - case (2): - p->warn |= MD_WARN_SYNTAX; - break; - case (3): - p->warn |= MD_WARN_ERR; - break; - default: - usage(); - return(0); - } - return(1); -} + extern int optreset; + extern int optind; + p = mmain_alloc(); -static int -parse(struct md_parse *p) -{ - ssize_t sz, i; - size_t pos; - char line[MD_LINE_SZ]; - int lnn; + if ( ! mmain_getopt(p, argc, argv, NULL)) + mmain_exit(p, 1); - /* - * This is a little more complicated than fgets. TODO: have - * some benchmarks that show it's faster (note that I want to - * check many, many manuals simultaneously, so speed is - * important). Fill a buffer (sized to the block size) with a - * single read, then parse \n-terminated lines into a line - * buffer, which is passed to the parser. Hard-code the line - * buffer to a particular size -- a reasonable assumption. - */ + optreset = optind = 1; + printf("here\n"); - for (lnn = 1, pos = 0; ; ) { - if (-1 == (sz = read(p->fdin, p->buf, p->bufsz))) { - warn("%s", p->in); - return(0); - } else if (0 == sz) + while (-1 != (c = getopt(argc, argv, "f:"))) + switch (c) { + case ('f'): + printf("%s\n", optarg); break; - - for (i = 0; i < sz; i++) { - if ('\n' != p->buf[i]) { - if (pos < sizeof(line)) { - line[(int)pos++] = p->buf[(int)i]; - continue; - } - warnx("%s: line %d too long", p->in, lnn); - return(0); + case ('?'): + if (mmain_isopt(optopt)) { + printf("ok: %d\n", optopt); + break; } - - line[(int)pos] = 0; - if ( ! mdoc_parseln(p->mdoc, lnn, line)) - return(0); - - lnn++; - pos = 0; + printf("bad: %d\n", optopt); + /* FALLTHROUGH */ + default: + mmain_usage(NULL); + mmain_exit(p, 1); + /* NOTREACHED */ } - } - - return(mdoc_endparse(p->mdoc)); -} - - -static int -msg_err(void *arg, int line, int col, const char *msg) -{ - struct md_parse *p; - - p = (struct md_parse *)arg; - - warnx("%s:%d: error: %s (column %d)", - p->in, line, msg, col); - return(0); -} + if (NULL == (mdoc = mmain_mdoc(p))) + mmain_exit(p, 1); -static void -msg_msg(void *arg, int line, int col, const char *msg) -{ - struct md_parse *p; - - p = (struct md_parse *)arg; - - if (0 == p->dbg) - return; - - warnx("%s:%d: debug: %s (column %d)", - p->in, line, msg, col); + treeprint(mdoc_node(mdoc), mdoc_meta(mdoc)); + mmain_exit(p, 0); + /* NOTREACHED */ } -static int -msg_warn(void *arg, int line, int col, - enum mdoc_warn type, const char *msg) -{ - struct md_parse *p; - - p = (struct md_parse *)arg; - - switch (type) { - case (WARN_COMPAT): - if (p->warn & MD_WARN_COMPAT) - break; - return(1); - case (WARN_SYNTAX): - if (p->warn & MD_WARN_SYNTAX) - break; - return(1); - } - - warnx("%s:%d: warning: %s (column %d)", - p->in, line, msg, col); - - if ( ! (p->warn & MD_WARN_ERR)) - return(1); - - warnx("%s: considering warnings as errors", __progname); - return(0); -} - - -static void -usage(void) -{ - - warnx("usage: %s [-v] [-Wwarn...] [infile]", __progname); -} - diff --git a/mmain.c b/mmain.c new file mode 100644 index 00000000..38f5ab81 --- /dev/null +++ b/mmain.c @@ -0,0 +1,328 @@ + /* $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/stat.h> +#include <sys/param.h> + +#include <assert.h> +#include <fcntl.h> +#include <err.h> +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "mmain.h" + +#define MD_LINE_SZ (256) /* Max input line size. */ + +struct mmain { + int warn; /* Warning flags. */ +#define MD_WARN_SYNTAX (1 << 0) /* Show syntax warnings. */ +#define MD_WARN_COMPAT (1 << 1) /* Show compat warnings. */ +#define MD_WARN_ALL (0x03) /* Show all warnings. */ +#define MD_WARN_ERR (1 << 2) /* Make warnings->errors. */ + int dbg; /* Debug level. */ + struct mdoc *mdoc; /* Active parser. */ + char *buf; /* Input buffer. */ + u_long bufsz; /* Input buffer size. */ + char in[MAXPATHLEN]; /* Input file name. */ + int fdin; /* Input file desc. */ +}; + +extern char *__progname; + +static int getsopts(struct mmain *, char *); +static int parse(struct mmain *); +static void msg_msg(void *, int, int, const char *); +static int msg_err(void *, int, int, const char *); +static int msg_warn(void *, int, int, + enum mdoc_warn, const char *); + +#ifdef __linux__ +extern int getsubopt(char **, char *const *, char **); +#endif + + +void +mmain_usage(const char *help) +{ + + warnx("usage: %s %s%s[-v] [-Wwarn...] [infile]", __progname, + help ? help : "", help ? " " : ""); +} + + +struct mmain * +mmain_alloc(void) +{ + struct mmain *p; + + if (NULL == (p = calloc(1, sizeof(struct mmain)))) + err(1, "malloc"); + + (void)strlcpy(p->in, "-", MAXPATHLEN); + p->fdin = STDIN_FILENO; + + return(p); +} + + +int +mmain_isopt(int c) +{ + + switch (c) { + case ('v'): + /* FALLTHROUGH */ + case ('W'): + return(1); + default: + break; + } + return(0); +} + + +int +mmain_getopt(struct mmain *p, int argc, + char *argv[], const char *help) +{ + int c; + + while (-1 != (c = getopt(argc, argv, ":vW:"))) + switch (c) { + case ('v'): + p->dbg++; + break; + case ('W'): + if ( ! getsopts(p, optarg)) + return(0); + break; + case ('?'): + break; + default: + mmain_usage(help); + return(0); + } + + argv += optind; + argc -= optind; + + if (0 == argc) + return(1); + + if (strlcpy(p->in, *argv++, MAXPATHLEN) < MAXPATHLEN) + return(1); + + warnx("filename too long"); + return(0); +} + + +__dead void +mmain_exit(struct mmain *p, int code) +{ + + if (p->mdoc) + mdoc_free(p->mdoc); + free(p); + exit(code); +} + + +struct mdoc * +mmain_mdoc(struct mmain *p) +{ + struct stat st; + int c; + struct mdoc_cb cb; + + cb.mdoc_err = msg_err; + cb.mdoc_warn = msg_warn; + cb.mdoc_msg = msg_msg; + + if (0 != strcmp(p->in, "-")) + if (-1 == (p->fdin = open(p->in, O_RDONLY, 0))) { + warn("%s", p->in); + return(0); + } + + /* Allocate a buffer to be BUFSIZ/block size. */ + + if (-1 == fstat(p->fdin, &st)) { + warn("%s", p->in); + p->bufsz = BUFSIZ; + } else + p->bufsz = MAX(st.st_blksize, BUFSIZ); + + p->buf = malloc(p->bufsz); + if (NULL == p->buf) + err(1, "malloc"); + + /* Allocate the parser. */ + + p->mdoc = mdoc_alloc(p, &cb); + + /* Parse the input file. */ + + c = parse(p); + free(p->buf); + + if (STDIN_FILENO != p->fdin) + if (-1 == close(p->fdin)) + warn("%s", p->in); + + return(c ? p->mdoc : NULL); +} + + +static int +getsopts(struct mmain *p, char *arg) +{ + char *v; + char *toks[] = { "all", "compat", + "syntax", "error", NULL }; + + while (*arg) + switch (getsubopt(&arg, toks, &v)) { + case (0): + p->warn |= MD_WARN_ALL; + break; + case (1): + p->warn |= MD_WARN_COMPAT; + break; + case (2): + p->warn |= MD_WARN_SYNTAX; + break; + case (3): + p->warn |= MD_WARN_ERR; + break; + default: + return(0); + } + + return(1); +} + + +static int +parse(struct mmain *p) +{ + ssize_t sz, i; + size_t pos; + char line[MD_LINE_SZ]; + int lnn; + + /* + * This is a little more complicated than fgets. TODO: have + * some benchmarks that show it's faster (note that I want to + * check many, many manuals simultaneously, so speed is + * important). Fill a buffer (sized to the block size) with a + * single read, then parse \n-terminated lines into a line + * buffer, which is passed to the parser. Hard-code the line + * buffer to a particular size -- a reasonable assumption. + */ + + for (lnn = 1, pos = 0; ; ) { + if (-1 == (sz = read(p->fdin, p->buf, p->bufsz))) { + warn("%s", p->in); + return(0); + } else if (0 == sz) + break; + + for (i = 0; i < sz; i++) { + if ('\n' != p->buf[i]) { + if (pos < sizeof(line)) { + line[(int)pos++] = p->buf[(int)i]; + continue; + } + warnx("%s: line %d too long", p->in, lnn); + return(0); + } + + line[(int)pos] = 0; + if ( ! mdoc_parseln(p->mdoc, lnn, line)) + return(0); + + lnn++; + pos = 0; + } + } + + return(mdoc_endparse(p->mdoc)); +} + + +static int +msg_err(void *arg, int line, int col, const char *msg) +{ + struct mmain *p; + + p = (struct mmain *)arg; + + warnx("%s:%d: error: %s (column %d)", + p->in, line, msg, col); + return(0); +} + + +static void +msg_msg(void *arg, int line, int col, const char *msg) +{ + struct mmain *p; + + p = (struct mmain *)arg; + + if (0 == p->dbg) + return; + + warnx("%s:%d: debug: %s (column %d)", + p->in, line, msg, col); +} + + +static int +msg_warn(void *arg, int line, int col, + enum mdoc_warn type, const char *msg) +{ + struct mmain *p; + + p = (struct mmain *)arg; + + switch (type) { + case (WARN_COMPAT): + if (p->warn & MD_WARN_COMPAT) + break; + return(1); + case (WARN_SYNTAX): + if (p->warn & MD_WARN_SYNTAX) + break; + return(1); + } + + warnx("%s:%d: warning: %s (column %d)", + p->in, line, msg, col); + + if ( ! (p->warn & MD_WARN_ERR)) + return(1); + + warnx("%s: considering warnings as errors", __progname); + return(0); +} diff --git a/mmain.h b/mmain.h new file mode 100644 index 00000000..6cb6ea39 --- /dev/null +++ b/mmain.h @@ -0,0 +1,45 @@ +/* $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 MMAIN_H +#define MMAIN_H + +/* + * This is a convenience library for utilities implementing mdoc(3) + * accepting a similar set of command-line patterns. mmain handles + * error reporting (to the terminal), preparing and reading the input + * file, and enacting the parse itself. + */ + +#include "mdoc.h" + +__BEGIN_DECLS + +struct mmain; + +struct mmain *mmain_alloc(void); +__dead void mmain_exit(struct mmain *, int); +int mmain_getopt(struct mmain *, int, + char *[], const char *); +int mmain_isopt(int); +struct mdoc *mmain_mdoc(struct mmain *); +void mmain_usage(const char *); + +__END_DECLS + +#endif /*!MMAIN_H*/ |