]> git.cameronkatri.com Git - mandoc.git/blobdiff - read.c
Stop parsing man(7) input when we found all we were searching for,
[mandoc.git] / read.c
diff --git a/read.c b/read.c
index 22b8d8b6966cf3df8a42b622d1d5591f56dfe96e..511ba7dc466deba542e433a2ef1f454785f769e3 100644 (file)
--- a/read.c
+++ b/read.c
@@ -1,7 +1,7 @@
-/*     $Id: read.c,v 1.30 2012/07/12 15:11:14 schwarze Exp $ */
+/*     $Id: read.c,v 1.39 2013/09/16 00:25:07 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #include "man.h"
 #include "main.h"
 
-#ifndef MAP_FILE
-#define        MAP_FILE        0
-#endif
-
 #define        REPARSE_LIMIT   1000
 
 struct buf {
@@ -71,10 +67,11 @@ struct      mparse {
 
 static void      resize_buf(struct buf *, size_t);
 static void      mparse_buf_r(struct mparse *, struct buf, int);
-static void      mparse_readfd_r(struct mparse *, int, const char *, int);
 static void      pset(const char *, int, struct mparse *);
 static int       read_whole_file(const char *, int, struct buf *, int *);
 static void      mparse_end(struct mparse *);
+static void      mparse_parse_buffer(struct mparse *, struct buf,
+                       const char *);
 
 static const enum mandocerr    mandoclimits[MANDOCLEVEL_MAX] = {
        MANDOCERR_OK,
@@ -95,6 +92,7 @@ static        const char * const      mandocerrs[MANDOCERR_MAX] = {
        "no title in document",
        "document title should be all caps",
        "unknown manual section",
+       "unknown manual volume or arch",
        "date missing, using today's date",
        "cannot parse date, using it verbatim",
        "prologue macros out of order",
@@ -108,11 +106,12 @@ static    const char * const      mandocerrs[MANDOCERR_MAX] = {
        "bad NAME section contents",
        "sections out of conventional order",
        "duplicate section name",
-       "section not in conventional manual section",
+       "section header suited to sections 2, 3, and 9 only",
 
        /* related to macros and nesting */
        "skipping obsolete macro",
        "skipping paragraph macro",
+       "moving paragraph macro out of list",
        "skipping no-space macro",
        "blocks badly nested",
        "child violates parent syntax",
@@ -178,6 +177,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "skipping unknown macro",
        "NOT IMPLEMENTED, please use groff: skipping request",
        "argument count wrong",
+       "skipping column outside column list",
        "skipping end of block that is not open",
        "missing end of block",
        "scope open on exit",
@@ -185,6 +185,7 @@ static      const char * const      mandocerrs[MANDOCERR_MAX] = {
        "macro requires line argument(s)",
        "macro requires body argument(s)",
        "macro requires argument(s)",
+       "request requires a numeric argument",
        "missing list type",
        "line argument(s) will be lost",
        "body argument(s) will be lost",
@@ -325,6 +326,15 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
                                break;
                        }
 
+                       /*
+                        * Make sure we have space for at least
+                        * one backslash and one other character
+                        * and the trailing NUL byte.
+                        */
+
+                       if (pos + 2 >= (int)ln.sz)
+                               resize_buf(&ln, 256);
+
                        /* 
                         * Warn about bogus characters.  If you're using
                         * non-ASCII encoding, you're screwing your
@@ -341,8 +351,6 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
                                mandoc_msg(MANDOCERR_BADCHAR, curp,
                                                curp->line, pos, NULL);
                                i++;
-                               if (pos >= (int)ln.sz)
-                                       resize_buf(&ln, 256);
                                ln.buf[pos++] = '?';
                                continue;
                        }
@@ -350,8 +358,6 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
                        /* Trailing backslash = a plain char. */
 
                        if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
-                               if (pos >= (int)ln.sz)
-                                       resize_buf(&ln, 256);
                                ln.buf[pos++] = blk.buf[i++];
                                continue;
                        }
@@ -393,10 +399,20 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
                                break;
                        }
 
-                       /* Some other escape sequence, copy & cont. */
+                       /* Catch escaped bogus characters. */
 
-                       if (pos + 1 >= (int)ln.sz)
-                               resize_buf(&ln, 256);
+                       c = (unsigned char) blk.buf[i+1];
+
+                       if ( ! (isascii(c) && 
+                                       (isgraph(c) || isblank(c)))) {
+                               mandoc_msg(MANDOCERR_BADCHAR, curp,
+                                               curp->line, pos, NULL);
+                               i += 2;
+                               ln.buf[pos++] = '?';
+                               continue;
+                       }
+
+                       /* Some other escape sequence, copy & cont. */
 
                        ln.buf[pos++] = blk.buf[i++];
                        ln.buf[pos++] = blk.buf[i++];
@@ -472,7 +488,7 @@ rerun:
                         */
                        if (curp->secondary) 
                                curp->secondary->sz -= pos + 1;
-                       mparse_readfd_r(curp, -1, ln.buf + of, 1);
+                       mparse_readfd(curp, -1, ln.buf + of);
                        if (MANDOCLEVEL_FATAL <= curp->file_status)
                                break;
                        pos = 0;
@@ -578,8 +594,7 @@ read_whole_file(const char *file, int fd, struct buf *fb, int *with_mmap)
                }
                *with_mmap = 1;
                fb->sz = (size_t)st.st_size;
-               fb->buf = mmap(NULL, fb->sz, PROT_READ, 
-                               MAP_FILE|MAP_SHARED, fd, 0);
+               fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0);
                if (fb->buf != MAP_FAILED)
                        return(1);
        }
@@ -646,19 +661,25 @@ mparse_end(struct mparse *curp)
 }
 
 static void
-mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file,
-               int re)
+mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)
 {
        const char      *svfile;
+       static int       recursion_depth;
+
+       if (64 < recursion_depth) {
+               mandoc_msg(MANDOCERR_ROFFLOOP, curp, curp->line, 0, NULL);
+               return;
+       }
 
        /* Line number is per-file. */
        svfile = curp->file;
        curp->file = file;
        curp->line = 1;
+       recursion_depth++;
 
        mparse_buf_r(curp, blk, 1);
 
-       if (0 == re && MANDOCLEVEL_FATAL > curp->file_status)
+       if (0 == --recursion_depth && MANDOCLEVEL_FATAL > curp->file_status)
                mparse_end(curp);
 
        curp->file = svfile;
@@ -673,12 +694,12 @@ mparse_readmem(struct mparse *curp, const void *buf, size_t len,
        blk.buf = UNCONST(buf);
        blk.sz = len;
 
-       mparse_parse_buffer(curp, blk, file, 0);
+       mparse_parse_buffer(curp, blk, file);
        return(curp->file_status);
 }
 
-static void
-mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
+enum mandoclevel
+mparse_readfd(struct mparse *curp, int fd, const char *file)
 {
        struct buf       blk;
        int              with_mmap;
@@ -687,7 +708,7 @@ mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
                if (-1 == (fd = open(file, O_RDONLY, 0))) {
                        perror(file);
                        curp->file_status = MANDOCLEVEL_SYSERR;
-                       return;
+                       goto out;
                }
        /*
         * Run for each opened file; may be called more than once for
@@ -698,10 +719,10 @@ mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
 
        if ( ! read_whole_file(file, fd, &blk, &with_mmap)) {
                curp->file_status = MANDOCLEVEL_SYSERR;
-               return;
+               goto out;
        }
 
-       mparse_parse_buffer(curp, blk, file, re);
+       mparse_parse_buffer(curp, blk, file);
 
 #ifdef HAVE_MMAP
        if (with_mmap)
@@ -712,13 +733,7 @@ mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
 
        if (STDIN_FILENO != fd && -1 == close(fd))
                perror(file);
-}
-
-enum mandoclevel
-mparse_readfd(struct mparse *curp, int fd, const char *file)
-{
-
-       mparse_readfd_r(curp, fd, file, 0);
+out:
        return(curp->file_status);
 }
 
@@ -738,7 +753,7 @@ mparse_alloc(enum mparset inttype, enum mandoclevel wlevel,
        curp->inttype = inttype;
        curp->defos = defos;
 
-       curp->roff = roff_alloc(curp);
+       curp->roff = roff_alloc(inttype, curp);
        return(curp);
 }