-/* $Id: read.c,v 1.179 2017/06/24 14:38:33 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
#include <assert.h>
#include <ctype.h>
-#if HAVE_ERR
-#include <err.h>
-#endif
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include "mdoc.h"
#include "man.h"
#include "libmandoc.h"
-#include "roff_int.h"
#define REPARSE_LIMIT 1000
static const enum mandocerr mandoclimits[MANDOCLEVEL_MAX] = {
MANDOCERR_OK,
- MANDOCERR_STYLE,
+ MANDOCERR_OK,
MANDOCERR_WARNING,
MANDOCERR_ERROR,
MANDOCERR_UNSUPP,
"Mdocdate found",
"Mdocdate missing",
+ "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 */
"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",
"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",
"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",
"missing eqn box, using \"\"",
/* related to bad macro arguments */
- "unterminated quoted argument",
"duplicate argument",
"skipping duplicate argument",
"skipping duplicate display type",
/* 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 \"\"",
/* 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",
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;
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;
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
}
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;
*with_mmap = 0;
off = 0;
+ retval = 0;
fb->sz = 0;
fb->buf = NULL;
for (;;) {
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