summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mdoc_action.c68
-rw-r--r--mdoc_validate.c137
2 files changed, 104 insertions, 101 deletions
diff --git a/mdoc_action.c b/mdoc_action.c
index 023d496b..9dcc52ed 100644
--- a/mdoc_action.c
+++ b/mdoc_action.c
@@ -50,7 +50,6 @@ struct actions {
static int concat(struct mdoc *, char *,
const struct mdoc_node *, size_t);
-static inline int order_rs(enum mdoct);
static int post_ar(POST_ARGS);
static int post_at(POST_ARGS);
@@ -67,7 +66,6 @@ static int post_nm(POST_ARGS);
static int post_os(POST_ARGS);
static int post_pa(POST_ARGS);
static int post_prol(POST_ARGS);
-static int post_rs(POST_ARGS);
static int post_sh(POST_ARGS);
static int post_st(POST_ARGS);
static int post_std(POST_ARGS);
@@ -161,7 +159,7 @@ static const struct actions mdoc_actions[MDOC_MAX] = {
{ NULL, NULL }, /* Qo */
{ NULL, NULL }, /* Qq */
{ NULL, NULL }, /* Re */
- { NULL, post_rs }, /* Rs */
+ { NULL, NULL }, /* Rs */
{ NULL, NULL }, /* Sc */
{ NULL, NULL }, /* So */
{ NULL, NULL }, /* Sq */
@@ -986,67 +984,3 @@ post_display(POST_ARGS)
m->flags &= ~MDOC_LITERAL;
return(1);
}
-
-
-static inline int
-order_rs(enum mdoct t)
-{
- int i;
-
- for (i = 0; i < (int)RSORD_MAX; i++)
- if (rsord[i] == t)
- return(i);
-
- abort();
- /* NOTREACHED */
-}
-
-
-/* ARGSUSED */
-static int
-post_rs(POST_ARGS)
-{
- struct mdoc_node *nn, *next, *prev;
- int o;
-
- if (MDOC_BLOCK != n->type)
- return(1);
-
- assert(n->body->child);
- for (next = NULL, nn = n->body->child->next; nn; nn = next) {
- o = order_rs(nn->tok);
-
- /* Remove `nn' from the chain. */
- next = nn->next;
- if (next)
- next->prev = nn->prev;
-
- prev = nn->prev;
- if (prev)
- prev->next = nn->next;
-
- nn->prev = nn->next = NULL;
-
- /*
- * Scan back until we reach a node that's ordered before
- * us, then set ourselves as being the next.
- */
- for ( ; prev; prev = prev->prev)
- if (order_rs(prev->tok) <= o)
- break;
-
- nn->prev = prev;
- if (prev) {
- if (prev->next)
- prev->next->prev = nn;
- nn->next = prev->next;
- prev->next = nn;
- continue;
- }
-
- n->body->child->prev = nn;
- nn->next = n->body->child;
- n->body->child = nn;
- }
- return(1);
-}
diff --git a/mdoc_validate.c b/mdoc_validate.c
index 44679b1e..693180ec 100644
--- a/mdoc_validate.c
+++ b/mdoc_validate.c
@@ -275,6 +275,25 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Ta */
};
+#define RSORD_MAX 14 /* Number of `Rs' blocks. */
+
+static const enum mdoct rsord[RSORD_MAX] = {
+ MDOC__A,
+ MDOC__T,
+ MDOC__B,
+ MDOC__I,
+ MDOC__J,
+ MDOC__R,
+ MDOC__N,
+ MDOC__V,
+ MDOC__P,
+ MDOC__Q,
+ MDOC__D,
+ MDOC__O,
+ MDOC__C,
+ MDOC__U
+};
+
int
mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *n)
@@ -1340,46 +1359,96 @@ post_st(POST_ARGS)
static int
post_rs(POST_ARGS)
{
- struct mdoc_node *nn;
+ struct mdoc_node *nn, *next, *prev;
+ int i, j;
if (MDOC_BODY != mdoc->last->type)
return(1);
- for (nn = mdoc->last->child; nn; nn = nn->next)
- switch (nn->tok) {
- case(MDOC__U):
- /* FALLTHROUGH */
- case(MDOC__Q):
- /* FALLTHROUGH */
- case(MDOC__C):
- /* FALLTHROUGH */
- case(MDOC__A):
- /* FALLTHROUGH */
- case(MDOC__B):
- /* FALLTHROUGH */
- case(MDOC__D):
- /* FALLTHROUGH */
- case(MDOC__I):
- /* FALLTHROUGH */
- case(MDOC__J):
- /* FALLTHROUGH */
- case(MDOC__N):
- /* FALLTHROUGH */
- case(MDOC__O):
- /* FALLTHROUGH */
- case(MDOC__P):
- /* FALLTHROUGH */
- case(MDOC__R):
- /* FALLTHROUGH */
- case(MDOC__T):
- /* FALLTHROUGH */
- case(MDOC__V):
- break;
- default:
- mdoc_nmsg(mdoc, nn, MANDOCERR_SYNTCHILD);
- return(0);
+ /*
+ * Make sure only certain types of nodes are allowed within the
+ * the `Rs' body. Delete offending nodes and raise a warning.
+ * Do this before re-ordering for the sake of clarity.
+ */
+
+ next = NULL;
+ for (nn = mdoc->last->child; nn; nn = next) {
+ for (i = 0; i < RSORD_MAX; i++)
+ if (nn->tok == rsord[i])
+ break;
+
+ if (i < RSORD_MAX) {
+ next = nn->next;
+ continue;
+ }
+
+ next = nn->next;
+ mdoc_nmsg(mdoc, nn, MANDOCERR_CHILD);
+ mdoc_node_delete(mdoc, nn);
+ }
+
+ /*
+ * The full `Rs' block needs special handling to order the
+ * sub-elements according to `rsord'. Pick through each element
+ * and correctly order it. This is a insertion sort.
+ */
+
+ next = NULL;
+ for (nn = mdoc->last->child->next; nn; nn = next) {
+ /* Determine order of `nn'. */
+ for (i = 0; i < RSORD_MAX; i++)
+ if (rsord[i] == nn->tok)
+ break;
+
+ /*
+ * Remove `nn' from the chain. This somewhat
+ * repeats mdoc_node_unlink(), but since we're
+ * just re-ordering, there's no need for the
+ * full unlink process.
+ */
+
+ if (NULL != (next = nn->next))
+ next->prev = nn->prev;
+
+ if (NULL != (prev = nn->prev))
+ prev->next = nn->next;
+
+ nn->prev = nn->next = NULL;
+
+ /*
+ * Scan back until we reach a node that's
+ * ordered before `nn'.
+ */
+
+ for ( ; prev ; prev = prev->prev) {
+ /* Determine order of `prev'. */
+ for (j = 0; j < RSORD_MAX; j++)
+ if (rsord[j] == prev->tok)
+ break;
+
+ if (j <= i)
+ break;
}
+ /*
+ * Set `nn' back into its correct place in front
+ * of the `prev' node.
+ */
+
+ nn->prev = prev;
+
+ if (prev) {
+ if (prev->next)
+ prev->next->prev = nn;
+ nn->next = prev->next;
+ prev->next = nn;
+ } else {
+ mdoc->last->child->prev = nn;
+ nn->next = mdoc->last->child;
+ mdoc->last->child = nn;
+ }
+ }
+
return(1);
}