aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/validate.c
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2009-02-24 11:43:13 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2009-02-24 11:43:13 +0000
commitb3bbf7061a5906d3086a9fa08f36d77d77302e81 (patch)
tree4c61c7eb127831f667461ddffce6d9b0b1b81e98 /validate.c
parentd77fc82b5d003f81e34efe052e70d2a129e9f872 (diff)
downloadmandoc-b3bbf7061a5906d3086a9fa08f36d77d77302e81.tar.gz
mandoc-b3bbf7061a5906d3086a9fa08f36d77d77302e81.tar.zst
mandoc-b3bbf7061a5906d3086a9fa08f36d77d77302e81.zip
Escape-sequence validation in place (for nodes).
Diffstat (limited to 'validate.c')
-rw-r--r--validate.c80
1 files changed, 63 insertions, 17 deletions
diff --git a/validate.c b/validate.c
index 085415ea..361fecb6 100644
--- a/validate.c
+++ b/validate.c
@@ -1,4 +1,4 @@
-/* $Id: validate.c,v 1.53 2009/02/23 22:51:10 kristaps Exp $ */
+/* $Id: validate.c,v 1.54 2009/02/24 11:43:13 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -35,7 +35,6 @@ typedef int (*v_post)(struct mdoc *);
/* FIXME: some sections should only occur in specific msecs. */
/* FIXME: ignoring Pp. */
/* FIXME: math symbols. */
-/* FIXME: valid character-escape checks. */
/* FIXME: .Fd only in synopsis section. */
struct valids {
@@ -109,6 +108,7 @@ static int post_xr(struct mdoc *);
static int post_nm(struct mdoc *);
static int post_bf(struct mdoc *);
static int post_root(struct mdoc *);
+static int pre_text(struct mdoc *, const struct mdoc_node *);
/* Collections of pre-child-parse routines. */
@@ -386,6 +386,22 @@ check_msec(struct mdoc *mdoc, struct mdoc_node *node,
static int
+check_parent(struct mdoc *mdoc, struct mdoc_node *n,
+ int tok, enum mdoc_type t)
+{
+
+ assert(n->parent);
+ if ((MDOC_ROOT == t || tok == n->parent->tok) &&
+ (t == n->parent->type))
+ return(1);
+
+ return(mdoc_nerr(mdoc, n, "require parent %s",
+ MDOC_ROOT == t ? "<root>" : mdoc_macronames[tok]));
+}
+
+
+
+static int
pre_display(struct mdoc *mdoc, struct mdoc_node *node)
{
struct mdoc_node *n;
@@ -922,6 +938,26 @@ ebool(struct mdoc *mdoc)
static int
+pre_text(struct mdoc *mdoc, const struct mdoc_node *n)
+{
+ size_t c;
+ const char *p;
+
+ for (p = n->data.text.string; *p; p++) {
+ if ('\\' != *p)
+ continue;
+ if ((c = mdoc_isescape(p))) {
+ p += (c - 1);
+ continue;
+ }
+ return(mdoc_nerr(mdoc, n, "bad escape sequence"));
+ }
+
+ return(1);
+}
+
+
+static int
post_root(struct mdoc *mdoc)
{
@@ -931,10 +967,10 @@ post_root(struct mdoc *mdoc)
return(mdoc_err(mdoc, "document lacks prologue"));
if (MDOC_BLOCK != mdoc->first->child->type)
- return(mdoc_err(mdoc, "lacking post-prologue `%s'",
+ return(mdoc_err(mdoc, "lacking post-prologue %s",
mdoc_macronames[MDOC_Sh]));
if (MDOC_Sh != mdoc->first->child->tok)
- return(mdoc_err(mdoc, "lacking post-prologue `%s'",
+ return(mdoc_err(mdoc, "lacking post-prologue %s",
mdoc_macronames[MDOC_Sh]));
return(1);
@@ -969,8 +1005,8 @@ post_sh_body(struct mdoc *mdoc)
*/
if (NULL == (n = mdoc->last->child))
- return(mdoc_warn(mdoc, WARN_COMPAT, "section NAME "
- "should contain %s and %s",
+ return(mdoc_warn(mdoc, WARN_SYNTAX,
+ "section should have %s and %s",
mdoc_macronames[MDOC_Nm],
mdoc_macronames[MDOC_Nd]));
@@ -979,9 +1015,8 @@ post_sh_body(struct mdoc *mdoc)
continue;
if (MDOC_TEXT == n->type)
continue;
- if ( ! (mdoc_nwarn(mdoc, n, WARN_COMPAT, "section "
- "NAME should contain %s as "
- "initial body child",
+ if ( ! (mdoc_nwarn(mdoc, n, WARN_SYNTAX,
+ "section should have %s first",
mdoc_macronames[MDOC_Nm])))
return(0);
}
@@ -989,8 +1024,8 @@ post_sh_body(struct mdoc *mdoc)
if (MDOC_ELEM == n->type && MDOC_Nd == n->tok)
return(1);
- return(mdoc_warn(mdoc, WARN_COMPAT, "section NAME should "
- "contain %s as the last child",
+ return(mdoc_warn(mdoc, WARN_SYNTAX,
+ "section should have %s last",
mdoc_macronames[MDOC_Nd]));
}
@@ -1003,19 +1038,22 @@ post_sh_head(struct mdoc *mdoc)
assert(MDOC_Sh == mdoc->last->tok);
- if ( ! xstrlcats(buf, mdoc->last->child, 64))
- return(mdoc_err(mdoc, "macro parameters too long"));
+ if ( ! xstrlcats(buf, mdoc->last->child, sizeof(buf)))
+ return(mdoc_err(mdoc, "argument too long"));
sec = mdoc_atosec(buf);
if (SEC_BODY == mdoc->lastnamed && SEC_NAME != sec)
- return(mdoc_err(mdoc, "section NAME must be first"));
+ return(mdoc_warn(mdoc, WARN_SYNTAX,
+ "section NAME should be first"));
if (SEC_CUSTOM == sec)
return(1);
if (sec == mdoc->lastnamed)
- return(mdoc_warn(mdoc, WARN_SYNTAX, "section repeated"));
+ return(mdoc_warn(mdoc, WARN_SYNTAX,
+ "section repeated"));
if (sec < mdoc->lastnamed)
- return(mdoc_warn(mdoc, WARN_SYNTAX, "section out of conventional order"));
+ return(mdoc_warn(mdoc, WARN_SYNTAX,
+ "section out of order"));
return(1);
}
@@ -1027,7 +1065,7 @@ mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *node)
v_pre *p;
if (MDOC_TEXT == node->type)
- return(1);
+ return(pre_text(mdoc, node));
assert(MDOC_ROOT != node->type);
if (NULL == mdoc_valids[node->tok].pre)
@@ -1044,6 +1082,14 @@ mdoc_valid_post(struct mdoc *mdoc)
{
v_post *p;
+ /*
+ * This check occurs after the macro's children have been filled
+ * in: postfix validation. Since this happens when we're
+ * rewinding the scope tree, it's possible to have multiple
+ * invocations (as by design, for now), we set bit MDOC_VALID to
+ * indicate that we've validated.
+ */
+
if (MDOC_VALID & mdoc->last->flags)
return(1);
mdoc->last->flags |= MDOC_VALID;