=================================================================== RCS file: /cvs/mandoc/read.c,v retrieving revision 1.98 retrieving revision 1.110 diff -u -p -r1.98 -r1.110 --- mandoc/read.c 2014/11/26 23:42:14 1.98 +++ mandoc/read.c 2015/01/15 02:29:26 1.110 @@ -1,7 +1,7 @@ -/* $Id: read.c,v 1.98 2014/11/26 23:42:14 schwarze Exp $ */ +/* $Id: read.c,v 1.110 2015/01/15 02:29:26 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons - * Copyright (c) 2010-2014 Ingo Schwarze + * Copyright (c) 2010-2015 Ingo Schwarze * Copyright (c) 2010, 2012 Joerg Sonnenberger * * Permission to use, copy, modify, and distribute this software for any @@ -41,7 +41,6 @@ #include "libmandoc.h" #include "mdoc.h" #include "man.h" -#include "main.h" #define REPARSE_LIMIT 1000 @@ -97,7 +96,6 @@ static const char * const mandocerrs[MANDOCERR_MAX] = "lower case character in document title", "missing manual section, using \"\"", "unknown manual section", - "unknown manual volume or arch", "missing date, using today's date", "cannot parse date, using it verbatim", "missing Os macro, using \"\"", @@ -121,6 +119,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = /* related to macros and nesting */ "obsolete macro", + "macro neither callable nor escaped", "skipping paragraph macro", "moving paragraph macro out of list", "skipping no-space macro", @@ -146,6 +145,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = "empty list item", "missing font type, using \\fR", "unknown font type, using \\fR", + "nothing follows prefix", "missing -std argument, adding it", "missing eqn box, using \"\"", @@ -188,8 +188,10 @@ static const char * const mandocerrs[MANDOCERR_MAX] = "ignore data in cell", "data block still open", "ignoring extra data cells", + "ignoring macro in table", /* related to document structure and macros */ + NULL, "input stack limit exceeded, infinite loop?", "skipping bad character", "skipping unknown macro", @@ -202,11 +204,14 @@ static const char * const mandocerrs[MANDOCERR_MAX] = /* related to request and macro arguments */ "escaped character not allowed in a name", "argument count wrong", + "NOT IMPLEMENTED: Bd -file", "missing list type, using -item", "missing manual name, using \"\"", "uname(3) system call failed, using UNKNOWN", "unknown standard specifier", "skipping request without numeric argument", + "NOT IMPLEMENTED: .so with absolute path or \"..\"", + ".so request failed", "skipping all arguments", "skipping excess arguments", "divide by zero", @@ -214,21 +219,6 @@ static const char * const mandocerrs[MANDOCERR_MAX] = "generic fatal error", "input too large", - "NOT IMPLEMENTED: Bd -file", - "NOT IMPLEMENTED: .so with absolute path or \"..\"", - ".so request failed", - - /* system errors */ - "cannot dup file descriptor", - "cannot exec", - "gunzip failed with code", - "cannot fork", - NULL, - "cannot open pipe", - "cannot read file", - "gunzip died from signal", - "cannot stat file", - "wait failed", }; static const char * const mandoclevels[MANDOCLEVEL_MAX] = { @@ -297,7 +287,8 @@ choose_parser(struct mparse *curp) /* Fall back to man(7) as a last resort. */ if (NULL == curp->pman) - curp->pman = man_alloc(curp->roff, curp, + curp->pman = man_alloc( + curp->roff, curp, curp->defos, MPARSE_QUICK & curp->options ? 1 : 0); assert(curp->pman); curp->man = curp->pman; @@ -315,10 +306,13 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size { const struct tbl_span *span; struct buf ln; + char *cp; size_t pos; /* byte number in the ln buffer */ enum rofferr rr; - int of, rc; + int of; int lnn; /* line number in the real file */ + int fd; + pid_t save_child; unsigned char c; memset(&ln, 0, sizeof(ln)); @@ -513,9 +507,6 @@ rerun: case ROFF_IGN: pos = 0; continue; - case ROFF_ERR: - assert(MANDOCLEVEL_FATAL <= curp->file_status); - break; case ROFF_SO: if ( ! (curp->options & MPARSE_SO) && (i >= blk.sz || blk.buf[i] == '\0')) { @@ -530,13 +521,23 @@ rerun: */ if (curp->secondary) curp->secondary->sz -= pos + 1; - mparse_readfd(curp, -1, ln.buf + of); - if (MANDOCLEVEL_FATAL <= curp->file_status) { + save_child = curp->child; + if (mparse_open(curp, &fd, ln.buf + of) == + MANDOCLEVEL_OK) + mparse_readfd(curp, fd, ln.buf + of); + else { mandoc_vmsg(MANDOCERR_SO_FAIL, curp, curp->line, pos, ".so %s", ln.buf + of); - break; + ln.sz = mandoc_asprintf(&cp, + ".sp\nSee the file %s.\n.sp", + ln.buf + of); + free(ln.buf); + ln.buf = cp; + of = 0; + mparse_buf_r(curp, ln, of, 0); } + curp->child = save_child; pos = 0; continue; default: @@ -570,35 +571,22 @@ rerun: * Do the same for ROFF_EQN. */ - rc = -1; + if (rr == ROFF_TBL) { + while ((span = roff_span(curp->roff)) != NULL) + if (curp->man == NULL) + mdoc_addspan(curp->mdoc, span); + else + man_addspan(curp->man, span); + } else if (rr == ROFF_EQN) { + if (curp->man == NULL) + mdoc_addeqn(curp->mdoc, roff_eqn(curp->roff)); + else + man_addeqn(curp->man, roff_eqn(curp->roff)); + } else if ((curp->man == NULL ? + mdoc_parseln(curp->mdoc, curp->line, ln.buf, of) : + man_parseln(curp->man, curp->line, ln.buf, of)) == 2) + break; - if (ROFF_TBL == rr) - while (NULL != (span = roff_span(curp->roff))) { - rc = curp->man ? - man_addspan(curp->man, span) : - mdoc_addspan(curp->mdoc, span); - if (0 == rc) - break; - } - else if (ROFF_EQN == rr) - rc = curp->mdoc ? - mdoc_addeqn(curp->mdoc, - roff_eqn(curp->roff)) : - man_addeqn(curp->man, - roff_eqn(curp->roff)); - else if (curp->man || curp->mdoc) - rc = curp->man ? - man_parseln(curp->man, - curp->line, ln.buf, of) : - mdoc_parseln(curp->mdoc, - curp->line, ln.buf, of); - - if (0 == rc) { - assert(MANDOCLEVEL_FATAL <= curp->file_status); - break; - } else if (2 == rc) - break; - /* Temporary buffers typically are not full. */ if (0 == start && '\0' == blk.buf[i]) @@ -622,11 +610,8 @@ read_whole_file(struct mparse *curp, const char *file, #if HAVE_MMAP struct stat st; if (-1 == fstat(fd, &st)) { - curp->file_status = MANDOCLEVEL_SYSERR; - if (curp->mmsg) - (*curp->mmsg)(MANDOCERR_SYSSTAT, curp->file_status, - file, 0, 0, strerror(errno)); - return(0); + perror(file); + exit((int)MANDOCLEVEL_SYSERR); } /* @@ -679,12 +664,8 @@ read_whole_file(struct mparse *curp, const char *file, return(1); } if (ssz == -1) { - curp->file_status = MANDOCLEVEL_SYSERR; - if (curp->mmsg) - (*curp->mmsg)(MANDOCERR_SYSREAD, - curp->file_status, file, 0, 0, - strerror(errno)); - break; + perror(file); + exit((int)MANDOCLEVEL_SYSERR); } off += (size_t)ssz; } @@ -708,7 +689,8 @@ mparse_end(struct mparse *curp) curp->mdoc = curp->pmdoc; else { if (curp->pman == NULL) - curp->pman = man_alloc(curp->roff, curp, + curp->pman = man_alloc( + curp->roff, curp, curp->defos, curp->options & MPARSE_QUICK ? 1 : 0); curp->man = curp->pman; } @@ -768,12 +750,12 @@ mparse_parse_buffer(struct mparse *curp, struct buf bl } enum mandoclevel -mparse_readmem(struct mparse *curp, const void *buf, size_t len, +mparse_readmem(struct mparse *curp, void *buf, size_t len, const char *file) { struct buf blk; - blk.buf = UNCONST(buf); + blk.buf = buf; blk.sz = len; mparse_parse_buffer(curp, blk, file); @@ -781,8 +763,6 @@ mparse_readmem(struct mparse *curp, const void *buf, s } /* - * If a file descriptor is given, use it and assume it points - * to the named file. Otherwise, open the named file. * Read the whole file into memory and call the parsers. * Called recursively when an .so request is encountered. */ @@ -792,14 +772,7 @@ mparse_readfd(struct mparse *curp, int fd, const char struct buf blk; int with_mmap; int save_filenc; - pid_t save_child; - save_child = curp->child; - if (fd != -1) - curp->child = 0; - else if (mparse_open(curp, &fd, file) >= MANDOCLEVEL_SYSERR) - goto out; - if (read_whole_file(curp, file, fd, &blk, &with_mmap)) { save_filenc = curp->filenc; curp->filenc = curp->options & @@ -818,8 +791,6 @@ mparse_readfd(struct mparse *curp, int fd, const char perror(file); mparse_wait(curp); -out: - curp->child = save_child; return(curp->file_status); } @@ -829,9 +800,7 @@ mparse_open(struct mparse *curp, int *fd, const char * int pfd[2]; int save_errno; char *cp; - enum mandocerr err; - pfd[1] = -1; curp->file = file; /* Unless zipped, try to just open the file. */ @@ -855,50 +824,38 @@ mparse_open(struct mparse *curp, int *fd, const char * if (access(file, R_OK) == -1) { if (cp != NULL) errno = save_errno; - err = MANDOCERR_SYSOPEN; - goto out; + free(cp); + *fd = -1; + curp->child = 0; + mandoc_msg(MANDOCERR_FILE, curp, 0, 0, strerror(errno)); + return(MANDOCLEVEL_ERROR); } /* Run gunzip(1). */ if (pipe(pfd) == -1) { - err = MANDOCERR_SYSPIPE; - goto out; + perror("pipe"); + exit((int)MANDOCLEVEL_SYSERR); } switch (curp->child = fork()) { case -1: - err = MANDOCERR_SYSFORK; - close(pfd[0]); - close(pfd[1]); - pfd[1] = -1; - break; + perror("fork"); + exit((int)MANDOCLEVEL_SYSERR); case 0: close(pfd[0]); if (dup2(pfd[1], STDOUT_FILENO) == -1) { - err = MANDOCERR_SYSDUP; - break; + perror("dup"); + exit((int)MANDOCLEVEL_SYSERR); } execlp("gunzip", "gunzip", "-c", file, NULL); - err = MANDOCERR_SYSEXEC; - break; + perror("exec"); + exit((int)MANDOCLEVEL_SYSERR); default: close(pfd[1]); *fd = pfd[0]; return(MANDOCLEVEL_OK); } - -out: - free(cp); - *fd = -1; - curp->child = 0; - curp->file_status = MANDOCLEVEL_SYSERR; - if (curp->mmsg) - (*curp->mmsg)(err, curp->file_status, curp->file, - 0, 0, strerror(errno)); - if (pfd[1] != -1) - exit(1); - return(curp->file_status); } enum mandoclevel @@ -910,22 +867,18 @@ mparse_wait(struct mparse *curp) return(MANDOCLEVEL_OK); if (waitpid(curp->child, &status, 0) == -1) { - mandoc_msg(MANDOCERR_SYSWAIT, curp, 0, 0, - strerror(errno)); - curp->file_status = MANDOCLEVEL_SYSERR; - return(curp->file_status); + perror("wait"); + exit((int)MANDOCLEVEL_SYSERR); } if (WIFSIGNALED(status)) { - mandoc_vmsg(MANDOCERR_SYSSIG, curp, 0, 0, - "%d", WTERMSIG(status)); - curp->file_status = MANDOCLEVEL_SYSERR; - return(curp->file_status); + mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, + "gunzip died from signal %d", WTERMSIG(status)); + return(MANDOCLEVEL_ERROR); } if (WEXITSTATUS(status)) { - mandoc_vmsg(MANDOCERR_SYSEXIT, curp, 0, 0, - "%d", WEXITSTATUS(status)); - curp->file_status = MANDOCLEVEL_SYSERR; - return(curp->file_status); + mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, + "gunzip failed with code %d", WEXITSTATUS(status)); + return(MANDOCLEVEL_ERROR); } return(MANDOCLEVEL_OK); } @@ -952,7 +905,8 @@ mparse_alloc(int options, enum mandoclevel wlevel, man curp->roff, curp, curp->defos, curp->options & MPARSE_QUICK ? 1 : 0); if (curp->options & MPARSE_MAN) - curp->pman = man_alloc(curp->roff, curp, + curp->pman = man_alloc( + curp->roff, curp, curp->defos, curp->options & MPARSE_QUICK ? 1 : 0); return(curp); @@ -1037,7 +991,7 @@ mandoc_msg(enum mandocerr er, struct mparse *m, while (er < mandoclimits[level]) level--; - if (level < m->wlevel) + if (level < m->wlevel && er != MANDOCERR_FILE) return; if (m->mmsg)