-/* $Id: read.c,v 1.39 2013/09/16 00:25:07 schwarze Exp $ */
+/* $Id: read.c,v 1.43 2014/01/06 21:34:31 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2014 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
* purpose with or without fee is hereby granted, provided that the above
#include <assert.h>
#include <ctype.h>
+#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdint.h>
struct roff *roff; /* roff parser (!NULL) */
int reparse_count; /* finite interp. stack */
mandocmsg mmsg; /* warning/error message handler */
- void *arg; /* argument to mmsg */
const char *file;
struct buf *secondary;
char *defos; /* default operating system */
+ int quick; /* abort the parse early */
};
static void resize_buf(struct buf *, size_t);
static void mparse_buf_r(struct mparse *, struct buf, int);
static void pset(const char *, int, struct mparse *);
-static int read_whole_file(const char *, int, struct buf *, int *);
+static int read_whole_file(struct mparse *, const char *, int,
+ struct buf *, int *);
static void mparse_end(struct mparse *);
static void mparse_parse_buffer(struct mparse *, struct buf,
const char *);
"generic fatal error",
+ "input too large",
"not a manual",
"column syntax is inconsistent",
"NOT IMPLEMENTED: .Bd -file",
"no document body",
"no document prologue",
"static buffer exhausted",
+
+ /* system errors */
+ "cannot open file",
+ "cannot stat file",
+ "cannot read file",
};
static const char * const mandoclevels[MANDOCLEVEL_MAX] = {
case (MPARSE_MDOC):
if (NULL == curp->pmdoc)
curp->pmdoc = mdoc_alloc(curp->roff, curp,
- curp->defos);
+ curp->defos, curp->quick);
assert(curp->pmdoc);
curp->mdoc = curp->pmdoc;
return;
case (MPARSE_MAN):
if (NULL == curp->pman)
- curp->pman = man_alloc(curp->roff, curp);
+ curp->pman = man_alloc(curp->roff, curp,
+ curp->quick);
assert(curp->pman);
curp->man = curp->pman;
return;
if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) {
if (NULL == curp->pmdoc)
curp->pmdoc = mdoc_alloc(curp->roff, curp,
- curp->defos);
+ curp->defos, curp->quick);
assert(curp->pmdoc);
curp->mdoc = curp->pmdoc;
return;
}
if (NULL == curp->pman)
- curp->pman = man_alloc(curp->roff, curp);
+ curp->pman = man_alloc(curp->roff, curp, curp->quick);
assert(curp->pman);
curp->man = curp->pman;
}
if (0 == rc) {
assert(MANDOCLEVEL_FATAL <= curp->file_status);
break;
- }
+ } else if (2 == rc)
+ break;
/* Temporary buffers typically are not full. */
}
static int
-read_whole_file(const char *file, int fd, struct buf *fb, int *with_mmap)
+read_whole_file(struct mparse *curp, const char *file, int fd,
+ struct buf *fb, int *with_mmap)
{
size_t off;
ssize_t ssz;
#ifdef HAVE_MMAP
struct stat st;
if (-1 == fstat(fd, &st)) {
- perror(file);
+ curp->file_status = MANDOCLEVEL_SYSERR;
+ if (curp->mmsg)
+ (*curp->mmsg)(MANDOCERR_SYSSTAT, curp->file_status,
+ file, 0, 0, strerror(errno));
return(0);
}
if (S_ISREG(st.st_mode)) {
if (st.st_size >= (1U << 31)) {
- fprintf(stderr, "%s: input too large\n", file);
+ curp->file_status = MANDOCLEVEL_FATAL;
+ if (curp->mmsg)
+ (*curp->mmsg)(MANDOCERR_TOOLARGE,
+ curp->file_status, file, 0, 0, NULL);
return(0);
}
*with_mmap = 1;
for (;;) {
if (off == fb->sz) {
if (fb->sz == (1U << 31)) {
- fprintf(stderr, "%s: input too large\n", file);
+ curp->file_status = MANDOCLEVEL_FATAL;
+ if (curp->mmsg)
+ (*curp->mmsg)(MANDOCERR_TOOLARGE,
+ curp->file_status,
+ file, 0, 0, NULL);
break;
}
resize_buf(fb, 65536);
return(1);
}
if (ssz == -1) {
- perror(file);
+ curp->file_status = MANDOCLEVEL_SYSERR;
+ if (curp->mmsg)
+ (*curp->mmsg)(MANDOCERR_SYSREAD,
+ curp->file_status, file, 0, 0,
+ strerror(errno));
break;
}
off += (size_t)ssz;
struct buf blk;
int with_mmap;
- if (-1 == fd)
- if (-1 == (fd = open(file, O_RDONLY, 0))) {
- perror(file);
- curp->file_status = MANDOCLEVEL_SYSERR;
- goto out;
- }
+ if (-1 == fd && -1 == (fd = open(file, O_RDONLY, 0))) {
+ curp->file_status = MANDOCLEVEL_SYSERR;
+ if (curp->mmsg)
+ (*curp->mmsg)(MANDOCERR_SYSOPEN,
+ curp->file_status,
+ file, 0, 0, strerror(errno));
+ goto out;
+ }
+
/*
* Run for each opened file; may be called more than once for
* each full parse sequence if the opened file is nested (i.e.,
* the parse phase for the file.
*/
- if ( ! read_whole_file(file, fd, &blk, &with_mmap)) {
- curp->file_status = MANDOCLEVEL_SYSERR;
+ if ( ! read_whole_file(curp, file, fd, &blk, &with_mmap))
goto out;
- }
mparse_parse_buffer(curp, blk, file);
struct mparse *
mparse_alloc(enum mparset inttype, enum mandoclevel wlevel,
- mandocmsg mmsg, void *arg, char *defos)
+ mandocmsg mmsg, char *defos, int quick)
{
struct mparse *curp;
curp->wlevel = wlevel;
curp->mmsg = mmsg;
- curp->arg = arg;
curp->inttype = inttype;
curp->defos = defos;
+ curp->quick = quick;
- curp->roff = roff_alloc(inttype, curp);
+ curp->roff = roff_alloc(inttype, curp, curp->quick);
return(curp);
}