=================================================================== RCS file: /cvs/docbook2mdoc/docbook2mdoc.c,v retrieving revision 1.109 retrieving revision 1.147 diff -u -p -r1.109 -r1.147 --- docbook2mdoc/docbook2mdoc.c 2019/04/12 10:34:48 1.109 +++ docbook2mdoc/docbook2mdoc.c 2019/05/01 17:20:47 1.147 @@ -1,4 +1,4 @@ -/* $Id: docbook2mdoc.c,v 1.109 2019/04/12 10:34:48 schwarze Exp $ */ +/* $Id: docbook2mdoc.c,v 1.147 2019/05/01 17:20:47 schwarze Exp $ */ /* * Copyright (c) 2014 Kristaps Dzonsons * Copyright (c) 2019 Ingo Schwarze @@ -21,6 +21,7 @@ #include #include +#include "xmalloc.h" #include "node.h" #include "macro.h" #include "format.h" @@ -39,9 +40,11 @@ pnode_printtext(struct format *f, struct pnode *n) char *cp; int accept_arg; + para_check(f); cp = n->b; accept_arg = f->flags & FMT_ARG; - if (f->linestate == LINE_MACRO && !n->spc && !accept_arg) { + if (f->linestate == LINE_MACRO && !accept_arg && + (n->flags & NFLAG_SPC) == 0) { for (;;) { if (*cp == '\0') return; @@ -70,30 +73,41 @@ pnode_printtext(struct format *f, struct pnode *n) */ if (f->linestate != LINE_MACRO && - (nn = TAILQ_NEXT(n, child)) != NULL && nn->spc == 0 && - (nn->node != NODE_TEXT && nn->node != NODE_ESCAPE)) { - macro_open(f, "Pf"); - accept_arg = 1; - f->flags |= FMT_CHILD; - nn->spc = 1; + (nn = TAILQ_NEXT(n, child)) != NULL && + (nn->flags & NFLAG_SPC) == 0) { + switch (pnode_class(nn->node)) { + case CLASS_LINE: + case CLASS_ENCL: + macro_open(f, "Pf"); + accept_arg = 1; + f->flags |= FMT_CHILD; + nn->flags |= NFLAG_SPC; + break; + default: + break; + } } switch (f->linestate) { case LINE_NEW: break; case LINE_TEXT: - if (n->spc) { - if (n->node == NODE_TEXT) + if (n->flags & NFLAG_SPC) { + if (n->flags & NFLAG_LINE && + pnode_class(n->node) == CLASS_TEXT) macro_close(f); else putchar(' '); } break; case LINE_MACRO: - if (accept_arg) - putchar(' '); - else + if (accept_arg == 0) macro_close(f); + else if (n->flags & NFLAG_SPC || + (f->flags & FMT_ARG) == 0 || + (nn = TAILQ_PREV(n, pnodeq, child)) == NULL || + pnode_class(nn->node) != CLASS_TEXT) + putchar(' '); break; } @@ -119,35 +133,41 @@ pnode_printtext(struct format *f, struct pnode *n) } static void -pnode_printpara(struct format *f, struct pnode *n) +pnode_printimagedata(struct format *f, struct pnode *n) { - struct pnode *np; + const char *cp; - if (n->parent == NULL) - return; + if ((cp = pnode_getattr_raw(n, ATTRKEY_FILEREF, NULL)) == NULL) + cp = pnode_getattr_raw(n, ATTRKEY_ENTITYREF, NULL); + if (cp != NULL) { + print_text(f, "[image:", ARG_SPACE); + print_text(f, cp, ARG_SPACE); + print_text(f, "]", 0); + } else + print_text(f, "[image]", ARG_SPACE); +} - if ((np = TAILQ_PREV(n, pnodeq, child)) == NULL) - np = n->parent; +static void +pnode_printrefnamediv(struct format *f, struct pnode *n) +{ + struct pnode *nc, *nn; + int comma; - f->flags = 0; - - switch (np->node) { - case NODE_ENTRY: - case NODE_GLOSSTERM: - case NODE_LISTITEM: - case NODE_TERM: - return; - case NODE_APPENDIX: - case NODE_LEGALNOTICE: - case NODE_PREFACE: - case NODE_SECTION: - if (f->level < 3) - return; - break; - default: - break; + f->parastate = PARA_HAVE; + macro_line(f, "Sh NAME"); + f->parastate = PARA_HAVE; + comma = 0; + TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) { + if (nc->node != NODE_REFNAME) + continue; + if (comma) + macro_addarg(f, ",", ARG_SPACE); + macro_open(f, "Nm"); + macro_addnode(f, nc, ARG_SPACE); + pnode_unlink(nc); + comma = 1; } - macro_line(f, "Pp"); + macro_close(f); } /* @@ -162,17 +182,18 @@ pnode_printrefsynopsisdiv(struct format *f, struct pno if (nc->node == NODE_TITLE) pnode_unlink(nc); + f->parastate = PARA_HAVE; macro_line(f, "Sh SYNOPSIS"); + f->parastate = PARA_HAVE; } /* * 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; - const char *title; + struct pnode *nc, *ncc; int flags, level; if (n->parent == NULL) @@ -180,75 +201,62 @@ pnode_printrefsect(struct format *f, struct pnode *n) 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_SECTION: + case NODE_APPENDIX: + if (level == 1) + flags |= ARG_UPPER; + break; + case NODE_SIMPLESECT: + if (level < 2) + level = 2; + break; + case NODE_NOTE: + if (level < 3) level = 3; - break; - default: - break; - } + break; + default: + abort(); } TAILQ_FOREACH(nc, &n->childq, child) if (nc->node == NODE_TITLE) break; - if (nc == NULL) { - switch (n->node) { - case NODE_PREFACE: - title = "Preface"; - break; - case NODE_APPENDIX: - title = "Appendix"; - break; - case NODE_LEGALNOTICE: - title = "Legal Notice"; - break; - case NODE_CAUTION: - title = "Caution"; - break; - case NODE_NOTE: - title = "Note"; - break; - case NODE_TIP: - title = "Tip"; - break; - case NODE_WARNING: - title = "Warning"; - break; - default: - title = "Unknown"; - break; - } - } - switch (level) { case 1: macro_close(f); + f->parastate = PARA_HAVE; macro_open(f, "Sh"); break; case 2: macro_close(f); + f->parastate = PARA_HAVE; macro_open(f, "Ss"); break; default: - pnode_printpara(f, n); + if (f->parastate == PARA_MID) + f->parastate = PARA_WANT; macro_open(f, "Sy"); break; } + macro_addnode(f, nc, flags); + macro_close(f); + /* + * DocBook has no equivalent for -split mode, + * so just switch the default in the AUTHORS section. + */ + if (nc != NULL) { - macro_addnode(f, nc, flags); + if (level == 1 && + (ncc = TAILQ_FIRST(&nc->childq)) != NULL && + ncc->node == NODE_TEXT && + strcasecmp(ncc->b, "AUTHORS") == 0) + macro_line(f, "An -nosplit"); pnode_unlink(nc); - } else - macro_addarg(f, title, flags | ARG_QUOTED); - macro_close(f); + } + f->parastate = level > 2 ? PARA_WANT : PARA_HAVE; } /* @@ -278,46 +286,6 @@ pnode_printciterefentry(struct format *f, struct pnode pnode_unlinksub(n); } -static void -pnode_printrefmeta(struct format *f, struct pnode *n) -{ - struct pnode *nc, *title, *manvol; - - title = manvol = NULL; - TAILQ_FOREACH(nc, &n->childq, child) { - if (nc->node == NODE_MANVOLNUM) - manvol = nc; - else if (nc->node == NODE_REFENTRYTITLE) - title = nc; - } - macro_close(f); - macro_open(f, "Dt"); - if (title == NULL) - macro_addarg(f, "UNKNOWN", ARG_SPACE); - else - macro_addnode(f, title, ARG_SPACE | ARG_SINGLE | ARG_UPPER); - if (manvol == NULL) - macro_addarg(f, "1", ARG_SPACE); - else - macro_addnode(f, manvol, ARG_SPACE | ARG_SINGLE); - macro_close(f); - pnode_unlink(n); -} - -static void -pnode_printfuncdef(struct format *f, struct pnode *n) -{ - struct pnode *nc; - - nc = TAILQ_FIRST(&n->childq); - if (nc != NULL && nc->node == NODE_TEXT) { - macro_argline(f, "Ft", nc->b); - pnode_unlink(nc); - } - macro_nodeline(f, "Fo", n, ARG_SINGLE); - pnode_unlinksub(n); -} - /* * The node is a little peculiar. * First, it can have arbitrary open and closing tokens, which default @@ -378,23 +346,74 @@ pnode_printmath(struct format *f, struct pnode *n) static void pnode_printfuncprototype(struct format *f, struct pnode *n) { - struct pnode *nc, *fdef; + struct pnode *fdef, *fps, *ftype, *nc, *nn; - TAILQ_FOREACH(fdef, &n->childq, child) - if (fdef->node == NODE_FUNCDEF) + /* + * Extract child and ignore child. + * Leave other children in place, to be treated as parameters. + */ + + fdef = NULL; + TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) { + switch (nc->node) { + case NODE_FUNCDEF: + if (fdef == NULL) { + fdef = nc; + TAILQ_REMOVE(&n->childq, nc, child); + nc->parent = NULL; + } break; + case NODE_VOID: + pnode_unlink(nc); + break; + default: + break; + } + } + /* + * If no children are left, the function is void; use .Fn. + * Otherwise, use .Fo. + */ + + nc = TAILQ_FIRST(&n->childq); if (fdef != NULL) { - pnode_printfuncdef(f, fdef); + ftype = TAILQ_FIRST(&fdef->childq); + if (ftype != NULL && ftype->node == NODE_TEXT) { + macro_argline(f, "Ft", ftype->b); + pnode_unlink(ftype); + } + if (nc == NULL) { + macro_open(f, "Fn"); + macro_addnode(f, fdef, ARG_SPACE | ARG_SINGLE); + macro_addarg(f, "void", ARG_SPACE); + macro_close(f); + } else + macro_nodeline(f, "Fo", fdef, ARG_SINGLE); pnode_unlink(fdef); - } else + } else if (nc == NULL) + macro_line(f, "Fn UNKNOWN void"); + else macro_line(f, "Fo UNKNOWN"); - TAILQ_FOREACH(nc, &n->childq, child) - macro_nodeline(f, "Fa", nc, ARG_SINGLE); + if (nc == NULL) + return; + while (nc != NULL) { + if ((fps = pnode_takefirst(nc, NODE_FUNCPARAMS)) != NULL) { + macro_open(f, "Fa \""); + macro_addnode(f, nc, ARG_QUOTED); + macro_addarg(f, "(", ARG_QUOTED); + macro_addnode(f, fps, ARG_QUOTED); + macro_addarg(f, ")", ARG_QUOTED); + putchar('"'); + macro_close(f); + } else + macro_nodeline(f, "Fa", nc, ARG_SINGLE); + pnode_unlink(nc); + nc = TAILQ_FIRST(&n->childq); + } macro_line(f, "Fc"); - pnode_unlinksub(n); } /* @@ -429,14 +448,13 @@ pnode_printarg(struct format *f, struct pnode *n) f->flags |= FMT_IMPL; } } - TAILQ_FOREACH(nc, &n->childq, child) { if (nc->node == NODE_TEXT) macro_open(f, "Ar"); pnode_print(f, nc); - if (isrep && nc->node == NODE_TEXT) - macro_addarg(f, "...", ARG_SPACE); } + if (isrep && f->linestate == LINE_MACRO) + macro_addarg(f, "...", ARG_SPACE); if (isop) { if (was_impl) macro_open(f, "Oc"); @@ -449,57 +467,76 @@ pnode_printarg(struct format *f, struct pnode *n) static void pnode_printgroup(struct format *f, struct pnode *n) { - struct pnode *nc, *nn; + struct pnode *nc; struct pattr *a; - int isop, sv; + int bar, isop, isrep, was_impl; isop = 1; - TAILQ_FOREACH(a, &n->attrq, child) + isrep = was_impl = 0; + TAILQ_FOREACH(a, &n->attrq, child) { if (a->key == ATTRKEY_CHOICE && - (a->val == ATTRVAL_PLAIN || a->val == ATTRVAL_REQ)) { + (a->val == ATTRVAL_PLAIN || a->val == ATTRVAL_REQ)) isop = 0; - break; + else if (a->key == ATTRKEY_REP && a->val == ATTRVAL_REPEAT) + isrep = 1; + } + if (isop) { + if (f->flags & FMT_IMPL) { + was_impl = 1; + macro_open(f, "Oo"); + } else { + macro_open(f, "Op"); + f->flags |= FMT_IMPL; } - - /* - * Make sure we're on a macro line. - * This will prevent pnode_print() for putting us on a - * subsequent line. - */ - sv = f->linestate == LINE_NEW; - if (isop) - macro_open(f, "Op"); - else if (sv) - macro_open(f, "No"); - f->flags |= FMT_IMPL; - - /* - * Keep on printing text separated by the vertical bar as long - * as we're within the same origin node as the group. - * This is kind of a nightmare. - * Eh, DocBook... - * FIXME: if there's a "Fl", we don't cut off the leading "-" - * like we do in pnode_print(). - */ + } else if (isrep) { + if (f->flags & FMT_IMPL) { + was_impl = 1; + macro_open(f, "Bro"); + } else { + macro_open(f, "Brq"); + f->flags |= FMT_IMPL; + } + } + bar = 0; TAILQ_FOREACH(nc, &n->childq, child) { - pnode_print(f, nc); - nn = TAILQ_NEXT(nc, child); - while (nn != NULL) { - if (nc->node != nn->node) - break; + if (bar && f->linestate == LINE_MACRO) macro_addarg(f, "|", ARG_SPACE); - macro_addnode(f, nn, ARG_SPACE); - nc = nn; - nn = TAILQ_NEXT(nn, child); - } + pnode_print(f, nc); + bar = 1; } - if (sv) - macro_close(f); - f->flags &= ~FMT_IMPL; + if (isop) { + if (was_impl) + macro_open(f, "Oc"); + else + f->flags &= ~FMT_IMPL; + } else if (isrep) { + if (was_impl) + macro_open(f, "Brc"); + else + f->flags &= ~FMT_IMPL; + } + if (isrep && f->linestate == LINE_MACRO) + macro_addarg(f, "...", ARG_SPACE); pnode_unlinksub(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; @@ -554,7 +591,8 @@ pnode_printauthor(struct format *f, struct pnode *n) if ((nc = pnode_findfirst(n, NODE_EMAIL)) != NULL) { f->flags |= FMT_CHILD; - pnode_print(f, nc); + macro_open(f, "Aq Mt"); + macro_addnode(f, nc, ARG_SPACE); pnode_unlink(nc); } @@ -571,6 +609,18 @@ pnode_printauthor(struct format *f, struct pnode *n) } static void +pnode_printxref(struct format *f, struct pnode *n) +{ + const char *linkend; + + linkend = pnode_getattr_raw(n, ATTRKEY_LINKEND, NULL); + if (linkend != NULL) { + macro_open(f, "Sx"); + macro_addarg(f, linkend, ARG_SPACE); + } +} + +static void pnode_printlink(struct format *f, struct pnode *n) { struct pnode *nc; @@ -613,35 +663,74 @@ pnode_printlink(struct format *f, struct pnode *n) if (TAILQ_FIRST(&n->childq) != NULL) macro_addnode(f, n, ARG_SPACE | ARG_SINGLE); pnode_unlinksub(n); - return; } } static void -pnode_printprologue(struct format *f, struct ptree *tree) +pnode_printolink(struct format *f, struct pnode *n) { - struct pnode *refmeta; + const char *uri, *ptr, *local; - refmeta = tree->root == NULL ? NULL : - pnode_findfirst(tree->root, NODE_REFMETA); + uri = pnode_getattr_raw(n, ATTRKEY_TARGETDOC, NULL); + ptr = pnode_getattr_raw(n, ATTRKEY_TARGETPTR, NULL); + local = pnode_getattr_raw(n, ATTRKEY_LOCALINFO, NULL); + if (uri == NULL) { + uri = ptr; + ptr = NULL; + } + if (uri == NULL) { + uri = local; + local = NULL; + } + if (uri == NULL) + return; - macro_line(f, "Dd $Mdocdate" "$"); - if (refmeta == NULL) { - macro_open(f, "Dt"); - macro_addarg(f, - pnode_getattr_raw(tree->root, ATTRKEY_ID, "UNKNOWN"), - ARG_SPACE | ARG_SINGLE | ARG_UPPER); - macro_addarg(f, "1", ARG_SPACE); + macro_open(f, "Lk"); + macro_addarg(f, uri, ARG_SPACE | ARG_SINGLE); + macro_addnode(f, n, ARG_SPACE | ARG_SINGLE); + if (ptr != NULL || local != NULL) { macro_close(f); - } else - pnode_printrefmeta(f, refmeta); + macro_open(f, "Pq"); + if (ptr != NULL) + macro_addarg(f, ptr, ARG_SPACE); + if (local != NULL) + macro_addarg(f, local, ARG_SPACE); + } + pnode_unlinksub(n); +} + +static void +pnode_printprologue(struct format *f, struct pnode *root) +{ + struct pnode *name, *nc; + + nc = TAILQ_FIRST(&root->childq); + assert(nc->node == NODE_DATE); + macro_nodeline(f, "Dd", nc, 0); + pnode_unlink(nc); + + macro_open(f, "Dt"); + name = TAILQ_FIRST(&root->childq); + assert(name->node == NODE_REFENTRYTITLE); + macro_addnode(f, name, ARG_SPACE | ARG_SINGLE | ARG_UPPER); + TAILQ_REMOVE(&root->childq, name, child); + name->parent = NULL; + nc = TAILQ_FIRST(&root->childq); + assert (nc->node == NODE_MANVOLNUM); + macro_addnode(f, nc, ARG_SPACE | ARG_SINGLE); + pnode_unlink(nc); + macro_line(f, "Os"); - if (tree->flags & TREE_EQN) { - macro_line(f, "EQ"); - print_text(f, "delim $$", 0); - macro_line(f, "EN"); + nc = TAILQ_FIRST(&root->childq); + if (nc != NULL && nc->node == NODE_TITLE) { + macro_line(f, "Sh NAME"); + macro_nodeline(f, "Nm", name, ARG_SINGLE); + macro_nodeline(f, "Nd", nc, 0); + pnode_unlink(nc); } + pnode_unlink(name); + f->parastate = PARA_HAVE; } /* @@ -651,15 +740,17 @@ pnode_printprologue(struct format *f, struct ptree *tr static void pnode_printvarlistentry(struct format *f, struct pnode *n) { - struct pnode *nc, *nn; - int first = 1; + struct pnode *nc, *nn, *ncc; + int comma; macro_open(f, "It"); + f->parastate = PARA_HAVE; f->flags |= FMT_IMPL; + comma = -1; TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) { if (nc->node != NODE_TERM && nc->node != NODE_GLOSSTERM) continue; - if (first == 0) { + if (comma != -1) { switch (f->linestate) { case LINE_NEW: break; @@ -667,20 +758,24 @@ pnode_printvarlistentry(struct format *f, struct pnode print_text(f, ",", 0); break; case LINE_MACRO: - macro_addarg(f, ",", 0); + macro_addarg(f, ",", comma); break; } } + f->parastate = PARA_HAVE; + comma = (ncc = TAILQ_FIRST(&nc->childq)) == NULL || + pnode_class(ncc->node) == CLASS_TEXT ? 0 : ARG_SPACE; pnode_print(f, nc); pnode_unlink(nc); - first = 0; } macro_close(f); + f->parastate = PARA_HAVE; while ((nc = TAILQ_FIRST(&n->childq)) != NULL) { pnode_print(f, nc); pnode_unlink(nc); } macro_close(f); + f->parastate = PARA_HAVE; } static void @@ -690,8 +785,9 @@ pnode_printtitle(struct format *f, struct pnode *n) TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) { if (nc->node == NODE_TITLE) { - pnode_printpara(f, nc); - pnode_print(f, nc); + if (f->parastate == PARA_MID) + f->parastate = PARA_WANT; + macro_nodeline(f, "Sy", nc, 0); pnode_unlink(nc); } } @@ -719,7 +815,9 @@ pnode_printtgroup1(struct format *f, struct pnode *n) macro_line(f, "Bl -bullet -compact"); while ((nc = pnode_findfirst(n, NODE_ENTRY)) != NULL) { macro_line(f, "It"); + f->parastate = PARA_HAVE; pnode_print(f, nc); + f->parastate = PARA_HAVE; pnode_unlink(nc); } macro_line(f, "El"); @@ -731,19 +829,24 @@ pnode_printtgroup2(struct format *f, struct pnode *n) { struct pnode *nr, *ne; + f->parastate = PARA_HAVE; macro_line(f, "Bl -tag -width Ds"); while ((nr = pnode_findfirst(n, NODE_ROW)) != NULL) { if ((ne = pnode_findfirst(n, NODE_ENTRY)) == NULL) break; macro_open(f, "It"); f->flags |= FMT_IMPL; + f->parastate = PARA_HAVE; pnode_print(f, ne); macro_close(f); pnode_unlink(ne); + f->parastate = PARA_HAVE; pnode_print(f, nr); + f->parastate = PARA_HAVE; pnode_unlink(nr); } macro_line(f, "El"); + f->parastate = PARA_WANT; pnode_unlinksub(n); } @@ -763,12 +866,14 @@ pnode_printtgroup(struct format *f, struct pnode *n) break; } + f->parastate = PARA_HAVE; macro_line(f, "Bl -ohang"); while ((nc = pnode_findfirst(n, NODE_ROW)) != NULL) { macro_line(f, "It Table Row"); pnode_printrow(f, nc); } macro_line(f, "El"); + f->parastate = PARA_WANT; pnode_unlinksub(n); } @@ -778,13 +883,17 @@ pnode_printlist(struct format *f, struct pnode *n) struct pnode *nc; pnode_printtitle(f, n); + f->parastate = PARA_HAVE; macro_argline(f, "Bl", n->node == NODE_ORDEREDLIST ? "-enum" : "-bullet"); TAILQ_FOREACH(nc, &n->childq, child) { macro_line(f, "It"); + f->parastate = PARA_HAVE; pnode_print(f, nc); + f->parastate = PARA_HAVE; } macro_line(f, "El"); + f->parastate = PARA_WANT; pnode_unlinksub(n); } @@ -794,6 +903,7 @@ pnode_printvariablelist(struct format *f, struct pnode struct pnode *nc; pnode_printtitle(f, n); + f->parastate = PARA_HAVE; macro_line(f, "Bl -tag -width Ds"); TAILQ_FOREACH(nc, &n->childq, child) { if (nc->node == NODE_VARLISTENTRY) @@ -802,6 +912,7 @@ pnode_printvariablelist(struct format *f, struct pnode macro_nodeline(f, "It", nc, 0); } macro_line(f, "El"); + f->parastate = PARA_WANT; pnode_unlinksub(n); } @@ -815,21 +926,22 @@ static void pnode_print(struct format *f, struct pnode *n) { struct pnode *nc, *nn; - enum linestate sv; + int was_impl; if (n == NULL) return; - sv = f->linestate; - if (n->spc) + if (n->flags & NFLAG_LINE && + (f->nofill || (f->flags & (FMT_ARG | FMT_IMPL)) == 0)) + macro_close(f); + + was_impl = f->flags & FMT_IMPL; + if (n->flags & NFLAG_SPC) f->flags &= ~FMT_NOSPC; else f->flags |= FMT_NOSPC; switch (n->node) { - case NODE_APPLICATION: - macro_open(f, "Nm"); - break; case NODE_ARG: pnode_printarg(f, n); break; @@ -840,11 +952,10 @@ pnode_print(struct format *f, struct pnode *n) macro_line(f, "An -split"); break; case NODE_BLOCKQUOTE: + f->parastate = PARA_HAVE; macro_line(f, "Bd -ragged -offset indent"); + f->parastate = PARA_HAVE; break; - case NODE_BOOKINFO: - macro_line(f, "Sh NAME"); - break; case NODE_CITEREFENTRY: pnode_printciterefentry(f, n); break; @@ -857,18 +968,30 @@ 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); - sv = LINE_TEXT; - macro_open(f, "An"); + pnode_printauthor(f, n); break; case NODE_EMAIL: - macro_open(f, "Aq Mt"); + if (was_impl) + macro_open(f, "Ao Mt"); + else { + macro_open(f, "Aq Mt"); + f->flags |= FMT_IMPL; + } break; 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"); + if (n->node == NODE_GLOSSTERM) + f->parastate = PARA_HAVE; break; case NODE_ENVAR: macro_open(f, "Ev"); @@ -879,6 +1002,10 @@ pnode_print(struct format *f, struct pnode *n) case NODE_FILENAME: macro_open(f, "Pa"); break; + case NODE_FOOTNOTE: + macro_line(f, "Bo"); + f->parastate = PARA_HAVE; + break; case NODE_FUNCTION: macro_open(f, "Fn"); break; @@ -888,14 +1015,17 @@ pnode_print(struct format *f, struct pnode *n) case NODE_FUNCSYNOPSISINFO: macro_open(f, "Fd"); break; + case NODE_IMAGEDATA: + pnode_printimagedata(f, n); + break; case NODE_INFORMALEQUATION: + f->parastate = PARA_HAVE; + macro_line(f, "Bd -ragged -offset indent"); + f->parastate = PARA_HAVE; + /* FALLTHROUGH */ + case NODE_INLINEEQUATION: macro_line(f, "EQ"); break; - case NODE_INLINEEQUATION: - if (f->linestate == LINE_NEW) - f->linestate = LINE_TEXT; - putchar('$'); - break; case NODE_ITEMIZEDLIST: pnode_printlist(f, n); break; @@ -903,18 +1033,28 @@ pnode_print(struct format *f, struct pnode *n) pnode_printgroup(f, n); break; case NODE_KEYSYM: + case NODE_PRODUCTNAME: macro_open(f, "Sy"); break; case NODE_LINK: pnode_printlink(f, n); break; case NODE_LITERAL: - macro_open(f, "Ql"); + 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; + } break; case NODE_LITERALLAYOUT: macro_close(f); + f->parastate = PARA_HAVE; macro_argline(f, "Bd", pnode_getattr(n, ATTRKEY_CLASS) == ATTRVAL_MONOSPACED ? "-literal" : "-unfilled"); + f->parastate = PARA_HAVE; break; case NODE_MARKUP: macro_open(f, "Ic"); @@ -935,14 +1075,20 @@ pnode_print(struct format *f, struct pnode *n) case NODE_MML_MSUP: pnode_printmath(f, n); break; + case NODE_OLINK: + pnode_printolink(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); break; case NODE_PARA: - pnode_printpara(f, n); + if (f->parastate == PARA_MID) + f->parastate = PARA_WANT; break; case NODE_PARAMDEF: case NODE_PARAMETER: @@ -952,25 +1098,34 @@ pnode_print(struct format *f, struct pnode *n) pnode_unlinksub(n); break; case NODE_QUOTE: - macro_open(f, "Qo"); + if ((nc = TAILQ_FIRST(&n->childq)) != NULL && + nc->node == NODE_FILENAME && + TAILQ_NEXT(nc, child) == NULL) { + if (n->flags & NFLAG_SPC) + nc->flags |= NFLAG_SPC; + } else if (was_impl) + macro_open(f, "Do"); + else { + macro_open(f, "Dq"); + f->flags |= FMT_IMPL; + } break; case NODE_PROGRAMLISTING: case NODE_SCREEN: case NODE_SYNOPSIS: + f->parastate = PARA_HAVE; macro_line(f, "Bd -literal"); + f->parastate = PARA_HAVE; break; - case NODE_REFENTRYINFO: - /* Suppress. */ - pnode_unlinksub(n); + case NODE_SYSTEMITEM: + pnode_printsystemitem(f, n); break; case NODE_REFNAME: - /* Suppress non-text children... */ + /* More often, these appear inside NODE_REFNAMEDIV. */ macro_open(f, "Nm"); - macro_addnode(f, n, ARG_SPACE | ARG_SINGLE); - pnode_unlinksub(n); break; case NODE_REFNAMEDIV: - macro_line(f, "Sh NAME"); + pnode_printrefnamediv(f, n); break; case NODE_REFPURPOSE: macro_open(f, "Nd"); @@ -978,22 +1133,32 @@ pnode_print(struct format *f, struct pnode *n) case NODE_REFSYNOPSISDIV: pnode_printrefsynopsisdiv(f, 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"); break; case NODE_SBR: - macro_line(f, "br"); + if (f->parastate == PARA_MID) + 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->flags &= ~(NFLAG_LINE | NFLAG_SPC); + break; + case NODE_SUPERSCRIPT: + fputs("\\(ha", stdout); + if ((nc = TAILQ_FIRST(&n->childq)) != NULL) + nc->flags &= ~(NFLAG_LINE | NFLAG_SPC); + break; case NODE_TEXT: case NODE_ESCAPE: pnode_printtext(f, n); @@ -1002,12 +1167,9 @@ pnode_print(struct format *f, struct pnode *n) pnode_printtgroup(f, n); break; case NODE_TITLE: - if (n->parent != NULL && - n->parent->node == NODE_BOOKINFO) { - macro_open(f, "Nd"); - break; - } - pnode_printpara(f, n); + case NODE_SUBTITLE: + if (f->parastate == PARA_MID) + f->parastate = PARA_WANT; macro_nodeline(f, "Sy", n, 0); pnode_unlinksub(n); break; @@ -1020,26 +1182,64 @@ pnode_print(struct format *f, struct pnode *n) case NODE_VARNAME: macro_open(f, "Va"); break; + case NODE_VOID: + print_text(f, "void", ARG_SPACE); + break; + case NODE_XREF: + pnode_printxref(f, n); + break; + case NODE_CAUTION: + case NODE_LEGALNOTICE: + case NODE_PREFACE: + case NODE_TIP: + case NODE_WARNING: + abort(); default: break; } + if (pnode_class(n->node) == CLASS_NOFILL) + f->nofill++; + TAILQ_FOREACH(nc, &n->childq, child) pnode_print(f, nc); switch (n->node) { + case NODE_EMAIL: + if (was_impl) { + f->flags &= ~FMT_NOSPC; + macro_open(f, "Ac"); + } else + f->flags &= ~FMT_IMPL; + break; case NODE_ESCAPE: case NODE_TERM: case NODE_TEXT: /* Accept more arguments to the previous macro. */ return; + case NODE_FOOTNOTE: + f->parastate = PARA_HAVE; + macro_line(f, "Bc"); + break; + case NODE_GLOSSTERM: + f->parastate = PARA_HAVE; + break; case NODE_INFORMALEQUATION: macro_line(f, "EN"); + macro_line(f, "Ed"); break; case NODE_INLINEEQUATION: - fputs("$ ", stdout); - f->linestate = sv; + macro_line(f, "EN"); break; + case NODE_LITERAL: + if (n->parent != NULL && n->parent->node == NODE_QUOTE) + /* nothing */; + else if (was_impl) { + f->flags &= ~FMT_NOSPC; + macro_open(f, "Sc"); + } else + f->flags &= ~FMT_IMPL; + break; case NODE_MEMBER: if ((nn = TAILQ_NEXT(n, child)) != NULL && nn->node != NODE_MEMBER) @@ -1066,64 +1266,67 @@ pnode_print(struct format *f, struct pnode *n) break; fputs(" } ", stdout); break; + case NODE_PARA: + if (f->parastate == PARA_MID) + f->parastate = PARA_WANT; + break; case NODE_QUOTE: - if (sv == LINE_NEW) - macro_close(f); - sv = f->linestate; - macro_open(f, "Qc"); - if (sv == LINE_NEW) - macro_close(f); + if ((nc = TAILQ_FIRST(&n->childq)) != NULL && + nc->node == NODE_FILENAME && + TAILQ_NEXT(nc, child) == NULL) + /* nothing */; + else if (was_impl) { + f->flags &= ~FMT_NOSPC; + macro_open(f, "Dc"); + } else + f->flags &= ~FMT_IMPL; break; - case NODE_REFNAME: - /* - * If we're in the NAME macro and we have multiple - * macros in sequence, then print out a - * trailing comma before the newline. - */ - if (n->parent != NULL && - n->parent->node == NODE_REFNAMEDIV && - TAILQ_NEXT(n, child) != NULL && - TAILQ_NEXT(n, child)->node == NODE_REFNAME) - macro_addarg(f, ",", ARG_SPACE); - if (sv == LINE_NEW) - macro_close(f); - 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: - f->level--; + if (n->parent != NULL) + f->level--; break; case NODE_BLOCKQUOTE: case NODE_LITERALLAYOUT: case NODE_PROGRAMLISTING: case NODE_SCREEN: case NODE_SYNOPSIS: + f->parastate = PARA_HAVE; macro_line(f, "Ed"); + f->parastate = PARA_WANT; break; case NODE_TITLE: - if (n->parent != NULL && - n->parent->node == NODE_BOOKINFO) - macro_line(f, "Sh AUTHORS"); + case NODE_SUBTITLE: + f->parastate = PARA_WANT; break; + case NODE_YEAR: + if ((nn = TAILQ_NEXT(n, child)) != NULL && + nn->node == NODE_YEAR && + f->linestate == LINE_TEXT) { + print_text(f, ",", 0); + nn->flags |= NFLAG_SPC; + if ((nc = TAILQ_FIRST(&nn->childq)) != NULL) + nc->flags |= NFLAG_SPC; + } default: break; } f->flags &= ~FMT_ARG; + if (pnode_class(n->node) == CLASS_NOFILL) + f->nofill--; } void -ptree_print(struct ptree *tree) +ptree_print_mdoc(struct ptree *tree) { struct format formatter; - formatter.level = 0; + formatter.level = formatter.nofill = 0; formatter.linestate = LINE_NEW; - pnode_printprologue(&formatter, tree); + formatter.parastate = PARA_HAVE; + pnode_printprologue(&formatter, tree->root); pnode_print(&formatter, tree->root); if (formatter.linestate != LINE_NEW) putchar('\n');