]> git.cameronkatri.com Git - mandoc.git/blobdiff - read.c
The CommonMark specification allows list markers fo the form "number) "
[mandoc.git] / read.c
diff --git a/read.c b/read.c
index d1ffb57813df1eac01e7c6459a0cd7b9bbe2de88..883f5412750893b9e4525ffb25ec57068d3be809 100644 (file)
--- a/read.c
+++ b/read.c
@@ -1,7 +1,7 @@
-/*     $Id: read.c,v 1.146 2015/11/07 14:22:29 schwarze Exp $ */
+/*     $Id: read.c,v 1.163 2017/03/07 20:00:08 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>
@@ -32,7 +30,6 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <stdarg.h>
-#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -50,8 +47,8 @@
 #define        REPARSE_LIMIT   1000
 
 struct mparse {
-       struct roff_man  *man; /* man parser */
        struct roff      *roff; /* roff parser (!NULL) */
+       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 */
@@ -69,7 +66,7 @@ struct        mparse {
 
 static void      choose_parser(struct mparse *);
 static void      resize_buf(struct buf *, size_t);
-static void      mparse_buf_r(struct mparse *, struct buf, size_t, int);
+static int       mparse_buf_r(struct mparse *, struct buf, size_t, int);
 static int       read_whole_file(struct mparse *, const char *, int,
                                struct buf *, int *);
 static void      mparse_end(struct mparse *);
@@ -110,11 +107,13 @@ 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 \"\"",
+       "description line outside NAME section",
        "sections out of conventional order",
        "duplicate section title",
        "unexpected section",
@@ -143,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",
@@ -152,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 \"\"",
@@ -177,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 \"\"",
@@ -291,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;
@@ -316,7 +310,7 @@ choose_parser(struct mparse *curp)
  * macros, inline equations, and input line traps)
  * and indirectly (for .so file inclusion).
  */
-static void
+static int
 mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
 {
        const struct tbl_span   *span;
@@ -324,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 */
@@ -429,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 */
@@ -509,13 +511,16 @@ rerun:
 
                switch (rr) {
                case ROFF_REPARSE:
-                       if (REPARSE_LIMIT >= ++curp->reparse_count)
-                               mparse_buf_r(curp, ln, of, 0);
-                       else
+                       if (++curp->reparse_count > REPARSE_LIMIT)
                                mandoc_msg(MANDOCERR_ROFFLOOP, curp,
                                    curp->line, pos, NULL);
-                       pos = 0;
-                       continue;
+                       else if (mparse_buf_r(curp, ln, of, 0) == 1 ||
+                           start == 1) {
+                               pos = 0;
+                               continue;
+                       }
+                       free(ln.buf);
+                       return 0;
                case ROFF_APPEND:
                        pos = strlen(ln.buf);
                        continue;
@@ -529,7 +534,7 @@ rerun:
                            (i >= blk.sz || blk.buf[i] == '\0')) {
                                curp->sodest = mandoc_strdup(ln.buf + of);
                                free(ln.buf);
-                               return;
+                               return 1;
                        }
                        /*
                         * We remove `so' clauses from our lookaside
@@ -539,9 +544,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;
@@ -562,15 +567,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);
 
                /*
@@ -603,19 +600,18 @@ rerun:
        }
 
        free(ln.buf);
+       return 1;
 }
 
 static int
 read_whole_file(struct mparse *curp, const char *file, int fd,
                struct buf *fb, int *with_mmap)
 {
+       struct stat      st;
        gzFile           gz;
        size_t           off;
        ssize_t          ssz;
 
-#if HAVE_MMAP
-       struct stat      st;
-
        if (fstat(fd, &st) == -1)
                err((int)MANDOCLEVEL_SYSERR, "%s", file);
 
@@ -637,7 +633,6 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
                if (fb->buf != MAP_FAILED)
                        return 1;
        }
-#endif
 
        if (curp->gzip) {
                if ((gz = gzdopen(fd, "rb")) == NULL)
@@ -683,10 +678,6 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
 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)
@@ -766,24 +757,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;
 }
 
-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, '.');
@@ -791,8 +777,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
@@ -801,18 +787,18 @@ 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 *
@@ -845,18 +831,17 @@ mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
 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
@@ -864,8 +849,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);
 
@@ -887,6 +871,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, ...)