version 1.43, 2009/01/15 15:59:19 |
version 1.46, 2009/01/16 14:15:12 |
|
|
|
|
#include "mdoc.h" |
#include "mdoc.h" |
|
|
#define MD_LINE_SZ (256) |
#define xfprintf (void)fprintf |
|
#define xprintf (void)printf |
|
#define xvfprintf (void)fvprintf |
|
|
|
#define MD_LINE_SZ (256) /* Max input line size. */ |
|
|
struct md_parse { |
struct md_parse { |
int warn; |
int warn; /* Warning flags. */ |
#define MD_WARN_ALL (1 << 0) |
#define MD_WARN_SYNTAX (1 << 0) /* Show syntax warnings. */ |
#define MD_WARN_ERR (1 << 1) |
#define MD_WARN_COMPAT (1 << 1) /* Show compat warnings. */ |
int dbg; |
#define MD_WARN_ALL (0x03) /* Show all warnings. */ |
struct mdoc *mdoc; |
#define MD_WARN_ERR (1 << 2) /* Make warnings->errors. */ |
char *buf; |
int dbg; /* Debug level. */ |
u_long bufsz; |
struct mdoc *mdoc; /* Active parser. */ |
char *name; |
char *buf; /* Input buffer. */ |
int fd; |
u_long bufsz; /* Input buffer size. */ |
|
char *name; /* Input file name. */ |
|
int fd; /* Input file desc. */ |
}; |
}; |
|
|
|
extern char *__progname; |
|
|
static void usage(void); |
static void usage(void); |
|
|
static int parse_begin(struct md_parse *); |
static int parse_begin(struct md_parse *); |
Line 53 static int io_leave(struct md_parse *, int); |
|
Line 61 static int io_leave(struct md_parse *, int); |
|
static int buf_begin(struct md_parse *); |
static int buf_begin(struct md_parse *); |
static int buf_leave(struct md_parse *, int); |
static int buf_leave(struct md_parse *, int); |
|
|
static int msg_err(void *, int, int, enum mdoc_err); |
|
static int msg_warn(void *, int, int, enum mdoc_warn); |
|
static void msg_msg(void *, int, int, const char *); |
static void msg_msg(void *, int, int, const char *); |
|
static int msg_err(void *, int, int, const char *); |
|
static int msg_warn(void *, int, int, |
|
enum mdoc_warn, const char *); |
|
|
#ifdef __linux__ |
#ifdef __linux__ |
extern int getsubopt(char **, char *const *, char **); |
extern int getsubopt(char **, char *const *, char **); |
Line 68 main(int argc, char *argv[]) |
|
Line 77 main(int argc, char *argv[]) |
|
struct md_parse parser; |
struct md_parse parser; |
char *opts, *v; |
char *opts, *v; |
#define ALL 0 |
#define ALL 0 |
#define ERROR 1 |
#define COMPAT 1 |
char *toks[] = { "all", "error", NULL }; |
#define SYNTAX 2 |
|
#define ERROR 3 |
|
char *toks[] = { "all", "compat", "syntax", |
|
"error", NULL }; |
|
|
extern char *optarg; |
extern char *optarg; |
extern int optind; |
extern int optind; |
Line 88 main(int argc, char *argv[]) |
|
Line 100 main(int argc, char *argv[]) |
|
case (ALL): |
case (ALL): |
parser.warn |= MD_WARN_ALL; |
parser.warn |= MD_WARN_ALL; |
break; |
break; |
|
case (COMPAT): |
|
parser.warn |= MD_WARN_COMPAT; |
|
break; |
|
case (SYNTAX): |
|
parser.warn |= MD_WARN_SYNTAX; |
|
break; |
case (ERROR): |
case (ERROR): |
parser.warn |= MD_WARN_ERR; |
parser.warn |= MD_WARN_ERR; |
break; |
break; |
Line 176 buf_begin(struct md_parse *p) |
|
Line 194 buf_begin(struct md_parse *p) |
|
} |
} |
|
|
|
|
|
/* TODO: remove this to a print-tree output filter. */ |
static void |
static void |
print_node(const struct mdoc_node *n, int indent) |
print_node(const struct mdoc_node *n, int indent) |
{ |
{ |
Line 186 print_node(const struct mdoc_node *n, int indent) |
|
Line 205 print_node(const struct mdoc_node *n, int indent) |
|
struct mdoc_arg *argv; |
struct mdoc_arg *argv; |
|
|
argv = NULL; |
argv = NULL; |
argc = 0; |
argc = sz = 0; |
params = NULL; |
params = NULL; |
sz = 0; |
|
|
|
t = mdoc_type2a(n->type); |
t = mdoc_type2a(n->type); |
|
|
switch (n->type) { |
switch (n->type) { |
case (MDOC_TEXT): |
case (MDOC_TEXT): |
assert(NULL == n->child); |
|
p = n->data.text.string; |
p = n->data.text.string; |
break; |
break; |
case (MDOC_BODY): |
case (MDOC_BODY): |
Line 225 print_node(const struct mdoc_node *n, int indent) |
|
Line 242 print_node(const struct mdoc_node *n, int indent) |
|
} |
} |
|
|
for (i = 0; i < indent; i++) |
for (i = 0; i < indent; i++) |
(void)printf(" "); |
xprintf(" "); |
(void)printf("%s (%s)", p, t); |
xprintf("%s (%s)", p, t); |
|
|
for (i = 0; i < (int)argc; i++) { |
for (i = 0; i < (int)argc; i++) { |
(void)printf(" -%s", mdoc_argnames[argv[i].arg]); |
xprintf(" -%s", mdoc_argnames[argv[i].arg]); |
if (argv[i].sz > 0) |
if (argv[i].sz > 0) |
(void)printf(" ["); |
xprintf(" ["); |
for (j = 0; j < (int)argv[i].sz; j++) |
for (j = 0; j < (int)argv[i].sz; j++) |
(void)printf(" [%s]", argv[i].value[j]); |
xprintf(" [%s]", argv[i].value[j]); |
if (argv[i].sz > 0) |
if (argv[i].sz > 0) |
(void)printf(" ]"); |
xprintf(" ]"); |
} |
} |
|
|
for (i = 0; i < (int)sz; i++) |
for (i = 0; i < (int)sz; i++) |
(void)printf(" [%s]", params[i]); |
xprintf(" [%s]", params[i]); |
|
|
(void)printf(" %d:%d\n", n->line, n->pos); |
xprintf(" %d:%d\n", n->line, n->pos); |
|
|
if (n->child) |
if (n->child) |
print_node(n->child, indent + 1); |
print_node(n->child, indent + 1); |
Line 274 parse_begin(struct md_parse *p) |
|
Line 291 parse_begin(struct md_parse *p) |
|
{ |
{ |
ssize_t sz, i; |
ssize_t sz, i; |
size_t pos; |
size_t pos; |
char line[256], sv[256]; |
char line[MD_LINE_SZ]; |
struct mdoc_cb cb; |
struct mdoc_cb cb; |
int lnn; |
int lnn; |
|
|
Line 295 parse_begin(struct md_parse *p) |
|
Line 312 parse_begin(struct md_parse *p) |
|
for (i = 0; i < sz; i++) { |
for (i = 0; i < sz; i++) { |
if ('\n' != p->buf[i]) { |
if ('\n' != p->buf[i]) { |
if (pos < sizeof(line)) { |
if (pos < sizeof(line)) { |
sv[(int)pos] = p->buf[(int)i]; |
line[(int)pos++] = p->buf[(int)i]; |
line[(int)pos++] = |
|
p->buf[(int)i]; |
|
continue; |
continue; |
} |
} |
warnx("%s: line %d too long", |
warnx("%s: line %d too long", |
Line 305 parse_begin(struct md_parse *p) |
|
Line 320 parse_begin(struct md_parse *p) |
|
return(parse_leave(p, 0)); |
return(parse_leave(p, 0)); |
} |
} |
|
|
line[(int)pos] = sv[(int)pos] = 0; |
line[(int)pos] = 0; |
if ( ! mdoc_parseln(p->mdoc, lnn, line)) |
if ( ! mdoc_parseln(p->mdoc, lnn, line)) |
return(parse_leave(p, 0)); |
return(parse_leave(p, 0)); |
|
|
Line 319 parse_begin(struct md_parse *p) |
|
Line 334 parse_begin(struct md_parse *p) |
|
|
|
|
|
static int |
static int |
msg_err(void *arg, int line, int col, enum mdoc_err type) |
msg_err(void *arg, int line, int col, const char *msg) |
{ |
{ |
char *lit; |
|
struct md_parse *p; |
struct md_parse *p; |
|
|
p = (struct md_parse *)arg; |
p = (struct md_parse *)arg; |
|
|
lit = NULL; |
xfprintf(stderr, "%s:%d: error: %s (column %d)\n", |
|
p->name, line, msg, col); |
switch (type) { |
|
case (ERR_SYNTAX_NOTEXT): |
|
lit = "syntax: context-free text disallowed"; |
|
break; |
|
case (ERR_SYNTAX_QUOTE): |
|
lit = "syntax: disallowed argument quotation"; |
|
break; |
|
case (ERR_SYNTAX_UNQUOTE): |
|
lit = "syntax: unterminated quotation"; |
|
break; |
|
case (ERR_SYNTAX_WS): |
|
lit = "syntax: whitespace in argument"; |
|
break; |
|
case (ERR_SYNTAX_ARGFORM): |
|
lit = "syntax: macro arguments malformed"; |
|
break; |
|
case (ERR_SYNTAX_NOPUNCT): |
|
lit = "syntax: macro doesn't understand punctuation"; |
|
break; |
|
case (ERR_SYNTAX_ARG): |
|
lit = "syntax: unknown argument for macro"; |
|
break; |
|
case (ERR_SCOPE_BREAK): |
|
lit = "scope: macro breaks prior scope"; |
|
break; |
|
case (ERR_SCOPE_NOCTX): |
|
lit = "scope: closure macro has no context"; |
|
break; |
|
case (ERR_SCOPE_NONEST): |
|
lit = "scope: macro may not be nested in the current context"; |
|
break; |
|
case (ERR_MACRO_NOTSUP): |
|
lit = "macro not supported"; |
|
break; |
|
case (ERR_MACRO_NOTCALL): |
|
lit = "macro not callable"; |
|
break; |
|
case (ERR_SEC_PROLOGUE): |
|
lit = "macro cannot be called in the prologue"; |
|
break; |
|
case (ERR_SEC_NPROLOGUE): |
|
lit = "macro called outside of prologue"; |
|
break; |
|
case (ERR_ARGS_EQ0): |
|
lit = "macro expects zero arguments"; |
|
break; |
|
case (ERR_ARGS_EQ1): |
|
lit = "macro expects one argument"; |
|
break; |
|
case (ERR_ARGS_GE1): |
|
lit = "macro expects one or more arguments"; |
|
break; |
|
case (ERR_ARGS_LE2): |
|
lit = "macro expects two or fewer arguments"; |
|
break; |
|
case (ERR_ARGS_LE8): |
|
lit = "macro expects eight or fewer arguments"; |
|
break; |
|
case (ERR_ARGS_MANY): |
|
lit = "macro has too many arguments"; |
|
break; |
|
case (ERR_SEC_PROLOGUE_OO): |
|
lit = "prologue macro is out-of-order"; |
|
break; |
|
case (ERR_SEC_PROLOGUE_REP): |
|
lit = "prologue macro repeated"; |
|
break; |
|
case (ERR_SEC_NAME): |
|
lit = "`NAME' section must be first"; |
|
break; |
|
case (ERR_SYNTAX_ARGVAL): |
|
lit = "syntax: expected value for macro argument"; |
|
break; |
|
case (ERR_SYNTAX_ARGBAD): |
|
lit = "syntax: invalid value(s) for macro argument"; |
|
break; |
|
case (ERR_SYNTAX_ARGMISS): |
|
lit = "syntax: missing required argument(s) for macro"; |
|
break; |
|
case (ERR_SYNTAX_ARGMANY): |
|
lit = "syntax: too many values for macro argument"; |
|
break; |
|
case (ERR_SYNTAX_CHILDBAD): |
|
lit = "syntax: invalid child for parent macro"; |
|
break; |
|
case (ERR_SYNTAX_PARENTBAD): |
|
lit = "syntax: invalid parent for macro"; |
|
break; |
|
case (ERR_SYNTAX_CHILDHEAD): |
|
lit = "syntax: expected only block-header section"; |
|
break; |
|
case (ERR_SYNTAX_CHILDBODY): |
|
lit = "syntax: expected only a block-body section"; |
|
break; |
|
case (ERR_SYNTAX_EMPTYHEAD): |
|
lit = "syntax: block-header section may not be empty"; |
|
break; |
|
case (ERR_SYNTAX_EMPTYBODY): |
|
lit = "syntax: block-body section may not be empty"; |
|
break; |
|
default: |
|
abort(); |
|
/* NOTREACHED */ |
|
} |
|
|
|
(void)fprintf(stderr, "%s:%d: error: %s (column %d)\n", |
|
p->name, line, lit, col); |
|
return(0); |
return(0); |
} |
} |
|
|
Line 446 msg_msg(void *arg, int line, int col, const char *msg) |
|
Line 353 msg_msg(void *arg, int line, int col, const char *msg) |
|
|
|
p = (struct md_parse *)arg; |
p = (struct md_parse *)arg; |
|
|
if (p->dbg < 2) |
if (0 == p->dbg) |
return; |
return; |
|
|
(void)printf("%s:%d: %s (column %d)\n", |
xfprintf(stderr, "%s:%d: debug: %s (column %d)\n", |
p->name, line, msg, col); |
p->name, line, msg, col); |
} |
} |
|
|
|
|
static int |
static int |
msg_warn(void *arg, int line, int col, enum mdoc_warn type) |
msg_warn(void *arg, int line, int col, |
|
enum mdoc_warn type, const char *msg) |
{ |
{ |
char *lit; |
|
struct md_parse *p; |
struct md_parse *p; |
extern char *__progname; |
|
|
|
p = (struct md_parse *)arg; |
p = (struct md_parse *)arg; |
|
|
if ( ! (p->warn & MD_WARN_ALL)) |
|
return(1); |
|
|
|
lit = NULL; |
|
|
|
switch (type) { |
switch (type) { |
case (WARN_SYNTAX_WS_EOLN): |
case (WARN_COMPAT): |
lit = "syntax: whitespace at end-of-line"; |
if (p->warn & MD_WARN_COMPAT) |
break; |
break; |
case (WARN_SYNTAX_QUOTED): |
return(1); |
lit = "syntax: quotation mark starting string"; |
case (WARN_SYNTAX): |
break; |
if (p->warn & MD_WARN_SYNTAX) |
case (WARN_SYNTAX_MACLIKE): |
break; |
lit = "syntax: macro-like argument"; |
return(1); |
break; |
|
case (WARN_SYNTAX_ARGLIKE): |
|
lit = "syntax: argument-like value"; |
|
break; |
|
case (WARN_SYNTAX_EMPTYBODY): |
|
lit = "syntax: macro suggests non-empty block-body section"; |
|
break; |
|
case (WARN_SYNTAX_EMPTYHEAD): |
|
lit = "syntax: macro suggests non-empty block-head section"; |
|
break; |
|
case (WARN_SYNTAX_NOBODY): |
|
lit = "syntax: macro suggests empty block-body section"; |
|
break; |
|
case (WARN_SEC_OO): |
|
lit = "section is out of conventional order"; |
|
break; |
|
case (WARN_SEC_REP): |
|
lit = "section repeated"; |
|
break; |
|
case (WARN_ARGS_GE1): |
|
lit = "macro suggests one or more arguments"; |
|
break; |
|
case (WARN_ARGS_EQ0): |
|
lit = "macro suggests zero arguments"; |
|
break; |
|
case (WARN_IGN_AFTER_BLK): |
|
lit = "ignore: macro ignored after block macro"; |
|
break; |
|
case (WARN_IGN_OBSOLETE): |
|
lit = "ignore: macro is obsolete"; |
|
break; |
|
case (WARN_IGN_BEFORE_BLK): |
|
lit = "ignore: macro before block macro ignored"; |
|
break; |
|
case (WARN_COMPAT_TROFF): |
|
lit = "compat: macro behaves differently in troff and nroff"; |
|
break; |
|
default: |
|
abort(); |
|
/* NOTREACHED */ |
|
} |
} |
|
|
|
xfprintf(stderr, "%s:%d: warning: %s (column %d)\n", |
|
p->name, line, msg, col); |
|
|
(void)fprintf(stderr, "%s:%d: warning: %s (column %d)\n", |
if ( ! (p->warn & MD_WARN_ERR)) |
p->name, line, lit, col); |
return(1); |
|
|
if (p->warn & MD_WARN_ERR) { |
xfprintf(stderr, "%s: considering warnings as errors\n", |
(void)fprintf(stderr, "%s: considering warnings as " |
__progname); |
"errors\n", __progname); |
return(0); |
return(0); |
|
} |
|
|
|
return(1); |
|
} |
} |
|
|
|
|
static void |
static void |
usage(void) |
usage(void) |
{ |
{ |
extern char *__progname; |
|
|
|
(void)fprintf(stderr, "usage: %s [-v] [-Wwarn...] [infile]\n", |
xfprintf(stderr, "usage: %s [-v] [-Wwarn...] [infile]\n", |
__progname); |
__progname); |
} |
} |
|
|