2003-06-04 03:07:47 +00:00
|
|
|
/*
|
2003-06-04 21:19:00 +00:00
|
|
|
* "$Id: mxmldoc.c,v 1.4 2003/06/04 21:19:00 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>
|
2003-06-04 21:19:00 +00:00
|
|
|
* <argument name="" direction="I|O|IO">
|
2003-06-04 16:30:40 +00:00
|
|
|
* <description>descriptive text</description>
|
|
|
|
* <type>type string</type>
|
2003-06-04 21:19:00 +00:00
|
|
|
* </argument>
|
2003-06-04 16:30:40 +00:00
|
|
|
* <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 int scan_file(const char *filename, FILE *fp,
|
|
|
|
mxml_node_t *doc);
|
2003-06-04 17:37:23 +00:00
|
|
|
static void sort_node(mxml_node_t *tree, mxml_node_t *func);
|
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...
|
|
|
|
*/
|
|
|
|
|
2003-06-04 17:37:23 +00:00
|
|
|
if (mxmlSaveFile(doc, fp, MXML_NO_CALLBACK))
|
2003-06-04 16:30:40 +00:00
|
|
|
{
|
|
|
|
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 21:19:00 +00:00
|
|
|
/*
|
|
|
|
* Basic states for file parser...
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define STATE_NONE 0 /* No state - whitespace, etc. */
|
|
|
|
#define STATE_PREPROCESSOR 1 /* Preprocessor directive */
|
|
|
|
#define STATE_C_COMMENT 2 /* Inside a C comment */
|
|
|
|
#define STATE_CXX_COMMENT 3 /* Inside a C++ comment */
|
|
|
|
#define STATE_STRING 4 /* Inside a string constant */
|
|
|
|
#define STATE_CHARACTER 5 /* Inside a character constant */
|
|
|
|
#define STATE_IDENTIFIER 6 /* Inside a keyword/identifier */
|
|
|
|
|
|
|
|
|
2003-06-04 03:07:47 +00:00
|
|
|
/*
|
2003-06-04 17:37:23 +00:00
|
|
|
* 'scan_file()' - Scan a source file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int /* O - 0 on success, -1 on error */
|
|
|
|
scan_file(const char *filename, /* I - Filename */
|
|
|
|
FILE *fp, /* I - File to scan */
|
|
|
|
mxml_node_t *tree) /* I - Function tree */
|
|
|
|
{
|
2003-06-04 21:19:00 +00:00
|
|
|
int state, /* Current parser state */
|
|
|
|
oldstate, /* Previous state */
|
|
|
|
oldch, /* Old character */
|
|
|
|
braces, /* Number of braces active */
|
|
|
|
parens; /* Number of active parenthesis */
|
|
|
|
int ch;
|
|
|
|
char buffer[16384],
|
|
|
|
*bufptr;
|
|
|
|
mxml_node_t *comment, /* <comment> node */
|
|
|
|
*function, /* <function> node */
|
|
|
|
*variable, /* <variable> or <argument> node */
|
|
|
|
*returnvalue, /* <returnvalue> node */
|
|
|
|
*type, /* <type> node */
|
|
|
|
*description; /* <description> node */
|
|
|
|
static const char *states[] =
|
|
|
|
{
|
|
|
|
"STATE_NONE",
|
|
|
|
"STATE_PREPROCESSOR",
|
|
|
|
"STATE_C_COMMENT",
|
|
|
|
"STATE_CXX_COMMENT",
|
|
|
|
"STATE_STRING",
|
|
|
|
"STATE_CHARACTER",
|
|
|
|
"STATE_IDENTIFIER"
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize the finite state machine...
|
|
|
|
*/
|
|
|
|
|
|
|
|
state = STATE_NONE;
|
|
|
|
braces = 0;
|
|
|
|
parens = 0;
|
|
|
|
bufptr = buffer;
|
|
|
|
|
|
|
|
comment = NULL;
|
|
|
|
function = NULL;
|
|
|
|
variable = NULL;
|
|
|
|
returnvalue = NULL;
|
|
|
|
type = NULL;
|
|
|
|
description = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read until end-of-file...
|
|
|
|
*/
|
|
|
|
|
|
|
|
while ((ch = getc(fp)) != EOF)
|
|
|
|
{
|
|
|
|
oldstate = state;
|
|
|
|
oldch = ch;
|
|
|
|
|
|
|
|
switch (state)
|
|
|
|
{
|
|
|
|
case STATE_NONE : /* No state - whitespace, etc. */
|
|
|
|
switch (ch)
|
|
|
|
{
|
|
|
|
case '/' : /* Possible C/C++ comment */
|
|
|
|
ch = getc(fp);
|
|
|
|
bufptr = buffer;
|
|
|
|
|
|
|
|
if (ch == '*')
|
|
|
|
state = STATE_C_COMMENT;
|
|
|
|
else if (ch == '/')
|
|
|
|
state = STATE_CXX_COMMENT;
|
|
|
|
else
|
|
|
|
ungetc(ch, fp);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '#' : /* Preprocessor */
|
|
|
|
state = STATE_PREPROCESSOR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '\'' : /* Character constant */
|
|
|
|
state = STATE_CHARACTER;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '\"' : /* String constant */
|
|
|
|
state = STATE_STRING;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '{' :
|
|
|
|
braces ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '}' :
|
|
|
|
if (braces > 0)
|
|
|
|
braces --;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '(' :
|
|
|
|
parens ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ')' :
|
|
|
|
if (parens > 0)
|
|
|
|
parens --;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default : /* Other */
|
|
|
|
if (isalpha(ch) || ch == '_')
|
|
|
|
{
|
|
|
|
state = STATE_IDENTIFIER;
|
|
|
|
bufptr = buffer;
|
|
|
|
*bufptr++ = ch;
|
|
|
|
}
|
|
|
|
else if (ch == '*')
|
|
|
|
{
|
|
|
|
puts("Identifier: <<< * >>>");
|
|
|
|
|
|
|
|
if (type)
|
|
|
|
mxmlNewText(type, 1, "*");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_PREPROCESSOR : /* Preprocessor directive */
|
|
|
|
if (ch == '\n')
|
|
|
|
state = STATE_NONE;
|
|
|
|
else if (ch == '\\')
|
|
|
|
getc(fp);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_C_COMMENT : /* Inside a C comment */
|
|
|
|
switch (ch)
|
|
|
|
{
|
|
|
|
case '\n' :
|
|
|
|
while ((ch = getc(fp)) != EOF)
|
|
|
|
if (ch == '*')
|
|
|
|
{
|
|
|
|
ch = getc(fp);
|
|
|
|
|
|
|
|
if (ch == '/')
|
|
|
|
{
|
|
|
|
*bufptr = '\0';
|
|
|
|
|
|
|
|
if (comment)
|
|
|
|
{
|
|
|
|
mxmlDelete(comment);
|
|
|
|
comment = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (variable)
|
|
|
|
{
|
|
|
|
description = mxmlNewElement(variable, "description");
|
|
|
|
mxmlNewText(description, 0, buffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
comment = mxmlNewText(MXML_NO_PARENT, 0, buffer);
|
|
|
|
|
|
|
|
printf("C comment: <<< %s >>>\n", buffer);
|
|
|
|
|
|
|
|
state = STATE_NONE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ungetc(ch, fp);
|
|
|
|
}
|
|
|
|
else if (ch == '\n' && bufptr < (buffer + sizeof(buffer) - 1))
|
|
|
|
*bufptr++ = ch;
|
|
|
|
else if (!isspace(ch))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (ch != EOF)
|
|
|
|
ungetc(ch, fp);
|
|
|
|
|
|
|
|
if (bufptr < (buffer + sizeof(buffer) - 1))
|
|
|
|
*bufptr++ = '\n';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '/' :
|
|
|
|
if (ch == '/' && bufptr > buffer && bufptr[-1] == '*')
|
|
|
|
{
|
|
|
|
while (bufptr > buffer &&
|
|
|
|
(bufptr[-1] == '*' || isspace(bufptr[-1])))
|
|
|
|
bufptr --;
|
|
|
|
*bufptr = '\0';
|
|
|
|
|
|
|
|
if (comment)
|
|
|
|
{
|
|
|
|
mxmlDelete(comment);
|
|
|
|
comment = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (variable)
|
|
|
|
{
|
|
|
|
description = mxmlNewElement(variable, "description");
|
|
|
|
mxmlNewText(description, 0, buffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
comment = mxmlNewText(MXML_NO_PARENT, 0, buffer);
|
|
|
|
|
|
|
|
printf("C comment: <<< %s >>>\n", buffer);
|
|
|
|
|
|
|
|
state = STATE_NONE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default :
|
|
|
|
if (ch == ' ' && bufptr == buffer)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (bufptr < (buffer + sizeof(buffer) - 1))
|
|
|
|
*bufptr++ = ch;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_CXX_COMMENT : /* Inside a C++ comment */
|
|
|
|
if (ch == '\n')
|
|
|
|
{
|
|
|
|
*bufptr = '\0';
|
|
|
|
|
|
|
|
if (comment)
|
|
|
|
{
|
|
|
|
mxmlDelete(comment);
|
|
|
|
comment = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (variable)
|
|
|
|
{
|
|
|
|
description = mxmlNewElement(variable, "description");
|
|
|
|
mxmlNewText(description, 0, buffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
comment = mxmlNewText(MXML_NO_PARENT, 0, buffer);
|
|
|
|
|
|
|
|
printf("C++ comment: <<< %s >>>\n", buffer);
|
|
|
|
}
|
|
|
|
else if (ch == ' ' && bufptr == buffer)
|
|
|
|
break;
|
|
|
|
else if (bufptr < (buffer + sizeof(buffer) - 1))
|
|
|
|
*bufptr++ = ch;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_STRING : /* Inside a string constant */
|
|
|
|
if (ch == '\\')
|
|
|
|
getc(fp);
|
|
|
|
else if (ch == '\"')
|
|
|
|
state = STATE_NONE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_CHARACTER : /* Inside a character constant */
|
|
|
|
if (ch == '\\')
|
|
|
|
getc(fp);
|
|
|
|
else if (ch == '\'')
|
|
|
|
state = STATE_NONE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_IDENTIFIER : /* Inside a keyword or identifier */
|
|
|
|
if (isalnum(ch) || ch == '_' || ch == '[' || ch == ']')
|
|
|
|
{
|
|
|
|
if (bufptr < (buffer + sizeof(buffer) - 1))
|
|
|
|
*bufptr++ = ch;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ungetc(ch, fp);
|
|
|
|
*bufptr = '\0';
|
|
|
|
printf("Identifier: <<< %s >>>\n", buffer);
|
|
|
|
|
|
|
|
if (!braces)
|
|
|
|
{
|
|
|
|
if (!type)
|
|
|
|
type = mxmlNewElement(MXML_NO_PARENT, "type");
|
|
|
|
|
|
|
|
if (!function && ch == '(')
|
|
|
|
{
|
|
|
|
function = mxmlNewElement(MXML_NO_PARENT, "function");
|
|
|
|
mxmlElementSetAttr(function, "name", buffer);
|
|
|
|
|
|
|
|
sort_node(tree, function);
|
|
|
|
|
|
|
|
returnvalue = mxmlNewElement(function, "returnvalue");
|
|
|
|
|
|
|
|
mxmlAdd(returnvalue, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, comment);
|
|
|
|
mxmlAdd(returnvalue, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
|
|
|
|
|
|
|
|
comment = NULL;
|
|
|
|
type = NULL;
|
|
|
|
}
|
|
|
|
else if (function && (ch == ')' || ch == ','))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Argument definition...
|
|
|
|
*/
|
|
|
|
|
|
|
|
variable = mxmlNewElement(function, "argument");
|
|
|
|
mxmlElementSetAttr(variable, "name", buffer);
|
|
|
|
|
|
|
|
mxmlAdd(variable, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
|
|
|
|
type = NULL;
|
|
|
|
}
|
|
|
|
else if (!function && (ch == ';' || ch == ','))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Variable definition...
|
|
|
|
*/
|
|
|
|
|
|
|
|
variable = mxmlNewElement(MXML_NO_PARENT, "variable");
|
|
|
|
mxmlElementSetAttr(variable, "name", buffer);
|
|
|
|
|
|
|
|
sort_node(tree, variable);
|
|
|
|
|
|
|
|
mxmlAdd(variable, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
|
|
|
|
type = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
mxmlNewText(type, type->child != NULL, buffer);
|
|
|
|
}
|
|
|
|
else if (type)
|
|
|
|
{
|
|
|
|
mxmlDelete(type);
|
|
|
|
type = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
state = STATE_NONE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (state != oldstate)
|
|
|
|
printf("changed states from %s to %s on receipt of character '%c'...\n",
|
|
|
|
states[oldstate], states[state], oldch);
|
|
|
|
#endif /* 0 */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* All done, return with no errors...
|
|
|
|
*/
|
|
|
|
|
|
|
|
return (0);
|
2003-06-04 17:37:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 'sort_node()' - Insert a node sorted into a tree.
|
2003-06-04 03:07:47 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
2003-06-04 17:37:23 +00:00
|
|
|
sort_node(mxml_node_t *tree, /* I - Tree to sort 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
|
|
|
/*
|
2003-06-04 17:37:23 +00:00
|
|
|
* Delete any existing definition at this level, if one exists...
|
2003-06-04 16:30:40 +00:00
|
|
|
*/
|
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);
|
|
|
|
|
|
|
|
/*
|
2003-06-04 17:37:23 +00:00
|
|
|
* Add the node into the tree at the proper place...
|
2003-06-04 16:30:40 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
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 17:37:23 +00:00
|
|
|
mxmlAdd(tree, MXML_ADD_AFTER, temp, node);
|
2003-06-04 03:07:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2003-06-04 21:19:00 +00:00
|
|
|
* End of "$Id: mxmldoc.c,v 1.4 2003/06/04 21:19:00 mike Exp $".
|
2003-06-04 03:07:47 +00:00
|
|
|
*/
|