+ /*
+ * 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;