]> git.cameronkatri.com Git - mandoc.git/blobdiff - read.c
The groff man-ext macros define fonts CB, CI, and CR,
[mandoc.git] / read.c
diff --git a/read.c b/read.c
index 5e030f652ac8b1c2572be5ed14b130590a01e59f..0a583445f2cd8a93e04608fcef99f06cd92556d3 100644 (file)
--- a/read.c
+++ b/read.c
@@ -1,7 +1,7 @@
-/*     $Id: read.c,v 1.177 2017/06/17 22:43:14 schwarze Exp $ */
+/*     $Id: read.c,v 1.196 2018/07/28 18:34:15 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2018 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2010, 2012 Joerg Sonnenberger <joerg@netbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -24,9 +24,6 @@
 
 #include <assert.h>
 #include <ctype.h>
-#if HAVE_ERR
-#include <err.h>
-#endif
 #include <errno.h>
 #include <fcntl.h>
 #include <stdarg.h>
@@ -42,7 +39,6 @@
 #include "mdoc.h"
 #include "man.h"
 #include "libmandoc.h"
-#include "roff_int.h"
 
 #define        REPARSE_LIMIT   1000
 
@@ -53,10 +49,10 @@ struct      mparse {
        const char       *file; /* filename of current input file */
        struct buf       *primary; /* buffer currently being parsed */
        struct buf       *secondary; /* preprocessed copy of input */
-       const char       *defos; /* default operating system */
+       const char       *os_s; /* default operating system */
        mandocmsg         mmsg; /* warning/error message handler */
        enum mandoclevel  file_status; /* status of current parse */
-       enum mandoclevel  wlevel; /* ignore messages below this */
+       enum mandocerr    mmin; /* ignore messages below this */
        int               options; /* parser options */
        int               gzip; /* current input file is gzipped */
        int               filenc; /* encoding of the current file */
@@ -75,7 +71,7 @@ static        void      mparse_parse_buffer(struct mparse *, struct buf,
 
 static const enum mandocerr    mandoclimits[MANDOCLEVEL_MAX] = {
        MANDOCERR_OK,
-       MANDOCERR_STYLE,
+       MANDOCERR_OK,
        MANDOCERR_WARNING,
        MANDOCERR_ERROR,
        MANDOCERR_UNSUPP,
@@ -86,34 +82,48 @@ static      const enum mandocerr    mandoclimits[MANDOCLEVEL_MAX] = {
 static const char * const      mandocerrs[MANDOCERR_MAX] = {
        "ok",
 
-       "generic style suggestion",
+       "base system convention",
 
        "Mdocdate found",
        "Mdocdate missing",
-       "legacy man(7) date format",
+       "unknown architecture",
+       "operating system explicitly specified",
        "RCS id missing",
+       "referenced manual not found",
+
+       "generic style suggestion",
+
+       "legacy man(7) date format",
+       "normalizing date format to",
+       "lower case character in document title",
+       "duplicate RCS id",
+       "possible typo in section name",
+       "unterminated quoted argument",
        "useless macro",
        "consider using OS macro",
        "errnos out of order",
        "duplicate errno",
-       "description line ends with a full stop",
+       "trailing delimiter",
        "no blank before trailing delimiter",
+       "fill mode already enabled, skipping",
+       "fill mode already disabled, skipping",
+       "verbatim \"--\", maybe consider using \\(em",
        "function name without markup",
+       "whitespace at end of input line",
+       "bad comment style",
 
        "generic warning",
 
        /* related to the prologue */
        "missing manual title, using UNTITLED",
        "missing manual title, using \"\"",
-       "lower case character in document title",
        "missing manual section, using \"\"",
        "unknown manual section",
        "missing date, using today's date",
        "cannot parse date, using it verbatim",
+       "date in the future, using it anyway",
        "missing Os macro, using \"\"",
-       "duplicate prologue macro",
        "late prologue macro",
-       "skipping late title macro",
        "prologue macros out of order",
 
        /* related to document structure */
@@ -131,6 +141,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "sections out of conventional order",
        "duplicate section title",
        "unexpected section",
+       "cross reference to self",
        "unusual Xr order",
        "unusual Xr punctuation",
        "AUTHORS section without An macro",
@@ -144,8 +155,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "blocks badly nested",
        "nested displays are not portable",
        "moving content out of list",
-       "fill mode already enabled, skipping",
-       "fill mode already disabled, skipping",
+       "first macro on line",
        "line scope broken",
        "skipping blank line in line scope",
 
@@ -162,6 +172,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "missing function name, using \"\"",
        "empty head in list item",
        "empty list item",
+       "missing argument, using next line",
        "missing font type, using \\fR",
        "unknown font type, using \\fR",
        "nothing follows prefix",
@@ -173,7 +184,6 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "missing eqn box, using \"\"",
 
        /* related to bad macro arguments */
-       "unterminated quoted argument",
        "duplicate argument",
        "skipping duplicate argument",
        "skipping duplicate display type",
@@ -192,9 +202,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        /* related to plain text */
        "blank line in fill mode, using .sp",
        "tab in filled text",
-       "whitespace at end of input line",
        "new sentence, new line",
-       "bad comment style",
        "invalid escape sequence",
        "undefined string, using \"\"",
 
@@ -220,6 +228,8 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
 
        /* related to document structure and macros */
        NULL,
+       "duplicate prologue macro",
+       "skipping late title macro",
        "input stack limit exceeded, infinite loop?",
        "skipping bad character",
        "skipping unknown macro",
@@ -331,7 +341,6 @@ choose_parser(struct mparse *curp)
 static int
 mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
 {
-       const struct tbl_span   *span;
        struct buf       ln;
        const char      *save_file;
        char            *cp;
@@ -522,21 +531,7 @@ rerun:
                if (curp->man->macroset == MACROSET_NONE)
                        choose_parser(curp);
 
-               /*
-                * Lastly, push down into the parsers themselves.
-                * If libroff returns ROFF_TBL, then add it to the
-                * currently open parse.  Since we only get here if
-                * there does exist data (see tbl_data.c), we're
-                * guaranteed that something's been allocated.
-                * Do the same for ROFF_EQN.
-                */
-
-               if (rr == ROFF_TBL)
-                       while ((span = roff_span(curp->roff)) != NULL)
-                               roff_addtbl(curp->man, span);
-               else if (rr == ROFF_EQN)
-                       roff_addeqn(curp->man, roff_eqn(curp->roff));
-               else if ((curp->man->macroset == MACROSET_MDOC ?
+               if ((curp->man->macroset == MACROSET_MDOC ?
                    mdoc_parseln(curp->man, curp->line, ln.buf, of) :
                    man_parseln(curp->man, curp->line, ln.buf, of)) == 2)
                                break;
@@ -563,9 +558,13 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
        gzFile           gz;
        size_t           off;
        ssize_t          ssz;
+       int              gzerrnum, retval;
 
-       if (fstat(fd, &st) == -1)
-               err((int)MANDOCLEVEL_SYSERR, "%s", file);
+       if (fstat(fd, &st) == -1) {
+               mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
+                   "fstat: %s", strerror(errno));
+               return 0;
+       }
 
        /*
         * If we're a regular file, try just reading in the whole entry
@@ -587,8 +586,24 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
        }
 
        if (curp->gzip) {
-               if ((gz = gzdopen(fd, "rb")) == NULL)
-                       err((int)MANDOCLEVEL_SYSERR, "%s", file);
+               /*
+                * Duplicating the file descriptor is required
+                * because we will have to call gzclose(3)
+                * to free memory used internally by zlib,
+                * but that will also close the file descriptor,
+                * which this function must not do.
+                */
+               if ((fd = dup(fd)) == -1) {
+                       mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
+                           "dup: %s", strerror(errno));
+                       return 0;
+               }
+               if ((gz = gzdopen(fd, "rb")) == NULL) {
+                       mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
+                           "gzdopen: %s", strerror(errno));
+                       close(fd);
+                       return 0;
+               }
        } else
                gz = NULL;
 
@@ -599,6 +614,7 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
 
        *with_mmap = 0;
        off = 0;
+       retval = 0;
        fb->sz = 0;
        fb->buf = NULL;
        for (;;) {
@@ -615,16 +631,29 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
                    read(fd, fb->buf + (int)off, fb->sz - off);
                if (ssz == 0) {
                        fb->sz = off;
-                       return 1;
+                       retval = 1;
+                       break;
+               }
+               if (ssz == -1) {
+                       if (curp->gzip)
+                               (void)gzerror(gz, &gzerrnum);
+                       mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, "read: %s",
+                           curp->gzip && gzerrnum != Z_ERRNO ?
+                           zError(gzerrnum) : strerror(errno));
+                       break;
                }
-               if (ssz == -1)
-                       err((int)MANDOCLEVEL_SYSERR, "%s", file);
                off += (size_t)ssz;
        }
 
-       free(fb->buf);
-       fb->buf = NULL;
-       return 0;
+       if (curp->gzip && (gzerrnum = gzclose(gz)) != Z_OK)
+               mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, "gzclose: %s",
+                   gzerrnum == Z_ERRNO ? strerror(errno) :
+                   zError(gzerrnum));
+       if (retval == 0) {
+               free(fb->buf);
+               fb->buf = NULL;
+       }
+       return retval;
 }
 
 static void
@@ -754,20 +783,20 @@ mparse_open(struct mparse *curp, const char *file)
 }
 
 struct mparse *
-mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
-    const char *defos)
+mparse_alloc(int options, enum mandocerr mmin, mandocmsg mmsg,
+    enum mandoc_os os_e, const char *os_s)
 {
        struct mparse   *curp;
 
        curp = mandoc_calloc(1, sizeof(struct mparse));
 
        curp->options = options;
-       curp->wlevel = wlevel;
+       curp->mmin = mmin;
        curp->mmsg = mmsg;
-       curp->defos = defos;
+       curp->os_s = os_s;
 
        curp->roff = roff_alloc(curp, options);
-       curp->man = roff_man_alloc( curp->roff, curp, curp->defos,
+       curp->man = roff_man_alloc(curp->roff, curp, curp->os_s,
                curp->options & MPARSE_QUICK ? 1 : 0);
        if (curp->options & MPARSE_MDOC) {
                curp->man->macroset = MACROSET_MDOC;
@@ -779,6 +808,7 @@ mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
                        curp->man->manmac = roffhash_alloc(MAN_TH, MAN_MAX);
        }
        curp->man->first->tok = TOKEN_NONE;
+       curp->man->meta.os_e = os_e;
        return curp;
 }
 
@@ -854,13 +884,13 @@ mandoc_msg(enum mandocerr er, struct mparse *m,
 {
        enum mandoclevel level;
 
+       if (er < m->mmin && er != MANDOCERR_FILE)
+               return;
+
        level = MANDOCLEVEL_UNSUPP;
        while (er < mandoclimits[level])
                level--;
 
-       if (level < m->wlevel && er != MANDOCERR_FILE)
-               return;
-
        if (m->mmsg)
                (*m->mmsg)(er, level, m->file, ln, col, msg);