]> git.cameronkatri.com Git - mandoc.git/blobdiff - read.c
In the SYNOPSIS, .Nm blocks can get broken if one of their children
[mandoc.git] / read.c
diff --git a/read.c b/read.c
index fd7b5ce1b8bb0a44078828ff04ea6488805a5485..6d831c48b3921f538db45cfc58f6eb19bbae6198 100644 (file)
--- a/read.c
+++ b/read.c
@@ -1,7 +1,7 @@
-/*     $Id: read.c,v 1.141 2015/09/14 15:36:14 schwarze Exp $ */
+/*     $Id: read.c,v 1.160 2017/02/03 18:18:23 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2017 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
 #include "config.h"
 
 #include <sys/types.h>
-#if HAVE_MMAP
 #include <sys/mman.h>
 #include <sys/stat.h>
-#endif
 
 #include <assert.h>
 #include <ctype.h>
+#if HAVE_ERR
+#include <err.h>
+#endif
 #include <errno.h>
 #include <fcntl.h>
 #include <stdarg.h>
@@ -47,9 +48,8 @@
 #define        REPARSE_LIMIT   1000
 
 struct mparse {
-       struct roff_man  *man; /* man parser */
        struct roff      *roff; /* roff parser (!NULL) */
-       const struct mchars *mchars; /* character table */
+       struct roff_man  *man; /* man parser */
        char             *sodest; /* filename pointed to by .so */
        const char       *file; /* filename of current input file */
        struct buf       *primary; /* buffer currently being parsed */
@@ -108,10 +108,11 @@ static    const char * const      mandocerrs[MANDOCERR_MAX] = {
        "no document body",
        "content before first section header",
        "first section is not \"NAME\"",
-       "NAME section without name",
+       "NAME section without Nm before Nd",
        "NAME section without description",
        "description not at the end of NAME",
        "bad NAME section content",
+       "missing comma before name",
        "missing description line, using \"\"",
        "sections out of conventional order",
        "duplicate section title",
@@ -141,7 +142,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "empty argument, using 0n",
        "missing display type, using -ragged",
        "list type is not the first argument",
-       "missing -width in -tag list, using 8n",
+       "missing -width in -tag list, using 6n",
        "missing utility name, using \"\"",
        "missing function name, using \"\"",
        "empty head in list item",
@@ -150,6 +151,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "unknown font type, using \\fR",
        "nothing follows prefix",
        "empty reference block",
+       "missing section argument",
        "missing -std argument, adding it",
        "missing option string, using \"\"",
        "missing resource identifier, using \"\"",
@@ -175,6 +177,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "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 \"\"",
@@ -215,6 +218,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        /* related to request and macro arguments */
        "escaped character not allowed in a name",
        "NOT IMPLEMENTED: Bd -file",
+       "skipping display without arguments",
        "missing list type, using -item",
        "missing manual name, using \"\"",
        "uname(3) system call failed, using UNKNOWN",
@@ -288,13 +292,6 @@ choose_parser(struct mparse *curp)
                }
        }
 
-       if (curp->man == NULL) {
-               curp->man = roff_man_alloc(curp->roff, curp, curp->defos,
-                   curp->options & MPARSE_QUICK ? 1 : 0);
-               curp->man->macroset = MACROSET_MAN;
-               curp->man->first->tok = TOKEN_NONE;
-       }
-
        if (format == MPARSE_MDOC) {
                mdoc_hash_init();
                curp->man->macroset = MACROSET_MDOC;
@@ -321,6 +318,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
        const char      *save_file;
        char            *cp;
        size_t           pos; /* byte number in the ln buffer */
+       size_t           j;  /* auxiliary byte number in the blk buffer */
        enum rofferr     rr;
        int              of;
        int              lnn; /* line number in the real file */
@@ -426,14 +424,21 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
                        }
 
                        if ('"' == blk.buf[i + 1] || '#' == blk.buf[i + 1]) {
+                               j = i;
                                i += 2;
                                /* Comment, skip to end of line */
                                for (; i < blk.sz; ++i) {
-                                       if ('\n' == blk.buf[i]) {
-                                               ++i;
-                                               ++lnn;
-                                               break;
-                                       }
+                                       if (blk.buf[i] != '\n')
+                                               continue;
+                                       if (blk.buf[i - 1] == ' ' ||
+                                           blk.buf[i - 1] == '\t')
+                                               mandoc_msg(
+                                                   MANDOCERR_SPACE_EOL,
+                                                   curp, curp->line,
+                                                   pos + i-1 - j, NULL);
+                                       ++i;
+                                       ++lnn;
+                                       break;
                                }
 
                                /* Backout trailing whitespaces */
@@ -536,9 +541,9 @@ rerun:
                        if (curp->secondary)
                                curp->secondary->sz -= pos + 1;
                        save_file = curp->file;
-                       if (mparse_open(curp, &fd, ln.buf + of) ==
-                           MANDOCLEVEL_OK) {
+                       if ((fd = mparse_open(curp, ln.buf + of)) != -1) {
                                mparse_readfd(curp, fd, ln.buf + of);
+                               close(fd);
                                curp->file = save_file;
                        } else {
                                curp->file = save_file;
@@ -559,15 +564,7 @@ rerun:
                        break;
                }
 
-               /*
-                * If input parsers have not been allocated, do so now.
-                * We keep these instanced between parsers, but set them
-                * locally per parse routine since we can use different
-                * parsers with each one.
-                */
-
-               if (curp->man == NULL ||
-                   curp->man->macroset == MACROSET_NONE)
+               if (curp->man->macroset == MACROSET_NONE)
                        choose_parser(curp);
 
                /*
@@ -610,12 +607,10 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
        size_t           off;
        ssize_t          ssz;
 
-#if HAVE_MMAP
        struct stat      st;
-       if (-1 == fstat(fd, &st)) {
-               perror(file);
-               exit((int)MANDOCLEVEL_SYSERR);
-       }
+
+       if (fstat(fd, &st) == -1)
+               err((int)MANDOCLEVEL_SYSERR, "%s", file);
 
        /*
         * If we're a regular file, try just reading in the whole entry
@@ -627,21 +622,18 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
        if (curp->gzip == 0 && S_ISREG(st.st_mode)) {
                if (st.st_size > 0x7fffffff) {
                        mandoc_msg(MANDOCERR_TOOLARGE, curp, 0, 0, NULL);
-                       return(0);
+                       return 0;
                }
                *with_mmap = 1;
                fb->sz = (size_t)st.st_size;
                fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0);
                if (fb->buf != MAP_FAILED)
-                       return(1);
+                       return 1;
        }
-#endif
 
        if (curp->gzip) {
-               if ((gz = gzdopen(fd, "rb")) == NULL) {
-                       perror(file);
-                       exit((int)MANDOCLEVEL_SYSERR);
-               }
+               if ((gz = gzdopen(fd, "rb")) == NULL)
+                       err((int)MANDOCLEVEL_SYSERR, "%s", file);
        } else
                gz = NULL;
 
@@ -668,27 +660,21 @@ 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);
-               }
-               if (ssz == -1) {
-                       perror(file);
-                       exit((int)MANDOCLEVEL_SYSERR);
+                       return 1;
                }
+               if (ssz == -1)
+                       err((int)MANDOCLEVEL_SYSERR, "%s", file);
                off += (size_t)ssz;
        }
 
        free(fb->buf);
        fb->buf = NULL;
-       return(0);
+       return 0;
 }
 
 static void
 mparse_end(struct mparse *curp)
 {
-
-       if (curp->man == NULL && curp->sodest == NULL)
-               curp->man = roff_man_alloc(curp->roff, curp, curp->defos,
-                   curp->options & MPARSE_QUICK ? 1 : 0);
        if (curp->man->macroset == MACROSET_NONE)
                curp->man->macroset = MACROSET_MAN;
        if (curp->man->macroset == MACROSET_MDOC)
@@ -748,7 +734,7 @@ mparse_readmem(struct mparse *curp, void *buf, size_t len,
        blk.sz = len;
 
        mparse_parse_buffer(curp, blk, file);
-       return(curp->file_status);
+       return curp->file_status;
 }
 
 /*
@@ -768,24 +754,19 @@ mparse_readfd(struct mparse *curp, int fd, const char *file)
                    (MPARSE_UTF8 | MPARSE_LATIN1);
                mparse_parse_buffer(curp, blk, file);
                curp->filenc = save_filenc;
-#if HAVE_MMAP
                if (with_mmap)
                        munmap(blk.buf, blk.sz);
                else
-#endif
                        free(blk.buf);
        }
-
-       if (fd != STDIN_FILENO && close(fd) == -1)
-               perror(file);
-
-       return(curp->file_status);
+       return curp->file_status;
 }
 
-enum mandoclevel
-mparse_open(struct mparse *curp, int *fd, const char *file)
+int
+mparse_open(struct mparse *curp, const char *file)
 {
        char             *cp;
+       int               fd;
 
        curp->file = file;
        cp = strrchr(file, '.');
@@ -793,8 +774,8 @@ mparse_open(struct mparse *curp, int *fd, const char *file)
 
        /* First try to use the filename as it is. */
 
-       if ((*fd = open(file, O_RDONLY)) != -1)
-               return(MANDOCLEVEL_OK);
+       if ((fd = open(file, O_RDONLY)) != -1)
+               return fd;
 
        /*
         * If that doesn't work and the filename doesn't
@@ -803,23 +784,23 @@ mparse_open(struct mparse *curp, int *fd, const char *file)
 
        if ( ! curp->gzip) {
                mandoc_asprintf(&cp, "%s.gz", file);
-               *fd = open(file, O_RDONLY);
+               fd = open(cp, O_RDONLY);
                free(cp);
-               if (*fd != -1) {
+               if (fd != -1) {
                        curp->gzip = 1;
-                       return(MANDOCLEVEL_OK);
+                       return fd;
                }
        }
 
        /* Neither worked, give up. */
 
        mandoc_msg(MANDOCERR_FILE, curp, 0, 0, strerror(errno));
-       return(MANDOCLEVEL_ERROR);
+       return -1;
 }
 
 struct mparse *
 mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
-    const struct mchars *mchars, const char *defos)
+    const char *defos)
 {
        struct mparse   *curp;
 
@@ -830,8 +811,7 @@ mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
        curp->mmsg = mmsg;
        curp->defos = defos;
 
-       curp->mchars = mchars;
-       curp->roff = roff_alloc(curp, curp->mchars, options);
+       curp->roff = roff_alloc(curp, options);
        curp->man = roff_man_alloc( curp->roff, curp, curp->defos,
                curp->options & MPARSE_QUICK ? 1 : 0);
        if (curp->options & MPARSE_MDOC) {
@@ -842,24 +822,23 @@ mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
                curp->man->macroset = MACROSET_MAN;
        }
        curp->man->first->tok = TOKEN_NONE;
-       return(curp);
+       return curp;
 }
 
 void
 mparse_reset(struct mparse *curp)
 {
-
        roff_reset(curp->roff);
+       roff_man_reset(curp->man);
+
+       free(curp->sodest);
+       curp->sodest = NULL;
 
-       if (curp->man != NULL)
-               roff_man_reset(curp->man);
        if (curp->secondary)
                curp->secondary->sz = 0;
 
        curp->file_status = MANDOCLEVEL_OK;
-
-       free(curp->sodest);
-       curp->sodest = NULL;
+       curp->gzip = 0;
 }
 
 void
@@ -867,8 +846,7 @@ mparse_free(struct mparse *curp)
 {
 
        roff_man_free(curp->man);
-       if (curp->roff)
-               roff_free(curp->roff);
+       roff_free(curp->roff);
        if (curp->secondary)
                free(curp->secondary->buf);
 
@@ -890,6 +868,13 @@ mparse_result(struct mparse *curp, struct roff_man **man,
                *man = curp->man;
 }
 
+void
+mparse_updaterc(struct mparse *curp, enum mandoclevel *rc)
+{
+       if (curp->file_status > *rc)
+               *rc = curp->file_status;
+}
+
 void
 mandoc_vmsg(enum mandocerr t, struct mparse *m,
                int ln, int pos, const char *fmt, ...)
@@ -928,13 +913,13 @@ const char *
 mparse_strerror(enum mandocerr er)
 {
 
-       return(mandocerrs[er]);
+       return mandocerrs[er];
 }
 
 const char *
 mparse_strlevel(enum mandoclevel lvl)
 {
-       return(mandoclevels[lvl]);
+       return mandoclevels[lvl];
 }
 
 void
@@ -950,5 +935,5 @@ mparse_getkeep(const struct mparse *p)
 {
 
        assert(p->secondary);
-       return(p->secondary->sz ? p->secondary->buf : NULL);
+       return p->secondary->sz ? p->secondary->buf : NULL;
 }