Add --intro and --title options to mxmldoc, and treat names starting

with "_" as private.
pull/193/head
Michael R Sweet 19 years ago
parent c720996a85
commit d9276fe08f
  1. 4
      CHANGES
  2. 10
      doc/mxml.html
  3. 18
      doc/mxmldoc.man
  4. 3
      doc/relnotes.html
  5. 312
      mxmldoc.c

@ -1,8 +1,10 @@
CHANGES - 08/16/2005 CHANGES - 09/21/2005
-------------------- --------------------
CHANGES IN Mini-XML 2.2.3 CHANGES IN Mini-XML 2.2.3
- The mxmldoc program now supports --title and --intro
options.
- The mxmlLoad*() functions could leak a node on an error - The mxmlLoad*() functions could leak a node on an error
(STR #27) (STR #27)
- The mxml_vsnprintf() function could get in an infinite - The mxml_vsnprintf() function could get in an infinite

@ -1831,13 +1831,19 @@ Ty Coon, President of Vice
<H1 align="right"><A name="RELNOTES">B - Release Notes</A></H1> <H1 align="right"><A name="RELNOTES">B - Release Notes</A></H1>
<H2><A NAME="7_1">Changes in Mini-XML 2.2.3</A></H2> <H2><A NAME="7_1">Changes in Mini-XML 2.2.3</A></H2>
<UL> <UL>
<LI>The mxmldoc program now supports --title and --intro options.</LI>
<LI>The mxmlLoad*() functions could leak a node on an error (STR #27)</LI>
<LI>The mxml_vsnprintf() function could get in an infinite loop on a
buffer overflow (STR #25)</LI>
<LI>Added new mxmlNewCDATA() and mxmlSetCDATA() functions to create and <LI>Added new mxmlNewCDATA() and mxmlSetCDATA() functions to create and
set CDATA nodes, which are really just special element nodes.</LI> set CDATA nodes, which are really just special element nodes.</LI>
<LI>Added new MXML_IGNORE type and MXML_IGNORE_CB callback to ignore
non-element nodes (i.e. whitespace)</LI>
<LI>mxmlLoad*() did not treat custom data as opaque, so whitespace
characters would be lost.</LI>
</UL> </UL>
<H2><A NAME="7_2">Changes in Mini-XML 2.2.2</A></H2> <H2><A NAME="7_2">Changes in Mini-XML 2.2.2</A></H2>
<UL> <UL>
<LI>Added new MXML_IGNORE type and MXML_IGNORE_CB callback to ignore
non-element nodes (i.e. whitespace)</LI>
<LI>mxmlLoad*() did not treat custom data as opaque, so whitespace <LI>mxmlLoad*() did not treat custom data as opaque, so whitespace
characters would be lost.</LI> characters would be lost.</LI>
</UL> </UL>

@ -15,13 +15,18 @@
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details. .\" GNU General Public License for more details.
.\" .\"
.TH mxmldoc 1 "mini-XML" "25 February 2005" "Michael Sweet" .TH mxmldoc 1 "mini-XML" "21 September 2005" "Michael Sweet"
.SH NAME .SH NAME
mxmldoc \- mini-xml documentation generator mxmldoc \- mini-xml documentation generator
.SH SYNOPSIS .SH SYNOPSIS
.B mxmldoc .B mxmldoc
[ --intro
.I introfile.html
] [ --title
.I title
] [
.I filename.xml .I filename.xml
[ ] [
.I source file(s) .I source file(s)
] > ] >
.I filename.html .I filename.html
@ -39,6 +44,15 @@ In general, any C or C++ source code is handled by
code with documentation that is formatted according to the CUPS code with documentation that is formatted according to the CUPS
Configuration Management Plan which is available at Configuration Management Plan which is available at
"http://www.cups.org/documentation.php". "http://www.cups.org/documentation.php".
.SH OPTIONS
.TP 5
\--intro introfile.html
.br
Inserts the specified file at the top of the output documentation.
.TP 5
\--title title
.br
Sets the title of the output documentation.
.SH SEE ALSO .SH SEE ALSO
mxml(3), Mini-XML Programmers Manual, http://www.easysw.com/~mike/mxml/ mxml(3), Mini-XML Programmers Manual, http://www.easysw.com/~mike/mxml/
.SH COPYRIGHT .SH COPYRIGHT

@ -7,6 +7,9 @@
<ul> <ul>
<li>The mxmldoc program now supports --title and --intro
options.</li>
<li>The mxmlLoad*() functions could leak a node on an <li>The mxmlLoad*() functions could leak a node on an
error (STR #27)</li> error (STR #27)</li>

@ -20,10 +20,12 @@
* *
* main() - Main entry for test program. * main() - Main entry for test program.
* add_variable() - Add a variable or argument. * add_variable() - Add a variable or argument.
* new_documentation() - Create a new documentation tree.
* safe_strcpy() - Copy a string allowing for overlapping strings. * safe_strcpy() - Copy a string allowing for overlapping strings.
* scan_file() - Scan a source file. * scan_file() - Scan a source file.
* sort_node() - Insert a node sorted into a tree. * sort_node() - Insert a node sorted into a tree.
* update_comment() - Update a comment node. * update_comment() - Update a comment node.
* usage() - Show program usage...
* write_documentation() - Write HTML documentation. * write_documentation() - Write HTML documentation.
* write_element() - Write an elements text nodes. * write_element() - Write an elements text nodes.
* write_string() - Write a string, quoting XHTML special chars * write_string() - Write a string, quoting XHTML special chars
@ -132,13 +134,17 @@
static mxml_node_t *add_variable(mxml_node_t *parent, const char *name, static mxml_node_t *add_variable(mxml_node_t *parent, const char *name,
mxml_node_t *type); mxml_node_t *type);
static mxml_node_t *new_documentation(mxml_node_t **mxmldoc);
static void safe_strcpy(char *dst, const char *src); static void safe_strcpy(char *dst, const char *src);
static int scan_file(const char *filename, FILE *fp, static int scan_file(const char *filename, FILE *fp,
mxml_node_t *doc); mxml_node_t *doc);
static void sort_node(mxml_node_t *tree, mxml_node_t *func); static void sort_node(mxml_node_t *tree, mxml_node_t *func);
static void update_comment(mxml_node_t *parent, static void update_comment(mxml_node_t *parent,
mxml_node_t *comment); mxml_node_t *comment);
static void write_documentation(mxml_node_t *doc); static void usage(const char *option);
static void write_documentation(const char *title,
const char *intro,
mxml_node_t *doc);
static void write_element(mxml_node_t *doc, mxml_node_t *element); static void write_element(mxml_node_t *doc, mxml_node_t *element);
static void write_string(const char *s); static void write_string(const char *s);
static const char *ws_cb(mxml_node_t *node, int where); static const char *ws_cb(mxml_node_t *node, int where);
@ -153,110 +159,153 @@ main(int argc, /* I - Number of command-line args */
char *argv[]) /* I - Command-line args */ char *argv[]) /* I - Command-line args */
{ {
int i; /* Looping var */ int i; /* Looping var */
int len; /* Length of argument */
FILE *fp; /* File to read */ FILE *fp; /* File to read */
mxml_node_t *doc; /* XML documentation tree */ mxml_node_t *doc; /* XML documentation tree */
mxml_node_t *mxmldoc; /* mxmldoc node */ mxml_node_t *mxmldoc; /* mxmldoc node */
const char *title; /* Title of documentation */
const char *introfile; /* Introduction file */
const char *xmlfile; /* XML file */
int update; /* Updated XML file */
/* /*
* Check arguments... * Check arguments...
*/ */
if (argc < 2) title = NULL;
{ introfile = NULL;
fputs("Usage: mxmldoc filename.xml [source files] >filename.html\n", stderr); xmlfile = NULL;
return (1); update = 0;
} doc = NULL;
mxmldoc = NULL;
/*
* Read the XML documentation file, if it exists...
*/
if ((fp = fopen(argv[1], "r")) != NULL)
{
/*
* Read the existing XML file...
*/
doc = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK);
fclose(fp); for (i = 1; i < argc; i ++)
if (!strcmp(argv[i], "--title") && !title)
{
/*
* Set title...
*/
if (!doc) i ++;
if (i < argc)
title = argv[i];
else
usage(NULL);
}
else if (!strcmp(argv[i], "--intro") && !introfile)
{ {
mxmldoc = NULL; /*
* Set intro file...
*/
fprintf(stderr, "mxmldoc: Unable to read the XML documentation file \"%s\"!\n", i ++;
argv[1]); if (i < argc)
introfile = argv[i];
else
usage(NULL);
} }
else if ((mxmldoc = mxmlFindElement(doc, doc, "mxmldoc", NULL, else if (argv[i][0] == '-')
NULL, MXML_DESCEND)) == NULL)
{ {
fprintf(stderr, "mxmldoc: XML documentation file \"%s\" is missing <mxmldoc> node!!\n", /*
argv[1]); * Unknown/bad option...
*/
mxmlDelete(doc); usage(argv[i]);
doc = NULL;
} }
} else
else {
{ /*
doc = NULL; * Process XML or source file...
mxmldoc = NULL; */
}
if (!doc) len = strlen(argv[i]);
{ if (len > 4 && !strcmp(argv[i] + len - 4, ".xml"))
/* {
* Create an empty XML documentation file... /*
*/ * Set XML file...
*/
doc = mxmlNewElement(NULL, "?xml version=\"1.0\"?"); if (xmlfile)
usage(NULL);
mxmldoc = mxmlNewElement(doc, "mxmldoc"); xmlfile = argv[i];
#ifdef MXML_INCLUDE_SCHEMA if (!doc)
/* {
* Currently we don't include the schema/namespace stuff with the if ((fp = fopen(argv[i], "r")) != NULL)
* XML output since some validators don't seem to like it... {
*/ /*
* Read the existing XML file...
*/
mxmlElementSetAttr(mxmldoc, "xmlns", "http://www.easysw.com"); doc = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK);
mxmlElementSetAttr(mxmldoc, "xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
mxmlElementSetAttr(mxmldoc, "xsi:schemaLocation",
"http://www.easysw.com/~mike/mxml/mxmldoc.xsd");
#endif /* MXML_INCLUDE_SCHEMA */
}
/* fclose(fp);
* Loop through all of the source files...
*/
for (i = 2; i < argc; i ++) if (!doc)
if ((fp = fopen(argv[i], "r")) == NULL) {
{ mxmldoc = NULL;
fprintf(stderr, "Unable to open source file \"%s\": %s\n", argv[i],
strerror(errno)); fprintf(stderr, "mxmldoc: Unable to read the XML documentation file \"%s\"!\n",
mxmlDelete(doc); argv[i]);
return (1); }
} else if ((mxmldoc = mxmlFindElement(doc, doc, "mxmldoc", NULL,
else if (scan_file(argv[i], fp, mxmldoc)) NULL, MXML_DESCEND)) == NULL)
{ {
fclose(fp); fprintf(stderr, "mxmldoc: XML documentation file \"%s\" is missing <mxmldoc> node!!\n",
mxmlDelete(doc); argv[i]);
return (1);
mxmlDelete(doc);
doc = NULL;
}
}
else
{
doc = NULL;
mxmldoc = NULL;
}
if (!doc)
doc = new_documentation(&mxmldoc);
}
}
else
{
/*
* Load source file...
*/
update = 1;
if (!doc)
doc = new_documentation(&mxmldoc);
if ((fp = fopen(argv[i], "r")) == NULL)
{
fprintf(stderr, "mxmldoc: Unable to open source file \"%s\": %s\n",
argv[i], strerror(errno));
mxmlDelete(doc);
return (1);
}
else if (scan_file(argv[i], fp, mxmldoc))
{
fclose(fp);
mxmlDelete(doc);
return (1);
}
else
fclose(fp);
}
} }
else
fclose(fp);
if (argc > 2) if (update && xmlfile)
{ {
/* /*
* Save the updated XML documentation file... * Save the updated XML documentation file...
*/ */
if ((fp = fopen(argv[1], "w")) != NULL) if ((fp = fopen(xmlfile, "w")) != NULL)
{ {
/* /*
* Write over the existing XML file... * Write over the existing XML file...
@ -264,8 +313,8 @@ main(int argc, /* I - Number of command-line args */
if (mxmlSaveFile(doc, fp, ws_cb)) if (mxmlSaveFile(doc, fp, ws_cb))
{ {
fprintf(stderr, "Unable to write the XML documentation file \"%s\": %s!\n", fprintf(stderr, "mxmldoc: Unable to write the XML documentation file \"%s\": %s!\n",
argv[1], strerror(errno)); xmlfile, strerror(errno));
fclose(fp); fclose(fp);
mxmlDelete(doc); mxmlDelete(doc);
return (1); return (1);
@ -275,8 +324,8 @@ main(int argc, /* I - Number of command-line args */
} }
else else
{ {
fprintf(stderr, "Unable to create the XML documentation file \"%s\": %s!\n", fprintf(stderr, "mxmldoc: Unable to create the XML documentation file \"%s\": %s!\n",
argv[1], strerror(errno)); xmlfile, strerror(errno));
mxmlDelete(doc); mxmlDelete(doc);
return (1); return (1);
} }
@ -286,7 +335,7 @@ main(int argc, /* I - Number of command-line args */
* Write HTML documentation... * Write HTML documentation...
*/ */
write_documentation(mxmldoc); write_documentation(title ? title : "Documentation", introfile, mxmldoc);
/* /*
* Delete the tree and return... * Delete the tree and return...
@ -412,6 +461,40 @@ add_variable(mxml_node_t *parent, /* I - Parent node */
} }
/*
* 'new_documentation()' - Create a new documentation tree.
*/
static mxml_node_t * /* O - New documentation */
new_documentation(mxml_node_t **mxmldoc)/* O - mxmldoc node */
{
mxml_node_t *doc; /* New documentation */
/*
* Create an empty XML documentation file...
*/
doc = mxmlNewElement(NULL, "?xml version=\"1.0\"?");
*mxmldoc = mxmlNewElement(doc, "mxmldoc");
#ifdef MXML_INCLUDE_SCHEMA
/*
* Currently we don't include the schema/namespace stuff with the
* XML output since some validators don't seem to like it...
*/
mxmlElementSetAttr(*mxmldoc, "xmlns", "http://www.easysw.com");
mxmlElementSetAttr(*mxmldoc, "xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
mxmlElementSetAttr(*mxmldoc, "xsi:schemaLocation",
"http://www.easysw.com/~mike/mxml/mxmldoc.xsd");
#endif /* MXML_INCLUDE_SCHEMA */
return (doc);
}
/* /*
* 'safe_strcpy()' - Copy a string allowing for overlapping strings. * 'safe_strcpy()' - Copy a string allowing for overlapping strings.
*/ */
@ -1636,6 +1719,9 @@ sort_node(mxml_node_t *tree, /* I - Tree to sort into */
if ((nodename = mxmlElementGetAttr(node, "name")) == NULL) if ((nodename = mxmlElementGetAttr(node, "name")) == NULL)
return; return;
if (nodename[0] == '_')
return; /* Hide private names */
#if DEBUG > 1 #if DEBUG > 1
fprintf(stderr, " nodename=%p (\"%s\")\n", nodename, nodename); fprintf(stderr, " nodename=%p (\"%s\")\n", nodename, nodename);
#endif /* DEBUG > 1 */ #endif /* DEBUG > 1 */
@ -1792,14 +1878,38 @@ update_comment(mxml_node_t *parent, /* I - Parent node */
} }
/*
* 'usage()' - Show program usage...
*/
static void
usage(const char *option) /* I - Unknown option */
{
if (option)
printf("mxmldoc: Bad option \"%s\"!\n\n", option);
puts("Usage: mxmldoc [options] [filename.xml] [source files] >filename.html");
puts("Options:");
puts(" --title title Set documentation title");
puts(" --intro introfile.html Set introduction file");
exit(1);
}
/* /*
* 'write_documentation()' - Write HTML documentation. * 'write_documentation()' - Write HTML documentation.
*/ */
static void static void
write_documentation(mxml_node_t *doc) /* I - XML documentation */ write_documentation(
const char *title, /* I - Title */
const char *introfile, /* I - Intro file */
mxml_node_t *doc) /* I - XML documentation */
{ {
int i; /* Looping var */ int i; /* Looping var */
FILE *fp; /* File */
char line[8192]; /* Line from file */
mxml_node_t *function, /* Current function */ mxml_node_t *function, /* Current function */
*scut, /* Struct/class/union/typedef */ *scut, /* Struct/class/union/typedef */
*arg, /* Current argument */ *arg, /* Current argument */
@ -1823,19 +1933,35 @@ write_documentation(mxml_node_t *doc) /* I - XML documentation */
* Standard header... * Standard header...
*/ */
puts("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" " printf("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
"<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n" "<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"
"<head>\n" "<head>\n"
"\t<title>Documentation</title>\n" "\t<title>%s</title>\n"
"\t<meta name='creator' content='" MXML_VERSION "'/>\n" "\t<meta name='creator' content='" MXML_VERSION "'/>\n"
"\t<style><!--\n" "\t<style><!--\n"
"\th1, h2, h3, p { font-family: sans-serif; text-align: justify; }\n" "\th1, h2, h3, p { font-family: sans-serif; text-align: justify; }\n"
"\ttt, pre a:link, pre a:visited, tt a:link, tt a:visited { font-weight: bold; color: #7f0000; }\n" "\ttt, pre a:link, pre a:visited, tt a:link, tt a:visited { font-weight: bold; color: #7f0000; }\n"
"\tpre { font-weight: bold; color: #7f0000; margin-left: 2em; }\n" "\tpre { font-weight: bold; color: #7f0000; margin-left: 2em; }\n"
"\t--></style>\n" "\t--></style>\n"
"</head>\n" "</head>\n"
"<body>"); "<body>\n", title);
/*
* Intro...
*/
if (introfile && (fp = fopen(introfile, "r")) != NULL)
{
/*
* Insert intro file before contents...
*/
while (fgets(line, sizeof(line), fp))
fputs(line, stdout);
fclose(fp);
}
/* /*
* Table of contents... * Table of contents...

Loading…
Cancel
Save