From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from localhost (fantadrom.bsd.lv [local]) by fantadrom.bsd.lv (OpenSMTPD) with ESMTPA id a5578cd0 for ; Sun, 24 Mar 2019 11:46:16 -0500 (EST) Date: Sun, 24 Mar 2019 11:46:16 -0500 (EST) X-Mailinglist: mandoc-source Reply-To: source@mandoc.bsd.lv MIME-Version: 1.0 From: schwarze@mandoc.bsd.lv To: source@mandoc.bsd.lv Subject: docbook2mdoc: As usual, whitespace handling is the heart and soul of X-Mailer: activitymail 1.26, http://search.cpan.org/dist/activitymail/ Content-Type: text/plain; charset=utf-8 Message-ID: Log Message: ----------- As usual, whitespace handling is the heart and soul of roff(7) processing, so overhaul it. Keep output line state and provide a set of output functions to open and close macro lines and to add arguments to them. Mostly avoid asserting output line state because elements can occur in any order and we should just deal with whatever comes in. This diff shortens the code by 60 lines, improves robustness and readability, and fixes some bugs. Modified Files: -------------- docbook2mdoc: docbook2mdoc.c Revision Data ------------- Index: docbook2mdoc.c =================================================================== RCS file: /home/cvs/mdocml/docbook2mdoc/docbook2mdoc.c,v retrieving revision 1.68 retrieving revision 1.69 diff -Ldocbook2mdoc.c -Ldocbook2mdoc.c -u -p -r1.68 -r1.69 --- docbook2mdoc.c +++ docbook2mdoc.c @@ -29,6 +29,12 @@ #include "extern.h" +enum linestate { + LINE_NEW = 0, + LINE_TEXT, + LINE_MACRO +}; + /* * Global parse state. * Keep this as simple and small as possible. @@ -46,7 +52,7 @@ struct parse { size_t bsz; /* current length of b */ size_t mbsz; /* max bsz allocation */ int level; /* header level, starting at 1 */ - int newln; /* output: are we on a fresh line */ + enum linestate linestate; }; struct node { @@ -587,34 +593,62 @@ pnode_findfirst(struct pnode *pn, enum n return res; } -#define MACROLINE_NORM 0 -#define MACROLINE_UPPER 1 -#define MACROLINE_NOWS 2 -/* - * Recursively print text presumably on a macro line. - * Convert all whitespace to regular spaces. - */ static void -pnode_printmacrolinetext(struct parse *p, struct pnode *pn, int fl) +macro_open(struct parse *p, const char *name) { - char *cp; - - if (p->newln == 0 && (fl & MACROLINE_NOWS) == 0) + switch (p->linestate) { + case LINE_TEXT: + putchar('\n'); + /* FALLTHROUGH */ + case LINE_NEW: + putchar('.'); + p->linestate = LINE_MACRO; + break; + case LINE_MACRO: putchar(' '); + break; + } + fputs(name, stdout); +} - bufclear(p); - bufappend_r(p, pn); +static void +macro_close(struct parse *p) +{ + assert(p->linestate == LINE_MACRO); + putchar('\n'); + p->linestate = LINE_NEW; +} + +static void +macro_line(struct parse *p, const char *name) +{ + macro_open(p, name); + macro_close(p); +} + +#define MACROLINE_UPPER 1 +#define MACROLINE_NOWS 2 +/* + * Print an argument string on a macro line, collapsing whitespace. + */ +static void +macro_addarg(struct parse *p, const char *arg, int fl) +{ + const char *cp; + int wantspace; - /* Convert all space to spaces. */ - for (cp = p->b; *cp != '\0'; cp++) - if (isspace((unsigned char)*cp)) - *cp = ' '; - - for (cp = p->b; isspace((unsigned char)*cp); cp++) - /* Spin past whitespace (XXX: necessary?) */ ; - for ( ; *cp != '\0'; cp++) { + assert(p->linestate == LINE_MACRO); + wantspace = !(fl & MACROLINE_NOWS); + for (cp = arg; *cp != '\0'; cp++) { + if (isspace((unsigned char)*cp)) { + wantspace = 1; + continue; + } else if (wantspace) { + putchar(' '); + wantspace = 0; + } /* Escape us if we look like a macro. */ - if ((cp == p->b || cp[-1] == ' ') && + if ((cp == arg || cp[-1] == ' ') && isupper((unsigned char)cp[0]) && islower((unsigned char)cp[1]) && (cp[2] == '\0' || cp[2] == ' ' || @@ -625,75 +659,47 @@ pnode_printmacrolinetext(struct parse *p putchar(toupper((unsigned char)*cp)); else putchar(*cp); - /* If we're a character escape, escape us. */ if (*cp == '\\') putchar('e'); } } static void -pnode_printmacrolinepart(struct parse *p, struct pnode *pn) +macro_argline(struct parse *p, const char *name, const char *arg) { - - pnode_printmacrolinetext(p, pn, 0); + macro_open(p, name); + macro_addarg(p, arg, 0); + macro_close(p); } /* - * Just pnode_printmacrolinepart() but with a newline. - * If no text, just the newline. + * Recurse nodes to print arguments on a macro line. */ static void -pnode_printmacroline(struct parse *p, struct pnode *pn) -{ - assert(p->newln == 0); - pnode_printmacrolinetext(p, pn, 0); - putchar('\n'); - p->newln = 1; -} - -static void -pnode_printmopen(struct parse *p) +macro_addnode(struct parse *p, struct pnode *pn, int fl) { - if (p->newln) { - putchar('.'); - p->newln = 0; - } else - putchar(' '); + bufclear(p); + bufappend_r(p, pn); + macro_addarg(p, p->b, fl); } static void -pnode_printmclose(struct parse *p, int sv) +macro_nodeline(struct parse *p, const char *name, struct pnode *pn) { - - if (sv && ! p->newln) { - putchar('\n'); - p->newln = 1; - } + macro_open(p, name); + macro_addnode(p, pn, 0); + macro_close(p); } /* - * Like pnode_printmclose() except we look to the next node, and, if - * found, see if it starts with punctuation. - * If it does, then we print that punctuation before the newline. + * If the next node is a text node starting with closing punctuation, + * emit the closing punctuation as a trailing macro argument. */ static void -pnode_printmclosepunct(struct parse *p, struct pnode *pn, int sv) +macro_closepunct(struct parse *p, struct pnode *pn) { - /* We wouldn't have done anything anyway. */ - if ( ! (sv && ! p->newln)) - return; - - /* No next node or it's not text. */ - if ((pn = TAILQ_NEXT(pn, child)) == NULL) { - pnode_printmclose(p, sv); - return; - } else if (pn->node != NODE_TEXT) { - pnode_printmclose(p, sv); - return; - } - - /* Only do this for the comma/period. */ - if (pn->bsz > 0 && + if ((pn = TAILQ_NEXT(pn, child)) != NULL && + pn->node == NODE_TEXT && pn->bsz > 0 && (pn->b[0] == ',' || pn->b[0] == '.') && (pn->bsz == 1 || isspace((unsigned char)pn->b[1]))) { putchar(' '); @@ -701,9 +707,7 @@ pnode_printmclosepunct(struct parse *p, pn->b++; pn->bsz--; } - - putchar('\n'); - p->newln = 1; + macro_close(p); } static void @@ -711,7 +715,6 @@ pnode_printpara(struct parse *p, struct { struct pnode *pp; - assert(p->newln); if ((pp = TAILQ_PREV(pn, pnodeq, child)) == NULL && (pp = pn->parent) == NULL) return; @@ -728,7 +731,7 @@ pnode_printpara(struct parse *p, struct default: break; } - puts(".Pp"); + macro_line(p, "Pp"); } /* @@ -803,24 +806,23 @@ pnode_printrefsect(struct parse *p, stru switch (level) { case 1: - fputs(".Sh", stdout); + macro_open(p, "Sh"); break; case 2: - fputs(".Ss", stdout); + macro_open(p, "Ss"); break; default: pnode_printpara(p, pn); - fputs(".Sy", stdout); + macro_open(p, "Sy"); break; } if (pp != NULL) { - p->newln = 0; - pnode_printmacrolinetext(p, pp, flags); - pnode_printmclose(p, 1); + macro_addnode(p, pp, flags); pnode_unlink(pp); } else - printf(" %s\n", title); + macro_addarg(p, title, 0); + macro_close(p); } /* @@ -832,22 +834,22 @@ pnode_printciterefentry(struct parse *p, struct pnode *pp, *title, *manvol; title = manvol = NULL; - TAILQ_FOREACH(pp, &pn->childq, child) + TAILQ_FOREACH(pp, &pn->childq, child) { if (pp->node == NODE_MANVOLNUM) manvol = pp; else if (pp->node == NODE_REFENTRYTITLE) title = pp; - - if (title != NULL) - pnode_printmacrolinepart(p, title); + } + macro_open(p, "Xr"); + if (title == NULL) + macro_addarg(p, "unknown", 0); else - fputs(" unknown ", stdout); - - if (manvol == NULL) { - puts(" 1"); - p->newln = 1; - } else - pnode_printmacrolinepart(p, manvol); + macro_addnode(p, title, 0); + if (manvol == NULL) + macro_addarg(p, "1", 0); + else + macro_addnode(p, manvol, 0); + macro_close(p); } static void @@ -856,26 +858,22 @@ pnode_printrefmeta(struct parse *p, stru struct pnode *pp, *title, *manvol; title = manvol = NULL; - assert(p->newln); - TAILQ_FOREACH(pp, &pn->childq, child) + TAILQ_FOREACH(pp, &pn->childq, child) { if (pp->node == NODE_MANVOLNUM) manvol = pp; else if (pp->node == NODE_REFENTRYTITLE) title = pp; - - fputs(".Dt", stdout); - p->newln = 0; - - if (title != NULL) - pnode_printmacrolinetext(p, title, MACROLINE_UPPER); + } + macro_open(p, "Dt"); + if (title == NULL) + macro_addarg(p, "UNKNOWN", 0); else - fputs(" UNKNOWN ", stdout); - - if (manvol == NULL) { - puts(" 1"); - p->newln = 1; - } else - pnode_printmacroline(p, manvol); + macro_addnode(p, title, MACROLINE_UPPER); + if (manvol == NULL) + macro_addarg(p, "1", 0); + else + macro_addnode(p, manvol, 0); + macro_close(p); } static void @@ -883,55 +881,47 @@ pnode_printfuncdef(struct parse *p, stru { struct pnode *pp, *ftype, *func; - assert(p->newln); ftype = func = NULL; - TAILQ_FOREACH(pp, &pn->childq, child) + TAILQ_FOREACH(pp, &pn->childq, child) { if (pp->node == NODE_TEXT) ftype = pp; else if (pp->node == NODE_FUNCTION) func = pp; - - if (ftype != NULL) { - fputs(".Ft", stdout); - p->newln = 0; - pnode_printmacroline(p, ftype); - } - - if (func != NULL) { - fputs(".Fo", stdout); - p->newln = 0; - pnode_printmacroline(p, func); - } else { - puts(".Fo UNKNOWN"); - p->newln = 1; } + if (ftype != NULL) + macro_nodeline(p, "Ft", ftype); + macro_open(p, "Fo"); + if (func == NULL) + macro_addarg(p, "UNKNOWN", 0); + else + macro_addnode(p, func, 0); + macro_close(p); } static void pnode_printparamdef(struct parse *p, struct pnode *pn) { struct pnode *pp, *ptype, *param; + int flags; - assert(p->newln); ptype = param = NULL; - TAILQ_FOREACH(pp, &pn->childq, child) + TAILQ_FOREACH(pp, &pn->childq, child) { if (pp->node == NODE_TEXT) ptype = pp; else if (pp->node == NODE_PARAMETER) param = pp; - - fputs(".Fa \"", stdout); - p->newln = 0; + } + macro_open(p, "Fa \""); + flags = MACROLINE_NOWS; if (ptype != NULL) { - pnode_printmacrolinetext(p, ptype, MACROLINE_NOWS); - putchar(' '); + macro_addnode(p, ptype, flags); + flags = 0; } - if (param != NULL) - pnode_printmacrolinepart(p, param); - - puts("\""); - p->newln = 1; + macro_addnode(p, param, flags); + flags = MACROLINE_NOWS; + macro_addarg(p, "\"", flags); + macro_close(p); } /* @@ -995,7 +985,6 @@ pnode_printfuncprototype(struct parse *p { struct pnode *pp, *fdef; - assert(p->newln); TAILQ_FOREACH(fdef, &pn->childq, child) if (fdef->node == NODE_FUNCDEF) break; @@ -1003,14 +992,13 @@ pnode_printfuncprototype(struct parse *p if (fdef != NULL) pnode_printfuncdef(p, fdef); else - puts(".Fo UNKNOWN"); + macro_line(p, "Fo UNKNOWN"); TAILQ_FOREACH(pp, &pn->childq, child) if (pp->node == NODE_PARAMDEF) pnode_printparamdef(p, pp); - puts(".Fc"); - p->newln = 1; + macro_line(p, "Fc"); } /* @@ -1029,26 +1017,22 @@ pnode_printarg(struct parse *p, struct p isop = 1; isrep = 0; - TAILQ_FOREACH(ap, &pn->attrq, child) + TAILQ_FOREACH(ap, &pn->attrq, child) { if (ap->key == ATTRKEY_CHOICE && (ap->val == ATTRVAL_PLAIN || ap->val == ATTRVAL_REQ)) isop = 0; else if (ap->key == ATTRKEY_REP && ap->val == ATTRVAL_REPEAT) isrep = 1; - - if (isop) { - pnode_printmopen(p); - fputs("Op", stdout); } + if (isop) + macro_open(p, "Op"); TAILQ_FOREACH(pp, &pn->childq, child) { - if (pp->node == NODE_TEXT) { - pnode_printmopen(p); - fputs("Ar", stdout); - } + if (pp->node == NODE_TEXT) + macro_open(p, "Ar"); pnode_print(p, pp); if (isrep && pp->node == NODE_TEXT) - fputs("...", stdout); + macro_addarg(p, "...", 0); } } @@ -1072,12 +1056,11 @@ pnode_printgroup(struct parse *p, struct * This will prevent pnode_print() for putting us on a * subsequent line. */ - sv = p->newln; - pnode_printmopen(p); + sv = p->linestate == LINE_NEW; if (isop) - fputs("Op", stdout); + macro_open(p, "Op"); else if (sv) - fputs("No", stdout); + macro_open(p, "No"); /* * Keep on printing text separated by the vertical bar as long @@ -1093,14 +1076,14 @@ pnode_printgroup(struct parse *p, struct while (np != NULL) { if (pp->node != np->node) break; - fputs(" |", stdout); - pnode_printmacrolinepart(p, np); + macro_addarg(p, "|", 0); + macro_addnode(p, np, 0); pp = np; np = TAILQ_NEXT(np, child); } } - - pnode_printmclose(p, sv); + if (sv) + macro_close(p); } static void @@ -1111,19 +1094,23 @@ pnode_printprologue(struct parse *p, str pp = p->root == NULL ? NULL : pnode_findfirst(p->root, NODE_REFMETA); - puts(".Dd $Mdocdate" "$"); + macro_line(p, "Dd $Mdocdate" "$"); if (pp != NULL) { pnode_printrefmeta(p, pp); pnode_unlink(pp); - } else - printf(".Dt %s 1\n", - pnode_getattr_raw(p->root, ATTRKEY_ID, "UNKNOWN")); - puts(".Os"); + } else { + macro_open(p, "Dt"); + macro_addarg(p, + pnode_getattr_raw(p->root, ATTRKEY_ID, "UNKNOWN"), 0); + macro_addarg(p, "1", 0); + macro_close(p); + } + macro_line(p, "Os"); if (p->flags & PARSE_EQN) { - puts(".EQ"); + macro_line(p, "EQ"); puts("delim $$"); - puts(".EN"); + macro_line(p, "EN"); } } @@ -1137,22 +1124,19 @@ pnode_printvarlistentry(struct parse *p, struct pnode *pp; int first = 1; - assert(p->newln); - fputs(".It", stdout); - p->newln = 0; - + macro_open(p, "It"); + TAILQ_FOREACH(pp, &pn->childq, child) { + if (pp->node != NODE_TERM) + continue; + if ( ! first) + putchar(','); + pnode_print(p, pp); + first = 0; + } + macro_close(p); TAILQ_FOREACH(pp, &pn->childq, child) - if (pp->node == NODE_TERM) { - if ( ! first) - putchar(','); + if (pp->node != NODE_TERM) pnode_print(p, pp); - pnode_unlink(pp); - first = 0; - } else - break; - - putchar('\n'); - p->newln = 1; } static void @@ -1160,16 +1144,12 @@ pnode_printrow(struct parse *p, struct p { struct pnode *pp; - puts(".Bl -dash -compact"); - + macro_line(p, "Bl -dash -compact"); TAILQ_FOREACH(pp, &pn->childq, child) { - assert(p->newln); - puts(".It"); + macro_line(p, "It"); pnode_print(p, pp); - pnode_printmclose(p, 1); } - assert(p->newln); - puts(".El"); + macro_line(p, "El"); } static void @@ -1177,23 +1157,20 @@ pnode_printtable(struct parse *p, struct { struct pnode *pp; - assert(p->newln); - TAILQ_FOREACH(pp, &pn->childq, child) + TAILQ_FOREACH(pp, &pn->childq, child) { if (pp->node == NODE_TITLE) { pnode_printpara(p, pp); pnode_print(p, pp); pnode_unlink(pp); } - assert(p->newln); - puts(".Bl -ohang"); + } + macro_line(p, "Bl -ohang"); while ((pp = pnode_findfirst(pn, NODE_ROW)) != NULL) { - puts(".It Table Row"); + macro_line(p, "It Table Row"); pnode_printrow(p, pp); - pnode_printmclose(p, 1); pnode_unlink(pp); } - assert(p->newln); - puts(".El"); + macro_line(p, "El"); } static void @@ -1201,28 +1178,20 @@ pnode_printlist(struct parse *p, struct { struct pnode *pp; - assert(p->newln); - TAILQ_FOREACH(pp, &pn->childq, child) + TAILQ_FOREACH(pp, &pn->childq, child) { if (pp->node == NODE_TITLE) { pnode_printpara(p, pp); pnode_print(p, pp); pnode_unlink(pp); } - assert(p->newln); - - if (pn->node == NODE_ORDEREDLIST) - puts(".Bl -enum"); - else - puts(".Bl -bullet"); - + } + macro_argline(p, "Bl", + pn->node == NODE_ORDEREDLIST ? "-enum" : "-bullet"); TAILQ_FOREACH(pp, &pn->childq, child) { - assert(p->newln); - puts(".It"); + macro_line(p, "It"); pnode_print(p, pp); - pnode_printmclose(p, 1); } - assert(p->newln); - puts(".El"); + macro_line(p, "El"); } static void @@ -1230,27 +1199,21 @@ pnode_printvariablelist(struct parse *p, { struct pnode *pp; - assert(p->newln); - TAILQ_FOREACH(pp, &pn->childq, child) + TAILQ_FOREACH(pp, &pn->childq, child) { if (pp->node == NODE_TITLE) { pnode_printpara(p, pp); pnode_print(p, pp); pnode_unlink(pp); } - - assert(p->newln); - puts(".Bl -tag -width Ds"); - TAILQ_FOREACH(pp, &pn->childq, child) - if (pp->node != NODE_VARLISTENTRY) { - assert(p->newln); - fputs(".It", stdout); - pnode_printmacroline(p, pp); - } else { - assert(p->newln); + } + macro_line(p, "Bl -tag -width Ds"); + TAILQ_FOREACH(pp, &pn->childq, child) { + if (pp->node == NODE_VARLISTENTRY) pnode_print(p, pp); - } - assert(p->newln); - puts(".El"); + else + macro_nodeline(p, "It", pp); + } + macro_line(p, "El"); } /* @@ -1265,17 +1228,17 @@ pnode_print(struct parse *p, struct pnod struct pnode *pp; const char *ccp; char *cp; - int last, sv; + int last; + enum linestate sv; if (pn == NULL) return; - sv = p->newln; + sv = p->linestate; switch (pn->node) { case NODE_APPLICATION: - pnode_printmopen(p); - fputs("Nm", stdout); + macro_open(p, "Nm"); break; case NODE_ANCHOR: /* Don't print anything! */ @@ -1285,88 +1248,71 @@ pnode_print(struct parse *p, struct pnod pnode_unlinksub(pn); break; case NODE_AUTHOR: - pnode_printmopen(p); - fputs("An", stdout); + macro_open(p, "An"); break; case NODE_AUTHORGROUP: - assert(p->newln); - puts(".An -split"); + macro_line(p, "An -split"); break; case NODE_BOOKINFO: - assert(p->newln); - puts(".Sh NAME"); + macro_line(p, "Sh NAME"); break; case NODE_CITEREFENTRY: - pnode_printmopen(p); - fputs("Xr", stdout); pnode_printciterefentry(p, pn); pnode_unlinksub(pn); break; case NODE_CITETITLE: - pnode_printmopen(p); - fputs("%T", stdout); + macro_open(p, "%T"); break; case NODE_CODE: - pnode_printmopen(p); - fputs("Li", stdout); + macro_open(p, "Li"); break; case NODE_COMMAND: - pnode_printmopen(p); - fputs("Nm", stdout); + macro_open(p, "Nm"); break; case NODE_CONSTANT: - pnode_printmopen(p); - fputs("Dv", stdout); + macro_open(p, "Dv"); break; case NODE_EDITOR: - puts("editor: "); - pnode_printmopen(p); - fputs("An", stdout); + if (p->linestate != LINE_NEW) + putchar('\n'); + puts("editor:"); + p->linestate = LINE_TEXT; + macro_open(p, "An"); break; case NODE_EMAIL: - pnode_printmopen(p); - fputs("Aq Mt", stdout); + macro_open(p, "Aq Mt"); break; case NODE_EMPHASIS: case NODE_FIRSTTERM: - pnode_printmopen(p); - fputs("Em", stdout); + macro_open(p, "Em"); break; case NODE_ENVAR: - pnode_printmopen(p); - fputs("Ev", stdout); + macro_open(p, "Ev"); break; case NODE_FILENAME: - pnode_printmopen(p); - fputs("Pa", stdout); + macro_open(p, "Pa"); break; case NODE_FUNCTION: - pnode_printmopen(p); - fputs("Fn", stdout); + macro_open(p, "Fn"); break; case NODE_FUNCPROTOTYPE: - assert(p->newln); pnode_printfuncprototype(p, pn); pnode_unlinksub(pn); break; case NODE_FUNCSYNOPSISINFO: - pnode_printmopen(p); - fputs("Fd", stdout); + macro_open(p, "Fd"); break; case NODE_INDEXTERM: return; case NODE_INFORMALEQUATION: - if ( ! p->newln) - putchar('\n'); - puts(".EQ"); - p->newln = 0; + macro_line(p, "EQ"); break; case NODE_INLINEEQUATION: - fputc('$', stdout); - p->newln = 0; + if (p->linestate == LINE_NEW) + p->linestate = LINE_TEXT; + putchar('$'); break; case NODE_ITEMIZEDLIST: - assert(p->newln); pnode_printlist(p, pn); pnode_unlinksub(pn); break; @@ -1375,28 +1321,22 @@ pnode_print(struct parse *p, struct pnod pnode_unlinksub(pn); break; case NODE_KEYSYM: - pnode_printmopen(p); - fputs("Sy", stdout); + macro_open(p, "Sy"); break; case NODE_LEGALNOTICE: - assert(p->newln); - puts(".Sh LEGAL NOTICE"); + macro_line(p, "Sh LEGAL NOTICE"); break; case NODE_LINK: ccp = pnode_getattr_raw(pn, ATTRKEY_LINKEND, NULL); if (ccp == NULL) break; - pnode_printmopen(p); - printf("Sx %s\n", ccp); - p->newln = 1; + macro_argline(p, "Sx", ccp); return; case NODE_LITERAL: - pnode_printmopen(p); - fputs("Li", stdout); + macro_open(p, "Li"); break; case NODE_LITERALLAYOUT: - assert(p->newln); - printf(".Bd %s\n", pnode_getattr(pn, ATTRKEY_CLASS) == + macro_argline(p, "Bd", pnode_getattr(pn, ATTRKEY_CLASS) == ATTRVAL_MONOSPACED ? "-literal" : "-unfilled"); break; case NODE_MML_MFENCED: @@ -1418,11 +1358,9 @@ pnode_print(struct parse *p, struct pnod pnode_unlinksub(pn); break; case NODE_OPTION: - pnode_printmopen(p); - fputs("Fl", stdout); + macro_open(p, "Fl"); break; case NODE_ORDEREDLIST: - assert(p->newln); pnode_printlist(p, pn); pnode_unlinksub(pn); break; @@ -1431,20 +1369,18 @@ pnode_print(struct parse *p, struct pnod break; case NODE_PARAMETER: /* Suppress non-text children... */ - pnode_printmopen(p); - fputs("Fa \"", stdout); - pnode_printmacrolinetext(p, pn, MACROLINE_NOWS); - fputs("\"", stdout); + macro_open(p, "Fa \""); + macro_addnode(p, pn, MACROLINE_NOWS); + macro_addarg(p, "\"", MACROLINE_NOWS); + macro_close(p); pnode_unlinksub(pn); break; case NODE_QUOTE: - pnode_printmopen(p); - fputs("Qo", stdout); + macro_open(p, "Qo"); break; case NODE_PROGRAMLISTING: case NODE_SCREEN: - assert(p->newln); - puts(".Bd -literal"); + macro_line(p, "Bd -literal"); break; case NODE_REFENTRYINFO: /* Suppress. */ @@ -1455,25 +1391,18 @@ pnode_print(struct parse *p, struct pnod break; case NODE_REFNAME: /* Suppress non-text children... */ - pnode_printmopen(p); - fputs("Nm", stdout); - p->newln = 0; - pnode_printmacrolinepart(p, pn); + macro_nodeline(p, "Nm", pn); pnode_unlinksub(pn); break; case NODE_REFNAMEDIV: - assert(p->newln); - puts(".Sh NAME"); + macro_line(p, "Sh NAME"); break; case NODE_REFPURPOSE: - assert(p->newln); - pnode_printmopen(p); - fputs("Nd", stdout); + macro_open(p, "Nd"); break; case NODE_REFSYNOPSISDIV: - assert(p->newln); pnode_printrefsynopsisdiv(p, pn); - puts(".Sh SYNOPSIS"); + macro_line(p, "Sh SYNOPSIS"); break; case NODE_PREFACE: case NODE_SECTION: @@ -1481,42 +1410,36 @@ pnode_print(struct parse *p, struct pnod case NODE_TIP: case NODE_CAUTION: case NODE_WARNING: - assert(p->newln); pnode_printrefsect(p, pn); break; case NODE_REPLACEABLE: - pnode_printmopen(p); - fputs("Ar", stdout); + macro_open(p, "Ar"); break; case NODE_SBR: - assert(p->newln); - puts(".br"); + macro_line(p, "br"); break; case NODE_SGMLTAG: - pnode_printmopen(p); - fputs("Li", stdout); + macro_open(p, "Li"); break; case NODE_STRUCTNAME: - pnode_printmopen(p); - fputs("Vt", stdout); + macro_open(p, "Vt"); break; case NODE_TABLE: case NODE_INFORMALTABLE: - assert(p->newln); pnode_printtable(p, pn); pnode_unlinksub(pn); break; case NODE_TEXT: - if (p->newln == 0) - putchar(' '); - bufclear(p); bufappend(p, pn); - if (p->bsz == 0) { assert(pn->real != pn->b); break; } + if (p->linestate == LINE_NEW) + p->linestate = LINE_TEXT; + else + putchar(' '); /* * Output all characters, squeezing out whitespace @@ -1524,7 +1447,6 @@ pnode_print(struct parse *p, struct pnod * XXX: all whitespace, including tabs (?). * Remember to escape control characters and escapes. */ - assert(p->bsz); cp = p->b; /* @@ -1551,34 +1473,27 @@ pnode_print(struct parse *p, struct pnod if (last == '\\') putchar('e'); } - p->newln = 0; break; case NODE_TITLE: - if (pn->parent->node == NODE_BOOKINFO) { - pnode_printmopen(p); - fputs("Nd", stdout); - } + if (pn->parent->node == NODE_BOOKINFO) + macro_open(p, "Nd"); break; case NODE_TYPE: - pnode_printmopen(p); - fputs("Vt", stdout); + macro_open(p, "Vt"); break; case NODE_USERINPUT: - pnode_printmopen(p); - fputs("Li", stdout); + macro_open(p, "Li"); break; case NODE_VARIABLELIST: - assert(p->newln); pnode_printvariablelist(p, pn); pnode_unlinksub(pn); break; case NODE_VARLISTENTRY: - assert(p->newln); pnode_printvarlistentry(p, pn); + pnode_unlinksub(pn); break; case NODE_VARNAME: - pnode_printmopen(p); - fputs("Va", stdout); + macro_open(p, "Va"); break; default: break; @@ -1589,14 +1504,11 @@ pnode_print(struct parse *p, struct pnod switch (pn->node) { case NODE_INFORMALEQUATION: - if ( ! p->newln) - putchar('\n'); - puts(".EN"); - p->newln = 1; + macro_line(p, "EN"); break; case NODE_INLINEEQUATION: fputs("$ ", stdout); - p->newln = sv; + p->linestate = sv; break; case NODE_MML_MROW: case NODE_MML_MI: @@ -1630,18 +1542,19 @@ pnode_print(struct parse *p, struct pnod case NODE_REFPURPOSE: case NODE_SGMLTAG: case NODE_STRUCTNAME: - case NODE_TEXT: case NODE_TYPE: case NODE_USERINPUT: case NODE_VARNAME: - pnode_printmclosepunct(p, pn, sv); + if (sv != LINE_MACRO && p->linestate == LINE_MACRO) + macro_closepunct(p, pn); break; case NODE_QUOTE: - pnode_printmclose(p, sv); - sv = p->newln; - pnode_printmopen(p); - fputs("Qc", stdout); - pnode_printmclose(p, sv); + if (sv == LINE_NEW) + macro_close(p); + sv = p->linestate; + macro_open(p, "Qc"); + if (sv == LINE_NEW) + macro_close(p); break; case NODE_REFNAME: /* @@ -1654,7 +1567,8 @@ pnode_print(struct parse *p, struct pnod TAILQ_NEXT(pn, child) != NULL && TAILQ_NEXT(pn, child)->node == NODE_REFNAME) fputs(" ,", stdout); - pnode_printmclose(p, sv); + if (sv == LINE_NEW) + macro_close(p); break; case NODE_PREFACE: case NODE_SECTION: @@ -1667,15 +1581,11 @@ pnode_print(struct parse *p, struct pnod case NODE_LITERALLAYOUT: case NODE_PROGRAMLISTING: case NODE_SCREEN: - assert(p->newln); - puts(".Ed"); - p->newln = 1; + macro_line(p, "Ed"); break; case NODE_TITLE: - if (pn->parent->node == NODE_BOOKINFO) { - pnode_printmclose(p, 1); - puts(".Sh AUTHORS"); - } + if (pn->parent->node == NODE_BOOKINFO) + macro_line(p, "Sh AUTHORS"); break; default: break; @@ -1717,9 +1627,11 @@ readfile(XML_Parser xp, int fd, * Exit when we've read all or errors have occured * during the parse sequence. */ - p.newln = 1; + p.linestate = LINE_NEW; pnode_printprologue(&p, p.root); pnode_print(&p, p.root); + if (p.linestate != LINE_NEW) + putchar('\n'); pnode_free(p.root); free(p.b); return rc != 0 && p.stop == 0; -- To unsubscribe send an email to source+unsubscribe@mandoc.bsd.lv