version 1.3, 2014/03/28 02:46:40 |
version 1.7, 2014/03/28 10:37:50 |
|
|
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
#include <unistd.h> |
|
|
/* |
/* |
* All recognised node types. |
* All recognised node types. |
|
|
enum nodeid { |
enum nodeid { |
NODE_ROOT = 0, /* Must comes first. */ |
NODE_ROOT = 0, /* Must comes first. */ |
/* Alpha-ordered hereafter. */ |
/* Alpha-ordered hereafter. */ |
|
NODE_ARG, |
NODE_CITEREFENTRY, |
NODE_CITEREFENTRY, |
|
NODE_CMDSYNOPSIS, |
NODE_CODE, |
NODE_CODE, |
|
NODE_COMMAND, |
NODE_FUNCDEF, |
NODE_FUNCDEF, |
NODE_FUNCPROTOTYPE, |
NODE_FUNCPROTOTYPE, |
NODE_FUNCSYNOPSIS, |
NODE_FUNCSYNOPSIS, |
NODE_FUNCSYNOPSISINFO, |
NODE_FUNCSYNOPSISINFO, |
NODE_FUNCTION, |
NODE_FUNCTION, |
NODE_MANVOLNUM, |
NODE_MANVOLNUM, |
|
NODE_OPTION, |
NODE_PARA, |
NODE_PARA, |
NODE_PARAMDEF, |
NODE_PARAMDEF, |
NODE_PARAMETER, |
NODE_PARAMETER, |
|
|
|
|
static const struct node nodes[NODE__MAX] = { |
static const struct node nodes[NODE__MAX] = { |
{ NULL, 0 }, |
{ NULL, 0 }, |
|
{ "arg", 0 }, |
{ "citerefentry", NODE_IGNTEXT }, |
{ "citerefentry", NODE_IGNTEXT }, |
|
{ "cmdsynopsis", NODE_IGNTEXT }, |
{ "code", 0 }, |
{ "code", 0 }, |
|
{ "command", 0 }, |
{ "funcdef", 0 }, |
{ "funcdef", 0 }, |
{ "funcprototype", NODE_IGNTEXT }, |
{ "funcprototype", NODE_IGNTEXT }, |
{ "funcsynopsis", NODE_IGNTEXT }, |
{ "funcsynopsis", NODE_IGNTEXT }, |
{ "funcsynopsisinfo", 0 }, |
{ "funcsynopsisinfo", 0 }, |
{ "function", 0 }, |
{ "function", 0 }, |
{ "manvolnum", 0 }, |
{ "manvolnum", 0 }, |
|
{ "option", 0 }, |
{ "para", 0 }, |
{ "para", 0 }, |
{ "paramdef", 0 }, |
{ "paramdef", 0 }, |
{ "parameter", 0 }, |
{ "parameter", 0 }, |
Line 131 isparent(enum nodeid node, enum nodeid parent) |
|
Line 140 isparent(enum nodeid node, enum nodeid parent) |
|
switch (node) { |
switch (node) { |
case (NODE_ROOT): |
case (NODE_ROOT): |
return(0); |
return(0); |
|
case (NODE_ARG): |
|
switch (parent) { |
|
case (NODE_ARG): |
|
case (NODE_CMDSYNOPSIS): |
|
return(1); |
|
default: |
|
break; |
|
} |
|
return(0); |
case (NODE_CITEREFENTRY): |
case (NODE_CITEREFENTRY): |
switch (parent) { |
switch (parent) { |
case (NODE_FUNCSYNOPSISINFO): |
case (NODE_FUNCSYNOPSISINFO): |
Line 147 isparent(enum nodeid node, enum nodeid parent) |
|
Line 165 isparent(enum nodeid node, enum nodeid parent) |
|
break; |
break; |
} |
} |
return(0); |
return(0); |
|
case (NODE_CMDSYNOPSIS): |
|
switch (parent) { |
|
case (NODE_PARA): |
|
case (NODE_REFSECT1): |
|
case (NODE_REFSYNOPSISDIV): |
|
return(1); |
|
default: |
|
break; |
|
} |
|
return(0); |
case (NODE_CODE): |
case (NODE_CODE): |
switch (parent) { |
switch (parent) { |
case (NODE_FUNCSYNOPSISINFO): |
case (NODE_FUNCSYNOPSISINFO): |
Line 163 isparent(enum nodeid node, enum nodeid parent) |
|
Line 191 isparent(enum nodeid node, enum nodeid parent) |
|
break; |
break; |
} |
} |
return(0); |
return(0); |
|
case (NODE_COMMAND): |
|
switch (parent) { |
|
case (NODE_CMDSYNOPSIS): |
|
case (NODE_FUNCSYNOPSISINFO): |
|
case (NODE_PARA): |
|
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_FUNCDEF): |
case (NODE_FUNCDEF): |
return(NODE_FUNCPROTOTYPE == parent); |
return(NODE_FUNCPROTOTYPE == parent); |
case (NODE_FUNCPROTOTYPE): |
case (NODE_FUNCPROTOTYPE): |
Line 185 isparent(enum nodeid node, enum nodeid parent) |
|
Line 230 isparent(enum nodeid node, enum nodeid parent) |
|
case (NODE_FUNCDEF): |
case (NODE_FUNCDEF): |
case (NODE_FUNCSYNOPSISINFO): |
case (NODE_FUNCSYNOPSISINFO): |
case (NODE_PARA): |
case (NODE_PARA): |
|
case (NODE_PROGRAMLISTING): |
case (NODE_REFDESCRIPTOR): |
case (NODE_REFDESCRIPTOR): |
case (NODE_REFENTRYTITLE): |
case (NODE_REFENTRYTITLE): |
case (NODE_REFNAME): |
case (NODE_REFNAME): |
Line 205 isparent(enum nodeid node, enum nodeid parent) |
|
Line 251 isparent(enum nodeid node, enum nodeid parent) |
|
break; |
break; |
} |
} |
return(0); |
return(0); |
|
case (NODE_OPTION): |
|
switch (parent) { |
|
case (NODE_ARG): |
|
case (NODE_FUNCSYNOPSISINFO): |
|
case (NODE_PARA): |
|
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_PARA): |
case (NODE_PARA): |
switch (parent) { |
switch (parent) { |
case (NODE_REFSECT1): |
case (NODE_REFSECT1): |
Line 222 isparent(enum nodeid node, enum nodeid parent) |
|
Line 285 isparent(enum nodeid node, enum nodeid parent) |
|
case (NODE_FUNCSYNOPSISINFO): |
case (NODE_FUNCSYNOPSISINFO): |
case (NODE_PARA): |
case (NODE_PARA): |
case (NODE_PARAMDEF): |
case (NODE_PARAMDEF): |
|
case (NODE_PROGRAMLISTING): |
case (NODE_REFDESCRIPTOR): |
case (NODE_REFDESCRIPTOR): |
case (NODE_REFENTRYTITLE): |
case (NODE_REFENTRYTITLE): |
case (NODE_REFNAME): |
case (NODE_REFNAME): |
Line 304 xml_char(void *arg, const XML_Char *p, int sz) |
|
Line 368 xml_char(void *arg, const XML_Char *p, int sz) |
|
{ |
{ |
struct parse *ps = arg; |
struct parse *ps = arg; |
struct pnode *dat; |
struct pnode *dat; |
|
int i; |
|
|
/* Stopped or no tree yet. */ |
/* Stopped or no tree yet. */ |
if (ps->stop || NODE_ROOT == ps->node) |
if (ps->stop || NODE_ROOT == ps->node) |
Line 318 xml_char(void *arg, const XML_Char *p, int sz) |
|
Line 383 xml_char(void *arg, const XML_Char *p, int sz) |
|
* Are we in the midst of processing text? |
* Are we in the midst of processing text? |
* If we're not processing text right now, then create a text |
* If we're not processing text right now, then create a text |
* node for doing so. |
* node for doing so. |
|
* However, don't do so unless we have some non-whitespace to |
|
* process! |
*/ |
*/ |
if (NODE_TEXT != ps->node) { |
if (NODE_TEXT != ps->node) { |
|
for (i = 0; i < sz; i++) |
|
if ( ! isspace((int)p[i])) |
|
break; |
|
if (i == sz) |
|
return; |
dat = calloc(1, sizeof(struct pnode)); |
dat = calloc(1, sizeof(struct pnode)); |
if (NULL == dat) { |
if (NULL == dat) { |
perror(NULL); |
perror(NULL); |
Line 473 pnode_unlink(struct pnode *pn) |
|
Line 545 pnode_unlink(struct pnode *pn) |
|
} |
} |
|
|
static void |
static void |
|
pnode_unlinksub(struct pnode *pn) |
|
{ |
|
|
|
while ( ! TAILQ_EMPTY(&pn->childq)) |
|
pnode_unlink(TAILQ_FIRST(&pn->childq)); |
|
} |
|
|
|
static void |
bufclear(struct parse *p) |
bufclear(struct parse *p) |
{ |
{ |
|
|
Line 526 pnode_printmacrolinepart(struct parse *p, struct pnode |
|
Line 606 pnode_printmacrolinepart(struct parse *p, struct pnode |
|
*cp = ' '; |
*cp = ' '; |
|
|
for (cp = p->b; isspace((int)*cp); cp++) |
for (cp = p->b; isspace((int)*cp); cp++) |
/* Spin. */ ; |
/* Spin past whitespace (XXX: necessary?) */ ; |
|
|
for ( ; '\0' != *cp; cp++) { |
for ( ; '\0' != *cp; cp++) { |
/* Escape us if we look like a macro. */ |
/* Escape us if we look like a macro. */ |
if ((cp == p->b || ' ' == *(cp - 1)) && |
if ((cp == p->b || ' ' == *(cp - 1)) && |
Line 560 pnode_printmacroline(struct parse *p, struct pnode *pn |
|
Line 639 pnode_printmacroline(struct parse *p, struct pnode *pn |
|
} |
} |
|
|
static void |
static void |
|
pnode_printrefsynopsisdiv(struct parse *p, struct pnode *pn) |
|
{ |
|
struct pnode *pp; |
|
|
|
TAILQ_FOREACH(pp, &pn->childq, child) |
|
if (NODE_TITLE == pp->node) { |
|
pnode_unlink(pp); |
|
break; |
|
} |
|
|
|
puts(".Sh SYNOPSIS"); |
|
} |
|
|
|
static void |
pnode_printrefsect(struct parse *p, struct pnode *pn) |
pnode_printrefsect(struct parse *p, struct pnode *pn) |
{ |
{ |
struct pnode *pp; |
struct pnode *pp; |
Line 568 pnode_printrefsect(struct parse *p, struct pnode *pn) |
|
Line 661 pnode_printrefsect(struct parse *p, struct pnode *pn) |
|
if (NODE_TITLE == pp->node) |
if (NODE_TITLE == pp->node) |
break; |
break; |
|
|
|
fputs(".Sh ", stdout); |
|
|
if (NULL != pp) { |
if (NULL != pp) { |
fputs(".Sh ", stdout); |
|
pnode_printmacroline(p, pp); |
pnode_printmacroline(p, pp); |
pnode_unlink(pp); |
pnode_unlink(pp); |
} else |
} else |
puts(".Sh UNKNOWN"); |
puts("UNKNOWN"); |
} |
} |
|
|
static void |
static void |
Line 589 pnode_printciterefentry(struct parse *p, struct pnode |
|
Line 683 pnode_printciterefentry(struct parse *p, struct pnode |
|
title = pp; |
title = pp; |
|
|
fputs(".Xr ", stdout); |
fputs(".Xr ", stdout); |
|
|
if (NULL != title) { |
if (NULL != title) { |
pnode_printmacrolinepart(p, title); |
pnode_printmacrolinepart(p, title); |
pnode_unlink(title); |
putchar(' '); |
} else |
} else |
fputs("unknown", stdout); |
fputs("unknown ", stdout); |
putchar(' '); |
|
if (NULL != manvol) { |
if (NULL != manvol) |
pnode_printmacroline(p, manvol); |
pnode_printmacroline(p, manvol); |
pnode_unlink(manvol); |
else |
} else |
|
puts("1"); |
puts("1"); |
} |
} |
|
|
Line 618 pnode_printrefmeta(struct parse *p, struct pnode *pn) |
|
Line 712 pnode_printrefmeta(struct parse *p, struct pnode *pn) |
|
fputs(".Dt ", stdout); |
fputs(".Dt ", stdout); |
|
|
if (NULL != title) { |
if (NULL != title) { |
|
/* FIXME: uppercase. */ |
pnode_printmacrolinepart(p, title); |
pnode_printmacrolinepart(p, title); |
pnode_unlink(title); |
putchar(' '); |
} else |
} else |
fputs("UNKNOWN", stdout); |
fputs("UNKNOWN ", stdout); |
putchar(' '); |
|
if (NULL != manvol) { |
if (NULL != manvol) |
pnode_printmacroline(p, manvol); |
pnode_printmacroline(p, manvol); |
pnode_unlink(manvol); |
else |
} else |
|
puts("1"); |
puts("1"); |
|
|
puts(".Os"); |
puts(".Os"); |
Line 691 pnode_printfuncprototype(struct parse *p, struct pnode |
|
Line 785 pnode_printfuncprototype(struct parse *p, struct pnode |
|
if (NODE_FUNCDEF == fdef->node) |
if (NODE_FUNCDEF == fdef->node) |
break; |
break; |
|
|
if (NULL != fdef) { |
if (NULL != fdef) |
pnode_printfuncdef(p, fdef); |
pnode_printfuncdef(p, fdef); |
pnode_unlink(fdef); |
else |
} else |
|
puts(".Fo UNKNOWN"); |
puts(".Fo UNKNOWN"); |
|
|
TAILQ_FOREACH(pp, &pn->childq, child) { |
TAILQ_FOREACH(pp, &pn->childq, child) |
if (NODE_PARAMDEF == pp->node) |
if (NODE_PARAMDEF == pp->node) |
pnode_printparamdef(p, pp); |
pnode_printparamdef(p, pp); |
pnode_unlink(pp); |
|
} |
|
|
|
puts(".Fc"); |
puts(".Fc"); |
} |
} |
|
|
|
/* TODO: handle "optional" values. */ |
|
static void |
|
pnode_printarg(struct parse *p, struct pnode *pn, int nested) |
|
{ |
|
struct pnode *pp; |
|
int sv = nested; |
|
|
|
if ( ! nested) |
|
fputs(".", stdout); |
|
nested = 1; |
|
TAILQ_FOREACH(pp, &pn->childq, child) |
|
if (NODE_OPTION == pp->node) { |
|
fputs("Fl ", stdout); |
|
pnode_printmacrolinepart(p, pp); |
|
} else if (NODE_TEXT == pp->node) { |
|
fputs("Ar ", stdout); |
|
pnode_printmacrolinepart(p, pp); |
|
} else if (NODE_ARG == pp->node) |
|
pnode_printarg(p, pp, nested); |
|
|
|
if ( ! sv) |
|
puts(""); |
|
} |
|
|
|
/* |
|
* Recursively search and return the first instance of "node". |
|
*/ |
|
static struct pnode * |
|
pnode_findfirst(struct pnode *pn, enum nodeid node) |
|
{ |
|
struct pnode *pp, *res; |
|
|
|
res = NULL; |
|
TAILQ_FOREACH(pp, &pn->childq, child) { |
|
res = pp->node == node ? pp : |
|
pnode_findfirst(pp, node); |
|
if (NULL != res) |
|
break; |
|
} |
|
|
|
return(res); |
|
} |
|
|
|
static void |
|
pnode_printprologue(struct parse *p, struct pnode *pn) |
|
{ |
|
struct pnode *pp; |
|
|
|
if (NULL != (pp = pnode_findfirst(p->root, NODE_REFMETA))) { |
|
pnode_printrefmeta(p, pp); |
|
pnode_unlink(pp); |
|
} else { |
|
puts(".\\\" Supplying bogus prologue..."); |
|
puts(".Dd $Mdocdate" "$"); |
|
puts(".Dt UNKNOWN 1"); |
|
puts(".Os"); |
|
} |
|
} |
|
|
/* |
/* |
* Print a parsed node (or ignore it--whatever). |
* Print a parsed node (or ignore it--whatever). |
* This is a recursive function. |
* This is a recursive function. |
Line 725 pnode_print(struct parse *p, struct pnode *pn) |
|
Line 875 pnode_print(struct parse *p, struct pnode *pn) |
|
printf(".\\\" %s\n", nodes[pn->node].name); |
printf(".\\\" %s\n", nodes[pn->node].name); |
|
|
switch (pn->node) { |
switch (pn->node) { |
|
case (NODE_ARG): |
|
pnode_printarg(p, pn, 0); |
|
pnode_unlinksub(pn); |
|
break; |
case (NODE_CITEREFENTRY): |
case (NODE_CITEREFENTRY): |
pnode_printciterefentry(p, pn); |
pnode_printciterefentry(p, pn); |
|
pnode_unlinksub(pn); |
break; |
break; |
case (NODE_CODE): |
case (NODE_CODE): |
fputs(".Li ", stdout); |
fputs(".Li ", stdout); |
pnode_printmacroline(p, pn); |
pnode_printmacroline(p, pn); |
|
pnode_unlinksub(pn); |
break; |
break; |
|
case (NODE_COMMAND): |
|
fputs(".Nm ", stdout); |
|
pnode_printmacroline(p, pn); |
|
pnode_unlinksub(pn); |
|
break; |
case (NODE_FUNCTION): |
case (NODE_FUNCTION): |
fputs(".Fn ", stdout); |
fputs(".Fn ", stdout); |
pnode_printmacroline(p, pn); |
pnode_printmacroline(p, pn); |
|
pnode_unlinksub(pn); |
break; |
break; |
case (NODE_FUNCPROTOTYPE): |
case (NODE_FUNCPROTOTYPE): |
pnode_printfuncprototype(p, pn); |
pnode_printfuncprototype(p, pn); |
|
pnode_unlinksub(pn); |
break; |
break; |
case (NODE_FUNCSYNOPSISINFO): |
case (NODE_FUNCSYNOPSISINFO): |
fputs(".Fd ", stdout); |
fputs(".Fd ", stdout); |
pnode_printmacroline(p, pn); |
pnode_printmacroline(p, pn); |
|
pnode_unlinksub(pn); |
break; |
break; |
case (NODE_PARA): |
case (NODE_PARA): |
/* FIXME: not always. */ |
/* FIXME: not always. */ |
Line 751 pnode_print(struct parse *p, struct pnode *pn) |
|
Line 915 pnode_print(struct parse *p, struct pnode *pn) |
|
fputs(".Fa \"", stdout); |
fputs(".Fa \"", stdout); |
pnode_printmacrolinepart(p, pn); |
pnode_printmacrolinepart(p, pn); |
puts("\""); |
puts("\""); |
|
pnode_unlinksub(pn); |
break; |
break; |
case (NODE_PROGRAMLISTING): |
case (NODE_PROGRAMLISTING): |
puts(".Bd -literal"); |
puts(".Bd -literal"); |
break; |
break; |
case (NODE_REFMETA): |
case (NODE_REFMETA): |
pnode_printrefmeta(p, pn); |
abort(); |
break; |
break; |
case (NODE_REFNAME): |
case (NODE_REFNAME): |
fputs(".Nm ", stdout); |
fputs(".Nm ", stdout); |
pnode_printmacroline(p, pn); |
pnode_printmacroline(p, pn); |
|
pnode_unlinksub(pn); |
return; |
return; |
case (NODE_REFNAMEDIV): |
case (NODE_REFNAMEDIV): |
puts(".Sh NAME"); |
puts(".Sh NAME"); |
Line 768 pnode_print(struct parse *p, struct pnode *pn) |
|
Line 934 pnode_print(struct parse *p, struct pnode *pn) |
|
case (NODE_REFPURPOSE): |
case (NODE_REFPURPOSE): |
fputs(".Nd ", stdout); |
fputs(".Nd ", stdout); |
pnode_printmacroline(p, pn); |
pnode_printmacroline(p, pn); |
|
pnode_unlinksub(pn); |
return; |
return; |
case (NODE_REFSYNOPSISDIV): |
case (NODE_REFSYNOPSISDIV): |
puts(".Sh SYNOPSIS"); |
pnode_printrefsynopsisdiv(p, pn); |
break; |
break; |
case (NODE_REFSECT1): |
case (NODE_REFSECT1): |
pnode_printrefsect(p, pn); |
pnode_printrefsect(p, pn); |
Line 849 readfile(XML_Parser xp, int fd, |
|
Line 1016 readfile(XML_Parser xp, int fd, |
|
* Exit when we've read all or errors have occured |
* Exit when we've read all or errors have occured |
* during the parse sequence. |
* during the parse sequence. |
*/ |
*/ |
|
pnode_printprologue(&p, p.root); |
pnode_print(&p, p.root); |
pnode_print(&p, p.root); |
pnode_free(p.root); |
pnode_free(p.root); |
free(p.b); |
free(p.b); |