=================================================================== RCS file: /cvs/mandoc/Attic/mmain.c,v retrieving revision 1.4 retrieving revision 1.15 diff -u -p -r1.4 -r1.15 --- mandoc/Attic/mmain.c 2009/02/23 15:38:20 1.4 +++ mandoc/Attic/mmain.c 2009/03/19 11:49:00 1.15 @@ -1,6 +1,6 @@ - /* $Id: mmain.c,v 1.4 2009/02/23 15:38:20 kristaps Exp $ */ +/* $Id: mmain.c,v 1.15 2009/03/19 11:49:00 kristaps Exp $ */ /* - * Copyright (c) 2008 Kristaps Dzonsons + * Copyright (c) 2008, 2009 Kristaps Dzonsons * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the @@ -30,7 +30,7 @@ #include "mmain.h" -#define MD_LINE_SZ (256) /* Max input line size. */ +#define MD_LINE_SZ (256) /* Input line step-size. */ struct mmain { int warn; /* Warning flags. */ @@ -41,36 +41,34 @@ struct mmain { int dbg; /* Debug level. */ struct mdoc *mdoc; /* Active parser. */ char *buf; /* Input buffer. */ - u_long bufsz; /* Input buffer size. */ - char *in; /* Input file name. */ + size_t bufsz; /* Input buffer size. */ + const char *in; /* Input file name. */ int fdin; /* Input file desc. */ + int pflags; /* Parse flags. */ }; extern char *__progname; -static int getsopts(struct mmain *, char *); +static void usage(const char *, const char *); +static int optswarn(struct mmain *, char *); +static int optsopt(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 **); -extern size_t strlcpy(char *, const char *, size_t); -extern size_t strlcat(char *, const char *, size_t); -#endif - - /* * Print our and our caller's usage message. */ void -mmain_usage(const char *help) +usage(const char *help, const char *args) { - warnx("usage: %s %s%s[-v] [-Wwarn...] [infile]", __progname, - help ? help : "", help ? " " : ""); + warnx("usage: %s %s%s[-v] [-foption...] [-Wwarn...]%s%s", + __progname, + help ? help : "", help ? " " : "", + args ? " " : "", args ? args : ""); } @@ -85,9 +83,6 @@ mmain_alloc(void) if (NULL == (p = calloc(1, sizeof(struct mmain)))) err(1, "malloc"); - p->in = "-"; - p->fdin = STDIN_FILENO; - return(p); } @@ -100,8 +95,9 @@ mmain_alloc(void) */ int mmain_getopt(struct mmain *p, int argc, char *argv[], - const char *help, const char *u, void *arg, - int (*getopt_cb)(void *, int, const char *)) + const char *help, const char *args, + const char *u, void *arg, + int (*getopt_cb)(void *, int, char *)) { int c; char opts[32]; /* XXX */ @@ -109,7 +105,7 @@ mmain_getopt(struct mmain *p, int argc, char *argv[], extern int optind; - sz = strlcpy(opts, "vW:", 32); + sz = strlcpy(opts, "VvW:f:", 32); assert(sz < 32); if (u) { @@ -122,74 +118,107 @@ mmain_getopt(struct mmain *p, int argc, char *argv[], /* LINTED */ while (-1 != (c = getopt(argc, argv, opts))) switch (c) { + case ('f'): + if ( ! optsopt(p, optarg)) + mmain_exit(p, 1); + break; case ('v'): p->dbg++; break; + case ('V'): + (void)printf("%s %s\n", __progname, VERSION); + mmain_exit(p, 0); + /* NOTREACHED */ case ('W'): - if ( ! getsopts(p, optarg)) - return(0); + if ( ! optswarn(p, optarg)) + mmain_exit(p, 1); break; case ('?'): - mmain_usage(help); - return(0); + usage(help, args); + mmain_exit(p, 1); + /* NOTREACHED */ default: assert(getopt_cb); if ((*getopt_cb)(arg, c, optarg)) break; - return(0); + mmain_exit(p, 1); + /* NOTREACHED */ } - argv += optind; - if ((argc -= optind) > 0) - p->in = *argv++; + return(optind); +} - return(1); + +void +mmain_reset(struct mmain *p) +{ + + if (p->mdoc) + mdoc_free(p->mdoc); + p->mdoc = NULL; } -dead_pre void -mmain_exit(struct mmain *p, int code) +void +mmain_free(struct mmain *p) { if (p->mdoc) mdoc_free(p->mdoc); free(p); +} + + +__dead void +mmain_exit(struct mmain *p, int code) +{ + + mmain_free(p); exit(code); } -struct mdoc * -mmain_mdoc(struct mmain *p) +void +mmain_prepare(struct mmain *p, const char *in) { 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 ((p->in = in)) { if (-1 == (p->fdin = open(p->in, O_RDONLY, 0))) { warn("%s", p->in); - return(0); + mmain_exit(p, 1); } + } else { + p->fdin = STDIN_FILENO; + 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->bufsz = (unsigned)BUFSIZ > st.st_blksize ? + (size_t)BUFSIZ : st.st_blksize; - p->buf = malloc(p->bufsz); - if (NULL == p->buf) - err(1, "malloc"); + if (NULL == (p->buf = realloc(p->buf, p->bufsz))) + err(1, "realloc"); +} + +struct mdoc * +mmain_process(struct mmain *p) +{ + int c; + struct mdoc_cb cb; + + /* XXX - in mmain_alloc.*/ + cb.mdoc_err = msg_err; + cb.mdoc_warn = msg_warn; + cb.mdoc_msg = msg_msg; + /* Allocate the parser. */ - p->mdoc = mdoc_alloc(p, &cb); + p->mdoc = mdoc_alloc(p, p->pflags, &cb); /* Parse the input file. */ @@ -204,10 +233,46 @@ mmain_mdoc(struct mmain *p) } +struct mdoc * +mmain_mdoc(struct mmain *p, const char *in) +{ + + mmain_prepare(p, in); + return(mmain_process(p)); +} + + static int -getsopts(struct mmain *p, char *arg) +optsopt(struct mmain *p, char *arg) { char *v; + char *toks[] = { "ign-scope", "ign-escape", + "ign-macro", NULL }; + + while (*arg) + switch (getsubopt(&arg, toks, &v)) { + case (0): + p->pflags |= MDOC_IGN_SCOPE; + break; + case (1): + p->pflags |= MDOC_IGN_ESCAPE; + break; + case (2): + p->pflags |= MDOC_IGN_MACRO; + break; + default: + warnx("unknown -f argument"); + return(0); + } + + return(1); +} + + +static int +optswarn(struct mmain *p, char *arg) +{ + char *v; char *toks[] = { "all", "compat", "syntax", "error", NULL }; @@ -226,6 +291,7 @@ getsopts(struct mmain *p, char *arg) p->warn |= MD_WARN_ERR; break; default: + warnx("unknown -W argument"); return(0); } @@ -236,104 +302,59 @@ getsopts(struct mmain *p, char *arg) static int parse(struct mmain *p) { - ssize_t sz, i; - size_t pos; - char line[MD_LINE_SZ]; - int lnn; + ssize_t sz; + int j, i, pos, len, lnn; + char *ln; - /* - * 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; ; ) { + for (ln = NULL, lnn = 1, len = 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++) { + for (i = 0; i < (int)sz; i++) { + if (pos >= len) { + len += MD_LINE_SZ; + ln = realloc(ln, (size_t)len); + if (NULL == ln) + err(1, "realloc"); + } + if ('\n' != p->buf[i]) { - if (pos < sizeof(line)) { - line[(int)pos++] = p->buf[(int)i]; + ln[pos++] = p->buf[i]; + continue; + } + + /* Check for escaped newline. */ + + if (pos > 0 && '\\' == ln[pos - 1]) { + for (j = pos - 1; j >= 0; j--) + if ('\\' != ln[j]) + break; + + if ( ! ((pos - j) % 2)) { + pos--; + lnn++; 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); + ln[pos] = 0; + if ( ! mdoc_parseln(p->mdoc, lnn, ln)) { + free(ln); + return(0); + } lnn++; pos = 0; } } + if (ln) + free(ln); + if (pos > 0) + warnx("%s: file not eof-terminated", p->in); 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); -}