=================================================================== RCS file: /cvs/mandoc/read.c,v retrieving revision 1.192 retrieving revision 1.197 diff -u -p -r1.192 -r1.197 --- mandoc/read.c 2017/07/20 14:36:36 1.192 +++ mandoc/read.c 2018/08/23 14:29:38 1.197 @@ -1,7 +1,7 @@ -/* $Id: read.c,v 1.192 2017/07/20 14:36:36 schwarze Exp $ */ +/* $Id: read.c,v 1.197 2018/08/23 14:29:38 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons - * Copyright (c) 2010-2017 Ingo Schwarze + * Copyright (c) 2010-2018 Ingo Schwarze * Copyright (c) 2010, 2012 Joerg Sonnenberger * * Permission to use, copy, modify, and distribute this software for any @@ -62,7 +62,7 @@ struct mparse { static void choose_parser(struct mparse *); static void resize_buf(struct buf *, size_t); -static int mparse_buf_r(struct mparse *, struct buf, size_t, int); +static enum rofferr 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 *); @@ -94,9 +94,10 @@ static const char * const mandocerrs[MANDOCERR_MAX] = "generic style suggestion", "legacy man(7) date format", + "normalizing date format to", "lower case character in document title", "duplicate RCS id", - "typo in section name", + "possible typo in section name", "unterminated quoted argument", "useless macro", "consider using OS macro", @@ -106,6 +107,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = "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", @@ -231,6 +233,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = "input stack limit exceeded, infinite loop?", "skipping bad character", "skipping unknown macro", + "ignoring request outside macro", "skipping insecure request", "skipping item outside list", "skipping column outside column list", @@ -241,6 +244,8 @@ static const char * const mandocerrs[MANDOCERR_MAX] = /* related to request and macro arguments */ "escaped character not allowed in a name", + "using macro argument outside macro", + "argument number is not numeric", "NOT IMPLEMENTED: Bd -file", "skipping display without arguments", "missing list type, using -item", @@ -249,6 +254,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = "uname(3) system call failed, using UNKNOWN", "unknown standard specifier", "skipping request without numeric argument", + "excessive shift", "NOT IMPLEMENTED: .so with absolute path or \"..\"", ".so request failed", "skipping all arguments", @@ -336,14 +342,14 @@ choose_parser(struct mparse *curp) * macros, inline equations, and input line traps) * and indirectly (for .so file inclusion). */ -static int +static enum rofferr mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start) { struct buf ln; const char *save_file; char *cp; size_t pos; /* byte number in the ln buffer */ - enum rofferr rr; + enum rofferr line_result, sub_result; int of; int lnn; /* line number in the real file */ int fd; @@ -466,20 +472,36 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size [curp->secondary->sz] = '\0'; } rerun: - rr = roff_parseln(curp->roff, curp->line, &ln, &of); + line_result = roff_parseln(curp->roff, curp->line, &ln, &of); - switch (rr) { + switch (line_result) { case ROFF_REPARSE: - if (++curp->reparse_count > REPARSE_LIMIT) + case ROFF_USERCALL: + if (++curp->reparse_count > REPARSE_LIMIT) { + sub_result = ROFF_IGN; mandoc_msg(MANDOCERR_ROFFLOOP, curp, curp->line, pos, NULL); - else if (mparse_buf_r(curp, ln, of, 0) == 1 || - start == 1) { + } else { + sub_result = mparse_buf_r(curp, ln, of, 0); + if (line_result == ROFF_USERCALL) { + if (sub_result == ROFF_USERRET) + sub_result = ROFF_CONT; + roff_userret(curp->roff); + } + if (start || sub_result == ROFF_CONT) { + pos = 0; + continue; + } + } + free(ln.buf); + return sub_result; + case ROFF_USERRET: + if (start) { pos = 0; continue; } free(ln.buf); - return 0; + return ROFF_USERRET; case ROFF_APPEND: pos = strlen(ln.buf); continue; @@ -493,7 +515,7 @@ rerun: (i >= blk.sz || blk.buf[i] == '\0')) { curp->sodest = mandoc_strdup(ln.buf + of); free(ln.buf); - return 1; + return ROFF_CONT; } /* * We remove `so' clauses from our lookaside @@ -545,7 +567,7 @@ rerun: } free(ln.buf); - return 1; + return ROFF_CONT; } static int @@ -556,6 +578,7 @@ read_whole_file(struct mparse *curp, const char *file, gzFile gz; size_t off; ssize_t ssz; + int gzerrnum, retval; if (fstat(fd, &st) == -1) { mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, @@ -583,9 +606,22 @@ read_whole_file(struct mparse *curp, const char *file, } if (curp->gzip) { + /* + * 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 @@ -598,6 +634,7 @@ read_whole_file(struct mparse *curp, const char *file, *with_mmap = 0; off = 0; + retval = 0; fb->sz = 0; fb->buf = NULL; for (;;) { @@ -614,19 +651,29 @@ read_whole_file(struct mparse *curp, const char *file, read(fd, fb->buf + (int)off, fb->sz - off); if (ssz == 0) { fb->sz = off; - return 1; + retval = 1; + break; } if (ssz == -1) { - mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, - "read: %s", strerror(errno)); + 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; } 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