=================================================================== RCS file: /cvs/docbook2mdoc/docbook2mdoc.c,v retrieving revision 1.74 retrieving revision 1.97 diff -u -p -r1.74 -r1.97 --- docbook2mdoc/docbook2mdoc.c 2019/03/26 18:32:07 1.74 +++ docbook2mdoc/docbook2mdoc.c 2019/04/07 17:42:36 1.97 @@ -1,4 +1,4 @@ -/* $Id: docbook2mdoc.c,v 1.74 2019/03/26 18:32:07 schwarze Exp $ */ +/* $Id: docbook2mdoc.c,v 1.97 2019/04/07 17:42:36 schwarze Exp $ */ /* * Copyright (c) 2014 Kristaps Dzonsons * Copyright (c) 2019 Ingo Schwarze @@ -21,242 +21,94 @@ #include #include "node.h" +#include "macro.h" #include "format.h" /* * The implementation of the mdoc(7) formatter. */ -enum linestate { - LINE_NEW = 0, - LINE_TEXT, - LINE_MACRO -}; - -struct format { - int level; /* Header level, starting at 1. */ - enum linestate linestate; -}; - static void pnode_print(struct format *, struct pnode *); static void -macro_open(struct format *p, const char *name) +pnode_printtext(struct format *f, struct pnode *n) { - switch (p->linestate) { - case LINE_TEXT: - putchar('\n'); - /* FALLTHROUGH */ - case LINE_NEW: - putchar('.'); - p->linestate = LINE_MACRO; - break; - case LINE_MACRO: - putchar(' '); - break; + struct pnode *nn; + char *cp; + char last; + + if (n->bsz == 0) { + assert(n->real < n->b); + return; } - fputs(name, stdout); -} -static void -macro_close(struct format *p) -{ - assert(p->linestate == LINE_MACRO); - putchar('\n'); - p->linestate = LINE_NEW; -} + /* + * Text preceding a macro without intervening whitespace + * requires a .Pf macro. + * Set the spacing flag to avoid a redundant .Ns macro. + */ -static void -macro_line(struct format *p, const char *name) -{ - macro_open(p, name); - macro_close(p); -} - -#define ARG_SPACE 1 /* Insert whitespace before this argument. */ -#define ARG_SINGLE 2 /* Quote argument if it contains whitespace. */ -#define ARG_QUOTED 4 /* We are already in a quoted argument. */ -#define ARG_UPPER 8 /* Covert argument to upper case. */ -/* - * Print an argument string on a macro line, collapsing whitespace. - */ -static void -macro_addarg(struct format *p, const char *arg, int flags) -{ - const char *cp; - - assert(p->linestate == LINE_MACRO); - - /* Quote if requested and necessary. */ - - if ((flags & (ARG_SINGLE | ARG_QUOTED)) == ARG_SINGLE) { - for (cp = arg; *cp != '\0'; cp++) - if (isspace((unsigned char)*cp)) - break; - if (*cp != '\0') { - if (flags & ARG_SPACE) { - putchar(' '); - flags &= ~ ARG_SPACE; - } - putchar('"'); - flags = ARG_QUOTED; - } + 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"); + nn->spc = 1; } - for (cp = arg; *cp != '\0'; cp++) { - - /* Collapse whitespace. */ - - if (isspace((unsigned char)*cp)) { - flags |= ARG_SPACE; - continue; - } else if (flags & ARG_SPACE) { + if (f->linestate == LINE_NEW) { + last = '\n'; + f->linestate = LINE_TEXT; + } else { + last = ' '; + if (n->spc || f->linestate == LINE_MACRO) putchar(' '); - flags &= ~ ARG_SPACE; - } - - /* Escape us if we look like a macro. */ - - if ((flags & ARG_QUOTED) == 0 && - (cp == arg || isspace((unsigned char)cp[-1])) && - isupper((unsigned char)cp[0]) && - islower((unsigned char)cp[1]) && - (cp[2] == '\0' || cp[2] == ' ' || - (islower((unsigned char)cp[2]) && - (cp[3] == '\0' || cp[3] == ' ')))) - fputs("\\&", stdout); - - if (*cp == '"') - fputs("\\(dq", stdout); - else if (flags & ARG_UPPER) - putchar(toupper((unsigned char)*cp)); - else - putchar(*cp); - if (*cp == '\\') - putchar('e'); } -} -static void -macro_argline(struct format *p, const char *name, const char *arg) -{ - macro_open(p, name); - macro_addarg(p, arg, ARG_SPACE); - macro_close(p); -} - -/* - * Recursively append text from the children of a node to a macro line. - */ -static void -macro_addnode(struct format *p, struct pnode *pn, int flags) -{ - int quote_now; - - assert(p->linestate == LINE_MACRO); - - /* - * If the only child is a text node, just add that text, - * letting macro_addarg() decide about quoting. - */ - - pn = TAILQ_FIRST(&pn->childq); - if (pn != NULL && pn->node == NODE_TEXT && - TAILQ_NEXT(pn, child) == NULL) { - macro_addarg(p, pn->b, flags); + if (n->node == NODE_ESCAPE) { + fputs(n->b, stdout); return; } /* - * If we want the argument quoted and are not already - * in a quoted context, quote now. + * Remove the prefix '-' from