version 1.2, 2011/03/20 11:43:06 |
version 1.4, 2011/03/20 16:05:21 |
|
|
#include <assert.h> |
#include <assert.h> |
#include <ctype.h> |
#include <ctype.h> |
#include <fcntl.h> |
#include <fcntl.h> |
|
#include <stdarg.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include <unistd.h> |
#include <unistd.h> |
|
|
#include "mandoc.h" |
#include "mandoc.h" |
|
#include "libmandoc.h" |
#include "mdoc.h" |
#include "mdoc.h" |
#include "man.h" |
#include "man.h" |
#include "roff.h" |
#include "roff.h" |
|
|
|
|
struct mparse { |
struct mparse { |
enum mandoclevel file_status; /* status of current parse */ |
enum mandoclevel file_status; /* status of current parse */ |
|
enum mandoclevel wlevel; /* ignore messages below this */ |
int line; /* line number in the file */ |
int line; /* line number in the file */ |
enum mparset inttype; /* which parser to use */ |
enum mparset inttype; /* which parser to use */ |
struct man *pman; /* persistent man parser */ |
struct man *pman; /* persistent man parser */ |
|
|
int reparse_count; /* finite interp. stack */ |
int reparse_count; /* finite interp. stack */ |
mandocmsg mmsg; /* warning/error message handler */ |
mandocmsg mmsg; /* warning/error message handler */ |
void *arg; /* argument to mmsg */ |
void *arg; /* argument to mmsg */ |
mevt_open evt_open; /* file-open event */ |
const char *file; |
mevt_close evt_close; /* file-close event */ |
|
const char *svfile; |
|
}; |
}; |
|
|
static void resize_buf(struct buf *, size_t); |
static void resize_buf(struct buf *, size_t); |
Line 68 static void pdesc(struct mparse *, const char *, int |
|
Line 69 static void pdesc(struct mparse *, const char *, int |
|
static int read_whole_file(const char *, int, struct buf *, int *); |
static int read_whole_file(const char *, int, struct buf *, int *); |
static void mparse_end(struct mparse *); |
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 void |
static void |
resize_buf(struct buf *buf, size_t initial) |
resize_buf(struct buf *buf, size_t initial) |
{ |
{ |
Line 103 pset(const char *buf, int pos, struct mparse *curp) |
|
Line 114 pset(const char *buf, int pos, struct mparse *curp) |
|
switch (curp->inttype) { |
switch (curp->inttype) { |
case (MPARSE_MDOC): |
case (MPARSE_MDOC): |
if (NULL == curp->pmdoc) |
if (NULL == curp->pmdoc) |
curp->pmdoc = mdoc_alloc |
curp->pmdoc = mdoc_alloc(&curp->regs, curp); |
(&curp->regs, curp->arg, curp->mmsg); |
|
assert(curp->pmdoc); |
assert(curp->pmdoc); |
curp->mdoc = curp->pmdoc; |
curp->mdoc = curp->pmdoc; |
return; |
return; |
case (MPARSE_MAN): |
case (MPARSE_MAN): |
if (NULL == curp->pman) |
if (NULL == curp->pman) |
curp->pman = man_alloc |
curp->pman = man_alloc(&curp->regs, curp); |
(&curp->regs, curp->arg, curp->mmsg); |
|
assert(curp->pman); |
assert(curp->pman); |
curp->man = curp->pman; |
curp->man = curp->pman; |
return; |
return; |
Line 121 pset(const char *buf, int pos, struct mparse *curp) |
|
Line 130 pset(const char *buf, int pos, struct mparse *curp) |
|
|
|
if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) { |
if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) { |
if (NULL == curp->pmdoc) |
if (NULL == curp->pmdoc) |
curp->pmdoc = mdoc_alloc |
curp->pmdoc = mdoc_alloc(&curp->regs, curp); |
(&curp->regs, curp->arg, curp->mmsg); |
|
assert(curp->pmdoc); |
assert(curp->pmdoc); |
curp->mdoc = curp->pmdoc; |
curp->mdoc = curp->pmdoc; |
return; |
return; |
} |
} |
|
|
if (NULL == curp->pman) |
if (NULL == curp->pman) |
curp->pman = man_alloc |
curp->pman = man_alloc(&curp->regs, curp); |
(&curp->regs, curp->arg, curp->mmsg); |
|
assert(curp->pman); |
assert(curp->pman); |
curp->man = curp->pman; |
curp->man = curp->pman; |
} |
} |
Line 195 mparse_buf_r(struct mparse *curp, struct buf blk, int |
|
Line 202 mparse_buf_r(struct mparse *curp, struct buf blk, int |
|
|
|
if ( ! (isascii(c) && |
if ( ! (isascii(c) && |
(isgraph(c) || isblank(c)))) { |
(isgraph(c) || isblank(c)))) { |
curp->mmsg(MANDOCERR_BADCHAR, curp->arg, |
mandoc_msg(MANDOCERR_BADCHAR, curp, |
curp->line, pos, "ignoring byte"); |
curp->line, pos, "ignoring byte"); |
i++; |
i++; |
continue; |
continue; |
|
|
if (REPARSE_LIMIT >= ++curp->reparse_count) |
if (REPARSE_LIMIT >= ++curp->reparse_count) |
mparse_buf_r(curp, ln, 0); |
mparse_buf_r(curp, ln, 0); |
else |
else |
curp->mmsg(MANDOCERR_ROFFLOOP, curp->arg, |
mandoc_msg(MANDOCERR_ROFFLOOP, curp, |
curp->line, pos, NULL); |
curp->line, pos, NULL); |
pos = 0; |
pos = 0; |
continue; |
continue; |
Line 491 mparse_end(struct mparse *curp) |
|
Line 498 mparse_end(struct mparse *curp) |
|
} |
} |
|
|
#if 0 |
#if 0 |
/* NOTE a parser may not have been assigned, yet. */ |
/* FIXME: NOTE a parser may not have been assigned, yet. */ |
|
|
if ( ! (curp->man || curp->mdoc)) { |
if ( ! (curp->man || curp->mdoc)) { |
/* FIXME: make into an mandoc.h error. */ |
/* FIXME: make into an mandoc.h error. */ |
Line 509 mparse_readfd_r(struct mparse *curp, int fd, const cha |
|
Line 516 mparse_readfd_r(struct mparse *curp, int fd, const cha |
|
{ |
{ |
const char *svfile; |
const char *svfile; |
|
|
if ( ! (*curp->evt_open)(curp->arg, file)) { |
|
curp->file_status = MANDOCLEVEL_SYSERR; |
|
return; |
|
} |
|
|
|
if (-1 == fd) |
if (-1 == fd) |
if (-1 == (fd = open(file, O_RDONLY, 0))) { |
if (-1 == (fd = open(file, O_RDONLY, 0))) { |
perror(file); |
perror(file); |
Line 521 mparse_readfd_r(struct mparse *curp, int fd, const cha |
|
Line 523 mparse_readfd_r(struct mparse *curp, int fd, const cha |
|
return; |
return; |
} |
} |
|
|
svfile = curp->svfile; |
svfile = curp->file; |
curp->svfile = file; |
curp->file = file; |
|
|
pdesc(curp, file, fd); |
pdesc(curp, file, fd); |
|
|
Line 532 mparse_readfd_r(struct mparse *curp, int fd, const cha |
|
Line 534 mparse_readfd_r(struct mparse *curp, int fd, const cha |
|
if (STDIN_FILENO != fd && -1 == close(fd)) |
if (STDIN_FILENO != fd && -1 == close(fd)) |
perror(file); |
perror(file); |
|
|
(*curp->evt_close)(curp->arg, svfile); |
curp->file = svfile; |
curp->svfile = svfile; |
|
} |
} |
|
|
enum mandoclevel |
enum mandoclevel |
Line 544 mparse_readfd(struct mparse *curp, int fd, const char |
|
Line 545 mparse_readfd(struct mparse *curp, int fd, const char |
|
return(curp->file_status); |
return(curp->file_status); |
} |
} |
|
|
void |
|
mparse_setstatus(struct mparse *curp, enum mandoclevel lvl) |
|
{ |
|
|
|
if (curp->file_status < lvl) |
|
curp->file_status = lvl; |
|
} |
|
|
|
struct mparse * |
struct mparse * |
mparse_alloc(enum mparset inttype, mevt_open eopen, |
mparse_alloc(enum mparset inttype, enum mandoclevel wlevel, mandocmsg mmsg, void *arg) |
mevt_close eclose, mandocmsg mmsg, void *arg) |
|
{ |
{ |
struct mparse *curp; |
struct mparse *curp; |
|
|
curp = mandoc_calloc(1, sizeof(struct mparse)); |
curp = mandoc_calloc(1, sizeof(struct mparse)); |
|
|
|
curp->wlevel = wlevel; |
curp->mmsg = mmsg; |
curp->mmsg = mmsg; |
curp->arg = arg; |
curp->arg = arg; |
curp->inttype = inttype; |
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); |
return(curp); |
} |
} |
|
|
Line 608 mparse_result(struct mparse *curp, struct mdoc **mdoc, |
|
Line 599 mparse_result(struct mparse *curp, struct mdoc **mdoc, |
|
|
|
*mdoc = curp->mdoc; |
*mdoc = curp->mdoc; |
*man = curp->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; |
|
|
|
(*m->mmsg)(er, level, m->file, ln, col, msg); |
|
|
|
if (m->file_status < level) |
|
m->file_status = level; |
} |
} |