version 1.1, 2014/03/28 02:04:47 |
version 1.4, 2014/03/28 10:00:40 |
|
|
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_FUNCPROTOTYPE, |
NODE_FUNCSYNOPSIS, |
NODE_FUNCSYNOPSIS, |
NODE_FUNCSYNOPSISINFO, |
NODE_FUNCSYNOPSISINFO, |
|
NODE_FUNCTION, |
NODE_MANVOLNUM, |
NODE_MANVOLNUM, |
|
NODE_OPTION, |
NODE_PARA, |
NODE_PARA, |
|
NODE_PARAMDEF, |
|
NODE_PARAMETER, |
NODE_PROGRAMLISTING, |
NODE_PROGRAMLISTING, |
NODE_REFCLASS, |
NODE_REFCLASS, |
NODE_REFDESCRIPTOR, |
NODE_REFDESCRIPTOR, |
|
|
|
|
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 }, |
|
{ "funcprototype", NODE_IGNTEXT }, |
{ "funcsynopsis", NODE_IGNTEXT }, |
{ "funcsynopsis", NODE_IGNTEXT }, |
{ "funcsynopsisinfo", 0 }, |
{ "funcsynopsisinfo", 0 }, |
|
{ "function", 0 }, |
{ "manvolnum", 0 }, |
{ "manvolnum", 0 }, |
|
{ "option", 0 }, |
{ "para", 0 }, |
{ "para", 0 }, |
|
{ "paramdef", 0 }, |
|
{ "parameter", 0 }, |
{ "programlisting", 0 }, |
{ "programlisting", 0 }, |
{ "refclass", NODE_IGNTEXT }, |
{ "refclass", NODE_IGNTEXT }, |
{ "refdescriptor", NODE_IGNTEXT }, |
{ "refdescriptor", NODE_IGNTEXT }, |
Line 121 isparent(enum nodeid node, enum nodeid parent) |
|
Line 139 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 137 isparent(enum nodeid node, enum nodeid parent) |
|
Line 164 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 153 isparent(enum nodeid node, enum nodeid parent) |
|
Line 190 isparent(enum nodeid node, enum nodeid parent) |
|
break; |
break; |
} |
} |
return(0); |
return(0); |
case (NODE_MANVOLNUM): |
case (NODE_COMMAND): |
switch (parent) { |
switch (parent) { |
case (NODE_CITEREFENTRY): |
case (NODE_CMDSYNOPSIS): |
case (NODE_REFMETA): |
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); |
return(1); |
default: |
default: |
break; |
break; |
} |
} |
return(0); |
return(0); |
|
case (NODE_FUNCDEF): |
|
return(NODE_FUNCPROTOTYPE == parent); |
|
case (NODE_FUNCPROTOTYPE): |
|
return(NODE_FUNCSYNOPSIS == parent); |
case (NODE_FUNCSYNOPSIS): |
case (NODE_FUNCSYNOPSIS): |
switch (parent) { |
switch (parent) { |
case (NODE_PARA): |
case (NODE_PARA): |
Line 174 isparent(enum nodeid node, enum nodeid parent) |
|
Line 223 isparent(enum nodeid node, enum nodeid parent) |
|
return(0); |
return(0); |
case (NODE_FUNCSYNOPSISINFO): |
case (NODE_FUNCSYNOPSISINFO): |
return(NODE_FUNCSYNOPSIS == parent); |
return(NODE_FUNCSYNOPSIS == parent); |
|
case (NODE_FUNCTION): |
|
switch (parent) { |
|
case (NODE_CODE): |
|
case (NODE_FUNCDEF): |
|
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_MANVOLNUM): |
|
switch (parent) { |
|
case (NODE_CITEREFENTRY): |
|
case (NODE_REFMETA): |
|
return(1); |
|
default: |
|
break; |
|
} |
|
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 183 isparent(enum nodeid node, enum nodeid parent) |
|
Line 276 isparent(enum nodeid node, enum nodeid parent) |
|
break; |
break; |
} |
} |
return(0); |
return(0); |
|
case (NODE_PARAMDEF): |
|
return(NODE_FUNCPROTOTYPE == parent); |
|
case (NODE_PARAMETER): |
|
switch (parent) { |
|
case (NODE_CODE): |
|
case (NODE_FUNCSYNOPSISINFO): |
|
case (NODE_PARA): |
|
case (NODE_PARAMDEF): |
|
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_PROGRAMLISTING): |
case (NODE_PROGRAMLISTING): |
switch (parent) { |
switch (parent) { |
case (NODE_PARA): |
case (NODE_PARA): |
Line 254 xml_char(void *arg, const XML_Char *p, int sz) |
|
Line 367 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 268 xml_char(void *arg, const XML_Char *p, int sz) |
|
Line 382 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 423 pnode_unlink(struct pnode *pn) |
|
Line 544 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 446 bufappend(struct parse *p, struct pnode *pn) |
|
Line 575 bufappend(struct parse *p, struct pnode *pn) |
|
p->b[p->bsz] = '\0'; |
p->b[p->bsz] = '\0'; |
} |
} |
|
|
|
static void |
|
bufappend_r(struct parse *p, struct pnode *pn) |
|
{ |
|
struct pnode *pp; |
|
|
|
if (NODE_TEXT == pn->node) |
|
bufappend(p, pn); |
|
TAILQ_FOREACH(pp, &pn->childq, child) |
|
bufappend_r(p, pp); |
|
} |
|
|
/* |
/* |
* Print text presumably on a macro line. |
* Print text presumably on a macro line. |
* Ignore any child macros. |
* Ignore any child macros. |
Line 454 bufappend(struct parse *p, struct pnode *pn) |
|
Line 594 bufappend(struct parse *p, struct pnode *pn) |
|
static void |
static void |
pnode_printmacrolinepart(struct parse *p, struct pnode *pn) |
pnode_printmacrolinepart(struct parse *p, struct pnode *pn) |
{ |
{ |
struct pnode *pp; |
|
char *cp; |
char *cp; |
|
|
bufclear(p); |
bufclear(p); |
while (NULL != (pp = TAILQ_FIRST(&pn->childq))) { |
bufappend_r(p, pn); |
if (NODE_TEXT == pp->node) |
|
bufappend(p, pp); |
|
pnode_unlink(pp); |
|
} |
|
|
|
/* Convert all space to spaces. */ |
/* Convert all space to spaces. */ |
for (cp = p->b; '\0' != *cp; cp++) |
for (cp = p->b; '\0' != *cp; cp++) |
Line 470 pnode_printmacrolinepart(struct parse *p, struct pnode |
|
Line 605 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 512 pnode_printrefsect(struct parse *p, struct pnode *pn) |
|
Line 646 pnode_printrefsect(struct parse *p, struct pnode *pn) |
|
if (NODE_TITLE == pp->node) |
if (NODE_TITLE == pp->node) |
break; |
break; |
|
|
if (NULL != pp) { |
fputs(".Sh ", stdout); |
fputs(".Sh ", stdout); |
|
|
if (NULL != pp) |
pnode_printmacroline(p, pp); |
pnode_printmacroline(p, pp); |
pnode_unlink(pp); |
else |
} else |
puts("UNKNOWN"); |
puts(".Sh UNKNOWN"); |
|
} |
} |
|
|
static void |
static void |
Line 533 pnode_printciterefentry(struct parse *p, struct pnode |
|
Line 667 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 558 pnode_printrefmeta(struct parse *p, struct pnode *pn) |
|
Line 692 pnode_printrefmeta(struct parse *p, struct pnode *pn) |
|
else if (NODE_REFENTRYTITLE == pp->node) |
else if (NODE_REFENTRYTITLE == pp->node) |
title = pp; |
title = pp; |
|
|
puts(".Dd $Mdocdate$"); |
puts(".Dd $Mdocdate" "$"); |
fputs(".Dt ", stdout); |
fputs(".Dt ", 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"); |
|
|
puts(".Os"); |
puts(".Os"); |
} |
} |
|
|
|
static void |
|
pnode_printfuncdef(struct parse *p, struct pnode *pn) |
|
{ |
|
struct pnode *pp, *ftype, *func; |
|
|
|
ftype = func = NULL; |
|
TAILQ_FOREACH(pp, &pn->childq, child) |
|
if (NODE_TEXT == pp->node) |
|
ftype = pp; |
|
else if (NODE_FUNCTION == pp->node) |
|
func = pp; |
|
|
|
if (NULL != ftype) { |
|
fputs(".Ft ", stdout); |
|
pnode_printmacroline(p, ftype); |
|
} |
|
|
|
if (NULL != func) { |
|
fputs(".Fo ", stdout); |
|
pnode_printmacroline(p, func); |
|
} else |
|
puts(".Fo UNKNOWN"); |
|
} |
|
|
|
static void |
|
pnode_printparamdef(struct parse *p, struct pnode *pn) |
|
{ |
|
struct pnode *pp, *ptype, *param; |
|
|
|
ptype = param = NULL; |
|
TAILQ_FOREACH(pp, &pn->childq, child) |
|
if (NODE_TEXT == pp->node) |
|
ptype = pp; |
|
else if (NODE_PARAMETER == pp->node) |
|
param = pp; |
|
|
|
fputs(".Fa \"", stdout); |
|
if (NULL != ptype) { |
|
pnode_printmacrolinepart(p, ptype); |
|
putchar(' '); |
|
} |
|
|
|
if (NULL != param) |
|
pnode_printmacrolinepart(p, param); |
|
else |
|
fputs("UNKNOWN", stdout); |
|
|
|
puts("\""); |
|
} |
|
|
|
static void |
|
pnode_printfuncprototype(struct parse *p, struct pnode *pn) |
|
{ |
|
struct pnode *pp, *fdef; |
|
|
|
TAILQ_FOREACH(fdef, &pn->childq, child) |
|
if (NODE_FUNCDEF == fdef->node) |
|
break; |
|
|
|
if (NULL != fdef) |
|
pnode_printfuncdef(p, fdef); |
|
else |
|
puts(".Fo UNKNOWN"); |
|
|
|
TAILQ_FOREACH(pp, &pn->childq, child) |
|
if (NODE_PARAMDEF == pp->node) |
|
pnode_printparamdef(p, pp); |
|
|
|
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(""); |
|
} |
|
|
/* |
/* |
* 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 595 pnode_print(struct parse *p, struct pnode *pn) |
|
Line 823 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): |
|
fputs(".Fn ", stdout); |
|
pnode_printmacroline(p, pn); |
|
pnode_unlinksub(pn); |
|
break; |
|
case (NODE_FUNCPROTOTYPE): |
|
pnode_printfuncprototype(p, pn); |
|
pnode_unlinksub(pn); |
|
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. */ |
puts(".Pp"); |
puts(".Pp"); |
break; |
break; |
|
case (NODE_PARAMETER): |
|
fputs(".Fa \"", stdout); |
|
pnode_printmacrolinepart(p, pn); |
|
puts("\""); |
|
pnode_unlinksub(pn); |
|
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); |
pnode_printrefmeta(p, pn); |
|
pnode_unlinksub(pn); |
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 626 pnode_print(struct parse *p, struct pnode *pn) |
|
Line 883 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"); |
puts(".Sh SYNOPSIS"); |
break; |
break; |
case (NODE_REFSECT1): |
case (NODE_REFSECT1): |
pnode_printrefsect(p, pn); |
pnode_printrefsect(p, pn); |
|
pnode_unlinksub(pn); |
break; |
break; |
case (NODE_TEXT): |
case (NODE_TEXT): |
bufclear(p); |
bufclear(p); |