summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2009-01-19 17:51:32 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2009-01-19 17:51:32 +0000
commit2e32d8081f19a0adc0f1c4091cc0e6720b1a24fe (patch)
tree308da3c4fc54485ffb916bd71b5a04b848513d70
parentd427476d5c4b9bd0804fa51647671e6b18e07afa (diff)
downloadmandoc-2e32d8081f19a0adc0f1c4091cc0e6720b1a24fe.tar.gz
More correct validation.
Elision of prologue macros from main tree.
-rw-r--r--macro.c33
-rw-r--r--mdoc.359
-rw-r--r--mdoc.c19
-rw-r--r--mdoc.h7
-rw-r--r--mdocml.c4
-rw-r--r--private.h2
-rw-r--r--validate.c58
7 files changed, 124 insertions, 58 deletions
diff --git a/macro.c b/macro.c
index a654856c..2185e181 100644
--- a/macro.c
+++ b/macro.c
@@ -961,9 +961,10 @@ macro_constant_delimited(MACRO_PROT_ARGS)
int
macro_constant(MACRO_PROT_ARGS)
{
- int c, lastarg, argc, fl;
- struct mdoc_arg argv[MDOC_LINEARG_MAX];
- char *p;
+ int c, lastarg, argc, fl;
+ struct mdoc_arg argv[MDOC_LINEARG_MAX];
+ char *p;
+ struct mdoc_node *n;
fl = 0;
if (MDOC_QUOTABLE & mdoc_macros[tok].flags)
@@ -1019,7 +1020,31 @@ macro_constant(MACRO_PROT_ARGS)
mdoc->next = MDOC_NEXT_SIBLING;
}
- return(rewind_elem(mdoc, tok));
+ if ( ! rewind_elem(mdoc, tok))
+ return(0);
+ if ( ! (MDOC_NOKEEP & mdoc_macros[tok].flags))
+ return(1);
+
+ assert(mdoc->last->tok == tok);
+ if (mdoc->last->parent->child == mdoc->last)
+ mdoc->last->parent->child = mdoc->last->prev;
+ if (mdoc->last->prev)
+ mdoc->last->prev->next = NULL;
+
+ n = mdoc->last;
+ assert(NULL == mdoc->last->next);
+
+ if (mdoc->last->prev) {
+ mdoc->last = mdoc->last->prev;
+ mdoc->next = MDOC_NEXT_SIBLING;
+ } else {
+ mdoc->last = mdoc->last->parent;
+ mdoc->next = MDOC_NEXT_CHILD;
+ }
+
+ mdoc_node_freelist(n);
+
+ return(1);
}
diff --git a/mdoc.3 b/mdoc.3
index 75ac1eea..560f84cb 100644
--- a/mdoc.3
+++ b/mdoc.3
@@ -7,12 +7,15 @@
.Nm mdoc_alloc ,
.Nm mdoc_parseln ,
.Nm mdoc_endparse ,
-.Nm mdoc_result ,
+.Nm mdoc_node ,
+.Nm mdoc_meta ,
.Nm mdoc_free
.Nd mdoc macro compiler library
.\"
.Sh SYNOPSIS
-.In mdoc.h
+.Fd #include <mdoc.h>
+.Vt extern const char * const * mdoc_macronames;
+.Vt extern const char * const * mdoc_argnames;
.Ft "struct mdoc *"
.Fn mdoc_alloc "void *data" "const struct mdoc_cb *cb"
.Ft void
@@ -20,7 +23,9 @@
.Ft int
.Fn mdoc_parseln "struct mdoc *mdoc" "int line" "char *buf"
.Ft "const struct mdoc_node *"
-.Fn mdoc_result "struct mdoc *mdoc"
+.Fn mdoc_node "struct mdoc *mdoc"
+.Ft "const struct mdoc_meta *"
+.Fn mdoc_meta "struct mdoc *mdoc"
.Ft int
.Fn mdoc_endparse "struct mdoc *mdoc"
.\"
@@ -35,13 +40,16 @@ parse each line in a document with
close the parsing session with
.Fn mdoc_endparse ,
operate over the syntax tree returned by
-.Fn mdoc_result ,
+.Fn mdoc_node
+and
+.Fn mdoc_meta ,
then free all allocated memory with
.Fn mdoc_free .
See the
.Sx EXAMPLES
section for a full example.
.Pp
+.\" Function descriptions.
Function descriptions follow:
.Bl -ohang -offset indent
.It Fn mdoc_alloc
@@ -64,14 +72,30 @@ is modified by this function.
Signals that the parse is complete. Note that if
.Fn mdoc_endparse
is called subsequent to
-.Fn mdoc_result ,
+.Fn mdoc_node ,
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
+.It Fn mdoc_node
+Returns the first node of the parse. Note that if
.Fn mdoc_parseln
or
.Fn mdoc_endparse
return 0, the tree will be incomplete.
+.It Fn mdoc_meta
+Returns the document's parsed meta-data. If this information has not
+yet been supplied or
+.Fn mdoc_parseln
+or
+.Fn mdoc_endparse
+return 0, the data will be incomplete.
+.El
+.Pp
+.\" Variable descriptions.
+The following variables are also defined:
+.Bl -ohang -offset indent
+.It Va mdoc_macronames
+An array of string-ified token names.
+.It Va mdoc_argnames
+An array of string-ified token argument names.
.El
.Pp
.Nm
@@ -105,8 +129,8 @@ while ((buf = fgetln(fp, &len))) {
if ( ! mdoc_endparse(mdoc))
errx(1, "mdoc_endparse");
-if (NULL == (node = mdoc_result(mdoc)))
- errx(1, "mdoc_result");
+if (NULL == (node = mdoc_node(mdoc)))
+ errx(1, "mdoc_node");
parsed(mdoc, node);
mdoc_free(mdoc);
@@ -127,13 +151,15 @@ utility was written by
.\"
.\"
.Sh BUGS
-Both bugs and incompabilities are documented in this section. An
-incompatible macro or behaviour is relative to the default
+Bugs, un-implemented macros and incompabilities are documented in this
+section. The baseline for determining whether macro parsing is
+.Qq incompatible
+is the default
.Xr groff 1
system bundled with
.Ox .
.Pp
-The
+Un-implemented: the
.Sq \&Xc
and
.Sq \&Xo
@@ -142,12 +168,15 @@ macros aren't handled when used to span lines for the
macro. Such usage is specifically discouraged in
.Xr mdoc.samples 7 .
.Pp
-When
+Bugs: when
.Sq \&It \-column
is invoked, whitespace is not stripped around
.Sq \&Ta
or tab-character separators.
.Pp
-The
+Incompatible: the
.Sq \&At
-macro only accepts a single parameter.
+macro only accepts a single parameter. Furthermore, several macros
+.Pf ( Sq \&Pp ,
+.Sq \&It ,
+and possibly others) accept multiple arguments with a warning.
diff --git a/mdoc.c b/mdoc.c
index e6c1c424..53c91c37 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -85,9 +85,9 @@ const char *const __mdoc_argnames[MDOC_ARG_MAX] = {
const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
{ NULL, 0 }, /* \" */
- { macro_constant, MDOC_PROLOGUE }, /* Dd */
- { macro_constant, MDOC_PROLOGUE }, /* Dt */
- { macro_constant, MDOC_PROLOGUE }, /* Os */
+ { macro_constant, MDOC_PROLOGUE | MDOC_NOKEEP }, /* Dd */
+ { macro_constant, MDOC_PROLOGUE | MDOC_NOKEEP }, /* Dt */
+ { macro_constant, MDOC_PROLOGUE | MDOC_NOKEEP }, /* Os */
{ macro_scoped, 0 }, /* Sh */
{ macro_scoped, 0 }, /* Ss */
{ macro_text, 0 }, /* Pp */
@@ -205,7 +205,6 @@ static void argfree(size_t, struct mdoc_arg *);
static void argcpy(struct mdoc_arg *,
const struct mdoc_arg *);
-static void mdoc_node_freelist(struct mdoc_node *);
static int mdoc_node_append(struct mdoc *,
struct mdoc_node *);
static void mdoc_elem_free(struct mdoc_elem *);
@@ -213,13 +212,21 @@ static void mdoc_text_free(struct mdoc_text *);
const struct mdoc_node *
-mdoc_result(struct mdoc *mdoc)
+mdoc_node(struct mdoc *mdoc)
{
return(mdoc->first);
}
+const struct mdoc_meta *
+mdoc_meta(struct mdoc *mdoc)
+{
+
+ return(&mdoc->meta);
+}
+
+
void
mdoc_meta_free(struct mdoc *mdoc)
{
@@ -671,7 +678,7 @@ mdoc_node_free(struct mdoc_node *p)
}
-static void
+void
mdoc_node_freelist(struct mdoc_node *p)
{
diff --git a/mdoc.h b/mdoc.h
index dd6b1509..ef2b5d3a 100644
--- a/mdoc.h
+++ b/mdoc.h
@@ -416,8 +416,11 @@ struct mdoc *mdoc_alloc(void *data, const struct mdoc_cb *);
/* Parse a single line (boolean retval). */
int mdoc_parseln(struct mdoc *, int, char *buf);
-/* Get parse result or NULL. */
-const struct mdoc_node *mdoc_result(struct mdoc *);
+/* Get result first node. */
+const struct mdoc_node *mdoc_node(struct mdoc *);
+
+/* Get result meta-information. */
+const struct mdoc_meta *mdoc_meta(struct mdoc *);
/* Signal end of parse sequence (boolean retval). */
int mdoc_endparse(struct mdoc *);
diff --git a/mdocml.c b/mdocml.c
index 0b91061c..0befca5a 100644
--- a/mdocml.c
+++ b/mdocml.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+ /* $Id$ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -232,7 +232,7 @@ parse_leave(struct md_parse *p, int code)
if ( ! mdoc_endparse(p->mdoc))
code = 0;
- if (p->print && (n = mdoc_result(p->mdoc)))
+ if (p->print && (n = mdoc_node(p->mdoc)))
(*p->print)(n);
mdoc_free(p->mdoc);
diff --git a/private.h b/private.h
index 234b67b8..7dfb24b3 100644
--- a/private.h
+++ b/private.h
@@ -57,6 +57,7 @@ struct mdoc_macro {
#define MDOC_QUOTABLE (1 << 3)
#define MDOC_PROLOGUE (1 << 4)
#define MDOC_TABSEP (1 << 5)
+#define MDOC_NOKEEP (1 << 6)
};
#define mdoc_nwarn(mdoc, node, type, fmt, ...) \
@@ -115,6 +116,7 @@ int mdoc_head_alloc(struct mdoc *, int, int, int);
int mdoc_tail_alloc(struct mdoc *, int, int, int);
int mdoc_body_alloc(struct mdoc *, int, int, int);
void mdoc_node_free(struct mdoc_node *);
+void mdoc_node_freelist(struct mdoc_node *);
void mdoc_sibling(struct mdoc *, int, struct mdoc_node **,
struct mdoc_node **, struct mdoc_node *);
void *mdoc_tokhash_alloc(void);
diff --git a/validate.c b/validate.c
index acccaf6c..3748e379 100644
--- a/validate.c
+++ b/validate.c
@@ -44,11 +44,11 @@ static int pre_check_msecs(struct mdoc *, struct mdoc_node *,
int, enum mdoc_msec *);
static int pre_check_stdarg(struct mdoc *, struct mdoc_node *);
static int post_check_children_count(struct mdoc *);
-static int post_check_children_lt(struct mdoc *, int);
-static int post_check_children_gt(struct mdoc *, int);
-static int post_check_children_wgt(struct mdoc *, int);
-static int post_check_children_eq(struct mdoc *, int);
-static int post_check_children_weq(struct mdoc *, int);
+static int post_check_children_lt(struct mdoc *, const char *, int);
+static int post_check_children_gt(struct mdoc *, const char *, int);
+static int post_check_children_wgt(struct mdoc *, const char *, int);
+static int post_check_children_eq(struct mdoc *, const char *, int);
+static int post_check_children_weq(struct mdoc *, const char *, int);
/* Specific pre-child-parse routines. */
@@ -258,62 +258,62 @@ post_check_children_count(struct mdoc *mdoc)
static int
-post_check_children_wgt(struct mdoc *mdoc, int sz)
+post_check_children_wgt(struct mdoc *mdoc, const char *p, int sz)
{
int i;
if ((i = post_check_children_count(mdoc)) > sz)
return(1);
return(mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests more "
- "than %d parameters (has %d)", sz, i));
+ "than %d %s (has %d)", sz, p, i));
}
static int
-post_check_children_gt(struct mdoc *mdoc, int sz)
+post_check_children_gt(struct mdoc *mdoc, const char *p, int sz)
{
int i;
if ((i = post_check_children_count(mdoc)) > sz)
return(1);
return(mdoc_err(mdoc, "macro requires more than %d "
- "parameters (has %d)", sz, i));
+ "%s (has %d)", sz, p, i));
}
static int
-post_check_children_weq(struct mdoc *mdoc, int sz)
+post_check_children_weq(struct mdoc *mdoc, const char *p, int sz)
{
int i;
if ((i = post_check_children_count(mdoc)) == sz)
return(1);
return(mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests %d "
- "parameters (has %d)", sz, i));
+ "%s (has %d)", sz, p, i));
}
static int
-post_check_children_eq(struct mdoc *mdoc, int sz)
+post_check_children_eq(struct mdoc *mdoc, const char *p, int sz)
{
int i;
if ((i = post_check_children_count(mdoc)) == sz)
return(1);
- return(mdoc_err(mdoc, "macro requires %d parameters "
- "(have %d)", sz, i));
+ return(mdoc_err(mdoc, "macro requires %d %s "
+ "(have %d)", sz, p, i));
}
static int
-post_check_children_lt(struct mdoc *mdoc, int sz)
+post_check_children_lt(struct mdoc *mdoc, const char *p, int sz)
{
int i;
if ((i = post_check_children_count(mdoc)) < sz)
return(1);
return(mdoc_err(mdoc, "macro requires less than %d "
- "parameters (have %d)", sz, i));
+ "%s (have %d)", sz, p, i));
}
@@ -367,7 +367,7 @@ berr_eq0(struct mdoc *mdoc)
if (MDOC_BODY != mdoc->last->type)
return(1);
- return(post_check_children_eq(mdoc, 0));
+ return(post_check_children_eq(mdoc, "body children", 0));
}
@@ -377,7 +377,7 @@ bwarn_ge1(struct mdoc *mdoc)
if (MDOC_BODY != mdoc->last->type)
return(1);
- return(post_check_children_wgt(mdoc, 0));
+ return(post_check_children_wgt(mdoc, "body children", 0));
}
@@ -386,7 +386,7 @@ ewarn_eq1(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- return(post_check_children_weq(mdoc, 1));
+ return(post_check_children_weq(mdoc, "parameters", 1));
}
@@ -395,7 +395,7 @@ ewarn_eq0(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- return(post_check_children_weq(mdoc, 0));
+ return(post_check_children_weq(mdoc, "parameters", 0));
}
@@ -404,7 +404,7 @@ ewarn_ge1(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- return(post_check_children_wgt(mdoc, 0));
+ return(post_check_children_wgt(mdoc, "parameters", 0));
}
@@ -413,7 +413,7 @@ eerr_eq1(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- return(post_check_children_eq(mdoc, 1));
+ return(post_check_children_eq(mdoc, "parameters", 1));
}
@@ -422,7 +422,7 @@ eerr_le2(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- return(post_check_children_lt(mdoc, 3));
+ return(post_check_children_lt(mdoc, "parameters", 3));
}
@@ -431,7 +431,7 @@ eerr_le1(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- return(post_check_children_lt(mdoc, 2));
+ return(post_check_children_lt(mdoc, "parameters", 2));
}
@@ -440,7 +440,7 @@ eerr_eq0(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- return(post_check_children_eq(mdoc, 0));
+ return(post_check_children_eq(mdoc, "parameters", 0));
}
@@ -449,7 +449,7 @@ eerr_ge1(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- return(post_check_children_gt(mdoc, 0));
+ return(post_check_children_gt(mdoc, "parameters", 0));
}
@@ -459,7 +459,7 @@ herr_eq0(struct mdoc *mdoc)
if (MDOC_HEAD != mdoc->last->type)
return(1);
- return(post_check_children_eq(mdoc, 0));
+ return(post_check_children_eq(mdoc, "parameters", 0));
}
@@ -469,7 +469,7 @@ hwarn_ge1(struct mdoc *mdoc)
if (MDOC_HEAD != mdoc->last->type)
return(1);
- return(post_check_children_wgt(mdoc, 0));
+ return(post_check_children_wgt(mdoc, "parameters", 0));
}
@@ -479,7 +479,7 @@ herr_ge1(struct mdoc *mdoc)
if (MDOC_HEAD != mdoc->last->type)
return(1);
- return(post_check_children_gt(mdoc, 0));
+ return(post_check_children_gt(mdoc, "parameters", 0));
}