=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/mandoc/main.c,v retrieving revision 1.26 retrieving revision 1.27 diff -c -r1.26 -r1.27 *** src/usr.bin/mandoc/main.c 2010/05/15 15:58:56 1.26 --- src/usr.bin/mandoc/main.c 2010/05/15 17:32:25 1.27 *************** *** 1,4 **** ! /* $Id: main.c,v 1.26 2010/05/15 15:58:56 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons * --- 1,4 ---- ! /* $Id: main.c,v 1.27 2010/05/15 17:32:25 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons * *************** *** 14,19 **** --- 14,21 ---- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + #include + #include #include #include *************** *** 64,74 **** #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. */ enum intt inttype; /* Input parsers... */ struct man *man; - struct man *lastman; struct mdoc *mdoc; - struct mdoc *lastmdoc; enum outt outtype; /* Output devices... */ out_mdoc outmdoc; out_man outman; --- 66,76 ---- #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 enum intt inttype; /* Input parsers... */ struct man *man; struct mdoc *mdoc; enum outt outtype; /* Output devices... */ out_mdoc outmdoc; out_man outman; *************** *** 77,110 **** char outopts[BUFSIZ]; }; ! #define FL_STRICT FL_NIGN_ESCAPE | \ ! FL_NIGN_MACRO ! static int foptions(int *, char *); ! static int toptions(struct curparse *, 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, const char *); - static int ffile(struct buf *, struct buf *, - const char *, struct curparse *); - static int fdesc(struct buf *, struct buf *, - struct curparse *); static int pset(const char *, int, struct curparse *, struct man **, struct mdoc **); ! static struct man *man_init(struct curparse *); ! static struct mdoc *mdoc_init(struct curparse *); ! static void version(void) __attribute__((noreturn)); static void usage(void) __attribute__((noreturn)); static const char *progname; - int main(int argc, char *argv[]) { ! int c, rc; ! struct buf ln, blk; struct curparse curp; progname = strrchr(argv[0], '/'); --- 79,107 ---- char outopts[BUFSIZ]; }; ! 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 int merr(void *, int, int, const char *); + static int moptions(enum intt *, char *); static int mwarn(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_error; + static int with_warning; int main(int argc, char *argv[]) { ! int c; struct curparse curp; progname = strrchr(argv[0], '/'); *************** *** 152,203 **** argc -= optind; argv += optind; - memset(&ln, 0, sizeof(struct buf)); - memset(&blk, 0, sizeof(struct buf)); - - rc = 1; - if (NULL == *argv) { curp.file = ""; curp.fd = STDIN_FILENO; ! c = fdesc(&blk, &ln, &curp); ! if ( ! (FL_IGN_ERRORS & curp.fflags)) ! rc = 1 == c ? 1 : 0; ! else ! rc = -1 == c ? 0 : 1; } ! while (rc && *argv) { ! c = ffile(&blk, &ln, *argv, &curp); ! if ( ! (FL_IGN_ERRORS & curp.fflags)) ! rc = 1 == c ? 1 : 0; ! else ! rc = -1 == c ? 0 : 1; ! argv++; ! if (*argv && rc) { ! if (curp.lastman) ! man_reset(curp.lastman); ! if (curp.lastmdoc) ! mdoc_reset(curp.lastmdoc); ! curp.lastman = NULL; ! curp.lastmdoc = NULL; ! } } - if (blk.buf) - free(blk.buf); - if (ln.buf) - free(ln.buf); if (curp.outfree) (*curp.outfree)(curp.outdata); - if (curp.mdoc) - mdoc_free(curp.mdoc); - if (curp.man) - man_free(curp.man); ! return(rc ? EXIT_SUCCESS : EXIT_FAILURE); } --- 149,174 ---- argc -= optind; argv += optind; if (NULL == *argv) { curp.file = ""; curp.fd = STDIN_FILENO; ! fdesc(&curp); } ! while (*argv) { ! ffile(*argv, &curp); ! if (with_error && !(curp.fflags & FL_IGN_ERRORS)) ! break; ! ++argv; } if (curp.outfree) (*curp.outfree)(curp.outdata); ! return((with_warning || with_error) ? ! EXIT_FAILURE : EXIT_SUCCESS); } *************** *** 267,306 **** } ! static int ! ffile(struct buf *blk, struct buf *ln, ! const char *file, struct curparse *curp) { - int c; curp->file = file; if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) { perror(curp->file); ! return(-1); } ! c = fdesc(blk, ln, curp); if (-1 == close(curp->fd)) perror(curp->file); ! return(c); } static int ! fdesc(struct buf *blk, struct buf *ln, struct curparse *curp) { - size_t sz; - ssize_t ssz; struct stat st; ! int j, i, pos, lnn, comment; struct man *man; struct mdoc *mdoc; - sz = BUFSIZ; man = NULL; mdoc = NULL; /* * Two buffers: ln and buf. buf is the input buffer optimised --- 238,366 ---- } ! static void ! ffile(const char *file, struct curparse *curp) { curp->file = file; if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) { perror(curp->file); ! with_error = 1; ! return; } ! fdesc(curp); if (-1 == close(curp->fd)) perror(curp->file); + } ! ! 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); } static int ! read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap) { struct stat st; ! size_t off; ! ssize_t ssz; ! ! if (-1 == fstat(curp->fd, &st)) { ! perror(curp->file); ! with_error = 1; ! return(0); ! } ! ! /* ! * If we're a regular file, try just reading in the whole entry ! * via mmap(). This is faster than reading it into blocks, and ! * since each file is only a few bytes to begin with, I'm not ! * concerned that this is going to tank any machines. ! */ ! ! if (S_ISREG(st.st_mode)) { ! if (st.st_size >= (1U << 31)) { ! fprintf(stderr, "%s: input too large\n", ! curp->file); ! with_error = 1; ! return(0); ! } ! *with_mmap = 1; ! fb->sz = st.st_size; ! fb->buf = mmap(NULL, fb->sz, PROT_READ, ! MAP_FILE, curp->fd, 0); ! if (fb->buf != MAP_FAILED) ! return(1); ! } ! ! /* ! * If this isn't a regular file (like, say, stdin), then we must ! * go the old way and just read things in bit by bit. ! */ ! ! *with_mmap = 0; ! off = 0; ! fb->sz = 0; ! fb->buf = NULL; ! for (;;) { ! if (off == fb->sz) { ! if (fb->sz == (1U << 31)) { ! fprintf(stderr, "%s: input too large\n", ! curp->file); ! break; ! } ! if (! resize_buf(fb, 65536)) ! break; ! } ! ssz = read(curp->fd, fb->buf + off, fb->sz - off); ! if (ssz == 0) { ! fb->sz = off; ! return(1); ! } ! if (ssz == -1) { ! perror(curp->file); ! break; ! } ! off += ssz; ! } ! ! free(fb->buf); ! fb->buf = NULL; ! with_error = 1; ! return(0); ! } ! ! ! static void ! fdesc(struct curparse *curp) ! { ! struct buf ln, blk; ! int j, i, pos, lnn, comment, with_mmap; struct man *man; struct mdoc *mdoc; man = NULL; mdoc = NULL; + memset(&ln, 0, sizeof(struct buf)); /* * Two buffers: ln and buf. buf is the input buffer optimised *************** *** 308,421 **** * growable, hence passed in by ptr-ptr. */ ! if (-1 == fstat(curp->fd, &st)) ! perror(curp->file); ! else if ((size_t)st.st_blksize > sz) ! sz = st.st_blksize; - if (sz > blk->sz) { - blk->buf = realloc(blk->buf, sz); - if (NULL == blk->buf) { - perror(NULL); - exit(EXIT_FAILURE); - } - blk->sz = sz; - } - /* Fill buf with file blocksize. */ ! for (lnn = pos = comment = 0; ; ) { ! if (-1 == (ssz = read(curp->fd, blk->buf, sz))) { ! perror(curp->file); ! return(-1); ! } else if (0 == ssz) ! break; ! /* Parse the read block into partial or full lines. */ ! for (i = 0; i < (int)ssz; i++) { ! if (pos >= (int)ln->sz) { ! ln->sz += 256; /* Step-size. */ ! ln->buf = realloc(ln->buf, ln->sz); ! if (NULL == ln->buf) { ! perror(NULL); ! return(EXIT_FAILURE); ! } ! } ! if ('\n' != blk->buf[i]) { ! if (comment) ! continue; ! ln->buf[pos++] = blk->buf[i]; ! /* Handle in-line `\"' comments. */ ! if (1 == pos || '\"' != ln->buf[pos - 1]) ! continue; ! for (j = pos - 2; j >= 0; j--) ! if ('\\' != ln->buf[j]) ! break; ! if ( ! ((pos - 2 - j) % 2)) ! continue; ! comment = 1; ! pos -= 2; ! for (; pos > 0; --pos) { ! if (ln->buf[pos - 1] != ' ') ! break; ! if (pos > 2 && ln->buf[pos - 2] == '\\') ! break; ! } continue; - } - - /* Handle escaped `\\n' newlines. */ - - if (pos > 0 && 0 == comment && - '\\' == ln->buf[pos - 1]) { - for (j = pos - 1; j >= 0; j--) - if ('\\' != ln->buf[j]) - break; - if ( ! ((pos - j) % 2)) { - pos--; - lnn++; - continue; - } } ! ln->buf[pos] = 0; ! lnn++; ! /* If unset, assign parser in pset(). */ ! if ( ! (man || mdoc) && ! pset(ln->buf, ! pos, curp, &man, &mdoc)) ! return(-1); ! pos = comment = 0; ! /* Pass down into parsers. */ ! if (man && ! man_parseln(man, lnn, ln->buf)) ! return(0); ! if (mdoc && ! mdoc_parseln(mdoc, lnn, ln->buf)) ! return(0); ! } } /* NOTE a parser may not have been assigned, yet. */ if ( ! (man || mdoc)) { fprintf(stderr, "%s: Not a manual\n", curp->file); ! return(0); } if (mdoc && ! mdoc_endparse(mdoc)) ! return(0); if (man && ! man_endparse(man)) ! return(0); /* If unset, allocate output dev now (if applicable). */ --- 368,454 ---- * growable, hence passed in by ptr-ptr. */ ! if (!read_whole_file(curp, &blk, &with_mmap)) ! return; /* Fill buf with file blocksize. */ ! for (i = lnn = pos = comment = 0; i < (int)blk.sz; ++i) { ! if (pos >= (int)ln.sz) { ! if (! resize_buf(&ln, 256)) ! goto bailout; ! } ! if ('\n' != blk.buf[i]) { ! if (comment) ! continue; ! ln.buf[pos++] = blk.buf[i]; ! /* Handle in-line `\"' comments. */ ! if (1 == pos || '\"' != ln.buf[pos - 1]) ! continue; ! for (j = pos - 2; j >= 0; j--) ! if ('\\' != ln.buf[j]) ! break; ! if ( ! ((pos - 2 - j) % 2)) ! continue; ! comment = 1; ! pos -= 2; ! for (; pos > 0; --pos) { ! if (ln.buf[pos - 1] != ' ') ! break; ! if (pos > 2 && ln.buf[pos - 2] == '\\') ! break; ! } ! continue; ! } ! /* Handle escaped `\\n' newlines. */ ! if (pos > 0 && 0 == comment && '\\' == ln.buf[pos - 1]) { ! for (j = pos - 1; j >= 0; j--) ! if ('\\' != ln.buf[j]) ! break; ! if ( ! ((pos - j) % 2)) { ! pos--; ! lnn++; continue; } + } ! ln.buf[pos] = 0; ! lnn++; ! /* If unset, assign parser in pset(). */ ! if ( ! (man || mdoc) && ! pset(ln.buf, pos, curp, &man, &mdoc)) ! goto bailout; ! pos = comment = 0; ! /* Pass down into parsers. */ ! if (man && ! man_parseln(man, lnn, ln.buf)) ! goto bailout; ! if (mdoc && ! mdoc_parseln(mdoc, lnn, ln.buf)) ! 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; } if (mdoc && ! mdoc_endparse(mdoc)) ! goto bailout; if (man && ! man_endparse(man)) ! goto bailout; /* If unset, allocate output dev now (if applicable). */ *************** *** 455,461 **** if (mdoc && curp->outmdoc) (*curp->outmdoc)(curp->outdata, mdoc); ! return(1); } --- 488,513 ---- if (mdoc && curp->outmdoc) (*curp->outmdoc)(curp->outdata, mdoc); ! cleanup: ! if (curp->mdoc) { ! mdoc_free(curp->mdoc); ! curp->mdoc = NULL; ! } ! if (curp->man) { ! man_free(curp->man); ! curp->man = NULL; ! } ! if (ln.buf) ! free(ln.buf); ! if (with_mmap) ! munmap(blk.buf, blk.sz); ! else ! free(blk.buf); ! return; ! ! bailout: ! with_error = 1; ! goto cleanup; } *************** *** 487,500 **** curp->mdoc = mdoc_init(curp); if (NULL == (*mdoc = curp->mdoc)) return(0); - curp->lastmdoc = *mdoc; return(1); case (INTT_MAN): if (NULL == curp->man) curp->man = man_init(curp); if (NULL == (*man = curp->man)) return(0); - curp->lastman = *man; return(1); default: break; --- 539,550 ---- *************** *** 505,511 **** curp->mdoc = mdoc_init(curp); if (NULL == (*mdoc = curp->mdoc)) return(0); - curp->lastmdoc = *mdoc; return(1); } --- 555,560 ---- *************** *** 513,519 **** curp->man = man_init(curp); if (NULL == (*man = curp->man)) return(0); - curp->lastman = *man; return(1); } --- 562,567 ---- *************** *** 648,653 **** --- 696,703 ---- (void)fprintf(stderr, "%s:%d:%d: error: %s\n", curp->file, line, col + 1, msg); + with_error = 1; + return(0); } *************** *** 665,673 **** (void)fprintf(stderr, "%s:%d:%d: warning: %s\n", curp->file, line, col + 1, msg); ! if ( ! (curp->wflags & WARN_WERR)) ! return(1); ! ! return(0); } --- 715,726 ---- (void)fprintf(stderr, "%s:%d:%d: warning: %s\n", curp->file, line, col + 1, msg); ! with_warning = 1; ! if (curp->wflags & WARN_WERR) { ! with_error = 1; ! return(0); ! } ! ! return(1); }