2003-06-04 03:07:47 +00:00
|
|
|
/*
|
2003-06-04 16:30:40 +00:00
|
|
|
* "$Id: mxmldoc.c,v 1.2 2003/06/04 16:30:40 mike Exp $"
|
2003-06-04 03:07:47 +00:00
|
|
|
*
|
2003-06-04 16:30:40 +00:00
|
|
|
* Documentation generator using mini-XML, a small XML-like file parsing
|
2003-06-04 03:07:47 +00:00
|
|
|
* library.
|
|
|
|
*
|
|
|
|
* Copyright 2003 by Michael Sweet.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* Contents:
|
|
|
|
*
|
|
|
|
* main() - Main entry for documentation generator.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Include necessary headers...
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "mxml.h"
|
|
|
|
|
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
/*
|
|
|
|
* This program scans source and header files and produces public API
|
|
|
|
* documentation for code that conforms to the CUPS Configuration
|
|
|
|
* Management Plan (CMP) coding standards. Please see the following web
|
|
|
|
* page for details:
|
|
|
|
*
|
|
|
|
* http://www.cups.org/cmp.html
|
|
|
|
*
|
|
|
|
* Using Mini-XML, this program creates and maintains an XML representation
|
|
|
|
* of the public API code documentation which can then be converted to HTML
|
|
|
|
* as desired. The following is a poor-man's schema:
|
|
|
|
*
|
|
|
|
* <namespace name=""> [name is usually "std"...]
|
|
|
|
* <constant name="">
|
|
|
|
* <description>descriptive text</description>
|
|
|
|
* </constant>
|
|
|
|
*
|
|
|
|
* <enumeration name="">
|
|
|
|
* <constant name="">...</constant>
|
|
|
|
* </enumeration>
|
|
|
|
*
|
|
|
|
* <typedef name="">
|
|
|
|
* <description>descriptive text</description>
|
|
|
|
* <type>type string</type>
|
|
|
|
* </typedef>
|
|
|
|
*
|
|
|
|
* <function name="">
|
|
|
|
* <description>descriptive text</description>
|
|
|
|
* <iargument name="">
|
|
|
|
* <description>descriptive text</description>
|
|
|
|
* <type>type string</type>
|
|
|
|
* </iargument>
|
|
|
|
* <oargument name="">
|
|
|
|
* <description>descriptive text</description>
|
|
|
|
* <type>type string</type>
|
|
|
|
* </oargument>
|
|
|
|
* <ioargument name="">
|
|
|
|
* <description>descriptive text</description>
|
|
|
|
* <type>type string</type>
|
|
|
|
* </ioargument>
|
|
|
|
* <returnvalue>
|
|
|
|
* <description>descriptive text</description>
|
|
|
|
* <type>type string</type>
|
|
|
|
* </returnvalue>
|
|
|
|
* <seealso>function names separated by spaces</seealso>
|
|
|
|
* </function>
|
|
|
|
*
|
|
|
|
* <variable name="">
|
|
|
|
* <description>descriptive text</description>
|
|
|
|
* <type>type string</type>
|
|
|
|
* </variable>
|
|
|
|
*
|
|
|
|
* <struct name="">
|
|
|
|
* <description>descriptive text</description>
|
|
|
|
* <variable name="">...</variable>
|
|
|
|
* <function name="">...</function>
|
|
|
|
* </struct>
|
|
|
|
*
|
|
|
|
* <class name="" parent="">
|
|
|
|
* <description>descriptive text</description>
|
|
|
|
* <class name="">...</class>
|
|
|
|
* <enumeration name="">...</enumeration>
|
|
|
|
* <function name="">...</function>
|
|
|
|
* <struct name="">...</struct>
|
|
|
|
* <variable name="">...</variable>
|
|
|
|
* </class>
|
|
|
|
* </namespace>
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2003-06-04 03:07:47 +00:00
|
|
|
/*
|
|
|
|
* Local functions...
|
|
|
|
*/
|
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
static void insert_node(mxml_node_t *tree, mxml_node_t *func);
|
|
|
|
static int scan_file(const char *filename, FILE *fp,
|
|
|
|
mxml_node_t *doc);
|
2003-06-04 03:07:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 'main()' - Main entry for test program.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int /* O - Exit status */
|
|
|
|
main(int argc, /* I - Number of command-line args */
|
|
|
|
char *argv[]) /* I - Command-line args */
|
|
|
|
{
|
2003-06-04 16:30:40 +00:00
|
|
|
int i; /* Looping var */
|
2003-06-04 03:07:47 +00:00
|
|
|
FILE *fp; /* File to read */
|
2003-06-04 16:30:40 +00:00
|
|
|
mxml_node_t *doc; /* XML documentation tree */
|
2003-06-04 03:07:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check arguments...
|
|
|
|
*/
|
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
if (argc < 2)
|
2003-06-04 03:07:47 +00:00
|
|
|
{
|
2003-06-04 16:30:40 +00:00
|
|
|
fputs("Usage: mxmldoc filename.xml [source files] >filename.html\n", stderr);
|
2003-06-04 03:07:47 +00:00
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2003-06-04 16:30:40 +00:00
|
|
|
* Read the XML documentation file, if it exists...
|
2003-06-04 03:07:47 +00:00
|
|
|
*/
|
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
if ((fp = fopen(argv[1], "r")) != NULL)
|
2003-06-04 03:07:47 +00:00
|
|
|
{
|
2003-06-04 16:30:40 +00:00
|
|
|
/*
|
|
|
|
* Read the existing XML file...
|
|
|
|
*/
|
2003-06-04 03:07:47 +00:00
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
doc = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK);
|
2003-06-04 03:07:47 +00:00
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
fclose(fp);
|
2003-06-04 03:07:47 +00:00
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
if (!doc)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Unable to read the XML documentation file \"%s\"!\n",
|
|
|
|
argv[1]);
|
|
|
|
return (1);
|
|
|
|
}
|
2003-06-04 03:07:47 +00:00
|
|
|
}
|
2003-06-04 16:30:40 +00:00
|
|
|
else
|
2003-06-04 03:07:47 +00:00
|
|
|
{
|
|
|
|
/*
|
2003-06-04 16:30:40 +00:00
|
|
|
* Create an empty XML documentation file...
|
2003-06-04 03:07:47 +00:00
|
|
|
*/
|
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
doc = mxmlNewElement(NULL, "namespace");
|
|
|
|
|
|
|
|
mxmlElementSetAttr(doc, "name", "std");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Loop through all of the source files...
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (i = 2; i < argc; i ++)
|
|
|
|
if ((fp = fopen(argv[i], "r")) == NULL)
|
2003-06-04 03:07:47 +00:00
|
|
|
{
|
2003-06-04 16:30:40 +00:00
|
|
|
fprintf(stderr, "Unable to open source file \"%s\": %s\n", argv[i],
|
|
|
|
strerror(errno));
|
|
|
|
mxmlDelete(doc);
|
2003-06-04 03:07:47 +00:00
|
|
|
return (1);
|
|
|
|
}
|
2003-06-04 16:30:40 +00:00
|
|
|
else if (scan_file(argv[i], fp, doc))
|
2003-06-04 03:07:47 +00:00
|
|
|
{
|
2003-06-04 16:30:40 +00:00
|
|
|
fclose(fp);
|
|
|
|
mxmlDelete(doc);
|
2003-06-04 03:07:47 +00:00
|
|
|
return (1);
|
|
|
|
}
|
2003-06-04 16:30:40 +00:00
|
|
|
else
|
|
|
|
fclose(fp);
|
2003-06-04 03:07:47 +00:00
|
|
|
|
|
|
|
/*
|
2003-06-04 16:30:40 +00:00
|
|
|
* Save the updated XML documentation file...
|
2003-06-04 03:07:47 +00:00
|
|
|
*/
|
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
if ((fp = fopen(argv[1], "w")) != NULL)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Write over the existing XML file...
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (mxmlSaveFile(doc, fp))
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Unable to write the XML documentation file \"%s\": %s!\n",
|
|
|
|
argv[1], strerror(errno));
|
|
|
|
fclose(fp);
|
|
|
|
mxmlDelete(doc);
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Unable to create the XML documentation file \"%s\": %s!\n",
|
|
|
|
argv[1], strerror(errno));
|
|
|
|
mxmlDelete(doc);
|
|
|
|
return (1);
|
|
|
|
}
|
2003-06-04 03:07:47 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Delete the tree and return...
|
|
|
|
*/
|
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
mxmlDelete(doc);
|
2003-06-04 03:07:47 +00:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2003-06-04 16:30:40 +00:00
|
|
|
* 'insert_node()' - Insert a node into a tree.
|
2003-06-04 03:07:47 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
2003-06-04 16:30:40 +00:00
|
|
|
insert_node(mxml_node_t *tree, /* I - Tree to insert into */
|
|
|
|
mxml_node_t *node) /* I - Node to add */
|
2003-06-04 03:07:47 +00:00
|
|
|
{
|
2003-06-04 16:30:40 +00:00
|
|
|
mxml_node_t *temp; /* Current node */
|
|
|
|
const char *tempname, /* Name of current node */
|
|
|
|
*nodename; /* Name of node */
|
2003-06-04 03:07:47 +00:00
|
|
|
|
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
/*
|
|
|
|
* Get the node name...
|
|
|
|
*/
|
2003-06-04 03:07:47 +00:00
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
nodename = mxmlElementGetAttr(node, "name");
|
2003-06-04 03:07:47 +00:00
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
/*
|
|
|
|
* Delete an existing definition, if one exists...
|
|
|
|
*/
|
2003-06-04 03:07:47 +00:00
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
if ((temp = mxmlFindElement(tree, tree, node->value.element.name,
|
|
|
|
"name", nodename, MXML_DESCEND_FIRST)) != NULL)
|
|
|
|
mxmlDelete(temp);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Insert the node into the tree...
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (temp = tree->child; temp; temp = temp->next)
|
|
|
|
{
|
|
|
|
if ((tempname = mxmlElementGetAttr(temp, "name")) == NULL)
|
|
|
|
continue;
|
2003-06-04 03:07:47 +00:00
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
if (strcmp(nodename, tempname) > 0)
|
2003-06-04 03:07:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
if (temp)
|
2003-06-04 03:07:47 +00:00
|
|
|
{
|
|
|
|
/*
|
2003-06-04 16:30:40 +00:00
|
|
|
* Insert node before this temp...
|
2003-06-04 03:07:47 +00:00
|
|
|
*/
|
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
node->next = temp;
|
|
|
|
node->prev = temp->prev;
|
2003-06-04 03:07:47 +00:00
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
if (temp->prev)
|
|
|
|
temp->prev->next = node;
|
2003-06-04 03:07:47 +00:00
|
|
|
else
|
2003-06-04 16:30:40 +00:00
|
|
|
tree->child = node;
|
2003-06-04 03:07:47 +00:00
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
temp->prev = node;
|
2003-06-04 03:07:47 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
2003-06-04 16:30:40 +00:00
|
|
|
* Append node to the end...
|
2003-06-04 03:07:47 +00:00
|
|
|
*/
|
|
|
|
|
2003-06-04 16:30:40 +00:00
|
|
|
node->prev = tree->last_child;
|
2003-06-04 03:07:47 +00:00
|
|
|
|
|
|
|
if (tree->last_child)
|
2003-06-04 16:30:40 +00:00
|
|
|
tree->last_child->next = node;
|
2003-06-04 03:07:47 +00:00
|
|
|
else
|
2003-06-04 16:30:40 +00:00
|
|
|
tree->last_child = node;
|
2003-06-04 03:07:47 +00:00
|
|
|
|
|
|
|
if (!tree->child)
|
2003-06-04 16:30:40 +00:00
|
|
|
tree->child = node;
|
2003-06-04 03:07:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 'scan_file()' - Scan a source file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int /* O - 0 on success, -1 on error */
|
2003-06-04 16:30:40 +00:00
|
|
|
scan_file(const char *filename, /* I - Filename */
|
|
|
|
FILE *fp, /* I - File to scan */
|
2003-06-04 03:07:47 +00:00
|
|
|
mxml_node_t *tree) /* I - Function tree */
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2003-06-04 16:30:40 +00:00
|
|
|
* End of "$Id: mxmldoc.c,v 1.2 2003/06/04 16:30:40 mike Exp $".
|
2003-06-04 03:07:47 +00:00
|
|
|
*/
|