summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2009-01-16 15:58:50 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2009-01-16 15:58:50 +0000
commit50c7e68a675c2b7d573e94e93564b37785d2cad6 (patch)
tree11e1cf0f02ae887d2f5cafa23e29d58e04a3d5d9
parent74e24071f684da83ad181e5fec715d15f5f4dfae (diff)
downloadmandoc-50c7e68a675c2b7d573e94e93564b37785d2cad6.tar.gz
Initial separation of tree/mdocml.1.
Finished mdoc.3. Broken build: mdocml.c.
-rw-r--r--mdoc.3123
-rw-r--r--mdoc.c3
-rw-r--r--mdocml.14
-rw-r--r--mdocml.c143
-rw-r--r--tree.c101
-rw-r--r--validate.c136
6 files changed, 366 insertions, 144 deletions
diff --git a/mdoc.3 b/mdoc.3
index 1cc4eaca..a1b468cd 100644
--- a/mdoc.3
+++ b/mdoc.3
@@ -9,20 +9,20 @@
.Nm mdoc_endparse ,
.Nm mdoc_result ,
.Nm mdoc_free
-.Nd mdoc macro compiler
+.Nd mdoc macro compiler library
.\"
.Sh SYNOPSIS
.In mdoc.h
.Ft "struct mdoc *"
.Fn mdoc_alloc "void *data" "const struct mdoc_cb *cb"
.Ft void
-.Fn mdoc_free "struct mdoc *"
+.Fn mdoc_free "struct mdoc *mdoc"
.Ft int
-.Fn mdoc_parseln "struct mdoc *" "int" "char *buf"
+.Fn mdoc_parseln "struct mdoc *mdoc" "int line" "char *buf"
.Ft "const struct mdoc_node *"
-.Fn mdoc_result "struct mdoc *"
+.Fn mdoc_result "struct mdoc *mdoc"
.Ft int
-.Fn mdoc_endparse "struct mdoc *"
+.Fn mdoc_endparse "struct mdoc *mdoc"
.\"
.Sh DESCRIPTION
The
@@ -41,16 +41,103 @@ then free all allocated memory with
See the
.Sx EXAMPLES
section for a full example.
-.\" 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
-.\" .Sh EXAMPLES
-.\" The next request is for sections 2, 3, and 9 error and signal handling only.
-.\" .Sh ERRORS
-.\" .Sh SEE ALSO
-.\" .Xr foobar 1
-.\" .Sh STANDARDS
-.\" .Sh HISTORY
-.\" .Sh AUTHORS
-.\" .Sh CAVEATS
-.\" .Sh BUGS
+.Pp
+Function descriptions follow:
+.Bl -ohang -offset indent
+.It Fn mdoc_alloc
+Allocates a parsing structure. The
+.Fa data
+pointer is passed to callbacks in
+.Fa cb ,
+which are documented further in the header file. Returns NULL on
+failure. If non-NULL, the pointer must be freed with
+.Fn mdoc_free .
+.It Fn mdoc_free
+Free all resources of a parser. The pointer is no longer valid after
+invocation.
+.It Fn mdoc_parseln
+Parse a nil-terminated line of input. This line should not contain the
+trailing newline. Returns 0 on failure, 1 on success. The input buffer
+.Fa buf
+is modified by this function.
+.It Fn mdoc_endparse
+Signals that the parse is complete. Note that if
+.Fn mdoc_endparse
+is called subsequent to
+.Fn mdoc_result ,
+the resulting tree is incomplete. Returns 0 on failure, 1 on success.
+.It Fn mdoc_result
+Returns the result of the parse or NULL on failure. Note that if
+.Fn mdoc_parseln
+or
+.Fn mdoc_endparse
+return 0, the tree will be incomplete.
+.El
+.Pp
+.Nm
+is
+.Ud
+.\"
+.Sh EXAMPLES
+The following example reads lines from stdin and parses them, operating
+on the finished parse tree with
+.Fn parsed .
+Note that, if the last line of the file isn't newline-terminated, this
+will truncate the file's last character (see
+.Xr fgetln 3 ) .
+Further, this example does not error-check nor free memory upon failure.
+.Bd -literal
+struct mdoc *mdoc;
+struct mdoc_node *node;
+char *buf;
+size_t len;
+int line;
+
+line = 1;
+mdoc = mdoc_alloc(NULL, NULL);
+
+while ((buf = fgetln(fp, &len))) {
+ buf[len - 1] = '\\0';
+ if ( ! mdoc_parseln(mdoc, line, buf))
+ errx(1, "mdoc_parseln");
+ line++;
+}
+
+if ( ! mdoc_endparse(mdoc))
+ errx(1, "mdoc_endparse");
+if (NULL == (node = mdoc_result(mdoc)))
+ errx(1, "mdoc_result");
+
+parsed(mdoc, node);
+mdoc_free(mdoc);
+.Ed
+.\"
+.Sh SEE ALSO
+.Xr mdoc 7 ,
+.Xr mdoc.samples 7 ,
+.Xr groff 1 ,
+.Xr mdocml 1
+.\"
+.\"
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An Kristaps Dzonsons Aq kristaps@kth.se .
+.\"
+.\"
+.Sh BUGS
+The
+.Sq \&Xc
+and
+.Sq \&Xo
+macros aren't handled when used to span lines for the
+.Sq \&It
+macro. Such usage is specifically discouraged in
+.Xr mdoc.samples 7 .
+.Pp
+When
+.Sq \&It \-column
+is invoked, whitespace is not stripped around
+.Sq \&Ta
+or tab-character separators.
diff --git a/mdoc.c b/mdoc.c
index e51f7771..783ea1a2 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -241,7 +241,8 @@ mdoc_alloc(void *data, const struct mdoc_cb *cb)
p = xcalloc(1, sizeof(struct mdoc));
p->data = data;
- (void)memcpy(&p->cb, cb, sizeof(struct mdoc_cb));
+ if (cb)
+ (void)memcpy(&p->cb, cb, sizeof(struct mdoc_cb));
p->last = xcalloc(1, sizeof(struct mdoc_node));
p->last->type = MDOC_ROOT;
diff --git a/mdocml.1 b/mdocml.1
index add2cf6a..ef1db230 100644
--- a/mdocml.1
+++ b/mdocml.1
@@ -56,6 +56,10 @@ reads from stdin, writes messages to stdout, and writes errors and
warnings to stderr.
.Pp
.Ex -std mdocml
+.Pp
+.Nm
+is
+.Ud
.\"
.Sh EXAMPLES
To validate this manual page:
diff --git a/mdocml.c b/mdocml.c
index af184833..ce104b5d 100644
--- a/mdocml.c
+++ b/mdocml.c
@@ -36,38 +36,42 @@
#define MD_LINE_SZ (256) /* Max input line size. */
+
struct md_parse {
- int warn; /* Warning flags. */
-#define MD_WARN_SYNTAX (1 << 0) /* Show syntax warnings. */
-#define MD_WARN_COMPAT (1 << 1) /* Show compat warnings. */
-#define MD_WARN_ALL (0x03) /* Show all warnings. */
-#define MD_WARN_ERR (1 << 2) /* Make warnings->errors. */
- int dbg; /* Debug level. */
- struct mdoc *mdoc; /* Active parser. */
- char *buf; /* Input buffer. */
- u_long bufsz; /* Input buffer size. */
- char *name; /* Input file name. */
- int fd; /* Input file desc. */
+ int warn; /* Warning flags. */
+#define MD_WARN_SYNTAX (1 << 0) /* Show syntax warnings. */
+#define MD_WARN_COMPAT (1 << 1) /* Show compat warnings. */
+#define MD_WARN_ALL (0x03) /* Show all warnings. */
+#define MD_WARN_ERR (1 << 2) /* Make warnings->errors. */
+ int dbg; /* Debug level. */
+ struct mdoc *mdoc; /* Active parser. */
+ char *buf; /* Input buffer. */
+ u_long bufsz; /* Input buffer size. */
+ char *name; /* Input file name. */
+ int fd; /* Input file desc. */
+ int (*fp)(const struct mdoc_node *, const char *);
};
-extern char *__progname;
+extern char *__progname;
+
+extern int
-static void usage(void);
+static void usage(void);
-static int parse_begin(struct md_parse *);
-static int parse_leave(struct md_parse *, int);
-static int io_begin(struct md_parse *);
-static int io_leave(struct md_parse *, int);
-static int buf_begin(struct md_parse *);
-static int buf_leave(struct md_parse *, int);
+static int parse_begin(struct md_parse *);
+static int parse_leave(struct md_parse *, int);
+static int io_begin(struct md_parse *);
+static int io_leave(struct md_parse *, int);
+static int buf_begin(struct md_parse *);
+static int buf_leave(struct md_parse *, int);
-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,
+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__
-extern int getsubopt(char **, char *const *, char **);
+extern int getsubopt(char **, char *const *, char **);
#endif
int
@@ -75,7 +79,7 @@ main(int argc, char *argv[])
{
int c;
struct md_parse parser;
- char *opts, *v;
+ char *opts, *v, *filter, *output;
#define ALL 0
#define COMPAT 1
#define SYNTAX 2
@@ -86,10 +90,18 @@ main(int argc, char *argv[])
extern char *optarg;
extern int optind;
+ output = filter = NULL;
+
(void)memset(&parser, 0, sizeof(struct md_parse));
- while (-1 != (c = getopt(argc, argv, "vW:")))
+ while (-1 != (c = getopt(argc, argv, "f:vW:o:")))
switch (c) {
+ case ('f'):
+ filter = optarg;
+ break;
+ case ('o'):
+ output = optarg;
+ break;
case ('v'):
parser.dbg++;
break;
@@ -194,79 +206,6 @@ buf_begin(struct md_parse *p)
}
-/* TODO: remove this to a print-tree output filter. */
-static void
-print_node(const struct mdoc_node *n, int indent)
-{
- const char *p, *t;
- int i, j;
- size_t argc, sz;
- char **params;
- struct mdoc_arg *argv;
-
- argv = NULL;
- argc = sz = 0;
- params = NULL;
-
- t = mdoc_type2a(n->type);
-
- switch (n->type) {
- case (MDOC_TEXT):
- p = n->data.text.string;
- break;
- case (MDOC_BODY):
- p = mdoc_macronames[n->tok];
- break;
- case (MDOC_HEAD):
- p = mdoc_macronames[n->tok];
- break;
- case (MDOC_TAIL):
- p = mdoc_macronames[n->tok];
- break;
- case (MDOC_ELEM):
- p = mdoc_macronames[n->tok];
- argv = n->data.elem.argv;
- argc = n->data.elem.argc;
- break;
- case (MDOC_BLOCK):
- p = mdoc_macronames[n->tok];
- argv = n->data.block.argv;
- argc = n->data.block.argc;
- break;
- case (MDOC_ROOT):
- p = "root";
- break;
- default:
- abort();
- /* NOTREACHED */
- }
-
- for (i = 0; i < indent; i++)
- xprintf(" ");
- xprintf("%s (%s)", p, t);
-
- for (i = 0; i < (int)argc; i++) {
- xprintf(" -%s", mdoc_argnames[argv[i].arg]);
- if (argv[i].sz > 0)
- xprintf(" [");
- for (j = 0; j < (int)argv[i].sz; j++)
- xprintf(" [%s]", argv[i].value[j]);
- if (argv[i].sz > 0)
- xprintf(" ]");
- }
-
- for (i = 0; i < (int)sz; i++)
- xprintf(" [%s]", params[i]);
-
- xprintf(" %d:%d\n", n->line, n->pos);
-
- if (n->child)
- print_node(n->child, indent + 1);
- if (n->next)
- print_node(n->next, indent);
-}
-
-
static int
parse_leave(struct md_parse *p, int code)
{
@@ -277,8 +216,8 @@ parse_leave(struct md_parse *p, int code)
if ( ! mdoc_endparse(p->mdoc))
code = 0;
- if ((n = mdoc_result(p->mdoc)))
- print_node(n, 0);
+ if (p->fp && (n = mdoc_result(p->mdoc)))
+ (*p->fp)(n, NULL);
mdoc_free(p->mdoc);
@@ -396,7 +335,7 @@ static void
usage(void)
{
- xfprintf(stderr, "usage: %s [-v] [-Wwarn...] [infile]\n",
- __progname);
+ xfprintf(stderr, "usage: %s [-v] [-Wwarn...] [-ffilter] "
+ "[-o outfile] [infile]\n", __progname);
}
diff --git a/tree.c b/tree.c
new file mode 100644
index 00000000..9fbdd245
--- /dev/null
+++ b/tree.c
@@ -0,0 +1,101 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <stdlib.h>
+
+#include "mdoc.h"
+
+
+#if 0
+/* TODO: remove this to a print-tree output filter. */
+static void
+print_node(const struct mdoc_node *n, int indent)
+{
+ const char *p, *t;
+ int i, j;
+ size_t argc, sz;
+ char **params;
+ struct mdoc_arg *argv;
+
+ argv = NULL;
+ argc = sz = 0;
+ params = NULL;
+
+ t = mdoc_type2a(n->type);
+
+ switch (n->type) {
+ case (MDOC_TEXT):
+ p = n->data.text.string;
+ break;
+ case (MDOC_BODY):
+ p = mdoc_macronames[n->tok];
+ break;
+ case (MDOC_HEAD):
+ p = mdoc_macronames[n->tok];
+ break;
+ case (MDOC_TAIL):
+ p = mdoc_macronames[n->tok];
+ break;
+ case (MDOC_ELEM):
+ p = mdoc_macronames[n->tok];
+ argv = n->data.elem.argv;
+ argc = n->data.elem.argc;
+ break;
+ case (MDOC_BLOCK):
+ p = mdoc_macronames[n->tok];
+ argv = n->data.block.argv;
+ argc = n->data.block.argc;
+ break;
+ case (MDOC_ROOT):
+ p = "root";
+ break;
+ default:
+ abort();
+ /* NOTREACHED */
+ }
+
+ for (i = 0; i < indent; i++)
+ xprintf(" ");
+ xprintf("%s (%s)", p, t);
+
+ for (i = 0; i < (int)argc; i++) {
+ xprintf(" -%s", mdoc_argnames[argv[i].arg]);
+ if (argv[i].sz > 0)
+ xprintf(" [");
+ for (j = 0; j < (int)argv[i].sz; j++)
+ xprintf(" [%s]", argv[i].value[j]);
+ if (argv[i].sz > 0)
+ xprintf(" ]");
+ }
+
+ for (i = 0; i < (int)sz; i++)
+ xprintf(" [%s]", params[i]);
+
+ xprintf(" %d:%d\n", n->line, n->pos);
+
+ if (n->child)
+ print_node(n->child, indent + 1);
+ if (n->next)
+ print_node(n->next, indent);
+}
+#endif
+
+int
+treeprint(const struct mdoc_node *node, const char *out)
+{
+}
diff --git a/validate.c b/validate.c
index 53ac48e2..98093752 100644
--- a/validate.c
+++ b/validate.c
@@ -45,6 +45,7 @@ static int pre_it(struct mdoc *, struct mdoc_node *);
static int pre_cd(struct mdoc *, struct mdoc_node *);
static int pre_er(struct mdoc *, struct mdoc_node *);
static int pre_ex(struct mdoc *, struct mdoc_node *);
+static int pre_an(struct mdoc *, struct mdoc_node *);
static int pre_prologue(struct mdoc *, struct mdoc_node *);
static int pre_prologue(struct mdoc *, struct mdoc_node *);
static int pre_prologue(struct mdoc *, struct mdoc_node *);
@@ -53,6 +54,7 @@ static int head_err_ge1(struct mdoc *);
static int head_warn_ge1(struct mdoc *);
static int head_err_eq0(struct mdoc *);
static int elem_err_eq0(struct mdoc *);
+static int elem_err_le1(struct mdoc *);
static int elem_err_eq1(struct mdoc *);
static int elem_err_ge1(struct mdoc *);
static int elem_warn_eq0(struct mdoc *);
@@ -63,6 +65,8 @@ static int elem_bool(struct mdoc *);
static int post_sh(struct mdoc *);
static int post_bl(struct mdoc *);
static int post_it(struct mdoc *);
+static int post_ex(struct mdoc *);
+static int post_an(struct mdoc *);
static v_pre pres_prologue[] = { pre_prologue, NULL };
static v_pre pres_d1[] = { pre_display, NULL };
@@ -74,6 +78,7 @@ static v_pre pres_sh[] = { pre_sh, NULL };
static v_pre pres_cd[] = { pre_cd, NULL };
static v_pre pres_er[] = { pre_er, NULL };
static v_pre pres_ex[] = { pre_ex, NULL };
+static v_pre pres_an[] = { pre_an, NULL };
static v_post posts_bool[] = { elem_err_eq1, elem_bool, NULL };
static v_post posts_bd[] = { head_err_eq0, body_warn_ge1, NULL };
@@ -89,6 +94,8 @@ static v_post posts_it[] = { post_it, NULL };
static v_post posts_ss[] = { head_err_ge1, NULL };
static v_post posts_pp[] = { elem_warn_eq0, NULL };
static v_post posts_d1[] = { head_err_ge1, NULL };
+static v_post posts_ex[] = { elem_err_le1, post_ex, NULL };
+static v_post posts_an[] = { post_an, NULL };
const struct valids mdoc_valids[MDOC_MAX] = {
@@ -101,7 +108,7 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ pres_sh, posts_sh }, /* Sh */
/* FIXME: preceding Pp. */
{ pres_ss, posts_ss }, /* Ss */
- /* FIXME: proceeding... */
+ /* FIXME: proceeding Pp */
{ NULL, posts_pp }, /* Pp */
{ pres_d1, posts_d1 }, /* D1 */
{ pres_d1, posts_d1 }, /* Dl */
@@ -113,17 +120,17 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* El */
{ pres_it, posts_it }, /* It */
{ NULL, posts_text }, /* Ad */
- /* FIXME: argument OR parameters. */
- { NULL, NULL }, /* An */
+ { pres_an, posts_an }, /* An */
{ NULL, NULL }, /* Ar */
{ pres_cd, posts_text }, /* Cd */
{ NULL, NULL }, /* Cm */
{ NULL, posts_text }, /* Dv */
{ pres_er, posts_text }, /* Er */
{ NULL, posts_text }, /* Ev */
- { pres_ex, posts_notext }, /* Ex */ /* FIXME: -std required */
+ { pres_ex, posts_ex }, /* Ex */
{ NULL, posts_text }, /* Fa */
- { NULL, NULL }, /* Fd */ /* FIXME: SYNOPSIS section. */
+ /* FIXME: only in SYNOPSIS section. */
+ { NULL, NULL }, /* Fd */
{ NULL, NULL }, /* Fl */
{ NULL, posts_text }, /* Fn */
{ NULL, NULL }, /* Ft */
@@ -131,15 +138,16 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, posts_wtext }, /* In */
{ NULL, posts_text }, /* Li */
{ NULL, posts_wtext }, /* Nd */
- { NULL, NULL }, /* Nm */ /* FIXME: If name not set? */
+ /* FIXME: check that name must be set/provided. */
+ { NULL, NULL }, /* Nm */
{ NULL, posts_wline }, /* Op */
{ NULL, NULL }, /* Ot */
{ NULL, NULL }, /* Pa */
- { NULL, posts_notext }, /* Rv */ /* -std required */
- { NULL, posts_notext }, /* St */ /* arg required */
+ { NULL, posts_notext }, /* Rv */ /* FIXME: -std required */
+ { NULL, posts_notext }, /* St */ /* FIXME: arg required */
{ NULL, posts_text }, /* Va */
{ NULL, posts_text }, /* Vt */
- { NULL, NULL }, /* Xr */ /* FIXME */
+ { NULL, NULL }, /* Xr */ /* FIXME: valid arguments */
{ NULL, posts_text }, /* %A */
{ NULL, posts_text }, /* %B */
{ NULL, posts_text }, /* %D */
@@ -154,7 +162,7 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Ac */
{ NULL, NULL }, /* Ao */
{ NULL, posts_wline }, /* Aq */
- { NULL, NULL }, /* At */ /* FIXME */
+ { NULL, NULL }, /* At */ /* FIXME: valid arguments */
{ NULL, NULL }, /* Bc */
{ NULL, NULL }, /* Bf */
{ NULL, NULL }, /* Bo */
@@ -176,7 +184,7 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Nx */
{ NULL, NULL }, /* Ox */
{ NULL, NULL }, /* Pc */
- { NULL, NULL }, /* Pf */ /* FIXME: 2 or more arguments */ /* First should be text. */
+ { NULL, NULL }, /* Pf */
{ NULL, NULL }, /* Po */
{ NULL, posts_wline }, /* Pq */ /* FIXME: ignore following Sh/Ss */
{ NULL, NULL }, /* Qc */
@@ -227,13 +235,13 @@ pre_check_parent(struct mdoc *mdoc, struct mdoc_node *node,
int tok, enum mdoc_type type)
{
- if (type != mdoc->last->parent->type)
+ if (type != node->parent->type)
return(mdoc_nerr(mdoc, node, "invalid macro parent class %s, expected %s",
- mdoc_type2a(mdoc->last->parent->type),
+ mdoc_type2a(node->parent->type),
mdoc_type2a(type)));
- if (MDOC_ROOT != type && tok == mdoc->last->parent->tok)
+ if (MDOC_ROOT != type && tok != node->parent->tok)
return(mdoc_nerr(mdoc, node, "invalid macro parent `%s', expected `%s'",
- mdoc_macronames[mdoc->last->parent->tok],
+ mdoc_macronames[node->parent->tok],
mdoc_macronames[tok]));
return(1);
}
@@ -300,6 +308,19 @@ elem_err_eq1(struct mdoc *mdoc)
static int
+elem_err_le1(struct mdoc *mdoc)
+{
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ if (NULL == mdoc->last->child)
+ return(1);
+ if (NULL == mdoc->last->child->next)
+ return(1);
+ return(mdoc_err(mdoc, "macro expects one or fewer parameters"));
+}
+
+
+static int
elem_err_eq0(struct mdoc *mdoc)
{
@@ -483,9 +504,8 @@ static int
pre_ss(struct mdoc *mdoc, struct mdoc_node *node)
{
- if (MDOC_BLOCK != mdoc->last->type)
+ if (MDOC_BLOCK != node->type)
return(1);
- assert(MDOC_Sh == mdoc->last->tok);
return(pre_check_parent(mdoc, node, MDOC_Sh, MDOC_BODY));
}
@@ -494,22 +514,49 @@ static int
pre_sh(struct mdoc *mdoc, struct mdoc_node *node)
{
- if (MDOC_BLOCK != mdoc->last->type)
+ if (MDOC_BLOCK != node->type)
return(1);
- assert(MDOC_Sh == mdoc->last->tok);
return(pre_check_parent(mdoc, node, -1, MDOC_ROOT));
}
static int
+pre_an(struct mdoc *mdoc, struct mdoc_node *node)
+{
+ assert(MDOC_ELEM == node->type);
+ assert(MDOC_An == node->tok);
+ if (1 >= node->data.elem.argc)
+ return(1);
+ return(mdoc_nerr(mdoc, node, "macro may only have one argument"));
+}
+
+
+static int
pre_ex(struct mdoc *mdoc, struct mdoc_node *node)
{
enum mdoc_msec msecs[3];
+ assert(MDOC_ELEM == node->type);
+
msecs[0] = MSEC_1;
msecs[1] = MSEC_6;
msecs[2] = MSEC_8;
- return(pre_check_msecs(mdoc, node, 3, msecs));
+ if ( ! pre_check_msecs(mdoc, node, 3, msecs))
+ return(0);
+
+ if (1 != node->data.elem.argc) {
+ if ( ! mdoc_nwarn(mdoc, node, WARN_COMPAT,
+ "macro suggests `%s' argument",
+ mdoc_argnames[MDOC_Std]))
+ return(0);
+ return(1);
+ }
+ if (MDOC_Std != node->data.elem.argv[0].arg)
+ if ( ! mdoc_nwarn(mdoc, node, WARN_COMPAT,
+ "macro suggests `%s' argument",
+ mdoc_argnames[MDOC_Std]))
+ return(0);
+ return(1);
}
@@ -537,9 +584,8 @@ static int
pre_it(struct mdoc *mdoc, struct mdoc_node *node)
{
- if (MDOC_BLOCK != mdoc->last->type)
+ if (MDOC_BLOCK != node->type)
return(1);
- assert(MDOC_It == mdoc->last->tok);
return(pre_check_parent(mdoc, node, MDOC_Bl, MDOC_BODY));
}
@@ -596,6 +642,51 @@ pre_prologue(struct mdoc *mdoc, struct mdoc_node *node)
}
+static int
+post_an(struct mdoc *mdoc)
+{
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ assert(MDOC_An == mdoc->last->tok);
+
+ if (0 != mdoc->last->data.elem.argc) {
+ if (NULL == mdoc->last->child)
+ return(1);
+ return(mdoc_err(mdoc, "macro expects either argument or parameters"));
+ }
+
+ if (mdoc->last->child)
+ return(1);
+ return(mdoc_err(mdoc, "macro expects either argument or parameters"));
+}
+
+
+static int
+post_ex(struct mdoc *mdoc)
+{
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ assert(MDOC_Ex == mdoc->last->tok);
+
+ if (0 == mdoc->last->data.elem.argc) {
+ if (mdoc->last->child)
+ return(1);
+ return(mdoc_err(mdoc, "macro expects `%s' or a single child",
+ mdoc_argnames[MDOC_Std]));
+ }
+ if (mdoc->last->child)
+ return(mdoc_err(mdoc, "macro expects `%s' or a single child",
+ mdoc_argnames[MDOC_Std]));
+ if (1 != mdoc->last->data.elem.argc)
+ return(mdoc_err(mdoc, "macro expects `%s' or a single child",
+ mdoc_argnames[MDOC_Std]));
+ if (MDOC_Std != mdoc->last->data.elem.argv[0].arg)
+ return(mdoc_err(mdoc, "macro expects `%s' or a single child",
+ mdoc_argnames[MDOC_Std]));
+ return(1);
+}
+
+
/* Warn if `Bl' type-specific syntax isn't reflected in items. */
static int
post_it(struct mdoc *mdoc)
@@ -704,7 +795,6 @@ post_it(struct mdoc *mdoc)
if (i == (size_t)sv)
return(1);
return(mdoc_err(mdoc, "expected %d list columns, have %d", sv, (int)i));
-
#undef TYPE_NONE
#undef TYPE_BODY
#undef TYPE_HEAD