=================================================================== RCS file: /cvs/docbook2mdoc/docbook2mdoc.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -p -r1.7 -r1.8 --- docbook2mdoc/docbook2mdoc.c 2014/03/28 10:37:50 1.7 +++ docbook2mdoc/docbook2mdoc.c 2014/03/28 12:11:18 1.8 @@ -1,4 +1,4 @@ -/* $Id: docbook2mdoc.c,v 1.7 2014/03/28 10:37:50 kristaps Exp $ */ +/* $Id: docbook2mdoc.c,v 1.8 2014/03/28 12:11:18 kristaps Exp $ */ /* * Copyright (c) 2014 Kristaps Dzonsons * @@ -59,6 +59,7 @@ enum nodeid { NODE_REFPURPOSE, NODE_REFSECT1, NODE_REFSYNOPSISDIV, + NODE_STRUCTNAME, NODE_SYNOPSIS, NODE_TEXT, NODE_TITLE, @@ -74,13 +75,13 @@ struct parse { int stop; /* should we stop now? */ struct pnode *root; /* root of parse tree */ struct pnode *cur; /* current node in tree */ - char *b; - size_t bsz; - size_t mbsz; + char *b; /* nil-terminated buffer for pre-print */ + size_t bsz; /* current length of b */ + size_t mbsz; /* max bsz allocation */ }; struct node { - const char *name; + const char *name; /* docbook element name */ unsigned int flags; #define NODE_IGNTEXT 1 /* ignore all contained text */ }; @@ -125,6 +126,7 @@ static const struct node nodes[NODE__MAX] = { { "refpurpose", 0 }, { "refsect1", 0 }, { "refsynopsisdiv", NODE_IGNTEXT }, + { "structname", 0 }, { "synopsis", 0 }, { NULL, 0 }, { "title", 0 }, @@ -132,6 +134,8 @@ static const struct node nodes[NODE__MAX] = { /* * Look up whether "parent" is a valid parent for "node". + * This is sucked directly from the DocBook specification: look at the + * "children" and "parent" sections of each node. */ static int isparent(enum nodeid node, enum nodeid parent) @@ -335,6 +339,26 @@ isparent(enum nodeid node, enum nodeid parent) return(parent == NODE_REFENTRY); case (NODE_REFSYNOPSISDIV): return(parent == NODE_REFENTRY); + case (NODE_STRUCTNAME): + switch (parent) { + case (NODE_CODE): + case (NODE_FUNCSYNOPSISINFO): + case (NODE_FUNCTION): + case (NODE_OPTION): + case (NODE_PARA): + case (NODE_PARAMETER): + case (NODE_PROGRAMLISTING): + case (NODE_REFDESCRIPTOR): + case (NODE_REFENTRYTITLE): + case (NODE_REFNAME): + case (NODE_REFPURPOSE): + case (NODE_SYNOPSIS): + case (NODE_TITLE): + return(1); + default: + break; + } + return(0); case (NODE_SYNOPSIS): switch (parent) { case (NODE_REFSYNOPSISDIV): @@ -363,6 +387,12 @@ isparent(enum nodeid node, enum nodeid parent) return(0); } +/* + * Process a stream of characters. + * We store text as nodes in and of themselves. + * If a text node is already open, append to it. + * If it's not open, open one under the current context. + */ static void xml_char(void *arg, const XML_Char *p, int sz) { @@ -423,10 +453,13 @@ xml_char(void *arg, const XML_Char *p, int sz) * Begin an element. * First, look for the element. * If we don't find it and we're not parsing, keep going. - * If we don't find it (and we're parsing), puke and exit. + * If we don't find it and we're parsing, puke and exit. * If we find it but we're not parsing yet (i.e., it's not a refentry * and thus out of context), keep going. - * If we're at the root and already have a tree, puke and exit. + * If we find it and we're at the root and already have a tree, puke and + * exit (FIXME: I don't think this is right?). + * If we find it but we're parsing a text node, close out the text node, + * return to its parent, and keep going. * Make sure that the element is in the right context. * Lastly, put the node onto our parse tree and continue. */ @@ -454,6 +487,7 @@ xml_elem_start(void *arg, const XML_Char *name, const else if (0 == strcmp(nodes[node].name, name)) break; + /* FIXME: do more with these error messages... */ if (NODE__MAX == node && NODE_ROOT == ps->node) { fprintf(stderr, "%s: ignoring node\n", name); return; @@ -493,7 +527,7 @@ xml_elem_start(void *arg, const XML_Char *name, const /* * Roll up the parse tree. - * Does nothing else special. + * If we're at a text node, roll that one up first. * If we hit the root, then assign ourselves as the NODE_ROOT. */ static void @@ -518,6 +552,9 @@ xml_elem_end(void *arg, const XML_Char *name) ps->node = ps->cur->node; } +/* + * Recursively free a node (NULL is ok). + */ static void pnode_free(struct pnode *pn) { @@ -535,6 +572,9 @@ pnode_free(struct pnode *pn) free(pn); } +/* + * Unlink a node from its parent and pnode_free() it. + */ static void pnode_unlink(struct pnode *pn) { @@ -544,6 +584,9 @@ pnode_unlink(struct pnode *pn) pnode_free(pn); } +/* + * Unlink all children of a node and pnode_free() them. + */ static void pnode_unlinksub(struct pnode *pn) { @@ -552,6 +595,9 @@ pnode_unlinksub(struct pnode *pn) pnode_unlink(TAILQ_FIRST(&pn->childq)); } +/* + * Reset the lookaside buffer. + */ static void bufclear(struct parse *p) { @@ -559,6 +605,11 @@ bufclear(struct parse *p) p->b[p->bsz = 0] = '\0'; } +/* + * Append NODE_TEXT contents to the current buffer, reallocating its + * size if necessary. + * The buffer is ALWAYS nil-terminated. + */ static void bufappend(struct parse *p, struct pnode *pn) { @@ -576,6 +627,12 @@ bufappend(struct parse *p, struct pnode *pn) p->b[p->bsz] = '\0'; } +/* + * Recursively append all NODE_TEXT nodes to the buffer. + * This descends into non-text nodes, but doesn't do anything beyond + * them. + * In other words, this is a recursive text grok. + */ static void bufappend_r(struct parse *p, struct pnode *pn) { @@ -588,8 +645,7 @@ bufappend_r(struct parse *p, struct pnode *pn) } /* - * Print text presumably on a macro line. - * Ignore any child macros. + * Recursively print text presumably on a macro line. * Convert all whitespace to regular spaces. */ static void @@ -638,6 +694,9 @@ pnode_printmacroline(struct parse *p, struct pnode *pn putchar('\n'); } +/* + * Start the SYNOPSIS macro, unlinking its [superfluous] title. + */ static void pnode_printrefsynopsisdiv(struct parse *p, struct pnode *pn) { @@ -652,6 +711,9 @@ pnode_printrefsynopsisdiv(struct parse *p, struct pnod puts(".Sh SYNOPSIS"); } +/* + * Start a hopefully-named `Sh' section. + */ static void pnode_printrefsect(struct parse *p, struct pnode *pn) { @@ -670,6 +732,9 @@ pnode_printrefsect(struct parse *p, struct pnode *pn) puts("UNKNOWN"); } +/* + * Start a reference, extracting the title and volume. + */ static void pnode_printciterefentry(struct parse *p, struct pnode *pn) { @@ -942,6 +1007,11 @@ pnode_print(struct parse *p, struct pnode *pn) case (NODE_REFSECT1): pnode_printrefsect(p, pn); break; + case (NODE_STRUCTNAME): + fputs(".Vt ", stdout); + pnode_printmacroline(p, pn); + pnode_unlinksub(pn); + return; case (NODE_TEXT): bufclear(p); bufappend(p, pn);