From 0cc4b9e665847454fab072264bac5d925aedf514 Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Sat, 14 Jun 2003 22:14:17 +0000 Subject: [PATCH] Fix mxmldoc handling of comments, now getting quite usable documentation. Add additional tests to testmxml. Bump to v1.0. --- CHANGES | 8 +- documentation.html | 21 ++++-- mxml.xml | 47 ++++++------ mxmldoc.c | 155 ++++++++++++++++++++++++++++++++++++++- testmxml.c | 177 +++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 366 insertions(+), 42 deletions(-) diff --git a/CHANGES b/CHANGES index 2456a17..a5382d6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,12 +1,14 @@ -README - 06/07/2003 +README - 06/14/2003 ------------------- -CHANGES IN Mini-XML 0.94 +CHANGES IN Mini-XML 1.0 - The mxmldoc program now handles function arguments, structures, unions, enumerations, classes, and - typedefs properly. Finally some documentation... + typedefs properly. + - Documentation provided via mxmldoc and more in-line + comments in the code. CHANGES IN Mini-XML 0.93 diff --git a/documentation.html b/documentation.html index 9142a11..b141ea4 100644 --- a/documentation.html +++ b/documentation.html @@ -58,7 +58,7 @@

mxmlAdd()

-

Local functions...

+

Add a node to a tree.

Syntax

 void
@@ -165,7 +165,7 @@ mxmlFindElement(
 

Element node or NULL


mxmlLoadFile()

-

mxml_node_t *Top nodeFILE *File to read frommxml_type_tCallback functionNew nodemxml_node_t *Create a new element node.mxml_node_t *Parent nodeconst char *Name of elementNew nodemxml_node_t *Create a new integer node.mxml_node_t *Parent nodeintInteger valueNew nodemxml_node_t *Create a new opaque string.mxml_node_t *Parent nodeconst char *Opaque stringNew nodemxml_node_t *Create a new real number node.mxml_node_t *Parent nodedoubleReal number valueNew nodemxml_node_t *Create a new text fragment node.mxml_node_t *Parent nodeintLeading whitespace?const char *StringRemove a node from its parent.mxml_node_t *Node to remove0 on success, -1 on errorintSave an XML tree to a file.mxml_node_t *Node to writeFILE *File to write tointWhitespace callbackNext node or NULLmxml_node_t *Walk to the next logical node in the tree.mxml_node_t *Current nodemxml_node_t *Top nodeintDescend into tree?Previous node or NULLmxml_node_t *Walk to the previous logical node in the tree.mxml_node_t *Current nodemxml_node_t *Top nodeintDescend into tree?Data types...char *Attribute namechar *Attribute valuestruct mxml_attr_sstruct mxml_value_smxml_node_t *First child nodemxml_node_t *Last child nodemxml_node_t *Next node under same parentmxml_node_t *Parent nodemxml_node_t *Previous node under same parentmxml_type_tNode typemxml_value_tNode valuechar *Fragment stringintLeading whitespace?struct mxml_text_sNode TypeXML element with attributesInteger valueOpaque stringReal valueText fragmentAttribute ValueElement ValueText ValueNode ValueNodeC++ support...Prototypes...C++ support...End of "$Id: documentation.html,v 1.3 2003/06/07 21:27:05 mike Exp $".enum mxml_type_emxml_attr_t *Attributeschar *Name of elementintNumber of attributesunion mxml_value_umxml_element_tElementintInteger numberchar *Opaque stringdoubleReal numbermxml_text_tText fragmentmxml_node_t *Current nodemxml_node_t *Parent nodeNode typeconst char *String to writeFile to write toint(*cb)(mxml_node_t *int) intWhere valueCurrent column

+

Load a file into an XML node tree.

Syntax

 mxml_node_t *
@@ -183,7 +183,7 @@ mxmlLoadFile(
 (*cb)(mxml_node_t *)Callback function
 

Returns

-

Local functions...

+

First node


mxmlNewElement()

Create a new element node.

@@ -370,7 +370,7 @@ mxmlWalkPrev(

mxml_attr_s

-

Data types...

+

Attribute Value

Definition

 struct mxml_attr_s
@@ -388,7 +388,7 @@ struct mxml_attr_s
 


mxml_node_s

-

mxml_node_t *First child nodemxml_node_t *Last child nodemxml_node_t *Next node under same parentmxml_node_t *Parent nodemxml_node_t *Previous node under same parentmxml_type_tNode typemxml_value_tNode valuechar *Fragment stringintLeading whitespace?struct mxml_text_sNode TypeXML element with attributesInteger valueOpaque stringReal valueText fragmentAttribute ValueElement ValueText ValueNode ValueNodeC++ support...Prototypes...C++ support...End of "$Id: documentation.html,v 1.3 2003/06/07 21:27:05 mike Exp $".enum mxml_type_emxml_attr_t *Attributeschar *Name of elementintNumber of attributesunion mxml_value_umxml_element_tElementintInteger numberchar *Opaque stringdoubleReal numbermxml_text_tText fragmentmxml_node_t *Current nodemxml_node_t *Parent nodeNode typeconst char *String to writeFile to write toint(*cb)(mxml_node_t *int) intWhere valueCurrent column

+

Node

Definition

 struct mxml_node_s
@@ -416,7 +416,7 @@ struct mxml_node_s
 


mxml_text_s

-

char *Fragment stringintLeading whitespace?struct mxml_text_sNode TypeXML element with attributesInteger valueOpaque stringReal valueText fragmentAttribute ValueElement ValueText ValueNode ValueNodeC++ support...Prototypes...C++ support...End of "$Id: documentation.html,v 1.3 2003/06/07 21:27:05 mike Exp $".enum mxml_type_emxml_attr_t *Attributeschar *Name of elementintNumber of attributesunion mxml_value_umxml_element_tElementintInteger numberchar *Opaque stringdoubleReal numbermxml_text_tText fragmentmxml_node_t *Current nodemxml_node_t *Parent nodeNode typeconst char *String to writeFile to write toint(*cb)(mxml_node_t *int) intWhere valueCurrent column

+

Text Value

Definition

 struct mxml_text_s
@@ -434,7 +434,7 @@ struct mxml_text_s
 


mxml_value_s

-

mxml_attr_t *Attributeschar *Name of elementintNumber of attributesunion mxml_value_umxml_element_tElementintInteger numberchar *Opaque stringdoubleReal numbermxml_text_tText fragmentmxml_node_t *Current nodemxml_node_t *Parent nodeNode typeconst char *String to writeFile to write toint(*cb)(mxml_node_t *int) intWhere valueCurrent column

+

Element Value

Definition

 struct mxml_value_s
@@ -462,30 +462,35 @@ struct mxml_value_s
 
 

mxml_attr_t

+

Attribute Value

Definition

 typedef struct mxml_attr_s mxml_attr_t;
 

mxml_element_t

+

Element Value

Definition

 typedef struct mxml_value_s mxml_element_t;
 

mxml_text_t

+

Text Value

Definition

 typedef struct mxml_text_s mxml_text_t;
 

mxml_type_t

+

Node Type

Definition

 typedef enum mxml_type_e mxml_type_t;
 

mxml_value_t

+

Node Value

Definition

 typedef union mxml_value_u mxml_value_t;
@@ -496,7 +501,7 @@ typedef union mxml_value_u mxml_value_t;
 
 

mxml_value_u

-

mxml_element_tElementintInteger numberchar *Opaque stringdoubleReal numbermxml_text_tText fragmentmxml_node_t *Current nodemxml_node_t *Parent nodeNode typeconst char *String to writeFile to write toint(*cb)(mxml_node_t *int) intWhere valueCurrent column

+

Node Value

Definition

 struct mxml_value_u
diff --git a/mxml.xml b/mxml.xml
index 86e4970..499c8a7 100644
--- a/mxml.xml
+++ b/mxml.xml
@@ -1,6 +1,5 @@
 
-FILE *File to write toCallback function
-Local functions...Add a node to a tree.mxml_node_t *Parent node
 intWhere to add
 mxml_node_t *Child node for where
@@ -30,9 +29,10 @@ direction="I">mxml_node_t *Current node<
 const char *Attribute value, or NULL for any
 intDescend into tree?
 
-Local functions...mxml_node_t
+First nodemxml_node_t
 *
-mxml_node_t *Top node
+Load a file into an XML node tree.mxml_node_t *Top node
 FILE *File to read from
 mxml_type_tCallback function
 
@@ -90,14 +90,16 @@ name="node" direction="I">mxml_node_t *Current nodemxml_node_t *Top node
 intDescend into tree?
 
-Data types...Attribute Valuechar *Attribute name
 char *Attribute value
 
-struct mxml_attr_s
-struct mxml_value_s
-mxml_node_t
-*First child node
+Attribute Valuestruct
+mxml_attr_s
+Element Valuestruct
+mxml_value_s
+Nodemxml_node_t *First child node
 mxml_node_t *Last child node
 mxml_node_t *Next node under same parent
 mxml_node_t *Parent node
@@ -105,31 +107,32 @@ name="name">char *Attribute namemxml_type_tNode type
 mxml_value_tNode value
 
-char
-*Fragment string
+Text Valuechar *Fragment string
 intLeading whitespace?
 
-struct mxml_text_s
+Text Valuestruct
+mxml_text_s
 Node TypeXML element with attributes
 Integer value
 Opaque string
 Real value
-Text fragmentAttribute ValueElement ValueText ValueNode ValueNodeC++ support...Prototypes...C++ support...End of "$Id: mxml.xml,v 1.3 2003/06/07 21:27:05 mike Exp $".
+Text fragment
 
-enum mxml_type_e
-mxml_attr_t
-*Attributes
+Node Typeenum
+mxml_type_e
+Element Valuemxml_attr_t *Attributes
 char *Name of element
 intNumber of attributes
 
-union mxml_value_u
-mxml_element_tElement
+Node Valueunion
+mxml_value_u
+Node Valuemxml_element_tElement
 intInteger number
 char *Opaque string
 doubleReal number
 mxml_text_tText fragment
-mxml_node_t *Current node
-mxml_node_t *Parent nodeNode type
-const char *String to writeFile to write to
-int(*cb)(mxml_node_t *int) intWhere valueCurrent column
+
diff --git a/mxmldoc.c b/mxmldoc.c
index 0e558b3..57d6cec 100644
--- a/mxmldoc.c
+++ b/mxmldoc.c
@@ -1,5 +1,5 @@
 /*
- * "$Id: mxmldoc.c,v 1.10 2003/06/07 21:27:05 mike Exp $"
+ * "$Id: mxmldoc.c,v 1.11 2003/06/14 22:14:17 mike Exp $"
  *
  * Documentation generator using mini-XML, a small XML-like file parsing
  * library.
@@ -18,6 +18,16 @@
  *
  * Contents:
  *
+ *   main()                - Main entry for test program.
+ *   add_variable()        - Add a variable or argument.
+ *   scan_file()           - Scan a source file.
+ *   sort_node()           - Insert a node sorted into a tree.
+ *   update_comment()      - Update a comment node.
+ *   write_documentation() - Write HTML documentation.
+ *   write_element()       - Write an elements text nodes.
+ *   write_string()        - Write a string, quoting XHTML special chars
+ *                           as needed...
+ *   ws_cb()               - Whitespace callback for saving.
  */
 
 /*
@@ -465,7 +475,28 @@ scan_file(const char  *filename,	/* I - Filename */
 		    type = NULL;
 		  }
 
+		  if (typedefnode)
+		  {
+		   /*
+		    * Copy comment for typedef as well as class/struct/union...
+		    */
+
+		    mxmlNewText(comment, 0,
+		                comment->last_child->value.text.string);
+		    description = mxmlNewElement(typedefnode, "description");
+#ifdef DEBUG
+		    fputs("    duplicating comment for typedef...\n", stderr);
+#endif /* DEBUG */
+		    update_comment(typedefnode, comment->last_child);
+		    mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
+		            comment->last_child);
+		  }
+
 		  description = mxmlNewElement(structclass, "description");
+#ifdef DEBUG
+		  fprintf(stderr, "    adding comment to %s...\n",
+		          structclass->value.element.name);
+#endif /* DEBUG */
 		  update_comment(structclass, comment->last_child);
 		  mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
 		          comment->last_child);
@@ -522,7 +553,27 @@ scan_file(const char  *filename,	/* I - Filename */
 		    type = NULL;
 		  }
 
+		  if (typedefnode)
+		  {
+		   /*
+		    * Copy comment for typedef as well as class/struct/union...
+		    */
+
+		    mxmlNewText(comment, 0,
+		                comment->last_child->value.text.string);
+		    description = mxmlNewElement(typedefnode, "description");
+#ifdef DEBUG
+		    fputs("    duplicating comment for typedef...\n", stderr);
+#endif /* DEBUG */
+		    update_comment(typedefnode, comment->last_child);
+		    mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
+		            comment->last_child);
+		  }
+
 		  description = mxmlNewElement(enumeration, "description");
+#ifdef DEBUG
+		  fputs("    adding comment to enumeration...\n", stderr);
+#endif /* DEBUG */
 		  update_comment(enumeration, comment->last_child);
 		  mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
 		          comment->last_child);
@@ -544,6 +595,7 @@ scan_file(const char  *filename,	/* I - Filename */
 #endif /* DEBUG */
 
                 enumeration = NULL;
+		constant    = NULL;
 
 	        if (braces > 0)
 		  braces --;
@@ -649,17 +701,38 @@ scan_file(const char  *filename,	/* I - Filename */
 		      *bufptr = '\0';
 
         	      if (comment->child != comment->last_child)
+		      {
+#ifdef DEBUG
+			fprintf(stderr, "    removing comment %p, last comment %p...\n",
+				comment->child, comment->last_child);
+#endif /* DEBUG */
 			mxmlDelete(comment->child);
+#ifdef DEBUG
+			fprintf(stderr, "    new comment %p, last comment %p...\n",
+				comment->child, comment->last_child);
+#endif /* DEBUG */
+		      }
+
+#ifdef DEBUG
+                      fprintf(stderr, "    processing comment, variable=%p, constant=%p, tree=\"%s\"\n",
+		              variable, constant, tree->value.element.name);
+#endif /* DEBUG */
 
 		      if (variable)
 		      {
         		description = mxmlNewElement(variable, "description");
+#ifdef DEBUG
+			fputs("    adding comment to variable...\n", stderr);
+#endif /* DEBUG */
 			update_comment(variable,
 			               mxmlNewText(description, 0, buffer));
 		      }
 		      else if (constant)
 		      {
         		description = mxmlNewElement(constant, "description");
+#ifdef DEBUG
+		        fputs("    adding comment to constant...\n", stderr);
+#endif /* DEBUG */
 			update_comment(constant,
 			               mxmlNewText(description, 0, buffer));
 		      }
@@ -668,12 +741,24 @@ scan_file(const char  *filename,	/* I - Filename */
 			                        NULL, NULL, MXML_DESCEND_FIRST))
                       {
         		description = mxmlNewElement(tree, "description");
+#ifdef DEBUG
+			fputs("    adding comment to parent...\n", stderr);
+#endif /* DEBUG */
 			update_comment(tree,
 			               mxmlNewText(description, 0, buffer));
 		      }
 		      else
+		      {
+#ifdef DEBUG
+		        fprintf(stderr, "    before adding comment, child=%p, last_child=%p\n",
+			        comment->child, comment->last_child);
+#endif /* DEBUG */
         		mxmlNewText(comment, 0, buffer);
-
+#ifdef DEBUG
+		        fprintf(stderr, "    after adding comment, child=%p, last_child=%p\n",
+			        comment->child, comment->last_child);
+#endif /* DEBUG */
+                      }
 #ifdef DEBUG
 		      fprintf(stderr, "C comment: <<< %s >>>\n", buffer);
 #endif /* DEBUG */
@@ -706,17 +791,33 @@ scan_file(const char  *filename,	/* I - Filename */
 		  *bufptr = '\0';
 
         	  if (comment->child != comment->last_child)
+		  {
+#ifdef DEBUG
+		    fprintf(stderr, "    removing comment %p, last comment %p...\n",
+			    comment->child, comment->last_child);
+#endif /* DEBUG */
 		    mxmlDelete(comment->child);
+#ifdef DEBUG
+		    fprintf(stderr, "    new comment %p, last comment %p...\n",
+			    comment->child, comment->last_child);
+#endif /* DEBUG */
+		  }
 
 		  if (variable)
 		  {
         	    description = mxmlNewElement(variable, "description");
+#ifdef DEBUG
+		    fputs("    adding comment to variable...\n", stderr);
+#endif /* DEBUG */
 		    update_comment(variable,
 			           mxmlNewText(description, 0, buffer));
 		  }
 		  else if (constant)
 		  {
         	    description = mxmlNewElement(constant, "description");
+#ifdef DEBUG
+		    fputs("    adding comment to constant...\n", stderr);
+#endif /* DEBUG */
 		    update_comment(constant,
 			           mxmlNewText(description, 0, buffer));
 		  }
@@ -725,6 +826,9 @@ scan_file(const char  *filename,	/* I - Filename */
 			                    NULL, NULL, MXML_DESCEND_FIRST))
                   {
         	    description = mxmlNewElement(tree, "description");
+#ifdef DEBUG
+		    fputs("    adding comment to parent...\n", stderr);
+#endif /* DEBUG */
 		    update_comment(tree,
 			           mxmlNewText(description, 0, buffer));
 		  }
@@ -755,17 +859,33 @@ scan_file(const char  *filename,	/* I - Filename */
 	    *bufptr = '\0';
 
             if (comment->child != comment->last_child)
+	    {
+#ifdef DEBUG
+	      fprintf(stderr, "    removing comment %p, last comment %p...\n",
+		      comment->child, comment->last_child);
+#endif /* DEBUG */
 	      mxmlDelete(comment->child);
+#ifdef DEBUG
+	      fprintf(stderr, "    new comment %p, last comment %p...\n",
+		      comment->child, comment->last_child);
+#endif /* DEBUG */
+	    }
 
 	    if (variable)
 	    {
               description = mxmlNewElement(variable, "description");
+#ifdef DEBUG
+	      fputs("    adding comment to variable...\n", stderr);
+#endif /* DEBUG */
 	      update_comment(variable,
 			     mxmlNewText(description, 0, buffer));
 	    }
 	    else if (constant)
 	    {
               description = mxmlNewElement(constant, "description");
+#ifdef DEBUG
+	      fputs("    adding comment to constant...\n", stderr);
+#endif /* DEBUG */
 	      update_comment(constant,
 			     mxmlNewText(description, 0, buffer));
 	    }
@@ -774,6 +894,9 @@ scan_file(const char  *filename,	/* I - Filename */
 			              NULL, NULL, MXML_DESCEND_FIRST))
             {
               description = mxmlNewElement(tree, "description");
+#ifdef DEBUG
+	      fputs("    adding comment to parent...\n", stderr);
+#endif /* DEBUG */
 	      update_comment(tree,
 			     mxmlNewText(description, 0, buffer));
 	    }
@@ -858,12 +981,24 @@ scan_file(const char  *filename,	/* I - Filename */
 	        function = mxmlNewElement(MXML_NO_PARENT, "function");
 		mxmlElementSetAttr(function, "name", buffer);
 
+#ifdef DEBUG
+                fprintf(stderr, "function: %s\n", buffer);
+		fprintf(stderr, "    child = (%p) %s\n",
+		        comment->child, comment->child->value.text.string);
+		fprintf(stderr, "    last_child = (%p) %s\n",
+		        comment->last_child,
+			comment->last_child->value.text.string);
+#endif /* DEBUG */
+
                 if (!type->last_child ||
 		    strcmp(type->last_child->value.text.string, "void"))
 		{
                   returnvalue = mxmlNewElement(function, "returnvalue");
 
 		  description = mxmlNewElement(returnvalue, "description");
+#ifdef DEBUG
+		  fputs("    adding comment to returnvalue...\n", stderr);
+#endif /* DEBUG */
 		  update_comment(returnvalue, comment->last_child);
 		  mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
 		          comment->last_child);
@@ -874,6 +1009,9 @@ scan_file(const char  *filename,	/* I - Filename */
 		  mxmlDelete(type);
 
 		description = mxmlNewElement(function, "description");
+#ifdef DEBUG
+		  fputs("    adding comment to function...\n", stderr);
+#endif /* DEBUG */
 		update_comment(function, comment->last_child);
 		mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
 		        comment->last_child);
@@ -937,7 +1075,7 @@ scan_file(const char  *filename,	/* I - Filename */
 		  type        = NULL;
 		  typedefnode = NULL;
 		}
-		else
+		else if (!parens)
 		{
 		 /*
 	          * Variable definition...
@@ -1080,6 +1218,11 @@ update_comment(mxml_node_t *parent,	/* I - Parent node */
   char	*ptr;				/* Pointer into comment */
 
 
+#ifdef DEBUG
+  fprintf(stderr, "update_comment(parent=%p, comment=%p)\n",
+          parent, comment);
+#endif /* DEBUG */
+
  /*
   * Range check the input...
   */
@@ -1157,6 +1300,10 @@ update_comment(mxml_node_t *parent,	/* I - Parent node */
     *ptr = '\0';
   for (; ptr > comment->value.text.string && isspace(*ptr); ptr --)
     *ptr = '\0';
+
+#ifdef DEBUG
+  fprintf(stderr, "    updated comment = %s\n", comment->value.text.string);
+#endif /* DEBUG */
 }
 
 
@@ -1779,5 +1926,5 @@ ws_cb(mxml_node_t *node,		/* I - Element node */
 
 
 /*
- * End of "$Id: mxmldoc.c,v 1.10 2003/06/07 21:27:05 mike Exp $".
+ * End of "$Id: mxmldoc.c,v 1.11 2003/06/14 22:14:17 mike Exp $".
  */
diff --git a/testmxml.c b/testmxml.c
index 9a46e6b..b37ba58 100644
--- a/testmxml.c
+++ b/testmxml.c
@@ -1,5 +1,5 @@
 /*
- * "$Id: testmxml.c,v 1.7 2003/06/04 21:19:00 mike Exp $"
+ * "$Id: testmxml.c,v 1.8 2003/06/14 22:14:17 mike Exp $"
  *
  * Test program for mini-XML, a small XML-like file parsing library.
  *
@@ -46,9 +46,17 @@ int					/* O - Exit status */
 main(int  argc,				/* I - Number of command-line args */
      char *argv[])			/* I - Command-line args */
 {
-  FILE		*fp;			/* File to read */
-  mxml_node_t	*tree,			/* XML tree */
-		*node;			/* Node which should be in test.xml */
+  FILE			*fp;		/* File to read */
+  mxml_node_t		*tree,		/* XML tree */
+			*node;		/* Node which should be in test.xml */
+  static const char	*types[] =	/* Strings for node types */
+			{
+			  "MXML_ELEMENT",
+			  "MXML_INTEGER",
+			  "MXML_OPAQUE",
+			  "MXML_REAL",
+			  "MXML_TEXT"
+			};
 
 
  /*
@@ -61,6 +69,165 @@ main(int  argc,				/* I - Number of command-line args */
     return (1);
   }
 
+ /*
+  * Test the basic functionality...
+  */
+
+  tree = mxmlNewElement(MXML_NO_PARENT, "element");
+
+  if (!tree)
+  {
+    fputs("ERROR: No parent node in basic test!\n", stderr);
+    return (1);
+  }
+
+  if (tree->type != MXML_ELEMENT)
+  {
+    fprintf(stderr, "ERROR: Parent has type %s (%d), expected MXML_ELEMENT!\n",
+            tree->type < MXML_ELEMENT || tree->type > MXML_TEXT ?
+	        "UNKNOWN" : types[tree->type], tree->type);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (strcmp(tree->value.element.name, "element"))
+  {
+    fprintf(stderr, "ERROR: Parent value is \"%s\", expected \"element\"!\n",
+            tree->value.element.name);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  mxmlNewInteger(tree, 123);
+  mxmlNewOpaque(tree, "opaque");
+  mxmlNewReal(tree, 123.4f);
+  mxmlNewText(tree, 1, "text");
+
+  node = tree->child;
+
+  if (!node)
+  {
+    fputs("ERROR: No first child node in basic test!\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (node->type != MXML_INTEGER)
+  {
+    fprintf(stderr, "ERROR: First child has type %s (%d), expected MXML_INTEGER!\n",
+            node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
+	        "UNKNOWN" : types[node->type], node->type);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (node->value.integer != 123)
+  {
+    fprintf(stderr, "ERROR: First child value is %d, expected 123!\n",
+            node->value.integer);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  node = node->next;
+
+  if (!node)
+  {
+    fputs("ERROR: No second child node in basic test!\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (node->type != MXML_OPAQUE)
+  {
+    fprintf(stderr, "ERROR: Second child has type %s (%d), expected MXML_OPAQUE!\n",
+            node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
+	        "UNKNOWN" : types[node->type], node->type);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (!node->value.opaque || strcmp(node->value.opaque, "opaque"))
+  {
+    fprintf(stderr, "ERROR: Second child value is \"%s\", expected \"opaque\"!\n",
+            node->value.opaque ? node->value.opaque : "(null)");
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  node = node->next;
+
+  if (!node)
+  {
+    fputs("ERROR: No third child node in basic test!\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (node->type != MXML_REAL)
+  {
+    fprintf(stderr, "ERROR: Third child has type %s (%d), expected MXML_REAL!\n",
+            node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
+	        "UNKNOWN" : types[node->type], node->type);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (node->value.real != 123.4f)
+  {
+    fprintf(stderr, "ERROR: Third child value is %f, expected 123.4!\n",
+            node->value.real);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  node = node->next;
+
+  if (!node)
+  {
+    fputs("ERROR: No fourth child node in basic test!\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (node->type != MXML_TEXT)
+  {
+    fprintf(stderr, "ERROR: Fourth child has type %s (%d), expected MXML_TEXT!\n",
+            node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
+	        "UNKNOWN" : types[node->type], node->type);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (!node->value.text.whitespace ||
+      !node->value.text.string || strcmp(node->value.text.string, "text"))
+  {
+    fprintf(stderr, "ERROR: Fourth child value is %d,\"%s\", expected 1,\"text\"!\n",
+            node->value.text.whitespace,
+	    node->value.text.string ? node->value.text.string : "(null)");
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  mxmlDelete(tree->child);
+  mxmlDelete(tree->child);
+  mxmlDelete(tree->child);
+  mxmlDelete(tree->child);
+
+  if (tree->child)
+  {
+    fputs("ERROR: Child pointer not NULL after deleting all children!\n", stderr);
+    return (1);
+  }
+
+  if (tree->last_child)
+  {
+    fputs("ERROR: Last child pointer not NULL after deleting all children!\n", stderr);
+    return (1);
+  }
+
+  mxmlDelete(tree);
+
  /*
   * Open the file...
   */
@@ -212,5 +379,5 @@ whitespace_cb(mxml_node_t *node,	/* I - Element node */
 
 
 /*
- * End of "$Id: testmxml.c,v 1.7 2003/06/04 21:19:00 mike Exp $".
+ * End of "$Id: testmxml.c,v 1.8 2003/06/14 22:14:17 mike Exp $".
  */