diff options
-rw-r--r-- | mdoc_action.c | 68 | ||||
-rw-r--r-- | mdoc_validate.c | 137 |
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); } |