]> git.cameronkatri.com Git - mandoc.git/blobdiff - read.c
Added `Er' in ERRORS scan to makewhatis.
[mandoc.git] / read.c
diff --git a/read.c b/read.c
index ede66023dcad40c6f157408cb384331b77e4a57a..da273ae183c98ec18a09301e9cefd9b3f1fb26a8 100644 (file)
--- a/read.c
+++ b/read.c
@@ -1,4 +1,4 @@
-/*     $Id: read.c,v 1.2 2011/03/20 11:43:06 kristaps Exp $ */
+/*     $Id: read.c,v 1.15 2011/05/26 20:36:21 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
  * 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/mman.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_MMAP
+# include <sys/stat.h>
+# include <sys/mman.h>
+#endif
 
 #include <assert.h>
 #include <ctype.h>
 #include <fcntl.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "mandoc.h"
+#include "libmandoc.h"
 #include "mdoc.h"
 #include "man.h"
-#include "roff.h"
 
 #ifndef MAP_FILE
 #define        MAP_FILE        0
@@ -44,6 +51,7 @@ struct        buf {
 
 struct mparse {
        enum mandoclevel  file_status; /* status of current parse */
+       enum mandoclevel  wlevel; /* ignore messages below this */
        int               line; /* line number in the file */
        enum mparset      inttype; /* which parser to use */
        struct man       *pman; /* persistent man parser */
@@ -55,9 +63,7 @@ struct        mparse {
        int               reparse_count; /* finite interp. stack */
        mandocmsg         mmsg; /* warning/error message handler */
        void             *arg; /* argument to mmsg */
-       mevt_open         evt_open; /* file-open event */
-       mevt_close        evt_close; /* file-close event */
-       const char       *svfile; 
+       const char       *file; 
 };
 
 static void      resize_buf(struct buf *, size_t);
@@ -68,6 +74,134 @@ static      void      pdesc(struct mparse *, const char *, int);
 static int       read_whole_file(const char *, int, struct buf *, int *);
 static void      mparse_end(struct mparse *);
 
+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",
+
+       "generic warning",
+
+       /* related to the prologue */
+       "no title in document",
+       "document title should be all caps",
+       "unknown manual section",
+       "date missing, using today's date",
+       "cannot parse date, using it verbatim",
+       "prologue macros out of order",
+       "duplicate prologue macro",
+       "macro not allowed in prologue",
+       "macro not allowed in body",
+
+       /* related to document structure */
+       ".so is fragile, better use ln(1)",
+       "NAME section must come first",
+       "bad NAME section contents",
+       "manual name not yet set",
+       "sections out of conventional order",
+       "duplicate section name",
+       "section not in conventional manual section",
+
+       /* related to macros and nesting */
+       "skipping obsolete macro",
+       "skipping paragraph macro",
+       "skipping no-space macro",
+       "blocks badly nested",
+       "child violates parent syntax",
+       "nested displays are not portable",
+       "already in literal mode",
+       "line scope broken",
+
+       /* related to missing macro arguments */
+       "skipping empty macro",
+       "argument count wrong",
+       "missing display type",
+       "list type must come first",
+       "tag lists require a width argument",
+       "missing font type",
+       "skipping end of block that is not open",
+
+       /* related to bad macro arguments */
+       "skipping argument",
+       "duplicate argument",
+       "duplicate display type",
+       "duplicate list type",
+       "unknown AT&T UNIX version",
+       "bad Boolean value",
+       "unknown font",
+       "unknown standard specifier",
+       "bad width argument",
+
+       /* related to plain text */
+       "blank line in non-literal context",
+       "tab in non-literal context",
+       "end of line whitespace",
+       "bad comment style",
+       "bad escape sequence",
+       "unterminated quoted string",
+       
+       "generic error",
+
+       /* related to tables */
+       "bad table syntax",
+       "bad table option",
+       "bad table layout",
+       "no table layout cells specified",
+       "no table data cells specified",
+       "ignore data in cell",
+       "data block still open",
+       "ignoring extra data cells",
+
+       "input stack limit exceeded, infinite loop?",
+       "skipping bad character",
+       "escaped character not allowed in a name",
+       "skipping text before the first section header",
+       "skipping unknown macro",
+       "NOT IMPLEMENTED, please use groff: skipping request",
+       "argument count wrong",
+       "skipping end of block that is not open",
+       "missing end of block",
+       "scope open on exit",
+       "uname(3) system call failed",
+       "macro requires line argument(s)",
+       "macro requires body argument(s)",
+       "macro requires argument(s)",
+       "missing list type",
+       "line argument(s) will be lost",
+       "body argument(s) will be lost",
+
+       "generic fatal error",
+
+       "not a manual",
+       "column syntax is inconsistent",
+       "NOT IMPLEMENTED: .Bd -file",
+       "line scope broken, syntax violated",
+       "argument count wrong, violates syntax",
+       "child violates parent syntax",
+       "argument count wrong, violates syntax",
+       "NOT IMPLEMENTED: .so with absolute path or \"..\"",
+       "no document body",
+       "no document prologue",
+       "static buffer exhausted",
+};
+
+static const char * const      mandoclevels[MANDOCLEVEL_MAX] = {
+       "SUCCESS",
+       "RESERVED",
+       "WARNING",
+       "ERROR",
+       "FATAL",
+       "BADARG",
+       "SYSERR"
+};
+
 static void
 resize_buf(struct buf *buf, size_t initial)
 {
@@ -103,15 +237,13 @@ pset(const char *buf, int pos, struct mparse *curp)
        switch (curp->inttype) {
        case (MPARSE_MDOC):
                if (NULL == curp->pmdoc) 
-                       curp->pmdoc = mdoc_alloc
-                               (&curp->regs, curp->arg, curp->mmsg);
+                       curp->pmdoc = mdoc_alloc(&curp->regs, curp);
                assert(curp->pmdoc);
                curp->mdoc = curp->pmdoc;
                return;
        case (MPARSE_MAN):
                if (NULL == curp->pman) 
-                       curp->pman = man_alloc
-                               (&curp->regs, curp->arg, curp->mmsg);
+                       curp->pman = man_alloc(&curp->regs, curp);
                assert(curp->pman);
                curp->man = curp->pman;
                return;
@@ -121,16 +253,14 @@ pset(const char *buf, int pos, struct mparse *curp)
 
        if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3))  {
                if (NULL == curp->pmdoc) 
-                       curp->pmdoc = mdoc_alloc
-                               (&curp->regs, curp->arg, curp->mmsg);
+                       curp->pmdoc = mdoc_alloc(&curp->regs, curp);
                assert(curp->pmdoc);
                curp->mdoc = curp->pmdoc;
                return;
        } 
 
        if (NULL == curp->pman) 
-               curp->pman = man_alloc
-                       (&curp->regs, curp->arg, curp->mmsg);
+               curp->pman = man_alloc(&curp->regs, curp);
        assert(curp->pman);
        curp->man = curp->pman;
 }
@@ -195,7 +325,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
 
                        if ( ! (isascii(c) && 
                                        (isgraph(c) || isblank(c)))) {
-                               curp->mmsg(MANDOCERR_BADCHAR, curp->arg, 
+                               mandoc_msg(MANDOCERR_BADCHAR, curp,
                                                curp->line, pos, "ignoring byte");
                                i++;
                                continue;
@@ -226,7 +356,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
                                continue;
                        }
 
-                       if ('"' == blk.buf[i + 1]) {
+                       if ('"' == blk.buf[i + 1] || '#' == blk.buf[i + 1]) {
                                i += 2;
                                /* Comment, skip to end of line */
                                for (; i < (int)blk.sz; ++i) {
@@ -282,7 +412,7 @@ rerun:
                        if (REPARSE_LIMIT >= ++curp->reparse_count)
                                mparse_buf_r(curp, ln, 0);
                        else
-                               curp->mmsg(MANDOCERR_ROFFLOOP, curp->arg, 
+                               mandoc_msg(MANDOCERR_ROFFLOOP, curp,
                                        curp->line, pos, NULL);
                        pos = 0;
                        continue;
@@ -317,7 +447,7 @@ rerun:
 
                /*
                 * If input parsers have not been allocated, do so now.
-                * We keep these instanced betwen parsers, but set them
+                * We keep these instanced between parsers, but set them
                 * locally per parse routine since we can use different
                 * parsers with each one.
                 */
@@ -401,19 +531,22 @@ pdesc(struct mparse *curp, const char *file, int fd)
 
        mparse_buf_r(curp, blk, 1);
 
+#ifdef HAVE_MMAP
        if (with_mmap)
                munmap(blk.buf, blk.sz);
        else
+#endif
                free(blk.buf);
 }
 
 static int
 read_whole_file(const char *file, int fd, struct buf *fb, int *with_mmap)
 {
-       struct stat      st;
        size_t           off;
        ssize_t          ssz;
 
+#ifdef HAVE_MMAP
+       struct stat      st;
        if (-1 == fstat(fd, &st)) {
                perror(file);
                return(0);
@@ -438,6 +571,7 @@ read_whole_file(const char *file, int fd, struct buf *fb, int *with_mmap)
                if (fb->buf != MAP_FAILED)
                        return(1);
        }
+#endif
 
        /*
         * If this isn't a regular file (like, say, stdin), then we must
@@ -490,16 +624,11 @@ mparse_end(struct mparse *curp)
                return;
        }
 
-#if 0
-       /* NOTE a parser may not have been assigned, yet. */
-
        if ( ! (curp->man || curp->mdoc)) {
-               /* FIXME: make into an mandoc.h error. */
-               fprintf(stderr, "%s: Not a manual\n", curp->file);
+               mandoc_msg(MANDOCERR_NOTMANUAL, curp, 1, 0, NULL);
                curp->file_status = MANDOCLEVEL_FATAL;
-               goto cleanup;
+               return;
        }
-#endif
 
        roff_endparse(curp->roff);
 }
@@ -509,11 +638,6 @@ mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
 {
        const char      *svfile;
 
-       if ( ! (*curp->evt_open)(curp->arg, file)) {
-               curp->file_status = MANDOCLEVEL_SYSERR;
-               return;
-       }
-
        if (-1 == fd)
                if (-1 == (fd = open(file, O_RDONLY, 0))) {
                        perror(file);
@@ -521,8 +645,8 @@ mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
                        return;
                }
 
-       svfile = curp->svfile;
-       curp->svfile = file;
+       svfile = curp->file;
+       curp->file = file;
 
        pdesc(curp, file, fd);
 
@@ -532,8 +656,7 @@ mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
        if (STDIN_FILENO != fd && -1 == close(fd))
                perror(file);
 
-       (*curp->evt_close)(curp->arg, svfile);
-       curp->svfile = svfile;
+       curp->file = svfile;
 }
 
 enum mandoclevel
@@ -544,29 +667,21 @@ mparse_readfd(struct mparse *curp, int fd, const char *file)
        return(curp->file_status);
 }
 
-void
-mparse_setstatus(struct mparse *curp, enum mandoclevel lvl)
-{
-
-       if (curp->file_status < lvl)
-               curp->file_status = lvl;
-}
-
 struct mparse *
-mparse_alloc(enum mparset inttype, mevt_open eopen, 
-               mevt_close eclose, mandocmsg mmsg, void *arg)
+mparse_alloc(enum mparset inttype, enum mandoclevel wlevel, mandocmsg mmsg, void *arg)
 {
        struct mparse   *curp;
 
+       assert(wlevel <= MANDOCLEVEL_FATAL);
+
        curp = mandoc_calloc(1, sizeof(struct mparse));
 
+       curp->wlevel = wlevel;
        curp->mmsg = mmsg;
        curp->arg = arg;
        curp->inttype = inttype;
-       curp->evt_open = eopen;
-       curp->evt_close = eclose;
 
-       curp->roff = roff_alloc(&curp->regs, arg, mmsg);
+       curp->roff = roff_alloc(&curp->regs, curp);
        return(curp);
 }
 
@@ -606,6 +721,55 @@ void
 mparse_result(struct mparse *curp, struct mdoc **mdoc, struct man **man)
 {
 
-       *mdoc = curp->mdoc;
-       *man = curp->man;
+       if (mdoc)
+               *mdoc = curp->mdoc;
+       if (man)
+               *man = curp->man;
+}
+
+void
+mandoc_vmsg(enum mandocerr t, struct mparse *m,
+               int ln, int pos, const char *fmt, ...)
+{
+       char             buf[256];
+       va_list          ap;
+
+       va_start(ap, fmt);
+       vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
+       va_end(ap);
+
+       mandoc_msg(t, m, ln, pos, buf);
+}
+
+void
+mandoc_msg(enum mandocerr er, struct mparse *m, 
+               int ln, int col, const char *msg)
+{
+       enum mandoclevel level;
+
+       level = MANDOCLEVEL_FATAL;
+       while (er < mandoclimits[level])
+               level--;
+
+       if (level < m->wlevel)
+               return;
+
+       if (m->mmsg)
+               (*m->mmsg)(er, level, m->file, ln, col, msg);
+
+       if (m->file_status < level)
+               m->file_status = level;
+}
+
+const char *
+mparse_strerror(enum mandocerr er)
+{
+
+       return(mandocerrs[er]);
+}
+
+const char *
+mparse_strlevel(enum mandoclevel lvl)
+{
+       return(mandoclevels[lvl]);
 }