summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile20
-rw-r--r--libmdocml.c6
-rw-r--r--libmdocml.h6
-rw-r--r--mdocml.144
-rw-r--r--mdocml.c2
-rw-r--r--private.h12
-rw-r--r--roff.c111
7 files changed, 132 insertions, 69 deletions
diff --git a/Makefile b/Makefile
index 5754e2e0..0b1bb189 100644
--- a/Makefile
+++ b/Makefile
@@ -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. */
};
diff --git a/mdocml.1 b/mdocml.1
index 79941da1..d522e659 100644
--- a/mdocml.1
+++ b/mdocml.1
@@ -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
diff --git a/mdocml.c b/mdocml.c
index eb71ddb6..4f7eac9a 100644
--- a/mdocml.c
+++ b/mdocml.c
@@ -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 : "-"));
}
diff --git a/private.h b/private.h
index f77a6773..6a2101f9 100644
--- a/private.h
+++ b/private.h
@@ -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);
diff --git a/roff.c b/roff.c
index 39f548f4..d7d88b71 100644
--- a/roff.c
+++ b/roff.c
@@ -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));
}