summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--action.c8
-rw-r--r--argv.c21
-rw-r--r--macro.c99
-rw-r--r--mdoc.c4
-rw-r--r--mdoc.h5
-rw-r--r--validate.c81
6 files changed, 115 insertions, 103 deletions
diff --git a/action.c b/action.c
index 554fad58..f9bc34d4 100644
--- a/action.c
+++ b/action.c
@@ -1,4 +1,4 @@
-/* $Id: action.c,v 1.11 2009/01/17 16:47:02 kristaps Exp $ */
+/* $Id: action.c,v 1.12 2009/01/19 17:02:58 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -269,7 +269,7 @@ post_dd(struct mdoc *mdoc)
assert(MDOC_TEXT == n->type);
p = n->data.text.string;
- if (xstrcmp(p, "$Mdocdate: January 17 2009 $")) {
+ if (xstrcmp(p, "$Mdocdate: January 19 2009 $")) {
mdoc->meta.date = time(NULL);
continue;
} else if (xstrcmp(p, "$")) {
@@ -298,6 +298,10 @@ int
mdoc_action_post(struct mdoc *mdoc)
{
+ if (MDOC_ACTED & mdoc->last->flags)
+ return(1);
+ mdoc->last->flags |= MDOC_ACTED;
+
if (MDOC_TEXT == mdoc->last->type)
return(1);
if (MDOC_ROOT == mdoc->last->type)
diff --git a/argv.c b/argv.c
index fd32241d..a2d62608 100644
--- a/argv.c
+++ b/argv.c
@@ -1,4 +1,4 @@
-/* $Id: argv.c,v 1.16 2009/01/17 20:10:36 kristaps Exp $ */
+/* $Id: argv.c,v 1.17 2009/01/19 17:02:58 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -78,7 +78,8 @@ mdoc_args(struct mdoc *mdoc, int line, int *pos, char *buf, int fl, char **v)
/* Parse routine for non-quoted string. */
- if ('\"' != buf[*pos]) {
+ assert(*pos > 0);
+ if ('\"' != buf[*pos] || ! (ARGS_QUOTED & fl)) {
*v = &buf[*pos];
/* FIXME: UGLY tab-sep processing. */
@@ -98,9 +99,14 @@ mdoc_args(struct mdoc *mdoc, int line, int *pos, char *buf, int fl, char **v)
}
(*pos)++;
}
- else
- while (buf[*pos] && ! isspace(buf[*pos]))
+ else {
+ while (buf[*pos]) {
+ if (isspace(buf[*pos]))
+ if ('\\' != buf[*pos - 1])
+ break;
(*pos)++;
+ }
+ }
if (0 == buf[*pos])
return(ARGS_WORD);
@@ -451,8 +457,13 @@ mdoc_argv(struct mdoc *mdoc, int line, int tok,
v->line = line;
v->pos = *pos;
- while (buf[*pos] && ! isspace(buf[*pos]))
+ assert(*pos > 0);
+ while (buf[*pos]) {
+ if (isspace(buf[*pos]))
+ if ('\\' != buf[*pos - 1])
+ break;
(*pos)++;
+ }
if (buf[*pos])
buf[(*pos)++] = 0;
diff --git a/macro.c b/macro.c
index 609517d1..6ea7b58f 100644
--- a/macro.c
+++ b/macro.c
@@ -1,4 +1,4 @@
-/* $Id: macro.c,v 1.41 2009/01/17 20:10:36 kristaps Exp $ */
+/* $Id: macro.c,v 1.42 2009/01/19 17:02:58 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -70,24 +70,19 @@ rewind_last(struct mdoc *mdoc, struct mdoc_node *to)
assert(to);
mdoc->next = MDOC_NEXT_SIBLING;
- if (mdoc->last == to) {
+
+ while (mdoc->last != to) {
if ( ! mdoc_valid_post(mdoc))
return(0);
if ( ! mdoc_action_post(mdoc))
return(0);
- return(1);
- }
-
- do {
mdoc->last = mdoc->last->parent;
assert(mdoc->last);
- if ( ! mdoc_valid_post(mdoc))
- return(0);
- if ( ! mdoc_action_post(mdoc))
- return(0);
- } while (mdoc->last != to);
+ }
- return(1);
+ if ( ! mdoc_valid_post(mdoc))
+ return(0);
+ return(mdoc_action_post(mdoc));
}
@@ -139,9 +134,7 @@ rewind_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
if (MDOC_ROOT == p->type)
return(REWIND_HALT);
- if (MDOC_TEXT == p->type)
- return(REWIND_NOHALT);
- if (MDOC_ELEM == p->type)
+ if (MDOC_VALID & p->flags)
return(REWIND_NOHALT);
switch (tok) {
@@ -276,6 +269,8 @@ rewind_dobreak(int tok, const struct mdoc_node *p)
return(1);
if (MDOC_TEXT == p->type)
return(1);
+ if (MDOC_VALID & p->flags)
+ return(1);
switch (tok) {
/* Implicit rules. */
@@ -328,14 +323,8 @@ rewind_subblock(enum mdoc_type type, struct mdoc *mdoc,
struct mdoc_node *n;
int c;
- c = rewind_dohalt(tok, type, mdoc->last);
- if (REWIND_HALT == c)
- return(1);
- if (REWIND_REWIND == c)
- return(rewind_last(mdoc, mdoc->last));
-
/* LINTED */
- for (n = mdoc->last->parent; n; n = n->parent) {
+ for (n = mdoc->last; n; n = n->parent) {
c = rewind_dohalt(tok, type, n);
if (REWIND_HALT == c)
return(1);
@@ -357,14 +346,8 @@ rewind_expblock(struct mdoc *mdoc, int tok, int line, int ppos)
struct mdoc_node *n;
int c;
- c = rewind_dohalt(tok, MDOC_BLOCK, mdoc->last);
- if (REWIND_HALT == c)
- return(mdoc_perr(mdoc, line, ppos, "closing macro has no context"));
- if (REWIND_REWIND == c)
- return(rewind_last(mdoc, mdoc->last));
-
/* LINTED */
- for (n = mdoc->last->parent; n; n = n->parent) {
+ for (n = mdoc->last; n; n = n->parent) {
c = rewind_dohalt(tok, MDOC_BLOCK, n);
if (REWIND_HALT == c)
return(mdoc_perr(mdoc, line, ppos, "closing macro has no context"));
@@ -386,14 +369,8 @@ rewind_impblock(struct mdoc *mdoc, int tok, int line, int ppos)
struct mdoc_node *n;
int c;
- c = rewind_dohalt(tok, MDOC_BLOCK, mdoc->last);
- if (REWIND_HALT == c)
- return(1);
- if (REWIND_REWIND == c)
- return(rewind_last(mdoc, mdoc->last));
-
/* LINTED */
- for (n = mdoc->last->parent; n; n = n->parent) {
+ for (n = mdoc->last; n; n = n->parent) {
c = rewind_dohalt(tok, MDOC_BLOCK, n);
if (REWIND_HALT == c)
return(1);
@@ -435,7 +412,6 @@ append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
}
-/* ARGSUSED */
int
macro_scoped_close(MACRO_PROT_ARGS)
{
@@ -521,15 +497,6 @@ macro_scoped_close(MACRO_PROT_ARGS)
}
-/*
- * A general text domain macro. When invoked, this opens a scope that
- * accepts words until either end-of-line, only-punctuation, or a
- * callable macro. If the word is punctuation (not only-punctuation),
- * then the scope is closed out, the punctuation appended, then the
- * scope opened again. If any terminating conditions are met, the scope
- * is closed out. If this is the first macro in the line and
- * only-punctuation remains, this punctuation is flushed.
- */
int
macro_text(MACRO_PROT_ARGS)
{
@@ -636,9 +603,6 @@ macro_text(MACRO_PROT_ARGS)
}
-/*
- * Implicit- or explicit-end multi-line scoped macro.
- */
int
macro_scoped(MACRO_PROT_ARGS)
{
@@ -740,11 +704,6 @@ macro_scoped(MACRO_PROT_ARGS)
}
-/*
- * When scoped to a line, a macro encompasses all of the contents. This
- * differs from constants or text macros, where a new macro will
- * terminate the existing context.
- */
int
macro_scoped_line(MACRO_PROT_ARGS)
{
@@ -798,10 +757,6 @@ macro_scoped_line(MACRO_PROT_ARGS)
}
-/*
- * Constant-scope macros accept a fixed number of arguments and behave
- * like constant macros except that they're scoped across lines.
- */
int
macro_constant_scoped(MACRO_PROT_ARGS)
{
@@ -901,12 +856,6 @@ macro_constant_scoped(MACRO_PROT_ARGS)
}
-/*
- * Delimited macros are like text macros except that, should punctuation
- * be encountered, the macro isn't re-started with remaining tokens
- * (it's only emitted once). Delimited macros can have a maximum number
- * of arguments.
- */
int
macro_constant_delimited(MACRO_PROT_ARGS)
{
@@ -1000,7 +949,7 @@ macro_constant_delimited(MACRO_PROT_ARGS)
mdoc->next = MDOC_NEXT_SIBLING;
}
- if ( ! flushed && rewind_elem(mdoc, tok))
+ if ( ! flushed && ! rewind_elem(mdoc, tok))
return(0);
if (ppos > 1)
@@ -1009,10 +958,6 @@ macro_constant_delimited(MACRO_PROT_ARGS)
}
-/*
- * Constant macros span an entire line: they constitute a macro and all
- * of its arguments and child data.
- */
int
macro_constant(MACRO_PROT_ARGS)
{
@@ -1090,8 +1035,24 @@ macro_obsolete(MACRO_PROT_ARGS)
int
macro_end(struct mdoc *mdoc)
{
+ struct mdoc_node *n;
assert(mdoc->first);
assert(mdoc->last);
+
+ /* Scan for open explicit scopes. */
+
+ n = MDOC_VALID & mdoc->last->flags ?
+ mdoc->last->parent : mdoc->last;
+
+ for ( ; n; n = n->parent) {
+ if (MDOC_BLOCK != n->type)
+ continue;
+ if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags))
+ continue;
+ mdoc_nerr(mdoc, n, "macro scope still open on exit");
+ return(0);
+ }
+
return(rewind_last(mdoc, mdoc->first));
}
diff --git a/mdoc.c b/mdoc.c
index e1df0b73..5aa88c25 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc.c,v 1.35 2009/01/17 20:10:36 kristaps Exp $ */
+/* $Id: mdoc.c,v 1.36 2009/01/19 17:02:58 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -725,6 +725,7 @@ argdup(size_t argsz, const struct mdoc_arg *args)
}
+/* FIXME: deprecate. */
char *
mdoc_node2a(struct mdoc_node *node)
{
@@ -741,6 +742,7 @@ mdoc_node2a(struct mdoc_node *node)
(void)xstrlcat(buf, node->data.text.string, 64);
else
(void)xstrlcat(buf, mdoc_macronames[node->tok], 64);
+ (void)xstrlcat(buf, "'", 64);
return(buf);
}
diff --git a/mdoc.h b/mdoc.h
index 5163041a..929e991b 100644
--- a/mdoc.h
+++ b/mdoc.h
@@ -1,4 +1,4 @@
-/* $Id: mdoc.h,v 1.25 2009/01/17 16:15:27 kristaps Exp $ */
+/* $Id: mdoc.h,v 1.26 2009/01/19 17:02:58 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -385,6 +385,9 @@ struct mdoc_node {
int line;
int pos;
int tok;
+ int flags;
+#define MDOC_VALID (1 << 0)
+#define MDOC_ACTED (1 << 1)
enum mdoc_type type;
union mdoc_data data;
};
diff --git a/validate.c b/validate.c
index bf5d1364..0a5e3f89 100644
--- a/validate.c
+++ b/validate.c
@@ -1,4 +1,4 @@
-/* $Id: validate.c,v 1.38 2009/01/17 20:10:36 kristaps Exp $ */
+/* $Id: validate.c,v 1.39 2009/01/19 17:02:59 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -29,6 +29,7 @@ typedef int (*v_post)(struct mdoc *);
/* FIXME: math symbols. */
/* FIXME: make sure prologue is complete. */
/* FIXME: valid character-escape checks. */
+/* FIXME: make sure required sections are included (NAME, ...). */
struct valids {
v_pre *pre;
@@ -45,7 +46,9 @@ 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);
/* Specific pre-child-parse routines. */
@@ -76,6 +79,7 @@ static int eerr_le2(struct mdoc *);
static int eerr_eq1(struct mdoc *);
static int eerr_ge1(struct mdoc *);
static int ewarn_eq0(struct mdoc *);
+static int ewarn_eq1(struct mdoc *);
static int bwarn_ge1(struct mdoc *);
static int berr_eq0(struct mdoc *);
static int ewarn_ge1(struct mdoc *);
@@ -117,6 +121,7 @@ static v_post posts_wline[] = { hwarn_ge1, berr_eq0, NULL };
static v_post posts_sh[] = { herr_ge1, bwarn_ge1, post_sh, NULL };
static v_post posts_bl[] = { herr_eq0, bwarn_ge1, post_bl, NULL };
static v_post posts_it[] = { post_it, NULL };
+static v_post posts_in[] = { ewarn_eq1, NULL };
static v_post posts_ss[] = { herr_ge1, NULL };
static v_post posts_pp[] = { ewarn_eq0, NULL };
static v_post posts_d1[] = { herr_ge1, NULL };
@@ -155,12 +160,12 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ pres_ex, posts_ex }, /* Ex */
{ NULL, posts_text }, /* Fa */
/* FIXME: only in SYNOPSIS section. */
- { NULL, NULL }, /* Fd */
+ { NULL, posts_wtext }, /* Fd */
{ NULL, NULL }, /* Fl */
{ NULL, posts_text }, /* Fn */
- { NULL, NULL }, /* Ft */
+ { NULL, posts_wtext }, /* Ft */
{ NULL, posts_text }, /* Ic */
- { NULL, posts_wtext }, /* In */
+ { NULL, posts_in }, /* In */
{ NULL, posts_text }, /* Li */
{ NULL, posts_wtext }, /* Nd */
{ NULL, posts_nm }, /* Nm */
@@ -188,7 +193,7 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, posts_wline }, /* Aq */
{ NULL, posts_at }, /* At */
{ NULL, NULL }, /* Bc */
- { NULL, NULL }, /* Bf */
+ { NULL, NULL }, /* Bf */ /* FIXME */
{ NULL, NULL }, /* Bo */
{ NULL, posts_wline }, /* Bq */
{ NULL, NULL }, /* Bsx */
@@ -253,6 +258,18 @@ post_check_children_count(struct mdoc *mdoc)
static int
+post_check_children_wgt(struct mdoc *mdoc, 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));
+}
+
+
+static int
post_check_children_gt(struct mdoc *mdoc, int sz)
{
int i;
@@ -260,7 +277,19 @@ post_check_children_gt(struct mdoc *mdoc, int sz)
if ((i = post_check_children_count(mdoc)) > sz)
return(1);
return(mdoc_err(mdoc, "macro requires more than %d "
- "parameters (have %d)", sz, i));
+ "parameters (has %d)", sz, i));
+}
+
+
+static int
+post_check_children_weq(struct mdoc *mdoc, 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));
}
@@ -338,9 +367,7 @@ berr_eq0(struct mdoc *mdoc)
if (MDOC_BODY != mdoc->last->type)
return(1);
- if (NULL == mdoc->last->child)
- return(1);
- return(mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests no body children"));
+ return(post_check_children_eq(mdoc, 0));
}
@@ -350,9 +377,16 @@ bwarn_ge1(struct mdoc *mdoc)
if (MDOC_BODY != mdoc->last->type)
return(1);
- if (mdoc->last->child)
- return(1);
- return(mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests one or more body children"));
+ return(post_check_children_wgt(mdoc, 0));
+}
+
+
+static int
+ewarn_eq1(struct mdoc *mdoc)
+{
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ return(post_check_children_weq(mdoc, 1));
}
@@ -361,10 +395,7 @@ ewarn_eq0(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- if (NULL == mdoc->last->child)
- return(1);
- return(mdoc_pwarn(mdoc, mdoc->last->child->line,
- mdoc->last->child->pos, WARN_SYNTAX, "macro suggests no parameters"));
+ return(post_check_children_weq(mdoc, 0));
}
@@ -373,9 +404,7 @@ ewarn_ge1(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- if (mdoc->last->child)
- return(1);
- return(mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests one or more parameters"));
+ return(post_check_children_wgt(mdoc, 0));
}
@@ -440,9 +469,7 @@ hwarn_ge1(struct mdoc *mdoc)
if (MDOC_HEAD != mdoc->last->type)
return(1);
- if (mdoc->last->child)
- return(1);
- return(mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests one or more parameters"));
+ return(post_check_children_wgt(mdoc, 0));
}
@@ -1003,11 +1030,11 @@ post_root(struct mdoc *mdoc)
if (NULL == mdoc->last->child)
return(mdoc_err(mdoc, "document has no data"));
if (NULL == mdoc->meta.title)
- return(mdoc_err(mdoc, "document has no incomplete prologue"));
+ return(mdoc_err(mdoc, "document has incomplete prologue"));
if (NULL == mdoc->meta.os)
- return(mdoc_err(mdoc, "document has no incomplete prologue"));
+ return(mdoc_err(mdoc, "document has incomplete prologue"));
if (0 == mdoc->meta.date)
- return(mdoc_err(mdoc, "document has no incomplete prologue"));
+ return(mdoc_err(mdoc, "document has incomplete prologue"));
return(1);
}
@@ -1059,6 +1086,10 @@ mdoc_valid_post(struct mdoc *mdoc)
{
v_post *p;
+ if (MDOC_VALID & mdoc->last->flags)
+ return(1);
+ mdoc->last->flags |= MDOC_VALID;
+
if (MDOC_TEXT == mdoc->last->type)
return(1);
if (MDOC_ROOT == mdoc->last->type)