=================================================================== RCS file: /cvs/docbook2mdoc/docbook2mdoc.c,v retrieving revision 1.117 retrieving revision 1.124 diff -u -p -r1.117 -r1.124 --- docbook2mdoc/docbook2mdoc.c 2019/04/13 15:13:31 1.117 +++ docbook2mdoc/docbook2mdoc.c 2019/04/14 20:13:25 1.124 @@ -1,4 +1,4 @@ -/* $Id: docbook2mdoc.c,v 1.117 2019/04/13 15:13:31 schwarze Exp $ */ +/* $Id: docbook2mdoc.c,v 1.124 2019/04/14 20:13:25 schwarze Exp $ */ /* * Copyright (c) 2014 Kristaps Dzonsons * Copyright (c) 2019 Ingo Schwarze @@ -30,6 +30,7 @@ */ static void pnode_print(struct format *, struct pnode *); +static void pnode_printrefentry(struct format *, struct pnode *); static void @@ -196,30 +197,35 @@ pnode_printrefsynopsisdiv(struct format *f, struct pno * Start a hopefully-named `Sh' section. */ static void -pnode_printrefsect(struct format *f, struct pnode *n) +pnode_printsection(struct format *f, struct pnode *n) { struct pnode *nc, *ncc; const char *title; int flags, level; - if (n->parent == NULL) + if (n->parent == NULL) { + pnode_printrefentry(f, n); return; + } level = ++f->level; flags = ARG_SPACE; - if (level == 1) - flags |= ARG_UPPER; - if (level < 3) { - switch (n->node) { - case NODE_CAUTION: - case NODE_NOTE: - case NODE_TIP: - case NODE_WARNING: + switch (n->node) { + case NODE_PREFACE: + case NODE_SECTION: + case NODE_APPENDIX: + if (level == 1) + flags |= ARG_UPPER; + break; + case NODE_SIMPLESECT: + case NODE_LEGALNOTICE: + if (level < 2) + level = 2; + break; + default: + if (level < 3) level = 3; - break; - default: - break; - } + break; } TAILQ_FOREACH(nc, &n->childq, child) @@ -515,6 +521,22 @@ pnode_printgroup(struct format *f, struct pnode *n) } static void +pnode_printsystemitem(struct format *f, struct pnode *n) +{ + switch (pnode_getattr(n, ATTRKEY_CLASS)) { + case ATTRVAL_IPADDRESS: + break; + case ATTRVAL_SYSTEMNAME: + macro_open(f, "Pa"); + break; + case ATTRVAL_EVENT: + default: + macro_open(f, "Sy"); + break; + } +} + +static void pnode_printauthor(struct format *f, struct pnode *n) { struct pnode *nc, *nn; @@ -636,7 +658,7 @@ pnode_printlink(struct format *f, struct pnode *n) static void pnode_printprologue(struct format *f, struct pnode *root) { - struct pnode *date, *refmeta, *name, *vol, *descr, *nc; + struct pnode *date, *refmeta, *name, *vol, *descr, *nc, *nn; const char *sname; /* Collect information. */ @@ -645,8 +667,8 @@ pnode_printprologue(struct format *f, struct pnode *ro date = pnode_takefirst(root, NODE_DATE); name = vol = NULL; - if ((refmeta = pnode_takefirst(root, NODE_REFMETA)) != NULL) { - TAILQ_FOREACH(nc, &refmeta->childq, child) { + if ((refmeta = pnode_findfirst(root, NODE_REFMETA)) != NULL) { + TAILQ_FOREACH_SAFE(nc, &refmeta->childq, child, nn) { switch (nc->node) { case NODE_REFENTRYTITLE: name = nc; @@ -655,8 +677,9 @@ pnode_printprologue(struct format *f, struct pnode *ro vol = nc; break; default: - break; + continue; } + TAILQ_REMOVE(&refmeta->childq, nc, child); } } @@ -699,10 +722,141 @@ pnode_printprologue(struct format *f, struct pnode *ro /* Clean up. */ pnode_unlink(date); - pnode_unlink(refmeta); + pnode_unlink(name); + pnode_unlink(vol); pnode_unlink(descr); } +static void +pnode_printrefentry(struct format *f, struct pnode *n) +{ + struct pnode *info, *meta, *nc, *title; + struct pnode *match, *later; + + /* Collect nodes that remained behind when writing 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; + } + 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: + case NODE_PREFACE: + 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) { + if ((match = calloc(1, sizeof(*match))) == NULL) { + perror(NULL); + exit(1); + } + match->node = NODE_SECTION; + match->spc = 1; + match->parent = n; + TAILQ_INIT(&match->childq); + TAILQ_INIT(&match->attrq); + if ((nc = pnode_alloc(match)) == NULL) { + perror(NULL); + exit(1); + } + nc->node = NODE_TITLE; + nc->spc = 1; + if ((nc = pnode_alloc(nc)) == NULL) { + perror(NULL); + exit(1); + } + nc->node = NODE_TEXT; + if ((nc->b = strdup("AUTHORS")) == NULL) { + perror(NULL); + exit(1); + } + nc->spc = 1; + 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); +} + /* * We can have multiple elements within a , which * we should comma-separate as list headers. @@ -886,9 +1040,6 @@ pnode_print(struct format *f, struct pnode *n) f->flags |= FMT_NOSPC; switch (n->node) { - case NODE_APPLICATION: - macro_open(f, "Nm"); - break; case NODE_ARG: pnode_printarg(f, n); break; @@ -913,9 +1064,13 @@ pnode_print(struct format *f, struct pnode *n) case NODE_CONSTANT: macro_open(f, "Dv"); break; + case NODE_COPYRIGHT: + print_text(f, "Copyright", ARG_SPACE); + fputs(" \\(co", stdout); + break; case NODE_EDITOR: print_text(f, "editor:", ARG_SPACE); - macro_open(f, "An"); + pnode_printauthor(f, n); break; case NODE_EMAIL: if (was_impl) @@ -928,7 +1083,9 @@ pnode_print(struct format *f, struct pnode *n) case NODE_EMPHASIS: case NODE_FIRSTTERM: case NODE_GLOSSTERM: - macro_open(f, "Em"); + if ((nc = TAILQ_FIRST(&n->childq)) != NULL && + pnode_class(nc->node) < CLASS_LINE) + macro_open(f, "Em"); break; case NODE_ENVAR: macro_open(f, "Ev"); @@ -967,8 +1124,10 @@ pnode_print(struct format *f, struct pnode *n) pnode_printlink(f, n); break; case NODE_LITERAL: - if (was_impl) - macro_open(f, "So"); + if (n->parent != NULL && n->parent->node == NODE_QUOTE) + macro_open(f, "Li"); + else if (was_impl) + macro_open(f, "So Li"); else { macro_open(f, "Ql"); f->flags |= FMT_IMPL; @@ -999,7 +1158,9 @@ pnode_print(struct format *f, struct pnode *n) pnode_printmath(f, n); break; case NODE_OPTION: - macro_open(f, "Fl"); + if ((nc = TAILQ_FIRST(&n->childq)) != NULL && + pnode_class(nc->node) < CLASS_LINE) + macro_open(f, "Fl"); break; case NODE_ORDEREDLIST: pnode_printlist(f, n); @@ -1027,10 +1188,12 @@ pnode_print(struct format *f, struct pnode *n) case NODE_SYNOPSIS: macro_line(f, "Bd -literal"); break; - case NODE_REFENTRYINFO: - /* Suppress. */ - pnode_unlinksub(n); + case NODE_SYSTEMITEM: + pnode_printsystemitem(f, n); break; + case NODE_REFENTRY: + pnode_printrefentry(f, n); + break; case NODE_REFNAME: /* More often, these appear inside NODE_REFNAMEDIV. */ macro_open(f, "Nm"); @@ -1046,13 +1209,14 @@ pnode_print(struct format *f, struct pnode *n) break; case NODE_PREFACE: case NODE_SECTION: + case NODE_SIMPLESECT: case NODE_APPENDIX: case NODE_LEGALNOTICE: case NODE_NOTE: case NODE_TIP: case NODE_CAUTION: case NODE_WARNING: - pnode_printrefsect(f, n); + pnode_printsection(f, n); break; case NODE_REPLACEABLE: macro_open(f, "Ar"); @@ -1060,6 +1224,19 @@ pnode_print(struct format *f, struct pnode *n) case NODE_SBR: macro_line(f, "br"); break; + case NODE_SUBSCRIPT: + if (f->linestate == LINE_MACRO) + macro_addarg(f, "_", 0); + else + print_text(f, "_", 0); + if ((nc = TAILQ_FIRST(&n->childq)) != NULL) + nc->spc = 0; + break; + case NODE_SUPERSCRIPT: + fputs("\\(ha", stdout); + if ((nc = TAILQ_FIRST(&n->childq)) != NULL) + nc->spc = 0; + break; case NODE_TEXT: case NODE_ESCAPE: pnode_printtext(f, n); @@ -1068,6 +1245,7 @@ pnode_print(struct format *f, struct pnode *n) pnode_printtgroup(f, n); break; case NODE_TITLE: + case NODE_SUBTITLE: pnode_printpara(f, n); macro_nodeline(f, "Sy", n, 0); pnode_unlinksub(n); @@ -1109,7 +1287,9 @@ pnode_print(struct format *f, struct pnode *n) macro_line(f, "EN"); break; case NODE_LITERAL: - if (was_impl) { + if (n->parent != NULL && n->parent->node == NODE_QUOTE) + /* nothing */; + else if (was_impl) { f->flags &= ~FMT_NOSPC; macro_open(f, "Sc"); } else