=================================================================== RCS file: /cvs/docbook2mdoc/docbook2mdoc.c,v retrieving revision 1.124 retrieving revision 1.146 diff -u -p -r1.124 -r1.146 --- docbook2mdoc/docbook2mdoc.c 2019/04/14 20:13:25 1.124 +++ docbook2mdoc/docbook2mdoc.c 2019/05/01 15:05:39 1.146 @@ -1,4 +1,4 @@ -/* $Id: docbook2mdoc.c,v 1.124 2019/04/14 20:13:25 schwarze Exp $ */ +/* $Id: docbook2mdoc.c,v 1.146 2019/05/01 15:05:39 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" @@ -30,7 +31,6 @@ */ static void pnode_print(struct format *, struct pnode *); -static void pnode_printrefentry(struct format *, struct pnode *); static void @@ -42,7 +42,8 @@ pnode_printtext(struct format *f, struct pnode *n) 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; @@ -71,14 +72,15 @@ pnode_printtext(struct format *f, struct pnode *n) */ if (f->linestate != LINE_MACRO && - (nn = TAILQ_NEXT(n, child)) != NULL && nn->spc == 0) { + (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->spc = 1; + nn->flags |= NFLAG_SPC; break; default: break; @@ -89,18 +91,22 @@ pnode_printtext(struct format *f, struct pnode *n) 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; } @@ -126,35 +132,18 @@ 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 ((np = TAILQ_PREV(n, pnodeq, child)) == NULL) - np = n->parent; - - 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; - } - macro_line(f, "Pp"); + 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); } static void @@ -163,7 +152,9 @@ pnode_printrefnamediv(struct format *f, struct pnode * struct pnode *nc, *nn; int comma; + 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) @@ -190,7 +181,9 @@ 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; } /* @@ -200,86 +193,53 @@ static void pnode_printsection(struct format *f, struct pnode *n) { struct pnode *nc, *ncc; - const char *title; int flags, level; - if (n->parent == NULL) { - pnode_printrefentry(f, n); + if (n->parent == NULL) return; - } level = ++f->level; flags = ARG_SPACE; 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: + case NODE_NOTE: if (level < 3) level = 3; 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; } - - if (nc != NULL) - macro_addnode(f, nc, flags); - else - macro_addarg(f, title, flags | ARG_QUOTED); + macro_addnode(f, nc, flags); macro_close(f); /* @@ -288,12 +248,14 @@ pnode_printsection(struct format *f, struct pnode *n) */ if (nc != NULL) { - ncc = TAILQ_FIRST(&nc->childq); - if (ncc != NULL && ncc->node == NODE_TEXT && + 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); } + f->parastate = level > 2 ? PARA_WANT : PARA_HAVE; } /* @@ -323,20 +285,6 @@ pnode_printciterefentry(struct format *f, struct pnode pnode_unlinksub(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 @@ -397,23 +345,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); } /* @@ -609,6 +608,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; @@ -651,212 +662,76 @@ 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 pnode *root) +pnode_printolink(struct format *f, struct pnode *n) { - struct pnode *date, *refmeta, *name, *vol, *descr, *nc, *nn; - const char *sname; + const char *uri, *ptr, *local; - /* Collect information. */ + 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; - if ((date = pnode_takefirst(root, NODE_PUBDATE)) == NULL) - date = pnode_takefirst(root, NODE_DATE); - - name = vol = NULL; - if ((refmeta = pnode_findfirst(root, NODE_REFMETA)) != NULL) { - TAILQ_FOREACH_SAFE(nc, &refmeta->childq, child, nn) { - switch (nc->node) { - case NODE_REFENTRYTITLE: - name = nc; - break; - case NODE_MANVOLNUM: - vol = nc; - break; - default: - continue; - } - TAILQ_REMOVE(&refmeta->childq, nc, child); - } + 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); + 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); +} - if (pnode_findfirst(root, NODE_REFNAMEDIV) == NULL && - ((nc = pnode_findfirst(root, NODE_BOOKINFO)) != NULL || - (nc = pnode_findfirst(root, NODE_REFENTRYINFO)) != NULL)) - descr = pnode_takefirst(nc, NODE_TITLE); - else - descr = NULL; +static void +pnode_printprologue(struct format *f, struct pnode *root) +{ + struct pnode *name, *nc; - /* Print prologue. */ + nc = TAILQ_FIRST(&root->childq); + assert(nc->node == NODE_DATE); + macro_nodeline(f, "Dd", nc, 0); + pnode_unlink(nc); - if (date == NULL) - macro_line(f, "Dd $Mdocdate" "$"); - else - macro_nodeline(f, "Dd", date, 0); - macro_open(f, "Dt"); - if (name == NULL) { - sname = pnode_getattr_raw(root, ATTRKEY_ID, "UNKNOWN"); - macro_addarg(f, sname, ARG_SPACE | ARG_SINGLE | ARG_UPPER); - } else - macro_addnode(f, name, ARG_SPACE | ARG_SINGLE | ARG_UPPER); - if (vol == NULL) - macro_addarg(f, "1", ARG_SPACE); - else - macro_addnode(f, vol, ARG_SPACE | ARG_SINGLE); + 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 (descr != NULL) { + nc = TAILQ_FIRST(&root->childq); + if (nc != NULL && nc->node == NODE_TITLE) { macro_line(f, "Sh NAME"); - if (name == NULL) - macro_argline(f, "Nm", sname); - else - macro_nodeline(f, "Nm", name, ARG_SINGLE); - macro_nodeline(f, "Nd", descr, 0); + macro_nodeline(f, "Nm", name, ARG_SINGLE); + macro_nodeline(f, "Nd", nc, 0); + pnode_unlink(nc); } - - /* Clean up. */ - - pnode_unlink(date); pnode_unlink(name); - pnode_unlink(vol); - pnode_unlink(descr); + f->parastate = PARA_HAVE; } -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. @@ -864,15 +739,17 @@ pnode_printrefentry(struct format *f, struct pnode *n) 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; @@ -880,20 +757,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 @@ -903,8 +784,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); } } @@ -932,7 +814,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"); @@ -944,19 +828,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); } @@ -976,12 +865,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); } @@ -991,13 +882,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); } @@ -1007,6 +902,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) @@ -1015,6 +911,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); } @@ -1033,8 +930,11 @@ pnode_print(struct format *f, struct pnode *n) if (n == NULL) return; + if (f->nofill && n->flags & NFLAG_LINE) + macro_close(f); + was_impl = f->flags & FMT_IMPL; - if (n->spc) + if (n->flags & NFLAG_SPC) f->flags &= ~FMT_NOSPC; else f->flags |= FMT_NOSPC; @@ -1050,7 +950,9 @@ 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_CITEREFENTRY: pnode_printciterefentry(f, n); @@ -1086,6 +988,8 @@ pnode_print(struct format *f, struct pnode *n) 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"); @@ -1096,6 +1000,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; @@ -1105,8 +1013,13 @@ 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"); @@ -1118,6 +1031,7 @@ 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: @@ -1135,8 +1049,10 @@ pnode_print(struct format *f, struct pnode *n) 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"); @@ -1157,6 +1073,9 @@ 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: if ((nc = TAILQ_FIRST(&n->childq)) != NULL && pnode_class(nc->node) < CLASS_LINE) @@ -1166,7 +1085,8 @@ pnode_print(struct format *f, struct pnode *n) 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: @@ -1176,7 +1096,12 @@ pnode_print(struct format *f, struct pnode *n) pnode_unlinksub(n); break; case NODE_QUOTE: - if (was_impl) + 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"); @@ -1186,14 +1111,13 @@ pnode_print(struct format *f, struct pnode *n) 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_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"); @@ -1207,22 +1131,18 @@ 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_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) @@ -1230,12 +1150,12 @@ pnode_print(struct format *f, struct pnode *n) else print_text(f, "_", 0); if ((nc = TAILQ_FIRST(&n->childq)) != NULL) - nc->spc = 0; + nc->flags &= ~(NFLAG_LINE | NFLAG_SPC); break; case NODE_SUPERSCRIPT: fputs("\\(ha", stdout); if ((nc = TAILQ_FIRST(&n->childq)) != NULL) - nc->spc = 0; + nc->flags &= ~(NFLAG_LINE | NFLAG_SPC); break; case NODE_TEXT: case NODE_ESCAPE: @@ -1246,7 +1166,8 @@ pnode_print(struct format *f, struct pnode *n) break; case NODE_TITLE: case NODE_SUBTITLE: - pnode_printpara(f, n); + if (f->parastate == PARA_MID) + f->parastate = PARA_WANT; macro_nodeline(f, "Sy", n, 0); pnode_unlinksub(n); break; @@ -1259,10 +1180,25 @@ 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); @@ -1279,6 +1215,13 @@ pnode_print(struct format *f, struct pnode *n) 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"); @@ -1321,34 +1264,56 @@ 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 (was_impl) { + 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_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: + 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 @@ -1356,8 +1321,9 @@ ptree_print_mdoc(struct ptree *tree) { struct format formatter; - formatter.level = 0; + formatter.level = formatter.nofill = 0; formatter.linestate = LINE_NEW; + formatter.parastate = PARA_HAVE; pnode_printprologue(&formatter, tree->root); pnode_print(&formatter, tree->root); if (formatter.linestate != LINE_NEW)