=================================================================== RCS file: /cvs/docbook2mdoc/reorg.c,v retrieving revision 1.1 retrieving revision 1.3 diff -u -p -r1.1 -r1.3 --- docbook2mdoc/reorg.c 2019/04/28 17:11:53 1.1 +++ docbook2mdoc/reorg.c 2019/04/28 19:59:01 1.3 @@ -1,4 +1,4 @@ -/* $Id: reorg.c,v 1.1 2019/04/28 17:11:53 schwarze Exp $ */ +/* $Id: reorg.c,v 1.3 2019/04/28 19:59:01 schwarze Exp $ */ /* * Copyright (c) 2019 Ingo Schwarze * @@ -14,6 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "string.h" #include "node.h" #include "reorg.h" @@ -22,12 +23,12 @@ * The implementation of the tree reorganizer. */ -void -ptree_reorg(struct ptree *tree) +static void +reorg_root(struct pnode *root) { - struct pnode *date, *descr, *name, *root, *vol, *nc; + struct pnode *date, *descr, *name, *vol, *nc; - if ((root = tree->root) == NULL) + if (root == NULL) return; /* Collect prologue information. */ @@ -69,4 +70,202 @@ ptree_reorg(struct ptree *tree) TAILQ_INSERT_HEAD(&root->childq, vol, child); TAILQ_INSERT_HEAD(&root->childq, name, child); TAILQ_INSERT_HEAD(&root->childq, date, child); +} + +static void +reorg_refentry(struct pnode *n) +{ + struct pnode *info, *meta, *nc, *title; + struct pnode *match, *later; + + /* Collect nodes that remained behind from the prologue. */ + + meta = NULL; + info = pnode_takefirst(n, NODE_BOOKINFO); + if (info != NULL && TAILQ_FIRST(&info->childq) == NULL) { + pnode_unlink(info); + info = NULL; + } + if (info == NULL) { + info = pnode_takefirst(n, NODE_REFENTRYINFO); + if (info != NULL && TAILQ_FIRST(&info->childq) == NULL) { + pnode_unlink(info); + info = NULL; + } + if (info == NULL) + info = pnode_takefirst(n, NODE_INFO); + meta = pnode_takefirst(n, NODE_REFMETA); + if (meta != NULL && TAILQ_FIRST(&meta->childq) == NULL) { + pnode_unlink(meta); + meta = NULL; + } + } + if (info == NULL && meta == NULL) + return; + + /* + * Find the best place to put this information. + * Use the last existing AUTHORS node, if any. + * Otherwise, put it behind all standard sections that + * conventionally precede AUTHORS, and also behind any + * non-standard sections that follow the last of these, + * but before the next standard section. + */ + + match = later = NULL; + TAILQ_FOREACH(nc, &n->childq, child) { + switch (nc->node) { + case NODE_REFENTRY: + case NODE_REFNAMEDIV: + case NODE_REFSYNOPSISDIV: + later = NULL; + continue; + case NODE_APPENDIX: + case NODE_INDEX: + if (later == NULL) + later = nc; + continue; + default: + break; + } + if ((title = pnode_findfirst(nc, NODE_TITLE)) == NULL || + (title = TAILQ_FIRST(&title->childq)) == NULL || + title->node != NODE_TEXT) + continue; + if (strcasecmp(title->b, "AUTHORS") == 0 || + strcasecmp(title->b, "AUTHOR") == 0) + match = nc; + else if (strcasecmp(title->b, "NAME") == 0 || + strcasecmp(title->b, "SYNOPSIS") == 0 || + strcasecmp(title->b, "DESCRIPTION") == 0 || + strcasecmp(title->b, "RETURN VALUES") == 0 || + strcasecmp(title->b, "ENVIRONMENT") == 0 || + strcasecmp(title->b, "FILES") == 0 || + strcasecmp(title->b, "EXIT STATUS") == 0 || + strcasecmp(title->b, "EXAMPLES") == 0 || + strcasecmp(title->b, "DIAGNOSTICS") == 0 || + strcasecmp(title->b, "ERRORS") == 0 || + strcasecmp(title->b, "SEE ALSO") == 0 || + strcasecmp(title->b, "STANDARDS") == 0 || + strcasecmp(title->b, "HISTORY") == 0) + later = NULL; + else if ((strcasecmp(title->b, "CAVEATS") == 0 || + strcasecmp(title->b, "BUGS") == 0) && + later == NULL) + later = nc; + } + + /* + * If no AUTHORS section was found, create one from scratch, + * and insert that at the place selected earlier. + */ + + if (match == NULL) { + match = pnode_alloc(NULL); + match->node = NODE_SECTION; + match->flags |= NFLAG_SPC; + match->parent = n; + nc = pnode_alloc(match); + nc->node = NODE_TITLE; + nc->flags |= NFLAG_SPC; + nc = pnode_alloc_text(nc, "AUTHORS"); + nc->flags |= NFLAG_SPC; + if (later == NULL) + TAILQ_INSERT_TAIL(&n->childq, match, child); + else + TAILQ_INSERT_BEFORE(later, match, child); + } + + /* + * Dump the stuff excised at the beginning + * into this AUTHORS section. + */ + + if (info != NULL) + TAILQ_INSERT_TAIL(&match->childq, info, child); + if (meta != NULL) + TAILQ_INSERT_TAIL(&match->childq, meta, child); +} + +static void +default_title(struct pnode *n, const char *title) +{ + struct pnode *nc; + + if (n->parent == NULL) + return; + + TAILQ_FOREACH(nc, &n->childq, child) + if (nc->node == NODE_TITLE) + return; + + nc = pnode_alloc(NULL); + nc->node = NODE_TITLE; + nc->parent = n; + TAILQ_INSERT_HEAD(&n->childq, nc, child); + pnode_alloc_text(nc, title); +} + +static void +reorg_recurse(struct pnode *n) +{ + struct pnode *nc; + + if (n == NULL) + return; + + switch (n->node) { + case NODE_APPENDIX: + if (n->parent == NULL) + reorg_refentry(n); + default_title(n, "Appendix"); + break; + case NODE_CAUTION: + default_title(n, "Caution"); + n->node = NODE_NOTE; + break; + case NODE_LEGALNOTICE: + default_title(n, "Legal Notice"); + n->node = NODE_SIMPLESECT; + break; + case NODE_NOTE: + default_title(n, "Note"); + break; + case NODE_PREFACE: + if (n->parent == NULL) + reorg_refentry(n); + default_title(n, "Preface"); + n->node = NODE_SECTION; + break; + case NODE_REFENTRY: + reorg_refentry(n); + break; + case NODE_SECTION: + if (n->parent == NULL) + reorg_refentry(n); + /* FALLTHROUGH */ + case NODE_SIMPLESECT: + default_title(n, "Untitled"); + break; + case NODE_TIP: + default_title(n, "Tip"); + n->node = NODE_NOTE; + break; + case NODE_WARNING: + default_title(n, "Warning"); + n->node = NODE_NOTE; + break; + default: + break; + } + + TAILQ_FOREACH(nc, &n->childq, child) + reorg_recurse(nc); +} + +void +ptree_reorg(struct ptree *tree) +{ + reorg_root(tree->root); + reorg_recurse(tree->root); }