summaryrefslogtreecommitdiffstats
path: root/mdoc_action.c
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2009-09-24 15:01:06 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2009-09-24 15:01:06 +0000
commit183e6ae0229d1ddcdf3a1f493eaae4a39d11d97a (patch)
treefcfba174f3984847528e7def61f307ee45c4ec54 /mdoc_action.c
parent6a2359747f92ffc48b612b8fb8a2e7a87a9dff8f (diff)
downloadmandoc-183e6ae0229d1ddcdf3a1f493eaae4a39d11d97a.tar.gz
Added EBADCHILD error (bad child of parent context).
`Rs' post-checks that all children are proper bibliographic elements. `Rs' correctly re-orders its children as per groff's output (including %C).
Diffstat (limited to 'mdoc_action.c')
-rw-r--r--mdoc_action.c95
1 files changed, 88 insertions, 7 deletions
diff --git a/mdoc_action.c b/mdoc_action.c
index fb780d37..91457bc1 100644
--- a/mdoc_action.c
+++ b/mdoc_action.c
@@ -32,6 +32,15 @@ struct actions {
int (*post)(POST_ARGS);
};
+static int concat(struct mdoc *,
+ const struct mdoc_node *,
+ char *, size_t);
+static inline int order_rs(int);
+
+#ifdef __linux__
+extern size_t strlcat(char *, const char *, size_t);
+#endif
+
static int post_ar(POST_ARGS);
static int post_at(POST_ARGS);
static int post_bl(POST_ARGS);
@@ -45,6 +54,7 @@ static int post_lb(POST_ARGS);
static int post_nm(POST_ARGS);
static int post_os(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);
@@ -141,7 +151,7 @@ static const struct actions mdoc_actions[MDOC_MAX] = {
{ NULL, NULL }, /* Qo */
{ NULL, NULL }, /* Qq */
{ NULL, NULL }, /* Re */
- { NULL, NULL }, /* Rs */
+ { NULL, post_rs }, /* Rs */
{ NULL, NULL }, /* Sc */
{ NULL, NULL }, /* So */
{ NULL, NULL }, /* Sq */
@@ -178,12 +188,23 @@ static const struct actions mdoc_actions[MDOC_MAX] = {
{ NULL, NULL }, /* sp */
};
-static int concat(struct mdoc *, const struct mdoc_node *,
- char *, size_t);
-
-#ifdef __linux__
-extern size_t strlcat(char *, const char *, size_t);
-#endif
+#define RSORD_MAX 13
+
+static const int 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
+};
int
@@ -899,3 +920,63 @@ post_display(POST_ARGS)
}
+static inline int
+order_rs(int t)
+{
+ int i;
+
+ for (i = 0; i < RSORD_MAX; i++)
+ if (rsord[i] == t)
+ return(i);
+
+ abort();
+ /* NOTREACHED */
+}
+
+
+static int
+post_rs(POST_ARGS)
+{
+ struct mdoc_node *nn, *next, *prev;
+ int o;
+
+ if (MDOC_BLOCK != n->type)
+ return(1);
+
+ 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);
+}