=================================================================== RCS file: /cvs/mandoc/read.c,v retrieving revision 1.1 retrieving revision 1.14 diff -u -p -r1.1 -r1.14 --- mandoc/read.c 2011/03/20 11:41:24 1.1 +++ mandoc/read.c 2011/04/30 10:18:24 1.14 @@ -1,4 +1,4 @@ -/* $Id: read.c,v 1.1 2011/03/20 11:41:24 kristaps Exp $ */ +/* $Id: read.c,v 1.14 2011/04/30 10:18:24 kristaps Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010, 2011 Ingo Schwarze @@ -15,21 +15,26 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include +#include #include #include #include +#include #include #include #include #include #include "mandoc.h" +#include "libmandoc.h" #include "mdoc.h" #include "man.h" -#include "roff.h" #ifndef MAP_FILE #define MAP_FILE 0 @@ -44,6 +49,7 @@ struct buf { struct mparse { enum mandoclevel file_status; /* status of current parse */ + enum mandoclevel wlevel; /* ignore messages below this */ int line; /* line number in the file */ enum mparset inttype; /* which parser to use */ struct man *pman; /* persistent man parser */ @@ -55,9 +61,7 @@ struct mparse { int reparse_count; /* finite interp. stack */ mandocmsg mmsg; /* warning/error message handler */ void *arg; /* argument to mmsg */ - mevt_open evt_open; /* file-open event */ - mevt_close evt_close; /* file-close event */ - const char *svfile; + const char *file; }; static void resize_buf(struct buf *, size_t); @@ -68,6 +72,134 @@ static void pdesc(struct mparse *, const char *, int static int read_whole_file(const char *, int, struct buf *, int *); static void mparse_end(struct mparse *); +static const enum mandocerr mandoclimits[MANDOCLEVEL_MAX] = { + MANDOCERR_OK, + MANDOCERR_WARNING, + MANDOCERR_WARNING, + MANDOCERR_ERROR, + MANDOCERR_FATAL, + MANDOCERR_MAX, + MANDOCERR_MAX +}; + +static const char * const mandocerrs[MANDOCERR_MAX] = { + "ok", + + "generic warning", + + /* related to the prologue */ + "no title in document", + "document title should be all caps", + "unknown manual section", + "date missing, using today's date", + "cannot parse date, using it verbatim", + "prologue macros out of order", + "duplicate prologue macro", + "macro not allowed in prologue", + "macro not allowed in body", + + /* related to document structure */ + ".so is fragile, better use ln(1)", + "NAME section must come first", + "bad NAME section contents", + "manual name not yet set", + "sections out of conventional order", + "duplicate section name", + "section not in conventional manual section", + + /* related to macros and nesting */ + "skipping obsolete macro", + "skipping paragraph macro", + "skipping no-space macro", + "blocks badly nested", + "child violates parent syntax", + "nested displays are not portable", + "already in literal mode", + "line scope broken", + + /* related to missing macro arguments */ + "skipping empty macro", + "argument count wrong", + "missing display type", + "list type must come first", + "tag lists require a width argument", + "missing font type", + "skipping end of block that is not open", + + /* related to bad macro arguments */ + "skipping argument", + "duplicate argument", + "duplicate display type", + "duplicate list type", + "unknown AT&T UNIX version", + "bad Boolean value", + "unknown font", + "unknown standard specifier", + "bad width argument", + + /* related to plain text */ + "blank line in non-literal context", + "tab in non-literal context", + "end of line whitespace", + "bad comment style", + "bad escape sequence", + "unterminated quoted string", + + "generic error", + + /* related to tables */ + "bad table syntax", + "bad table option", + "bad table layout", + "no table layout cells specified", + "no table data cells specified", + "ignore data in cell", + "data block still open", + "ignoring extra data cells", + + "input stack limit exceeded, infinite loop?", + "skipping bad character", + "escaped character not allowed in a name", + "skipping text before the first section header", + "skipping unknown macro", + "NOT IMPLEMENTED, please use groff: skipping request", + "argument count wrong", + "skipping end of block that is not open", + "missing end of block", + "scope open on exit", + "uname(3) system call failed", + "macro requires line argument(s)", + "macro requires body argument(s)", + "macro requires argument(s)", + "missing list type", + "line argument(s) will be lost", + "body argument(s) will be lost", + + "generic fatal error", + + "not a manual", + "column syntax is inconsistent", + "NOT IMPLEMENTED: .Bd -file", + "line scope broken, syntax violated", + "argument count wrong, violates syntax", + "child violates parent syntax", + "argument count wrong, violates syntax", + "NOT IMPLEMENTED: .so with absolute path or \"..\"", + "no document body", + "no document prologue", + "static buffer exhausted", +}; + +static const char * const mandoclevels[MANDOCLEVEL_MAX] = { + "SUCCESS", + "RESERVED", + "WARNING", + "ERROR", + "FATAL", + "BADARG", + "SYSERR" +}; + static void resize_buf(struct buf *buf, size_t initial) { @@ -103,15 +235,13 @@ pset(const char *buf, int pos, struct mparse *curp) switch (curp->inttype) { case (MPARSE_MDOC): if (NULL == curp->pmdoc) - curp->pmdoc = mdoc_alloc - (&curp->regs, curp->arg, curp->mmsg); + curp->pmdoc = mdoc_alloc(&curp->regs, curp); assert(curp->pmdoc); curp->mdoc = curp->pmdoc; return; case (MPARSE_MAN): if (NULL == curp->pman) - curp->pman = man_alloc - (&curp->regs, curp->arg, curp->mmsg); + curp->pman = man_alloc(&curp->regs, curp); assert(curp->pman); curp->man = curp->pman; return; @@ -121,16 +251,14 @@ pset(const char *buf, int pos, struct mparse *curp) if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) { if (NULL == curp->pmdoc) - curp->pmdoc = mdoc_alloc - (&curp->regs, curp->arg, curp->mmsg); + curp->pmdoc = mdoc_alloc(&curp->regs, curp); assert(curp->pmdoc); curp->mdoc = curp->pmdoc; return; } if (NULL == curp->pman) - curp->pman = man_alloc - (&curp->regs, curp->arg, curp->mmsg); + curp->pman = man_alloc(&curp->regs, curp); assert(curp->pman); curp->man = curp->pman; } @@ -195,7 +323,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int if ( ! (isascii(c) && (isgraph(c) || isblank(c)))) { - curp->mmsg(MANDOCERR_BADCHAR, curp->arg, + mandoc_msg(MANDOCERR_BADCHAR, curp, curp->line, pos, "ignoring byte"); i++; continue; @@ -226,7 +354,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int continue; } - if ('"' == blk.buf[i + 1]) { + if ('"' == blk.buf[i + 1] || '#' == blk.buf[i + 1]) { i += 2; /* Comment, skip to end of line */ for (; i < (int)blk.sz; ++i) { @@ -282,7 +410,7 @@ rerun: if (REPARSE_LIMIT >= ++curp->reparse_count) mparse_buf_r(curp, ln, 0); else - curp->mmsg(MANDOCERR_ROFFLOOP, curp->arg, + mandoc_msg(MANDOCERR_ROFFLOOP, curp, curp->line, pos, NULL); pos = 0; continue; @@ -317,7 +445,7 @@ rerun: /* * If input parsers have not been allocated, do so now. - * We keep these instanced betwen parsers, but set them + * We keep these instanced between parsers, but set them * locally per parse routine since we can use different * parsers with each one. */ @@ -490,16 +618,11 @@ mparse_end(struct mparse *curp) return; } -#if 0 - /* NOTE a parser may not have been assigned, yet. */ - if ( ! (curp->man || curp->mdoc)) { - /* FIXME: make into an mandoc.h error. */ - fprintf(stderr, "%s: Not a manual\n", curp->file); + mandoc_msg(MANDOCERR_NOTMANUAL, curp, 1, 0, NULL); curp->file_status = MANDOCLEVEL_FATAL; - goto cleanup; + return; } -#endif roff_endparse(curp->roff); } @@ -509,11 +632,6 @@ mparse_readfd_r(struct mparse *curp, int fd, const cha { const char *svfile; - if ( ! (*curp->evt_open)(curp->arg, file)) { - curp->file_status = MANDOCLEVEL_SYSERR; - return; - } - if (-1 == fd) if (-1 == (fd = open(file, O_RDONLY, 0))) { perror(file); @@ -521,8 +639,8 @@ mparse_readfd_r(struct mparse *curp, int fd, const cha return; } - svfile = curp->svfile; - curp->svfile = file; + svfile = curp->file; + curp->file = file; pdesc(curp, file, fd); @@ -532,8 +650,7 @@ mparse_readfd_r(struct mparse *curp, int fd, const cha if (STDIN_FILENO != fd && -1 == close(fd)) perror(file); - (*curp->evt_close)(curp->arg, svfile); - curp->svfile = svfile; + curp->file = svfile; } enum mandoclevel @@ -544,29 +661,21 @@ mparse_readfd(struct mparse *curp, int fd, const char return(curp->file_status); } -void -mparse_setstatus(struct mparse *curp, enum mandoclevel lvl) -{ - - if (curp->file_status < lvl) - curp->file_status = lvl; -} - struct mparse * -mparse_alloc(enum mparset inttype, mevt_open eopen, - mevt_close eclose, mandocmsg mmsg, void *arg) +mparse_alloc(enum mparset inttype, enum mandoclevel wlevel, mandocmsg mmsg, void *arg) { struct mparse *curp; + assert(wlevel <= MANDOCLEVEL_FATAL); + curp = mandoc_calloc(1, sizeof(struct mparse)); + curp->wlevel = wlevel; curp->mmsg = mmsg; curp->arg = arg; curp->inttype = inttype; - curp->evt_open = eopen; - curp->evt_close = eclose; - curp->roff = roff_alloc(&curp->regs, arg, mmsg); + curp->roff = roff_alloc(&curp->regs, curp); return(curp); } @@ -606,6 +715,55 @@ void mparse_result(struct mparse *curp, struct mdoc **mdoc, struct man **man) { - *mdoc = curp->mdoc; - *man = curp->man; + if (mdoc) + *mdoc = curp->mdoc; + if (man) + *man = curp->man; +} + +void +mandoc_vmsg(enum mandocerr t, struct mparse *m, + int ln, int pos, const char *fmt, ...) +{ + char buf[256]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf) - 1, fmt, ap); + va_end(ap); + + mandoc_msg(t, m, ln, pos, buf); +} + +void +mandoc_msg(enum mandocerr er, struct mparse *m, + int ln, int col, const char *msg) +{ + enum mandoclevel level; + + level = MANDOCLEVEL_FATAL; + while (er < mandoclimits[level]) + level--; + + if (level < m->wlevel) + return; + + if (m->mmsg) + (*m->mmsg)(er, level, m->file, ln, col, msg); + + if (m->file_status < level) + m->file_status = level; +} + +const char * +mparse_strerror(enum mandocerr er) +{ + + return(mandocerrs[er]); +} + +const char * +mparse_strlevel(enum mandoclevel lvl) +{ + return(mandoclevels[lvl]); }