diff options
-rw-r--r-- | Makefile | 20 | ||||
-rw-r--r-- | libmdocml.c | 6 | ||||
-rw-r--r-- | libmdocml.h | 6 | ||||
-rw-r--r-- | mdocml.1 | 44 | ||||
-rw-r--r-- | mdocml.c | 2 | ||||
-rw-r--r-- | private.h | 12 | ||||
-rw-r--r-- | roff.c | 111 |
7 files changed, 132 insertions, 69 deletions
@@ -2,15 +2,15 @@ CFLAGS += -W -Wall -Wno-unused-parameter -g LINTFLAGS += -c -e -f -u -LNS = mdocml.ln html4_strict.ln dummy.ln libmdocml.ln roff.ln +LNS = mdocml.ln html4_strict.ln validate.ln libmdocml.ln roff.ln LLNS = llib-lmdocml.ln LIBS = libmdocml.a -OBJS = mdocml.o html4_strict.o dummy.o libmdocml.o roff.o +OBJS = mdocml.o html4_strict.o validate.o libmdocml.o roff.o -SRCS = mdocml.c html4_strict.c dummy.c libmdocml.c roff.c +SRCS = mdocml.c html4_strict.c validate.c libmdocml.c roff.c HEADS = libmdocml.h private.h @@ -49,8 +49,8 @@ mdocml.tgz: $(INSTALL) ( cd .dist/ && tar zcf ../mdocml.tgz mdocml/ ) rm -rf .dist/ -llib-lmdocml.ln: mdocml.ln libmdocml.ln html4_strict.ln dummy.ln roff.ln - $(LINT) $(LINTFLAGS) -Cmdocml mdocml.ln libmdocml.ln html4_strict.ln dummy.ln roff.ln +llib-lmdocml.ln: mdocml.ln libmdocml.ln html4_strict.ln validate.ln roff.ln + $(LINT) $(LINTFLAGS) -Cmdocml mdocml.ln libmdocml.ln html4_strict.ln validate.ln roff.ln mdocml.ln: mdocml.c @@ -58,8 +58,14 @@ mdocml.o: mdocml.c mdocml.c: libmdocml.h -libmdocml.a: libmdocml.o html4_strict.o dummy.o roff.o - $(AR) rs $@ libmdocml.o html4_strict.o dummy.o roff.o +libmdocml.a: libmdocml.o html4_strict.o validate.o roff.o + $(AR) rs $@ libmdocml.o html4_strict.o validate.o roff.o + +validate.ln: validate.c + +validate.o: validate.c + +validate.c: private.h libmdocml.h html4_strict.ln: html4_strict.c diff --git a/libmdocml.c b/libmdocml.c index c7920e23..95a0ba2b 100644 --- a/libmdocml.c +++ b/libmdocml.c @@ -141,7 +141,7 @@ md_run_leave(const struct md_args *args, struct md_mbuf *mbuf, c = -1; break; default: - if ( ! md_exit_dummy(data, -1 == c ? 0 : 1)) + if ( ! md_exit_valid(data, -1 == c ? 0 : 1)) c = -1; break; } @@ -173,7 +173,7 @@ md_run_enter(const struct md_args *args, struct md_mbuf *mbuf, fp = md_line_html4_strict; break; default: - fp = md_line_dummy; + fp = md_line_valid; break; } @@ -244,7 +244,7 @@ md_run(const struct md_args *args, (args, &mbuf, &rbuf); break; default: - data = md_init_dummy + data = md_init_valid (args, &mbuf, &rbuf); break; } diff --git a/libmdocml.h b/libmdocml.h index 52bd3324..c2576146 100644 --- a/libmdocml.h +++ b/libmdocml.h @@ -21,7 +21,7 @@ #include <sys/types.h> -struct md_params_dummy { +struct md_params_valid { int dummy; }; @@ -30,12 +30,12 @@ struct md_params_html4_strict { }; union md_params { - struct md_params_dummy dummy; + struct md_params_valid valid; struct md_params_html4_strict html4_strict; }; enum md_type { - MD_DUMMY, /* Dummy type echoes input. */ + MD_VALID, /* Validate input only. */ MD_HTML4_STRICT /* HTML4.01-strict. */ }; @@ -7,22 +7,28 @@ .Dt mdocml 1 .Os .\" -.Op foo .Sh NAME .Nm mdocml .Nd compile manpage source into mark-up language .\" .Sh SYNOPSIS .Nm mdocml -.Op Fl W +.Op Fl vW +.Op Fl f Ar filter .Op Fl o Ar outfile .Op Ar infile .\" .Sh DESCRIPTION The .Nm -utility compiles manpage source into a mark-up language. Its arguments -are as follows: +utility parses +.Xr mdoc +formatted manual source and passes results into the output filter +dictated by +.Fl f Ar filter . +The only current output filter is +.Ar validate , +the default. The arguments are as follows: .Bl -tag -width "\-o outfile" .It Fl o Ar outfile Place output in @@ -36,9 +42,17 @@ Read input from which may be .Qq \- for standard input. The default is standard input. +.It Fl v +Print messages (output depends on filter). .It Fl W -Print warnings. +Print warnings (output depends on filter). .El +.Ss Validate Filter +The validate filter, specified by +.Fl f Ar validate , +is the default filter. It produces no output, so specifying +.Fl o Ar outfile +results in an empty file. .\" The following requests should be uncommented and used where appropriate. .\" This next request is for sections 2, 3, and 9 function return values only. .\" .Sh RETURN VALUES @@ -63,14 +77,24 @@ utility was written by .An Kristaps Dzonsons Aq kristaps@kth.se . .\" .Sh CAVEATS -The +Most caveats of .Nm -engine doesn't understand +stem from ambiguities in +.Xr mdoc 7 +or the necessary limitations of converting an ad hoc language into +structured ones: +.Bl -enum -compact -offset indent +.It +The engine doesn't understand .Sq \&Xo and .Sq \&Xc troff macros. -.Pp -.Em All -macro arguments may be quoted, instead of only some. +.It +All macro arguments may be quoted, instead of only some. +.It +Blank lines raise warnings. +.It +Non-ascii characters may cause issues. +.El .\" .Sh BUGS @@ -80,8 +80,6 @@ main(int argc, char *argv[]) if (1 == argc) in = *argv++; - args.type = MD_DUMMY; - return(begin_io(&args, out ? out : "-", in ? in : "-")); } @@ -212,13 +212,13 @@ struct roffcb { void (*roffmsg)(const struct md_args *, enum roffmsg, const char *, const char *, const char *, int, char *); - int (*roffhead)(void); - int (*rofftail)(void); + int (*roffhead)(const struct md_args *); + int (*rofftail)(const struct md_args *); int (*roffin)(const struct md_args *, int, int *, char **); int (*roffout)(const struct md_args *, int); int (*roffblkin)(const struct md_args *, int); int (*roffblkout)(const struct md_args *, int); - int (*roffspecial)(int); + int (*roffspecial)(const struct md_args *, int); }; __BEGIN_DECLS @@ -233,10 +233,10 @@ void *md_init_html4_strict(const struct md_args *, int md_line_html4_strict(void *, char *, size_t); int md_exit_html4_strict(void *, int); -void *md_init_dummy(const struct md_args *, +void *md_init_valid(const struct md_args *, struct md_mbuf *, const struct md_rbuf *); -int md_line_dummy(void *, char *, size_t); -int md_exit_dummy(void *, int); +int md_line_valid(void *, char *, size_t); +int md_exit_valid(void *, int); int md_buf_puts(struct md_mbuf *, const char *, size_t); int md_buf_putchar(struct md_mbuf *, char); @@ -85,19 +85,21 @@ struct roffnode { struct rofftree { struct roffnode *last; /* Last parsed node. */ - time_t date; /* `Dd' results. */ char *cur; + + time_t date; /* `Dd' results. */ char os[64]; /* `Os' results. */ char title[64]; /* `Dt' results. */ char section[64]; /* `Dt' results. */ char volume[64]; /* `Dt' results. */ + int state; #define ROFF_PRELUDE (1 << 1) /* In roff prelude. */ - /* FIXME: if we had prev ptrs, this wouldn't be necessary. */ #define ROFF_PRELUDE_Os (1 << 2) /* `Os' is parsed. */ #define ROFF_PRELUDE_Dt (1 << 3) /* `Dt' is parsed. */ #define ROFF_PRELUDE_Dd (1 << 4) /* `Dd' is parsed. */ #define ROFF_BODY (1 << 5) /* In roff body. */ + struct md_mbuf *mbuf; /* Output (or NULL). */ const struct md_args *args; /* Global args. */ const struct md_rbuf *rbuf; /* Input. */ @@ -175,8 +177,7 @@ static const int roffparent_It[] = { ROFF_Bl, ROFF_It, ROFF_MAX }; static const int roffparent_Re[] = { ROFF_Rs, ROFF_MAX }; /* Table of all known tokens. */ -static const struct rofftok tokens[ROFF_MAX] = - { +static const struct rofftok tokens[ROFF_MAX] = { {roff_comment, NULL, NULL, NULL, 0, ROFF_COMMENT, 0 }, /* \" */ { roff_Dd, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Dd */ { roff_Dt, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Dt */ @@ -273,17 +274,16 @@ static const struct rofftok tokens[ROFF_MAX] = { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ux */ { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xc */ { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xo */ - { roff_layout, NULL, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Fo */ + { roff_layout, NULL, NULL, roffchild_Fo, 0, ROFF_LAYOUT, 0 }, /* Fo */ { roff_close, NULL, roffparent_Fc, NULL, ROFF_Fo, ROFF_LAYOUT, 0 }, /* Fc */ - { roff_layout, NULL, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Oo */ + { roff_layout, NULL, NULL, roffchild_Oo, 0, ROFF_LAYOUT, 0 }, /* Oo */ { roff_close, NULL, roffparent_Oc, NULL, ROFF_Oo, ROFF_LAYOUT, 0 }, /* Oc */ { roff_layout, roffarg_Bk, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Bk */ { roff_close, NULL, NULL, NULL, ROFF_Bk, ROFF_LAYOUT, 0 }, /* Ek */ }; /* Table of all known token arguments. */ -static const int tokenargs[ROFF_ARGMAX] = - { +static const int tokenargs[ROFF_ARGMAX] = { 0, 0, 0, 0, 0, ROFF_VALUE, ROFF_VALUE, 0, 0, 0, 0, 0, @@ -301,8 +301,7 @@ static const int tokenargs[ROFF_ARGMAX] = 0, 0, 0, 0, }; -const char *const toknamesp[ROFF_MAX] = - { +const char *const toknamesp[ROFF_MAX] = { "\\\"", "Dd", "Dt", "Os", "Sh", "Ss", "Pp", "D1", "Dl", "Bd", "Ed", "Bl", @@ -331,8 +330,7 @@ const char *const toknamesp[ROFF_MAX] = "Bk", "Ek", }; -const char *const tokargnamesp[ROFF_ARGMAX] = - { +const char *const tokargnamesp[ROFF_ARGMAX] = { "split", "nosplit", "ragged", "unfilled", "literal", "file", "offset", "bullet", "dash", @@ -355,7 +353,6 @@ const char *const tokargnamesp[ROFF_ARGMAX] = "svid4", "filled", "words", }; - const char *const *toknames = toknamesp; const char *const *tokargnames = tokargnamesp; @@ -363,23 +360,36 @@ const char *const *tokargnames = tokargnamesp; int roff_free(struct rofftree *tree, int flush) { - int error; + int error, tok; assert(tree->mbuf); if ( ! flush) tree->mbuf = NULL; /* LINTED */ - while (tree->last) + while (tree->last) { + if (tree->last->parent) { + tok = tree->last->tok; + if (tokens[tok].ctx == 0) { + warnx("%s: closing out explicit scope " + "of `%s' from line %zu", + tree->rbuf->name, + toknames[tok], + tree->last->line); + tree->mbuf = NULL; + } + } if ( ! (*tokens[tree->last->tok].cb) (tree->last->tok, tree, NULL, ROFF_EXIT)) /* Disallow flushing. */ tree->mbuf = NULL; + } error = tree->mbuf ? 0 : 1; if (tree->mbuf && (ROFF_PRELUDE & tree->state)) { - /*roff_warn(tree, "prelude never finished");*/ + warnx("%s: prelude never finished", + tree->rbuf->name); error = 1; } @@ -411,7 +421,7 @@ int roff_engine(struct rofftree *tree, char *buf, size_t sz) { - tree->cur = buf; + tree->cur = NULL; if (0 == sz) { roff_warn(tree, buf, "blank line"); @@ -540,17 +550,17 @@ roffparse(struct rofftree *tree, char *buf, size_t sz) */ if ( ! roffscan(tree->last->tok, tokens[tok].parents)) { - warnx("%s: invalid parent `%s' for `%s' (line %zu)", - tree->rbuf->name, - toknames[tree->last->tok], - toknames[tok], tree->rbuf->line); + roff_err(tree, *argvp, "`%s' has invalid parent `%s' " + "from line %zu", toknames[tok], + toknames[tree->rbuf->line], + tree->rbuf->line); return(0); } if ( ! roffscan(tok, tokens[tree->last->tok].children)) { - warnx("%s: invalid child `%s' for `%s' (line %zu)", - tree->rbuf->name, toknames[tok], - toknames[tree->last->tok], + roff_err(tree, *argvp, "`%s' is invalid child for " + "`%s' from line %zu", toknames[tok], + toknames[tree->rbuf->line], tree->rbuf->line); return(0); } @@ -632,6 +642,7 @@ roffparse(struct rofftree *tree, char *buf, size_t sz) assert(tree->last); assert(tok != tokens[tok].ctx && 0 != tokens[tok].ctx); + /* LINTED */ do { t = tree->last->tok; if ( ! (*tokens[t].cb)(t, tree, NULL, ROFF_EXIT)) @@ -901,6 +912,8 @@ roff_layout(ROFFCALL_ARGS) return((*tree->cb->roffblkout)(tree->args, tok)); } + assert(tree->mbuf); + i = 0; argv++; @@ -924,8 +937,15 @@ roff_layout(ROFFCALL_ARGS) return(0); if ( ! (ROFF_PARSED & tokens[tok].flags)) { + while (*argv) { + if ( ! md_buf_putstring(tree->mbuf, *argv++)) + return(0); + if ( ! md_buf_putchar(tree->mbuf, ' ')) + return(0); + } - /* TODO: print all tokens. */ + if ( ! md_buf_putchar(tree->mbuf, '\n')) + return(0); if ( ! ((*tree->cb->roffout)(tree->args, tok))) return(0); @@ -940,19 +960,22 @@ roff_layout(ROFFCALL_ARGS) toknames[c]); return(0); } - if ( ! (*tokens[c].cb)(c, tree, - argv, ROFF_ENTER)) + if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER)) return(0); + break; } - /* TODO: print token. */ - - argv++; + if ( ! md_buf_putstring(tree->mbuf, *argv++)) + return(0); + if ( ! md_buf_putchar(tree->mbuf, ' ')) + return(0); } - if ( ! ((*tree->cb->roffout)(tree->args, tok))) + if (NULL == *argv && ! md_buf_putchar(tree->mbuf, '\n')) return(0); + if ( ! ((*tree->cb->roffout)(tree->args, tok))) + return(0); return((*tree->cb->roffblkin)(tree->args, tok)); } @@ -964,6 +987,8 @@ roff_text(ROFFCALL_ARGS) int i, c, argcp[ROFF_MAXARG]; char *v, *argvp[ROFF_MAXARG]; + assert(tree->mbuf); + if (ROFF_PRELUDE & tree->state) { roff_err(tree, *argv, "`%s' disallowed in prelude", toknames[tok]); @@ -990,9 +1015,14 @@ roff_text(ROFFCALL_ARGS) return(0); if ( ! (ROFF_PARSED & tokens[tok].flags)) { - - /* TODO: print all tokens. */ - + while (*argv) { + if ( ! md_buf_putstring(tree->mbuf, *argv++)) + return(0); + if ( ! md_buf_putchar(tree->mbuf, ' ')) + return(0); + } + if ( ! md_buf_putchar(tree->mbuf, '\n')) + return(0); return((*tree->cb->roffout)(tree->args, tok)); } @@ -1007,13 +1037,18 @@ roff_text(ROFFCALL_ARGS) if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER)) return(0); + break; } - /* TODO: print token. */ - - argv++; + if ( ! md_buf_putstring(tree->mbuf, *argv++)) + return(0); + if ( ! md_buf_putchar(tree->mbuf, ' ')) + return(0); } + if (NULL == *argv && ! md_buf_putchar(tree->mbuf, '\n')) + return(0); + return((*tree->cb->roffout)(tree->args, tok)); } @@ -1041,7 +1076,7 @@ static int roff_special(ROFFCALL_ARGS) { - return((*tree->cb->roffspecial)(tok)); + return((*tree->cb->roffspecial)(tree->args, tok)); } |