=================================================================== RCS file: /cvs/docbook2mdoc/docbook2mdoc.c,v retrieving revision 1.41 retrieving revision 1.44 diff -u -p -r1.41 -r1.44 --- docbook2mdoc/docbook2mdoc.c 2014/10/12 15:34:44 1.41 +++ docbook2mdoc/docbook2mdoc.c 2015/03/19 10:04:32 1.44 @@ -1,4 +1,4 @@ -/* $Id: docbook2mdoc.c,v 1.41 2014/10/12 15:34:44 kristaps Exp $ */ +/* $Id: docbook2mdoc.c,v 1.44 2015/03/19 10:04:32 schwarze Exp $ */ /* * Copyright (c) 2014 Kristaps Dzonsons * @@ -37,6 +37,8 @@ struct parse { enum nodeid node; /* current (NODE_ROOT if pre-tree) */ const char *fname; /* filename */ int stop; /* should we stop now? */ +#define PARSE_EQN 1 + unsigned int flags; /* document-wide flags */ struct pnode *root; /* root of parse tree */ struct pnode *cur; /* current node in tree */ char *b; /* nil-terminated buffer for pre-print */ @@ -89,102 +91,102 @@ static const char *attrvals[ATTRVAL__MAX] = { }; static const struct node nodes[NODE__MAX] = { - { NULL, 0 }, - { "acronym", 0 }, - { "anchor", NODE_IGNTEXT }, - { "application", 0 }, - { "arg", 0 }, - { "caution", NODE_IGNTEXT }, - { "citerefentry", NODE_IGNTEXT }, - { "cmdsynopsis", NODE_IGNTEXT }, - { "code", 0 }, + { NULL, 0 }, + { "acronym", 0 }, + { "anchor", NODE_IGNTEXT }, + { "application", 0 }, + { "arg", 0 }, + { "caution", NODE_IGNTEXT }, + { "citerefentry", NODE_IGNTEXT }, + { "cmdsynopsis", NODE_IGNTEXT }, + { "code", 0 }, { "colspec", NODE_IGNTEXT }, - { "command", 0 }, - { "constant", 0 }, - { "copyright", NODE_IGNTEXT }, - { "date", 0 }, + { "command", 0 }, + { "constant", 0 }, + { "copyright", NODE_IGNTEXT }, + { "date", 0 }, { "emphasis", 0 }, { "entry", 0 }, { "envar", 0 }, { "fieldsynopsis", NODE_IGNTEXT }, { "filename", 0 }, { "funcdef", 0 }, - { "funcprototype", NODE_IGNTEXT }, - { "funcsynopsis", NODE_IGNTEXT }, - { "funcsynopsisinfo", 0 }, - { "function", 0 }, - { "group", NODE_IGNTEXT }, + { "funcprototype", NODE_IGNTEXT }, + { "funcsynopsis", NODE_IGNTEXT }, + { "funcsynopsisinfo", 0 }, + { "function", 0 }, + { "group", NODE_IGNTEXT }, { "holder", NODE_IGNTEXT }, { "info", NODE_IGNTEXT }, - { "informalequation", NODE_IGNTEXT }, - { "informaltable", NODE_IGNTEXT }, - { "inlineequation", NODE_IGNTEXT }, - { "itemizedlist", NODE_IGNTEXT }, - { "link", 0 }, - { "listitem", NODE_IGNTEXT }, - { "literal", 0 }, - { "manvolnum", 0 }, - { "mml:math", NODE_IGNTEXT }, - { "mml:mfenced", 0 }, - { "mml:mfrac", 0 }, - { "mml:mi", 0 }, - { "mml:mn", 0 }, - { "mml:mo", 0 }, - { "mml:mrow", 0 }, - { "mml:msub", 0 }, - { "mml:msup", 0 }, - { "modifier", 0 }, - { "note", NODE_IGNTEXT }, - { "option", 0 }, - { "orderedlist", NODE_IGNTEXT }, - { "para", 0 }, + { "informalequation", NODE_IGNTEXT }, + { "informaltable", NODE_IGNTEXT }, + { "inlineequation", NODE_IGNTEXT }, + { "itemizedlist", NODE_IGNTEXT }, + { "link", 0 }, + { "listitem", NODE_IGNTEXT }, + { "literal", 0 }, + { "manvolnum", 0 }, + { "mml:math", NODE_IGNTEXT }, + { "mml:mfenced", 0 }, + { "mml:mfrac", 0 }, + { "mml:mi", 0 }, + { "mml:mn", 0 }, + { "mml:mo", 0 }, + { "mml:mrow", 0 }, + { "mml:msub", 0 }, + { "mml:msup", 0 }, + { "modifier", 0 }, + { "note", NODE_IGNTEXT }, + { "option", 0 }, + { "orderedlist", NODE_IGNTEXT }, + { "para", 0 }, { "paramdef", 0 }, - { "parameter", 0 }, - { "programlisting", 0 }, - { "prompt", 0 }, - { "quote", 0 }, - { "refclass", NODE_IGNTEXT }, - { "refdescriptor", NODE_IGNTEXT }, - { "refentry", NODE_IGNTEXT }, - { "refentryinfo", NODE_IGNTEXT }, - { "refentrytitle", 0 }, - { "refmeta", NODE_IGNTEXT }, - { "refmetainfo", NODE_IGNTEXT }, - { "refmiscinfo", NODE_IGNTEXT }, - { "refname", 0 }, - { "refnamediv", NODE_IGNTEXT }, - { "refpurpose", 0 }, - { "refsect1", NODE_IGNTEXT }, - { "refsect2", NODE_IGNTEXT }, - { "refsect3", NODE_IGNTEXT }, - { "refsection", NODE_IGNTEXT }, - { "refsynopsisdiv", NODE_IGNTEXT }, - { "replaceable", 0 }, - { "row", NODE_IGNTEXT }, - { "sbr", NODE_IGNTEXT }, - { "screen", NODE_IGNTEXT }, - { "sgmltag", 0 }, - { "structname", 0 }, - { "synopsis", 0 }, - { "table", NODE_IGNTEXT }, - { "tbody", NODE_IGNTEXT }, - { "term", 0 }, - { NULL, 0 }, - { "tfoot", NODE_IGNTEXT }, - { "tgroup", NODE_IGNTEXT }, - { "thead", NODE_IGNTEXT }, - { "tip", NODE_IGNTEXT }, - { "title", 0 }, - { "trademark", 0 }, - { "type", 0 }, - { "ulink", 0 }, - { "userinput", 0 }, - { "variablelist", NODE_IGNTEXT }, - { "varlistentry", NODE_IGNTEXT }, - { "varname", 0 }, - { "warning", NODE_IGNTEXT }, - { "wordasword", 0 }, - { "year", NODE_IGNTEXT }, + { "parameter", 0 }, + { "programlisting", 0 }, + { "prompt", 0 }, + { "quote", 0 }, + { "refclass", NODE_IGNTEXT }, + { "refdescriptor", NODE_IGNTEXT }, + { "refentry", NODE_IGNTEXT }, + { "refentryinfo", NODE_IGNTEXT }, + { "refentrytitle", 0 }, + { "refmeta", NODE_IGNTEXT }, + { "refmetainfo", NODE_IGNTEXT }, + { "refmiscinfo", NODE_IGNTEXT }, + { "refname", 0 }, + { "refnamediv", NODE_IGNTEXT }, + { "refpurpose", 0 }, + { "refsect1", NODE_IGNTEXT }, + { "refsect2", NODE_IGNTEXT }, + { "refsect3", NODE_IGNTEXT }, + { "refsection", NODE_IGNTEXT }, + { "refsynopsisdiv", NODE_IGNTEXT }, + { "replaceable", 0 }, + { "row", NODE_IGNTEXT }, + { "sbr", NODE_IGNTEXT }, + { "screen", NODE_IGNTEXT }, + { "sgmltag", 0 }, + { "structname", 0 }, + { "synopsis", 0 }, + { "table", NODE_IGNTEXT }, + { "tbody", NODE_IGNTEXT }, + { "term", 0 }, + { NULL, 0 }, + { "tfoot", NODE_IGNTEXT }, + { "tgroup", NODE_IGNTEXT }, + { "thead", NODE_IGNTEXT }, + { "tip", NODE_IGNTEXT }, + { "title", 0 }, + { "trademark", 0 }, + { "type", 0 }, + { "ulink", 0 }, + { "userinput", 0 }, + { "variablelist", NODE_IGNTEXT }, + { "varlistentry", NODE_IGNTEXT }, + { "varname", 0 }, + { "warning", NODE_IGNTEXT }, + { "wordasword", 0 }, + { "year", NODE_IGNTEXT }, }; static int warn = 0; @@ -246,7 +248,7 @@ xml_char(void *arg, const XML_Char *p, int sz) /* Append to current buffer. */ assert(sz >= 0); - ps->cur->b = realloc(ps->cur->b, + ps->cur->b = realloc(ps->cur->b, ps->cur->bsz + (size_t)sz); if (NULL == ps->cur->b) { perror(NULL); @@ -305,7 +307,6 @@ xml_elem_start(void *arg, const XML_Char *name, const ps->node = ps->cur->node; } - for (node = 0; node < NODE__MAX; node++) if (NULL == nodes[node].name) continue; @@ -315,7 +316,7 @@ xml_elem_start(void *arg, const XML_Char *name, const if (NODE__MAX == node && NODE_ROOT == ps->node) { return; } else if (NODE__MAX == node) { - fprintf(stderr, "%s:%zu:%zu: unknown node \"%s\"\n", + fprintf(stderr, "%s:%zu:%zu: unknown node \"%s\"\n", ps->fname, XML_GetCurrentLineNumber(ps->xml), XML_GetCurrentColumnNumber(ps->xml), name); ps->stop = 1; @@ -341,6 +342,9 @@ xml_elem_start(void *arg, const XML_Char *name, const return; } + if (NODE_INLINEEQUATION == node) + ps->flags |= PARSE_EQN; + if (NULL == (dat = calloc(1, sizeof(struct pnode)))) { perror(NULL); exit(EXIT_FAILURE); @@ -366,21 +370,21 @@ xml_elem_start(void *arg, const XML_Char *name, const if (0 == strcmp(*att, attrkeys[key])) break; if (ATTRKEY__MAX == key) { - if (warn) + if (warn) fprintf(stderr, "%s:%zu:%zu: warning: " - "unknown attribute \"%s\"\n", - ps->fname, + "unknown attribute \"%s\"\n", + ps->fname, XML_GetCurrentLineNumber(ps->xml), - XML_GetCurrentColumnNumber(ps->xml), + XML_GetCurrentColumnNumber(ps->xml), *att); continue; } else if ( ! isattrkey(node, key)) { if (warn) fprintf(stderr, "%s:%zu:%zu: warning: " - "bad attribute \"%s\"\n", - ps->fname, + "bad attribute \"%s\"\n", + ps->fname, XML_GetCurrentLineNumber(ps->xml), - XML_GetCurrentColumnNumber(ps->xml), + XML_GetCurrentColumnNumber(ps->xml), *att); continue; } @@ -390,10 +394,10 @@ xml_elem_start(void *arg, const XML_Char *name, const if (ATTRVAL__MAX != val && ! isattrval(key, val)) { if (warn) fprintf(stderr, "%s:%zu:%zu: warning: " - "bad attribute value \"%s\"\n", - ps->fname, + "bad attribute value \"%s\"\n", + ps->fname, XML_GetCurrentLineNumber(ps->xml), - XML_GetCurrentColumnNumber(ps->xml), + XML_GetCurrentColumnNumber(ps->xml), *(att + 1)); continue; } @@ -537,7 +541,7 @@ bufappend_r(struct parse *p, struct pnode *pn) bufappend_r(p, pp); } -/* +/* * Recursively search and return the first instance of "node". */ static struct pnode * @@ -585,12 +589,12 @@ pnode_printmacrolinetext(struct parse *p, struct pnode /* Escape us if we look like a macro. */ if ((cp == p->b || ' ' == *(cp - 1)) && isupper((int)*cp) && - '\0' != *(cp + 1) && + '\0' != *(cp + 1) && islower((int)*(cp + 1)) && - ('\0' == *(cp + 2) || + ('\0' == *(cp + 2) || ' ' == *(cp + 2) || (islower((int)*(cp + 2)) && - ('\0' == *(cp + 3) || + ('\0' == *(cp + 3) || ' ' == *(cp + 3))))) fputs("\\&", stdout); if (MACROLINE_UPPER & fl) @@ -653,7 +657,7 @@ static void pnode_printmclosepunct(struct parse *p, struct pnode *pn, int sv) { /* We wouldn't have done anything anyway. */ - if ( ! (sv && ! p->newln)) + if ( ! (sv && ! p->newln)) return; /* No next node or it's not text. */ @@ -663,7 +667,7 @@ pnode_printmclosepunct(struct parse *p, struct pnode * } else if (NODE_TEXT != pn->node) { pnode_printmclose(p, sv); return; - } + } /* Only do this for the comma/period. */ if (pn->bsz > 0 && @@ -673,7 +677,7 @@ pnode_printmclosepunct(struct parse *p, struct pnode * putchar(pn->b[0]); pn->b++; pn->bsz--; - } + } putchar('\n'); p->newln = 1; @@ -687,7 +691,7 @@ pnode_printrefsynopsisdiv(struct parse *p, struct pnod { struct pnode *pp; - TAILQ_FOREACH(pp, &pn->childq, child) + TAILQ_FOREACH(pp, &pn->childq, child) if (NODE_TITLE == pp->node) { pnode_unlink(pp); return; @@ -738,7 +742,7 @@ pnode_printrefsect(struct parse *p, struct pnode *pn) p->newln = 0; if (NULL != pp) { - pnode_printmacrolinetext(p, pp, + pnode_printmacrolinetext(p, pp, NODE_REFSECT1 == pn->node ? MACROLINE_UPPER : 0); pnode_printmclose(p, 1); @@ -917,13 +921,13 @@ pnode_printmath(struct parse *p, struct pnode *pn) switch (pn->node) { case (NODE_MML_MSUP): - printf(" sup "); + fputs(" sup ", stdout); break; case (NODE_MML_MFRAC): - printf(" over "); + fputs(" over ", stdout); break; case (NODE_MML_MSUB): - printf(" sub "); + fputs(" sub ", stdout); break; default: break; @@ -940,7 +944,7 @@ pnode_printfuncprototype(struct parse *p, struct pnode assert(p->newln); TAILQ_FOREACH(fdef, &pn->childq, child) - if (NODE_FUNCDEF == fdef->node) + if (NODE_FUNCDEF == fdef->node) break; if (NULL != fdef) @@ -948,7 +952,7 @@ pnode_printfuncprototype(struct parse *p, struct pnode else puts(".Fo UNKNOWN"); - TAILQ_FOREACH(pp, &pn->childq, child) + TAILQ_FOREACH(pp, &pn->childq, child) if (NODE_PARAMDEF == pp->node) pnode_printparamdef(p, pp); @@ -956,7 +960,7 @@ pnode_printfuncprototype(struct parse *p, struct pnode p->newln = 1; } -/* +/* * The element is more complicated than it should be because text * nodes are treated like ".Ar foo", but non-text nodes need to be * re-sent into the printer (i.e., without the preceding ".Ar"). @@ -972,10 +976,10 @@ pnode_printarg(struct parse *p, struct pnode *pn) isop = 1; isrep = 0; - TAILQ_FOREACH(ap, &pn->attrq, child) + TAILQ_FOREACH(ap, &pn->attrq, child) if (ATTRKEY_CHOICE == ap->key && (ATTRVAL_PLAIN == ap->val || - ATTRVAL_REQ == ap->val)) + ATTRVAL_REQ == ap->val)) isop = 0; else if (ATTRKEY_REP == ap->key && (ATTRVAL_REPEAT == ap->val)) @@ -990,9 +994,9 @@ pnode_printarg(struct parse *p, struct pnode *pn) if (NODE_TEXT == pp->node) { pnode_printmopen(p); fputs("Ar", stdout); - } + } pnode_print(p, pp); - if (NODE_TEXT == pp->node && isrep) + if (NODE_TEXT == pp->node && isrep) fputs("...", stdout); } } @@ -1005,7 +1009,7 @@ pnode_printgroup(struct parse *p, struct pnode *pn) int isop, sv; isop = 1; - TAILQ_FOREACH(ap, &pn->attrq, child) + TAILQ_FOREACH(ap, &pn->attrq, child) if (ATTRKEY_CHOICE == ap->key && (ATTRVAL_PLAIN == ap->val || ATTRVAL_REQ == ap->val)) { @@ -1013,14 +1017,14 @@ pnode_printgroup(struct parse *p, struct pnode *pn) break; } - /* + /* * Make sure we're on a macro line. * This will prevent pnode_print() for putting us on a * subsequent line. */ sv = p->newln; pnode_printmopen(p); - if (isop) + if (isop) fputs("Op", stdout); else if (sv) fputs("No", stdout); @@ -1066,26 +1070,39 @@ pnode_printprologue(struct parse *p, struct pnode *pn) puts(".Dt UNKNOWN 1"); puts(".Os"); } + + if (PARSE_EQN & p->flags) { + puts(".EQ"); + puts("delim $$"); + puts(".EN"); + } } +/* + * We can have multiple elements within a , which + * we should comma-separate as list headers. + */ static void pnode_printvarlistentry(struct parse *p, struct pnode *pn) { struct pnode *pp; + int first = 1; assert(p->newln); + fputs(".It", stdout); + p->newln = 0; + TAILQ_FOREACH(pp, &pn->childq, child) if (NODE_TERM == pp->node) { - assert(p->newln); - fputs(".It", stdout); - p->newln = 0; + if ( ! first) + putchar(','); pnode_print(p, pp); pnode_unlink(pp); - pnode_printmclose(p, 1); - return; - } + first = 0; + } else + break; - puts(".It"); + putchar('\n'); p->newln = 1; } @@ -1260,6 +1277,16 @@ pnode_print(struct parse *p, struct pnode *pn) pnode_printmopen(p); fputs("Fd", stdout); break; + case (NODE_INFORMALEQUATION): + if ( ! p->newln) + putchar('\n'); + puts(".EQ"); + p->newln = 0; + break; + case (NODE_INLINEEQUATION): + fputc('$', stdout); + p->newln = 0; + break; case (NODE_ITEMIZEDLIST): assert(p->newln); pnode_printlist(p, pn); @@ -1273,12 +1300,6 @@ pnode_print(struct parse *p, struct pnode *pn) pnode_printmopen(p); fputs("Li", stdout); break; - case (NODE_MML_MATH): - if ( ! p->newln) - putchar('\n'); - puts(".EQ"); - p->newln = 0; - break; case (NODE_MML_MFENCED): pnode_printmathfenced(p, pn); pnode_unlinksub(pn); @@ -1287,7 +1308,9 @@ pnode_print(struct parse *p, struct pnode *pn) case (NODE_MML_MI): case (NODE_MML_MN): case (NODE_MML_MO): - putchar('{'); + if (TAILQ_EMPTY(&pn->childq)) + break; + fputs(" { ", stdout); break; case (NODE_MML_MFRAC): case (NODE_MML_MSUB): @@ -1306,8 +1329,8 @@ pnode_print(struct parse *p, struct pnode *pn) break; case (NODE_PARA): assert(p->newln); - if (NULL != pn->parent && - NODE_LISTITEM == pn->parent->node) + if (NULL != pn->parent && + NODE_LISTITEM == pn->parent->node) break; puts(".Pp"); break; @@ -1413,7 +1436,7 @@ pnode_print(struct parse *p, struct pnode *pn) /* * Output all characters, squeezing out whitespace - * between newlines. + * between newlines. * XXX: all whitespace, including tabs (?). * Remember to escape control characters and escapes. */ @@ -1475,17 +1498,23 @@ pnode_print(struct parse *p, struct pnode *pn) pnode_print(p, pp); switch (pn->node) { - case (NODE_MML_MATH): + case (NODE_INFORMALEQUATION): if ( ! p->newln) putchar('\n'); puts(".EN"); p->newln = 1; break; + case (NODE_INLINEEQUATION): + fputs("$ ", stdout); + p->newln = sv; + break; case (NODE_MML_MROW): case (NODE_MML_MI): case (NODE_MML_MN): case (NODE_MML_MO): - putchar('}'); + if (TAILQ_EMPTY(&pn->childq)) + break; + fputs(" } ", stdout); break; case (NODE_APPLICATION): case (NODE_ARG): @@ -1524,10 +1553,10 @@ pnode_print(struct parse *p, struct pnode *pn) * macros in sequence, then print out a * trailing comma before the newline. */ - if (NULL != pn->parent && + if (NULL != pn->parent && NODE_REFNAMEDIV == pn->parent->node && NULL != TAILQ_NEXT(pn, child) && - NODE_REFNAME == TAILQ_NEXT(pn, child)->node) + NODE_REFNAME == TAILQ_NEXT(pn, child)->node) fputs(" ,", stdout); pnode_printmclose(p, sv); break; @@ -1548,7 +1577,7 @@ pnode_print(struct parse *p, struct pnode *pn) * Invoke the parser context with each buffer fill. */ static int -readfile(XML_Parser xp, int fd, +readfile(XML_Parser xp, int fd, char *b, size_t bsz, const char *fn) { struct parse p; @@ -1569,12 +1598,12 @@ readfile(XML_Parser xp, int fd, if (0 == (rc = XML_Parse(xp, b, ssz, 0 == ssz))) fprintf(stderr, "%s:%zu:%zu: %s\n", fn, XML_GetCurrentLineNumber(xp), - XML_GetCurrentColumnNumber(xp), + XML_GetCurrentColumnNumber(xp), XML_ErrorString (XML_GetErrorCode(xp))); else if ( ! p.stop && ssz > 0) continue; - /* + /* * Exit when we've read all or errors have occured * during the parse sequence. */ @@ -1631,7 +1660,7 @@ main(int argc, char *argv[]) fname = argv[0]; /* Read from stdin or a file. */ - fd = 0 == strcmp(fname, "-") ? + fd = 0 == strcmp(fname, "-") ? STDIN_FILENO : open(fname, O_RDONLY, 0); /*