=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/mandoc/main.c,v retrieving revision 1.44 retrieving revision 1.45 diff -c -r1.44 -r1.45 *** src/usr.bin/mandoc/main.c 2010/08/18 01:03:22 1.44 --- src/usr.bin/mandoc/main.c 2010/08/20 00:53:35 1.45 *************** *** 1,4 **** ! /* $Id: main.c,v 1.44 2010/08/18 01:03:22 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons * Copyright (c) 2010 Ingo Schwarze --- 1,4 ---- ! /* $Id: main.c,v 1.45 2010/08/20 00:53:35 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons * Copyright (c) 2010 Ingo Schwarze *************** *** 64,80 **** struct curparse { const char *file; /* Current parse. */ int fd; /* Current parse. */ ! int wflags; ! /* FIXME: set by max error */ ! #define WARN_WALL (1 << 0) /* All-warnings mask. */ ! #define WARN_WERR (1 << 2) /* Warnings->errors. */ ! int fflags; ! #define FL_IGN_SCOPE (1 << 0) /* Ignore scope errors. */ ! #define FL_NIGN_ESCAPE (1 << 1) /* Don't ignore bad escapes. */ ! #define FL_NIGN_MACRO (1 << 2) /* Don't ignore bad macros. */ ! #define FL_IGN_ERRORS (1 << 4) /* Ignore failed parse. */ ! #define FL_STRICT FL_NIGN_ESCAPE | \ ! FL_NIGN_MACRO /* ignore nothing */ enum intt inttype; /* which parser to use */ struct man *man; /* man parser */ struct mdoc *mdoc; /* mdoc parser */ --- 64,71 ---- struct curparse { const char *file; /* Current parse. */ int fd; /* Current parse. */ ! enum mandoclevel wlevel; /* Ignore messages below this. */ ! int wstop; /* Stop after a file with a warning. */ enum intt inttype; /* which parser to use */ struct man *man; /* man parser */ struct mdoc *mdoc; /* mdoc parser */ *************** *** 88,93 **** --- 79,104 ---- char outopts[BUFSIZ]; /* buf of output opts */ }; + static const char * const mandoclevels[MANDOCLEVEL_MAX] = { + "SUCCESS", + "RESERVED", + "WARNING", + "ERROR", + "FATAL", + "BADARG", + "SYSERR" + }; + + static const enum mandocerr mandoclimits[MANDOCLEVEL_MAX] = { + MANDOCERR_OK, + MANDOCERR_WARNING, + MANDOCERR_WARNING, + MANDOCERR_ERROR, + MANDOCERR_FATAL, + MANDOCERR_MAX, + MANDOCERR_MAX + }; + static const char * const mandocerrs[MANDOCERR_MAX] = { "ok", *************** *** 164,191 **** "no document body", "no document prologue", "utsname system call failed", ! "memory exhausted", }; static void fdesc(struct curparse *); static void ffile(const char *, struct curparse *); - static int foptions(int *, char *); - static struct man *man_init(struct curparse *); - static struct mdoc *mdoc_init(struct curparse *); - static struct roff *roff_init(struct curparse *); static int moptions(enum intt *, char *); static int mmsg(enum mandocerr, void *, int, int, const char *); ! static int pset(const char *, int, struct curparse *, struct man **, struct mdoc **); static int toptions(struct curparse *, char *); static void usage(void) __attribute__((noreturn)); static void version(void) __attribute__((noreturn)); ! static int woptions(int *, char *); static const char *progname; ! static int with_fatal; ! static int with_error; int main(int argc, char *argv[]) --- 175,197 ---- "no document body", "no document prologue", "utsname system call failed", ! "static buffer exhausted", }; static void fdesc(struct curparse *); static void ffile(const char *, struct curparse *); static int moptions(enum intt *, char *); static int mmsg(enum mandocerr, void *, int, int, const char *); ! static void pset(const char *, int, struct curparse *, struct man **, struct mdoc **); static int toptions(struct curparse *, char *); static void usage(void) __attribute__((noreturn)); static void version(void) __attribute__((noreturn)); ! static int woptions(struct curparse *, char *); static const char *progname; ! static enum mandoclevel exit_status = MANDOCLEVEL_OK; int main(int argc, char *argv[]) *************** *** 203,219 **** curp.inttype = INTT_AUTO; curp.outtype = OUTT_ASCII; /* LINTED */ ! while (-1 != (c = getopt(argc, argv, "f:m:O:T:VW:"))) switch (c) { - case ('f'): - if ( ! foptions(&curp.fflags, optarg)) - return(EXIT_FAILURE); - break; case ('m'): if ( ! moptions(&curp.inttype, optarg)) ! return(EXIT_FAILURE); break; case ('O'): (void)strlcat(curp.outopts, optarg, BUFSIZ); --- 209,222 ---- curp.inttype = INTT_AUTO; curp.outtype = OUTT_ASCII; + curp.wlevel = MANDOCLEVEL_FATAL; /* LINTED */ ! while (-1 != (c = getopt(argc, argv, "m:O:T:VW:"))) switch (c) { case ('m'): if ( ! moptions(&curp.inttype, optarg)) ! return(MANDOCLEVEL_BADARG); break; case ('O'): (void)strlcat(curp.outopts, optarg, BUFSIZ); *************** *** 221,231 **** break; case ('T'): if ( ! toptions(&curp, optarg)) ! return(EXIT_FAILURE); break; case ('W'): ! if ( ! woptions(&curp.wflags, optarg)) ! return(EXIT_FAILURE); break; case ('V'): version(); --- 224,234 ---- break; case ('T'): if ( ! toptions(&curp, optarg)) ! return(MANDOCLEVEL_BADARG); break; case ('W'): ! if ( ! woptions(&curp, optarg)) ! return(MANDOCLEVEL_BADARG); break; case ('V'): version(); *************** *** 247,254 **** while (*argv) { ffile(*argv, &curp); ! ! if (with_fatal && !(curp.fflags & FL_IGN_ERRORS)) break; ++argv; } --- 250,256 ---- while (*argv) { ffile(*argv, &curp); ! if (MANDOCLEVEL_OK != exit_status && curp.wstop) break; ++argv; } *************** *** 262,269 **** if (curp.roff) roff_free(curp.roff); ! return((with_fatal || with_error) ? ! EXIT_FAILURE : EXIT_SUCCESS); } --- 264,270 ---- if (curp.roff) roff_free(curp.roff); ! return(exit_status); } *************** *** 272,278 **** { (void)printf("%s %s\n", progname, VERSION); ! exit(EXIT_SUCCESS); } --- 273,279 ---- { (void)printf("%s %s\n", progname, VERSION); ! exit(MANDOCLEVEL_OK); } *************** *** 283,338 **** (void)fprintf(stderr, "usage: %s [-V] [-foption] " "[-mformat] [-Ooption] [-Toutput] " "[-Werr] [file...]\n", progname); ! exit(EXIT_FAILURE); } - static struct man * - man_init(struct curparse *curp) - { - int pflags; - - /* Defaults from mandoc.1. */ - - pflags = MAN_IGN_MACRO | MAN_IGN_ESCAPE; - - if (curp->fflags & FL_NIGN_MACRO) - pflags &= ~MAN_IGN_MACRO; - if (curp->fflags & FL_NIGN_ESCAPE) - pflags &= ~MAN_IGN_ESCAPE; - - return(man_alloc(&curp->regs, curp, pflags, mmsg)); - } - - - static struct roff * - roff_init(struct curparse *curp) - { - - return(roff_alloc(&curp->regs, mmsg, curp)); - } - - - static struct mdoc * - mdoc_init(struct curparse *curp) - { - int pflags; - - /* Defaults from mandoc.1. */ - - pflags = MDOC_IGN_MACRO | MDOC_IGN_ESCAPE; - - if (curp->fflags & FL_IGN_SCOPE) - pflags |= MDOC_IGN_SCOPE; - if (curp->fflags & FL_NIGN_ESCAPE) - pflags &= ~MDOC_IGN_ESCAPE; - if (curp->fflags & FL_NIGN_MACRO) - pflags &= ~MDOC_IGN_MACRO; - - return(mdoc_alloc(&curp->regs, curp, pflags, mmsg)); - } - - static void ffile(const char *file, struct curparse *curp) { --- 284,293 ---- (void)fprintf(stderr, "usage: %s [-V] [-foption] " "[-mformat] [-Ooption] [-Toutput] " "[-Werr] [file...]\n", progname); ! exit(MANDOCLEVEL_BADARG); } static void ffile(const char *file, struct curparse *curp) { *************** *** 340,346 **** curp->file = file; if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) { perror(curp->file); ! with_fatal = 1; return; } --- 295,301 ---- curp->file = file; if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) { perror(curp->file); ! exit_status = MANDOCLEVEL_SYSERR; return; } *************** *** 351,374 **** } ! static int resize_buf(struct buf *buf, size_t initial) { - void *tmp; - size_t sz; ! if (buf->sz == 0) ! sz = initial; ! else ! sz = 2 * buf->sz; ! tmp = realloc(buf->buf, sz); ! if (NULL == tmp) { perror(NULL); ! return(0); } - buf->buf = tmp; - buf->sz = sz; - return(1); } --- 306,321 ---- } ! static void resize_buf(struct buf *buf, size_t initial) { ! buf->sz = buf->sz ? 2 * buf->sz : initial; ! buf->buf = realloc(buf->buf, buf->sz); ! if (NULL == buf->buf) { perror(NULL); ! exit(MANDOCLEVEL_SYSERR); } } *************** *** 381,387 **** if (-1 == fstat(curp->fd, &st)) { perror(curp->file); - with_fatal = 1; return(0); } --- 328,333 ---- *************** *** 396,402 **** if (st.st_size >= (1U << 31)) { fprintf(stderr, "%s: input too large\n", curp->file); - with_fatal = 1; return(0); } *with_mmap = 1; --- 342,347 ---- *************** *** 423,430 **** curp->file); break; } ! if (! resize_buf(fb, 65536)) ! break; } ssz = read(curp->fd, fb->buf + (int)off, fb->sz - off); if (ssz == 0) { --- 368,374 ---- curp->file); break; } ! resize_buf(fb, 65536); } ssz = read(curp->fd, fb->buf + (int)off, fb->sz - off); if (ssz == 0) { *************** *** 440,446 **** free(fb->buf); fb->buf = NULL; - with_fatal = 1; return(0); } --- 384,389 ---- *************** *** 467,479 **** * memory mapped. ln is a line buffer and grows on-demand. */ ! if ( ! read_whole_file(curp, &blk, &with_mmap)) return; if (NULL == curp->roff) ! curp->roff = roff_init(curp); ! if (NULL == (roff = curp->roff)) ! goto bailout; for (i = 0, lnn = 1; i < (int)blk.sz;) { pos = 0; --- 410,424 ---- * memory mapped. ln is a line buffer and grows on-demand. */ ! if ( ! read_whole_file(curp, &blk, &with_mmap)) { ! exit_status = MANDOCLEVEL_SYSERR; return; + } if (NULL == curp->roff) ! curp->roff = roff_alloc(&curp->regs, curp, mmsg); ! assert(curp->roff); ! roff = curp->roff; for (i = 0, lnn = 1; i < (int)blk.sz;) { pos = 0; *************** *** 496,505 **** c = (unsigned char) blk.buf[i]; if ( ! (isascii(c) && (isgraph(c) || isblank(c)))) { ! if ( ! mmsg(MANDOCERR_BADCHAR, curp, ! lnn_start, pos, ! "ignoring byte")) ! goto bailout; i++; continue; } --- 441,448 ---- c = (unsigned char) blk.buf[i]; if ( ! (isascii(c) && (isgraph(c) || isblank(c)))) { ! mmsg(MANDOCERR_BADCHAR, curp, ! lnn_start, pos, "ignoring byte"); i++; continue; } *************** *** 507,514 **** /* Trailing backslash is like a plain character. */ if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) { if (pos >= (int)ln.sz) ! if (! resize_buf(&ln, 256)) ! goto bailout; ln.buf[pos++] = blk.buf[i++]; continue; } --- 450,456 ---- /* Trailing backslash is like a plain character. */ if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) { if (pos >= (int)ln.sz) ! resize_buf(&ln, 256); ln.buf[pos++] = blk.buf[i++]; continue; } *************** *** 540,555 **** } /* Some other escape sequence, copy and continue. */ if (pos + 1 >= (int)ln.sz) ! if (! resize_buf(&ln, 256)) ! goto bailout; ln.buf[pos++] = blk.buf[i++]; ln.buf[pos++] = blk.buf[i++]; } if (pos >= (int)ln.sz) ! if (! resize_buf(&ln, 256)) ! goto bailout; ln.buf[pos] = '\0'; /* --- 482,495 ---- } /* Some other escape sequence, copy and continue. */ if (pos + 1 >= (int)ln.sz) ! resize_buf(&ln, 256); ln.buf[pos++] = blk.buf[i++]; ln.buf[pos++] = blk.buf[i++]; } if (pos >= (int)ln.sz) ! resize_buf(&ln, 256); ln.buf[pos] = '\0'; /* *************** *** 567,576 **** &ln.buf, &ln.sz, of, &of); } while (ROFF_RERUN == re); ! if (ROFF_IGN == re) continue; ! else if (ROFF_ERR == re) ! goto bailout; /* * If input parsers have not been allocated, do so now. --- 507,518 ---- &ln.buf, &ln.sz, of, &of); } while (ROFF_RERUN == re); ! if (ROFF_IGN == re) { continue; ! } else if (ROFF_ERR == re) { ! assert(MANDOCLEVEL_FATAL <= exit_status); ! goto cleanup; ! } /* * If input parsers have not been allocated, do so now. *************** *** 580,611 **** */ if ( ! (man || mdoc)) ! if ( ! pset(ln.buf + of, pos - of, curp, &man, &mdoc)) ! goto bailout; /* Lastly, push down into the parsers themselves. */ ! if (man && ! man_parseln(man, lnn_start, ln.buf, of)) ! goto bailout; ! if (mdoc && ! mdoc_parseln(mdoc, lnn_start, ln.buf, of)) ! goto bailout; } /* NOTE a parser may not have been assigned, yet. */ if ( ! (man || mdoc)) { fprintf(stderr, "%s: Not a manual\n", curp->file); ! goto bailout; } /* Clean up the parse routine ASTs. */ ! if (mdoc && ! mdoc_endparse(mdoc)) ! goto bailout; ! if (man && ! man_endparse(man)) ! goto bailout; ! if (roff && ! roff_endparse(roff)) ! goto bailout; /* If unset, allocate output dev now (if applicable). */ --- 522,571 ---- */ if ( ! (man || mdoc)) ! pset(ln.buf + of, pos - of, curp, &man, &mdoc); /* Lastly, push down into the parsers themselves. */ ! if (man && ! man_parseln(man, lnn_start, ln.buf, of)) { ! assert(MANDOCLEVEL_FATAL <= exit_status); ! goto cleanup; ! } ! if (mdoc && ! mdoc_parseln(mdoc, lnn_start, ln.buf, of)) { ! assert(MANDOCLEVEL_FATAL <= exit_status); ! goto cleanup; ! } } + /* + * With -Wstop and warnings or errors of at least + * the requested level, do not produce output. + */ + + if (MANDOCLEVEL_OK != exit_status && curp->wstop) + goto cleanup; + /* NOTE a parser may not have been assigned, yet. */ if ( ! (man || mdoc)) { fprintf(stderr, "%s: Not a manual\n", curp->file); ! exit_status = MANDOCLEVEL_FATAL; ! goto cleanup; } /* Clean up the parse routine ASTs. */ ! if (mdoc && ! mdoc_endparse(mdoc)) { ! assert(MANDOCLEVEL_FATAL <= exit_status); ! goto cleanup; ! } ! if (man && ! man_endparse(man)) { ! assert(MANDOCLEVEL_FATAL <= exit_status); ! goto cleanup; ! } ! if (roff && ! roff_endparse(roff)) { ! assert(MANDOCLEVEL_FATAL <= exit_status); ! goto cleanup; ! } /* If unset, allocate output dev now (if applicable). */ *************** *** 681,694 **** free(blk.buf); return; - - bailout: - with_fatal = 1; - goto cleanup; } ! static int pset(const char *buf, int pos, struct curparse *curp, struct man **man, struct mdoc **mdoc) { --- 641,650 ---- free(blk.buf); return; } ! static void pset(const char *buf, int pos, struct curparse *curp, struct man **man, struct mdoc **mdoc) { *************** *** 706,745 **** for (i = 1; buf[i]; i++) if (' ' != buf[i] && '\t' != buf[i]) break; ! if (0 == buf[i]) ! return(1); } switch (curp->inttype) { case (INTT_MDOC): if (NULL == curp->mdoc) ! curp->mdoc = mdoc_init(curp); ! if (NULL == (*mdoc = curp->mdoc)) ! return(0); ! return(1); case (INTT_MAN): if (NULL == curp->man) ! curp->man = man_init(curp); ! if (NULL == (*man = curp->man)) ! return(0); ! return(1); default: break; } if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) { if (NULL == curp->mdoc) ! curp->mdoc = mdoc_init(curp); ! if (NULL == (*mdoc = curp->mdoc)) ! return(0); ! return(1); } if (NULL == curp->man) ! curp->man = man_init(curp); ! if (NULL == (*man = curp->man)) ! return(0); ! return(1); } --- 662,700 ---- for (i = 1; buf[i]; i++) if (' ' != buf[i] && '\t' != buf[i]) break; ! if ('\0' == buf[i]) ! return; } switch (curp->inttype) { case (INTT_MDOC): if (NULL == curp->mdoc) ! curp->mdoc = mdoc_alloc(&curp->regs, curp, mmsg); ! assert(curp->mdoc); ! *mdoc = curp->mdoc; ! return; case (INTT_MAN): if (NULL == curp->man) ! curp->man = man_alloc(&curp->regs, curp, mmsg); ! assert(curp->man); ! *man = curp->man; ! return; default: break; } if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) { if (NULL == curp->mdoc) ! curp->mdoc = mdoc_alloc(&curp->regs, curp, mmsg); ! assert(curp->mdoc); ! *mdoc = curp->mdoc; ! return; } if (NULL == curp->man) ! curp->man = man_alloc(&curp->regs, curp, mmsg); ! assert(curp->man); ! *man = curp->man; } *************** *** 770,777 **** curp->outtype = OUTT_ASCII; else if (0 == strcmp(arg, "lint")) { curp->outtype = OUTT_LINT; ! curp->wflags |= WARN_WALL; ! curp->fflags |= FL_STRICT; } else if (0 == strcmp(arg, "tree")) curp->outtype = OUTT_TREE; --- 725,731 ---- curp->outtype = OUTT_ASCII; else if (0 == strcmp(arg, "lint")) { curp->outtype = OUTT_LINT; ! curp->wlevel = MANDOCLEVEL_WARNING; } else if (0 == strcmp(arg, "tree")) curp->outtype = OUTT_TREE; *************** *** 793,834 **** static int ! foptions(int *fflags, char *arg) { char *v, *o; ! const char *toks[8]; ! toks[0] = "ign-scope"; ! toks[1] = "no-ign-escape"; ! toks[2] = "no-ign-macro"; ! toks[3] = "ign-errors"; ! toks[4] = "strict"; ! toks[5] = "ign-escape"; ! toks[6] = NULL; while (*arg) { o = arg; switch (getsubopt(&arg, UNCONST(toks), &v)) { case (0): ! *fflags |= FL_IGN_SCOPE; break; case (1): ! *fflags |= FL_NIGN_ESCAPE; ! break; case (2): ! *fflags |= FL_NIGN_MACRO; break; case (3): ! *fflags |= FL_IGN_ERRORS; break; case (4): ! *fflags |= FL_STRICT; break; - case (5): - *fflags &= ~FL_NIGN_ESCAPE; - break; default: ! fprintf(stderr, "%s: Bad argument\n", o); return(0); } } --- 747,783 ---- static int ! woptions(struct curparse *curp, char *arg) { char *v, *o; ! const char *toks[6]; ! toks[0] = "stop"; ! toks[1] = "all"; ! toks[2] = "warning"; ! toks[3] = "error"; ! toks[4] = "fatal"; ! toks[5] = NULL; while (*arg) { o = arg; switch (getsubopt(&arg, UNCONST(toks), &v)) { case (0): ! curp->wstop = 1; break; case (1): ! /* FALLTHROUGH */ case (2): ! curp->wlevel = MANDOCLEVEL_WARNING; break; case (3): ! curp->wlevel = MANDOCLEVEL_ERROR; break; case (4): ! curp->wlevel = MANDOCLEVEL_FATAL; break; default: ! fprintf(stderr, "-W%s: Bad argument\n", o); return(0); } } *************** *** 838,906 **** static int - woptions(int *wflags, char *arg) - { - char *v, *o; - const char *toks[3]; - - toks[0] = "all"; - toks[1] = "error"; - toks[2] = NULL; - - while (*arg) { - o = arg; - switch (getsubopt(&arg, UNCONST(toks), &v)) { - case (0): - *wflags |= WARN_WALL; - break; - case (1): - *wflags |= WARN_WERR; - break; - default: - fprintf(stderr, "%s: Bad argument\n", o); - return(0); - } - } - - return(1); - } - - - static int mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg) { struct curparse *cp; ! const char *level; ! int rc; cp = (struct curparse *)arg; ! level = NULL; ! rc = 1; ! if (t >= MANDOCERR_FATAL) { ! with_fatal = 1; ! level = "FATAL"; ! rc = 0; ! } else { ! if ( ! (WARN_WALL & cp->wflags)) ! return(1); ! if (t >= MANDOCERR_ERROR) { ! with_error = 1; ! level = "ERROR"; ! } ! if (WARN_WERR & cp->wflags) { ! with_fatal = 1; ! rc = 0; ! } ! } ! ! fprintf(stderr, "%s:%d:%d:", cp->file, ln, col + 1); ! if (level) ! fprintf(stderr, " %s:", level); ! fprintf(stderr, " %s", mandocerrs[t]); if (msg) fprintf(stderr, ": %s", msg); fputc('\n', stderr); ! return(rc); } --- 787,813 ---- static int mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg) { struct curparse *cp; ! enum mandoclevel level; + level = MANDOCLEVEL_FATAL; + while (t < mandoclimits[level]) + level--; + cp = (struct curparse *)arg; ! if (level < cp->wlevel) ! return(1); ! fprintf(stderr, "%s:%d:%d: %s: %s", ! cp->file, ln, col + 1, mandoclevels[level], mandocerrs[t]); if (msg) fprintf(stderr, ": %s", msg); fputc('\n', stderr); ! if (exit_status < level) ! exit_status = level; ! ! return(level < MANDOCLEVEL_FATAL); }