=================================================================== RCS file: /cvs/mandoc/read.c,v retrieving revision 1.97 retrieving revision 1.103 diff -u -p -r1.97 -r1.103 --- mandoc/read.c 2014/11/26 21:40:17 1.97 +++ mandoc/read.c 2014/11/30 05:29:00 1.103 @@ -1,4 +1,4 @@ -/* $Id: read.c,v 1.97 2014/11/26 21:40:17 schwarze Exp $ */ +/* $Id: read.c,v 1.103 2014/11/30 05:29:00 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010-2014 Ingo Schwarze @@ -97,7 +97,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 +120,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 +146,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 \"\"", @@ -202,6 +203,7 @@ 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", @@ -214,7 +216,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", @@ -317,7 +318,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size struct buf ln; 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 */ unsigned char c; @@ -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]) @@ -780,29 +768,26 @@ mparse_readmem(struct mparse *curp, const void *buf, s return(curp->file_status); } +/* + * 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. + */ enum mandoclevel mparse_readfd(struct mparse *curp, int fd, const char *file) { struct buf blk; int with_mmap; int save_filenc; + pid_t save_child; - 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)); - return(curp->file_status); - } + save_child = curp->child; + if (fd != -1) + curp->child = 0; + else if (mparse_open(curp, &fd, file) >= MANDOCLEVEL_SYSERR) + 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., - * from `so'). Simply sucks in the whole file and moves into - * the parse phase for the file. - */ - if (read_whole_file(curp, file, fd, &blk, &with_mmap)) { save_filenc = curp->filenc; curp->filenc = curp->options & @@ -817,9 +802,12 @@ mparse_readfd(struct mparse *curp, int fd, const char free(blk.buf); } - if (STDIN_FILENO != fd && -1 == close(fd)) + if (fd != STDIN_FILENO && close(fd) == -1) perror(file); + mparse_wait(curp); +out: + curp->child = save_child; return(curp->file_status); } @@ -827,21 +815,40 @@ enum mandoclevel mparse_open(struct mparse *curp, int *fd, const char *file) { 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. */ + if ((cp = strrchr(file, '.')) == NULL || strcmp(cp + 1, "gz")) { curp->child = 0; - if ((*fd = open(file, O_RDONLY)) == -1) { - err = MANDOCERR_SYSOPEN; - goto out; - } - return(MANDOCLEVEL_OK); + if ((*fd = open(file, O_RDONLY)) != -1) + return(MANDOCLEVEL_OK); + + /* Open failed; try to append ".gz". */ + + mandoc_asprintf(&cp, "%s.gz", file); + file = cp; + } else + cp = NULL; + + /* Before forking, make sure the file can be read. */ + + save_errno = errno; + if (access(file, R_OK) == -1) { + if (cp != NULL) + errno = save_errno; + err = MANDOCERR_SYSOPEN; + goto out; } + /* Run gunzip(1). */ + if (pipe(pfd) == -1) { err = MANDOCERR_SYSPIPE; goto out; @@ -870,11 +877,12 @@ mparse_open(struct mparse *curp, int *fd, const char * } out: + free(cp); *fd = -1; curp->child = 0; curp->file_status = MANDOCLEVEL_SYSERR; if (curp->mmsg) - (*curp->mmsg)(err, curp->file_status, file, + (*curp->mmsg)(err, curp->file_status, curp->file, 0, 0, strerror(errno)); if (pfd[1] != -1) exit(1);