gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r22954 - in monkey/branches/MonkeyBacktracking/monkey: . sr


From: gnunet
Subject: [GNUnet-SVN] r22954 - in monkey/branches/MonkeyBacktracking/monkey: . src src/include src/mi src/minixml src/pathologist src/util
Date: Sun, 29 Jul 2012 19:41:22 +0200

Author: safey
Date: 2012-07-29 19:41:22 +0200 (Sun, 29 Jul 2012)
New Revision: 22954

Added:
   monkey/branches/MonkeyBacktracking/monkey/src/include/monkey_common.h
   monkey/branches/MonkeyBacktracking/monkey/src/include/mxml.h
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/Makefile.am
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/config.h
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-attr.c
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-entity.c
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-file.c
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-get.c
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-index.c
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-node.c
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-private.c
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-private.h
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-search.c
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-set.c
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-string.c
   monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxmldoc.c
   
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_action.h
   monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_edb.h
   
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_xml_writer.h
   monkey/branches/MonkeyBacktracking/monkey/src/pathologist/test_pathologist.c
Removed:
   monkey/branches/MonkeyBacktracking/monkey/src/include/monkey_common.h
   monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_action.h
   monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_edb.h
   monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_xml_writer.h
Modified:
   monkey/branches/MonkeyBacktracking/monkey/configure.ac
   monkey/branches/MonkeyBacktracking/monkey/src/Makefile.am
   monkey/branches/MonkeyBacktracking/monkey/src/include/Makefile.am
   monkey/branches/MonkeyBacktracking/monkey/src/mi/Makefile.am
   monkey/branches/MonkeyBacktracking/monkey/src/pathologist/Makefile.am
   monkey/branches/MonkeyBacktracking/monkey/src/pathologist/action_api.c
   monkey/branches/MonkeyBacktracking/monkey/src/pathologist/edb_api.c
   monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist.c
   monkey/branches/MonkeyBacktracking/monkey/src/pathologist/xml_writer.c
   monkey/branches/MonkeyBacktracking/monkey/src/util/Makefile.am
Log:
Adding a test case

Modified: monkey/branches/MonkeyBacktracking/monkey/configure.ac
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/configure.ac      2012-07-29 
11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/configure.ac      2012-07-29 
17:41:22 UTC (rev 22954)
@@ -216,6 +216,7 @@
 src/Makefile
 src/include/Makefile
 src/mi/Makefile
+src/minixml/Makefile
 src/util/Makefile
 src/pathologist/Makefile
 refs/src/Makefile

Modified: monkey/branches/MonkeyBacktracking/monkey/src/Makefile.am
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/Makefile.am   2012-07-29 
11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/src/Makefile.am   2012-07-29 
17:41:22 UTC (rev 22954)
@@ -1,2 +1,2 @@
-SUBDIRS = include mi util pathologist .
+SUBDIRS = include mi util minixml pathologist .
 

Modified: monkey/branches/MonkeyBacktracking/monkey/src/include/Makefile.am
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/include/Makefile.am   
2012-07-29 11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/src/include/Makefile.am   
2012-07-29 17:41:22 UTC (rev 22954)
@@ -4,4 +4,6 @@
 
 monkeyinclude_HEADERS = \
   monkey_common.h \
-  plibc.h
+  plibc.h \
+  gdbmi.h \
+  mxml.h

Deleted: monkey/branches/MonkeyBacktracking/monkey/src/include/monkey_common.h
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/include/monkey_common.h       
2012-07-29 11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/src/include/monkey_common.h       
2012-07-29 17:41:22 UTC (rev 22954)
@@ -1,443 +0,0 @@
-/**
- * @file monkey_common.h
- * @brief commonly used definitions
- * @author Safey A.Halim
- */
-
-#ifndef MONKEY_COMMON_H
-#define MONKEY_COMMON_H
-
-#include <stdio.h>
-/**
- * Named constants for return values.
- */
-#define MONKEY_OK      1
-#define MONKEY_SYSERR -1
-#define MONKEY_YES     1
-#define MONKEY_NO      0
-
-/**
- * Use this for fatal errors that cannot be handled
- */
-#define MONKEY_assert(cond) do { if (! (cond)) { fprintf(stderr, "Assertion 
failed at %s:%d.\n", __FILE__, __LINE__); abort(); } } while(0)
-
-/**
- * Use this for fatal errors that cannot be handled
- */
-#define MONKEY_assert_at(cond, f, l) do { if (! (cond)) { fprintf(stderr, 
"Assertion failed at %s:%d.\n", f, l); abort(); } } while(0)
-
-/**
- * Use this for internal assertion violations that are
- * not fatal (can be handled) but should not occur.
- */
-#define MONKEY_break(cond)  do { if (! (cond)) { fprintf(stderr, "Assertion 
failed at %s:%d.\n", __FILE__, __LINE__); } } while(0)
-
-
-/* ******************** doubly-linked list *************** */
-/* To avoid mistakes: head->prev == tail->next == NULL     */
-
-/**
- * Insert an element at the head of a DLL. Assumes that head, tail and
- * element are structs with prev and next fields.
- *
- * @param head pointer to the head of the DLL
- * @param tail pointer to the tail of the DLL
- * @param element element to insert
- */
-#define MONKEY_CONTAINER_DLL_insert(head,tail,element) do { \
-  MONKEY_assert ( ( (element)->prev == NULL) && ((head) != (element))); \
-  MONKEY_assert ( ( (element)->next == NULL) && ((tail) != (element))); \
-  (element)->next = (head); \
-  (element)->prev = NULL; \
-  if ((tail) == NULL) \
-    (tail) = element; \
-  else \
-    (head)->prev = element; \
-  (head) = (element); } while (0)
-
-
-/**
- * Insert an element at the tail of a DLL. Assumes that head, tail and
- * element are structs with prev and next fields.
- *
- * @param head pointer to the head of the DLL
- * @param tail pointer to the tail of the DLL
- * @param element element to insert
- */
-#define MONKEY_CONTAINER_DLL_insert_tail(head,tail,element) do { \
-  MONKEY_assert ( ( (element)->prev == NULL) && ((head) != (element))); \
-  MONKEY_assert ( ( (element)->next == NULL) && ((tail) != (element))); \
-  (element)->prev = (tail); \
-  (element)->next = NULL; \
-  if ((head) == NULL) \
-    (head) = element; \
-  else \
-    (tail)->next = element; \
-  (tail) = (element); } while (0)
-
-
-/**
- * Insert an element into a DLL after the given other element.  Insert
- * at the head if the other element is NULL.
- *
- * @param head pointer to the head of the DLL
- * @param tail pointer to the tail of the DLL
- * @param other prior element, NULL for insertion at head of DLL
- * @param element element to insert
- */
-#define MONKEY_CONTAINER_DLL_insert_after(head,tail,other,element) do { \
-  MONKEY_assert ( ( (element)->prev == NULL) && ((head) != (element))); \
-  MONKEY_assert ( ( (element)->next == NULL) && ((tail) != (element))); \
-  (element)->prev = (other); \
-  if (NULL == other) \
-    { \
-      (element)->next = (head); \
-      (head) = (element); \
-    } \
-  else \
-    { \
-      (element)->next = (other)->next; \
-      (other)->next = (element); \
-    } \
-  if (NULL == (element)->next) \
-    (tail) = (element); \
-  else \
-    (element)->next->prev = (element); } while (0)
-
-
-/**
- * Insert an element into a DLL before the given other element.  Insert
- * at the tail if the other element is NULL.
- *
- * @param head pointer to the head of the DLL
- * @param tail pointer to the tail of the DLL
- * @param other prior element, NULL for insertion at head of DLL
- * @param element element to insert
- */
-#define MONKEY_CONTAINER_DLL_insert_before(head,tail,other,element) do { \
-  MONKEY_assert ( ( (element)->prev == NULL) && ((head) != (element))); \
-  MONKEY_assert ( ( (element)->next == NULL) && ((tail) != (element))); \
-  (element)->next = (other); \
-  if (NULL == other) \
-    { \
-      (element)->prev = (tail); \
-      (tail) = (element); \
-    } \
-  else \
-    { \
-      (element)->prev = (other)->prev; \
-      (other)->prev = (element); \
-    } \
-  if (NULL == (element)->prev) \
-    (head) = (element); \
-  else \
-    (element)->prev->next = (element); } while (0)
-
-
-/**
- * Remove an element from a DLL. Assumes
- * that head, tail and element are structs
- * with prev and next fields.
- *
- * @param head pointer to the head of the DLL
- * @param tail pointer to the tail of the DLL
- * @param element element to remove
- */
-#define MONKEY_CONTAINER_DLL_remove(head,tail,element) do { \
-  MONKEY_assert ( ( (element)->prev != NULL) || ((head) == (element))); \
-  MONKEY_assert ( ( (element)->next != NULL) || ((tail) == (element))); \
-  if ((element)->prev == NULL) \
-    (head) = (element)->next;  \
-  else \
-    (element)->prev->next = (element)->next; \
-  if ((element)->next == NULL) \
-    (tail) = (element)->prev;  \
-  else \
-    (element)->next->prev = (element)->prev; \
-  (element)->next = NULL; \
-  (element)->prev = NULL; } while (0)
-
-
-#define MONKEY_MIN(a,b) (((a) < (b)) ? (a) : (b))
-
-#define MONKEY_MAX(a,b) (((a) > (b)) ? (a) : (b))
-
-/* ************************* allocation functions ****************** */
-
-/**
- * Maximum allocation with MONKEY_malloc macro.
- */
-#define MONKEY_MAX_MALLOC_CHECKED (1024 * 1024 * 40)
-
-/**
- * Wrapper around malloc. Allocates size bytes of memory.
- * The memory will be zero'ed out.
- *
- * @param size the number of bytes to allocate, must be
- *        smaller than 40 MB.
- * @return pointer to size bytes of memory, never NULL (!)
- */
-#define MONKEY_malloc(size) MONKEY_xmalloc_(size, __FILE__, __LINE__)
-
-/**
- * Allocate and initialize a block of memory.
- *
- * @param buf data to initalize the block with
- * @param size the number of bytes in buf (and size of the allocation)
- * @return pointer to size bytes of memory, never NULL (!)
- */
-#define MONKEY_memdup(buf,size) MONKEY_xmemdup_(buf, size, __FILE__, __LINE__)
-
-/**
- * Wrapper around malloc. Allocates size bytes of memory.
- * The memory will be zero'ed out.
- *
- * @param size the number of bytes to allocate
- * @return pointer to size bytes of memory, NULL if we do not have enough 
memory
- */
-#define MONKEY_malloc_large(size) MONKEY_xmalloc_unchecked_(size, __FILE__, 
__LINE__)
-
-/**
- * Wrapper around realloc. Rellocates size bytes of memory.
- *
- * @param ptr the pointer to reallocate
- * @param size the number of bytes to reallocate
- * @return pointer to size bytes of memory
- */
-#define MONKEY_realloc(ptr, size) MONKEY_xrealloc_(ptr, size, __FILE__, 
__LINE__)
-
-/**
- * Wrapper around free. Frees the memory referred to by ptr.
- * Note that is is generally better to free memory that was
- * allocated with MONKEY_array_grow using MONKEY_array_grow(mem, size, 0) 
instead of MONKEY_free.
- *
- * @param ptr location where to free the memory. ptr must have
- *     been returned by MONKEY_strdup, MONKEY_strndup, MONKEY_malloc or 
MONKEY_array_grow earlier.
- */
-#define MONKEY_free(ptr) MONKEY_xfree_(ptr, __FILE__, __LINE__)
-
-/**
- * Free the memory pointed to by ptr if ptr is not NULL.
- * Equivalent to if (ptr!=null)MONKEY_free(ptr).
- *
- * @param ptr the location in memory to free
- */
-#define MONKEY_free_non_null(ptr) do { void * __x__ = ptr; if (__x__ != NULL) 
{ MONKEY_free(__x__); } } while(0)
-
-/**
- * Wrapper around MONKEY_strdup.  Makes a copy of the zero-terminated string
- * pointed to by a.
- *
- * @param a pointer to a zero-terminated string
- * @return a copy of the string including zero-termination
- */
-#define MONKEY_strdup(a) MONKEY_xstrdup_(a,__FILE__,__LINE__)
-
-/**
- * Wrapper around MONKEY_strndup.  Makes a partial copy of the string
- * pointed to by a.
- *
- * @param a pointer to a string
- * @param length of the string to duplicate
- * @return a partial copy of the string including zero-termination
- */
-#define MONKEY_strndup(a,length) MONKEY_xstrndup_(a,length,__FILE__,__LINE__)
-
-/**
- * Grow a well-typed (!) array.  This is a convenience
- * method to grow a vector <tt>arr</tt> of size <tt>size</tt>
- * to the new (target) size <tt>tsize</tt>.
- * <p>
- *
- * Example (simple, well-typed stack):
- *
- * <pre>
- * static struct foo * myVector = NULL;
- * static int myVecLen = 0;
- *
- * static void push(struct foo * elem) {
- *   MONKEY_array_grow(myVector, myVecLen, myVecLen+1);
- *   memcpy(&myVector[myVecLen-1], elem, sizeof(struct foo));
- * }
- *
- * static void pop(struct foo * elem) {
- *   if (myVecLen == 0) die();
- *   memcpy(elem, myVector[myVecLen-1], sizeof(struct foo));
- *   MONKEY_array_grow(myVector, myVecLen, myVecLen-1);
- * }
- * </pre>
- *
- * @param arr base-pointer of the vector, may be NULL if size is 0;
- *        will be updated to reflect the new address. The TYPE of
- *        arr is important since size is the number of elements and
- *        not the size in bytes
- * @param size the number of elements in the existing vector (number
- *        of elements to copy over)
- * @param tsize the target size for the resulting vector, use 0 to
- *        free the vector (then, arr will be NULL afterwards).
- */
-#define MONKEY_array_grow(arr,size,tsize) MONKEY_xgrow_((void**)&arr, 
sizeof(arr[0]), &size, tsize, __FILE__, __LINE__)
-
-/**
- * Append an element to a list (growing the
- * list by one).
- */
-#define MONKEY_array_append(arr,size,element) do { 
MONKEY_array_grow(arr,size,size+1); arr[size-1] = element; } while(0)
-
-/**
- * Like snprintf, just aborts if the buffer is of insufficient size.
- *
- * @param buf pointer to buffer that is written to
- * @param size number of bytes in buf
- * @param format format strings
- * @param ... data for format string
- * @return number of bytes written to buf or negative value on error
- */
-int
-MONKEY_snprintf (char *buf, size_t size, const char *format, ...);
-
-
-/**
- * Like asprintf, just portable.
- *
- * @param buf set to a buffer of sufficient size (allocated, caller must free)
- * @param format format string (see printf, fprintf, etc.)
- * @param ... data for format string
- * @return number of bytes in "*buf" excluding 0-termination
- */
-int
-MONKEY_asprintf (char **buf, const char *format, ...);
-
-
-/**
- * Replace all occurrences of a substring in a string
- * @param string target string
- * @param substr substring to replace
- * @param replacement substitution of the substring
- */
-char *
-MONKEY_str_replace_all ( const char *string, const char *substr, const char 
*replacement );
-
-/* ************** internal implementations, use macros above! ************** */
-
-/**
- * Allocate memory. Checks the return value, aborts if no more
- * memory is available.  Don't use MONKEY_xmalloc_ directly. Use the
- * MONKEY_malloc macro.
- * The memory will be zero'ed out.
- *
- * @param size number of bytes to allocate
- * @param filename where is this call being made (for debugging)
- * @param linenumber line where this call is being made (for debugging)
- * @return allocated memory, never NULL
- */
-void *
-MONKEY_xmalloc_ (size_t size, const char *filename, int linenumber);
-
-
-
-/**
- * Allocate and initialize memory. Checks the return value, aborts if no more
- * memory is available.  Don't use MONKEY_xmemdup_ directly. Use the
- * MONKEY_memdup macro.
- *
- * @param buf buffer to initialize from (must contain size bytes)
- * @param size number of bytes to allocate
- * @param filename where is this call being made (for debugging)
- * @param linenumber line where this call is being made (for debugging)
- * @return allocated memory, never NULL
- */
-void *
-MONKEY_xmemdup_ (const void *buf, size_t size, const char *filename,
-                 int linenumber);
-
-
-/**
- * Allocate memory.  This function does not check if the allocation
- * request is within reasonable bounds, allowing allocations larger
- * than 40 MB.  If you don't expect the possibility of very large
- * allocations, use MONKEY_malloc instead.  The memory will be zero'ed
- * out.
- *
- * @param size number of bytes to allocate
- * @param filename where is this call being made (for debugging)
- * @param linenumber line where this call is being made (for debugging)
- * @return pointer to size bytes of memory, NULL if we do not have enough 
memory
- */
-void *
-MONKEY_xmalloc_unchecked_ (size_t size, const char *filename, int linenumber);
-
-/**
- * Reallocate memory. Checks the return value, aborts if no more
- * memory is available.
- */
-void *
-MONKEY_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber);
-
-/**
- * Free memory. Merely a wrapper for the case that we
- * want to keep track of allocations.  Don't use MONKEY_xfree_
- * directly. Use the MONKEY_free macro.
- *
- * @param ptr pointer to memory to free
- * @param filename where is this call being made (for debugging)
- * @param linenumber line where this call is being made (for debugging)
- */
-void
-MONKEY_xfree_ (void *ptr, const char *filename, int linenumber);
-
-
-/**
- * Dup a string. Don't call MONKEY_xstrdup_ directly. Use the MONKEY_strdup 
macro.
- * @param str string to duplicate
- * @param filename where is this call being made (for debugging)
- * @param linenumber line where this call is being made (for debugging)
- * @return the duplicated string
- */
-char *
-MONKEY_xstrdup_ (const char *str, const char *filename, int linenumber);
-
-/**
- * Dup partially a string. Don't call MONKEY_xstrndup_ directly. Use the 
MONKEY_strndup macro.
- *
- * @param str string to duplicate
- * @param len length of the string to duplicate
- * @param filename where is this call being made (for debugging)
- * @param linenumber line where this call is being made (for debugging)
- * @return the duplicated string
- */
-char *
-MONKEY_xstrndup_ (const char *str, size_t len, const char *filename,
-                  int linenumber);
-
-/**
- * Grow an array, the new elements are zeroed out.
- * Grows old by (*oldCount-newCount)*elementSize
- * bytes and sets *oldCount to newCount.
- *
- * Don't call MONKEY_xgrow_ directly. Use the MONKEY_array_grow macro.
- *
- * @param old address of the pointer to the array
- *        *old may be NULL
- * @param elementSize the size of the elements of the array
- * @param oldCount address of the number of elements in the *old array
- * @param newCount number of elements in the new array, may be 0 (then *old 
will be NULL afterwards)
- * @param filename where is this call being made (for debugging)
- * @param linenumber line where this call is being made (for debugging)
- */
-void
-MONKEY_xgrow_ (void **old, size_t elementSize, unsigned int *oldCount,
-               unsigned int newCount, const char *filename, int linenumber);
-
-
-
-
-#if __STDC_VERSION__ < 199901L
-#if __GNUC__ >= 2
-#define __func__ __FUNCTION__
-#else
-#define __func__ "<unknown>"
-#endif
-#endif
-
-#endif /* MONKEY_COMMON_H */

Added: monkey/branches/MonkeyBacktracking/monkey/src/include/monkey_common.h
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/include/monkey_common.h       
                        (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/include/monkey_common.h       
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,443 @@
+/**
+ * @file monkey_common.h
+ * @brief commonly used definitions
+ * @author Safey A.Halim
+ */
+
+#ifndef MONKEY_COMMON_H
+#define MONKEY_COMMON_H
+
+#include <stdio.h>
+/**
+ * Named constants for return values.
+ */
+#define MONKEY_OK      1
+#define MONKEY_SYSERR -1
+#define MONKEY_YES     1
+#define MONKEY_NO      0
+
+/**
+ * Use this for fatal errors that cannot be handled
+ */
+#define MONKEY_assert(cond) do { if (! (cond)) { fprintf(stderr, "Assertion 
failed at %s:%d.\n", __FILE__, __LINE__); abort(); } } while(0)
+
+/**
+ * Use this for fatal errors that cannot be handled
+ */
+#define MONKEY_assert_at(cond, f, l) do { if (! (cond)) { fprintf(stderr, 
"Assertion failed at %s:%d.\n", f, l); abort(); } } while(0)
+
+/**
+ * Use this for internal assertion violations that are
+ * not fatal (can be handled) but should not occur.
+ */
+#define MONKEY_break(cond)  do { if (! (cond)) { fprintf(stderr, "Assertion 
failed at %s:%d.\n", __FILE__, __LINE__); } } while(0)
+
+
+/* ******************** doubly-linked list *************** */
+/* To avoid mistakes: head->prev == tail->next == NULL     */
+
+/**
+ * Insert an element at the head of a DLL. Assumes that head, tail and
+ * element are structs with prev and next fields.
+ *
+ * @param head pointer to the head of the DLL
+ * @param tail pointer to the tail of the DLL
+ * @param element element to insert
+ */
+#define MONKEY_CONTAINER_DLL_insert(head,tail,element) do { \
+  MONKEY_assert ( ( (element)->prev == NULL) && ((head) != (element))); \
+  MONKEY_assert ( ( (element)->next == NULL) && ((tail) != (element))); \
+  (element)->next = (head); \
+  (element)->prev = NULL; \
+  if ((tail) == NULL) \
+    (tail) = element; \
+  else \
+    (head)->prev = element; \
+  (head) = (element); } while (0)
+
+
+/**
+ * Insert an element at the tail of a DLL. Assumes that head, tail and
+ * element are structs with prev and next fields.
+ *
+ * @param head pointer to the head of the DLL
+ * @param tail pointer to the tail of the DLL
+ * @param element element to insert
+ */
+#define MONKEY_CONTAINER_DLL_insert_tail(head,tail,element) do { \
+  MONKEY_assert ( ( (element)->prev == NULL) && ((head) != (element))); \
+  MONKEY_assert ( ( (element)->next == NULL) && ((tail) != (element))); \
+  (element)->prev = (tail); \
+  (element)->next = NULL; \
+  if ((head) == NULL) \
+    (head) = element; \
+  else \
+    (tail)->next = element; \
+  (tail) = (element); } while (0)
+
+
+/**
+ * Insert an element into a DLL after the given other element.  Insert
+ * at the head if the other element is NULL.
+ *
+ * @param head pointer to the head of the DLL
+ * @param tail pointer to the tail of the DLL
+ * @param other prior element, NULL for insertion at head of DLL
+ * @param element element to insert
+ */
+#define MONKEY_CONTAINER_DLL_insert_after(head,tail,other,element) do { \
+  MONKEY_assert ( ( (element)->prev == NULL) && ((head) != (element))); \
+  MONKEY_assert ( ( (element)->next == NULL) && ((tail) != (element))); \
+  (element)->prev = (other); \
+  if (NULL == other) \
+    { \
+      (element)->next = (head); \
+      (head) = (element); \
+    } \
+  else \
+    { \
+      (element)->next = (other)->next; \
+      (other)->next = (element); \
+    } \
+  if (NULL == (element)->next) \
+    (tail) = (element); \
+  else \
+    (element)->next->prev = (element); } while (0)
+
+
+/**
+ * Insert an element into a DLL before the given other element.  Insert
+ * at the tail if the other element is NULL.
+ *
+ * @param head pointer to the head of the DLL
+ * @param tail pointer to the tail of the DLL
+ * @param other prior element, NULL for insertion at head of DLL
+ * @param element element to insert
+ */
+#define MONKEY_CONTAINER_DLL_insert_before(head,tail,other,element) do { \
+  MONKEY_assert ( ( (element)->prev == NULL) && ((head) != (element))); \
+  MONKEY_assert ( ( (element)->next == NULL) && ((tail) != (element))); \
+  (element)->next = (other); \
+  if (NULL == other) \
+    { \
+      (element)->prev = (tail); \
+      (tail) = (element); \
+    } \
+  else \
+    { \
+      (element)->prev = (other)->prev; \
+      (other)->prev = (element); \
+    } \
+  if (NULL == (element)->prev) \
+    (head) = (element); \
+  else \
+    (element)->prev->next = (element); } while (0)
+
+
+/**
+ * Remove an element from a DLL. Assumes
+ * that head, tail and element are structs
+ * with prev and next fields.
+ *
+ * @param head pointer to the head of the DLL
+ * @param tail pointer to the tail of the DLL
+ * @param element element to remove
+ */
+#define MONKEY_CONTAINER_DLL_remove(head,tail,element) do { \
+  MONKEY_assert ( ( (element)->prev != NULL) || ((head) == (element))); \
+  MONKEY_assert ( ( (element)->next != NULL) || ((tail) == (element))); \
+  if ((element)->prev == NULL) \
+    (head) = (element)->next;  \
+  else \
+    (element)->prev->next = (element)->next; \
+  if ((element)->next == NULL) \
+    (tail) = (element)->prev;  \
+  else \
+    (element)->next->prev = (element)->prev; \
+  (element)->next = NULL; \
+  (element)->prev = NULL; } while (0)
+
+
+#define MONKEY_MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+#define MONKEY_MAX(a,b) (((a) > (b)) ? (a) : (b))
+
+/* ************************* allocation functions ****************** */
+
+/**
+ * Maximum allocation with MONKEY_malloc macro.
+ */
+#define MONKEY_MAX_MALLOC_CHECKED (1024 * 1024 * 40)
+
+/**
+ * Wrapper around malloc. Allocates size bytes of memory.
+ * The memory will be zero'ed out.
+ *
+ * @param size the number of bytes to allocate, must be
+ *        smaller than 40 MB.
+ * @return pointer to size bytes of memory, never NULL (!)
+ */
+#define MONKEY_malloc(size) MONKEY_xmalloc_(size, __FILE__, __LINE__)
+
+/**
+ * Allocate and initialize a block of memory.
+ *
+ * @param buf data to initalize the block with
+ * @param size the number of bytes in buf (and size of the allocation)
+ * @return pointer to size bytes of memory, never NULL (!)
+ */
+#define MONKEY_memdup(buf,size) MONKEY_xmemdup_(buf, size, __FILE__, __LINE__)
+
+/**
+ * Wrapper around malloc. Allocates size bytes of memory.
+ * The memory will be zero'ed out.
+ *
+ * @param size the number of bytes to allocate
+ * @return pointer to size bytes of memory, NULL if we do not have enough 
memory
+ */
+#define MONKEY_malloc_large(size) MONKEY_xmalloc_unchecked_(size, __FILE__, 
__LINE__)
+
+/**
+ * Wrapper around realloc. Rellocates size bytes of memory.
+ *
+ * @param ptr the pointer to reallocate
+ * @param size the number of bytes to reallocate
+ * @return pointer to size bytes of memory
+ */
+#define MONKEY_realloc(ptr, size) MONKEY_xrealloc_(ptr, size, __FILE__, 
__LINE__)
+
+/**
+ * Wrapper around free. Frees the memory referred to by ptr.
+ * Note that is is generally better to free memory that was
+ * allocated with MONKEY_array_grow using MONKEY_array_grow(mem, size, 0) 
instead of MONKEY_free.
+ *
+ * @param ptr location where to free the memory. ptr must have
+ *     been returned by MONKEY_strdup, MONKEY_strndup, MONKEY_malloc or 
MONKEY_array_grow earlier.
+ */
+#define MONKEY_free(ptr) MONKEY_xfree_(ptr, __FILE__, __LINE__)
+
+/**
+ * Free the memory pointed to by ptr if ptr is not NULL.
+ * Equivalent to if (ptr!=null)MONKEY_free(ptr).
+ *
+ * @param ptr the location in memory to free
+ */
+#define MONKEY_free_non_null(ptr) do { void * __x__ = ptr; if (__x__ != NULL) 
{ MONKEY_free(__x__); } } while(0)
+
+/**
+ * Wrapper around MONKEY_strdup.  Makes a copy of the zero-terminated string
+ * pointed to by a.
+ *
+ * @param a pointer to a zero-terminated string
+ * @return a copy of the string including zero-termination
+ */
+#define MONKEY_strdup(a) MONKEY_xstrdup_(a,__FILE__,__LINE__)
+
+/**
+ * Wrapper around MONKEY_strndup.  Makes a partial copy of the string
+ * pointed to by a.
+ *
+ * @param a pointer to a string
+ * @param length of the string to duplicate
+ * @return a partial copy of the string including zero-termination
+ */
+#define MONKEY_strndup(a,length) MONKEY_xstrndup_(a,length,__FILE__,__LINE__)
+
+/**
+ * Grow a well-typed (!) array.  This is a convenience
+ * method to grow a vector <tt>arr</tt> of size <tt>size</tt>
+ * to the new (target) size <tt>tsize</tt>.
+ * <p>
+ *
+ * Example (simple, well-typed stack):
+ *
+ * <pre>
+ * static struct foo * myVector = NULL;
+ * static int myVecLen = 0;
+ *
+ * static void push(struct foo * elem) {
+ *   MONKEY_array_grow(myVector, myVecLen, myVecLen+1);
+ *   memcpy(&myVector[myVecLen-1], elem, sizeof(struct foo));
+ * }
+ *
+ * static void pop(struct foo * elem) {
+ *   if (myVecLen == 0) die();
+ *   memcpy(elem, myVector[myVecLen-1], sizeof(struct foo));
+ *   MONKEY_array_grow(myVector, myVecLen, myVecLen-1);
+ * }
+ * </pre>
+ *
+ * @param arr base-pointer of the vector, may be NULL if size is 0;
+ *        will be updated to reflect the new address. The TYPE of
+ *        arr is important since size is the number of elements and
+ *        not the size in bytes
+ * @param size the number of elements in the existing vector (number
+ *        of elements to copy over)
+ * @param tsize the target size for the resulting vector, use 0 to
+ *        free the vector (then, arr will be NULL afterwards).
+ */
+#define MONKEY_array_grow(arr,size,tsize) MONKEY_xgrow_((void**)&arr, 
sizeof(arr[0]), &size, tsize, __FILE__, __LINE__)
+
+/**
+ * Append an element to a list (growing the
+ * list by one).
+ */
+#define MONKEY_array_append(arr,size,element) do { 
MONKEY_array_grow(arr,size,size+1); arr[size-1] = element; } while(0)
+
+/**
+ * Like snprintf, just aborts if the buffer is of insufficient size.
+ *
+ * @param buf pointer to buffer that is written to
+ * @param size number of bytes in buf
+ * @param format format strings
+ * @param ... data for format string
+ * @return number of bytes written to buf or negative value on error
+ */
+int
+MONKEY_snprintf (char *buf, size_t size, const char *format, ...);
+
+
+/**
+ * Like asprintf, just portable.
+ *
+ * @param buf set to a buffer of sufficient size (allocated, caller must free)
+ * @param format format string (see printf, fprintf, etc.)
+ * @param ... data for format string
+ * @return number of bytes in "*buf" excluding 0-termination
+ */
+int
+MONKEY_asprintf (char **buf, const char *format, ...);
+
+
+/**
+ * Replace all occurrences of a substring in a string
+ * @param string target string
+ * @param substr substring to replace
+ * @param replacement substitution of the substring
+ */
+char *
+MONKEY_str_replace_all ( const char *string, const char *substr, const char 
*replacement );
+
+/* ************** internal implementations, use macros above! ************** */
+
+/**
+ * Allocate memory. Checks the return value, aborts if no more
+ * memory is available.  Don't use MONKEY_xmalloc_ directly. Use the
+ * MONKEY_malloc macro.
+ * The memory will be zero'ed out.
+ *
+ * @param size number of bytes to allocate
+ * @param filename where is this call being made (for debugging)
+ * @param linenumber line where this call is being made (for debugging)
+ * @return allocated memory, never NULL
+ */
+void *
+MONKEY_xmalloc_ (size_t size, const char *filename, int linenumber);
+
+
+
+/**
+ * Allocate and initialize memory. Checks the return value, aborts if no more
+ * memory is available.  Don't use MONKEY_xmemdup_ directly. Use the
+ * MONKEY_memdup macro.
+ *
+ * @param buf buffer to initialize from (must contain size bytes)
+ * @param size number of bytes to allocate
+ * @param filename where is this call being made (for debugging)
+ * @param linenumber line where this call is being made (for debugging)
+ * @return allocated memory, never NULL
+ */
+void *
+MONKEY_xmemdup_ (const void *buf, size_t size, const char *filename,
+                 int linenumber);
+
+
+/**
+ * Allocate memory.  This function does not check if the allocation
+ * request is within reasonable bounds, allowing allocations larger
+ * than 40 MB.  If you don't expect the possibility of very large
+ * allocations, use MONKEY_malloc instead.  The memory will be zero'ed
+ * out.
+ *
+ * @param size number of bytes to allocate
+ * @param filename where is this call being made (for debugging)
+ * @param linenumber line where this call is being made (for debugging)
+ * @return pointer to size bytes of memory, NULL if we do not have enough 
memory
+ */
+void *
+MONKEY_xmalloc_unchecked_ (size_t size, const char *filename, int linenumber);
+
+/**
+ * Reallocate memory. Checks the return value, aborts if no more
+ * memory is available.
+ */
+void *
+MONKEY_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber);
+
+/**
+ * Free memory. Merely a wrapper for the case that we
+ * want to keep track of allocations.  Don't use MONKEY_xfree_
+ * directly. Use the MONKEY_free macro.
+ *
+ * @param ptr pointer to memory to free
+ * @param filename where is this call being made (for debugging)
+ * @param linenumber line where this call is being made (for debugging)
+ */
+void
+MONKEY_xfree_ (void *ptr, const char *filename, int linenumber);
+
+
+/**
+ * Dup a string. Don't call MONKEY_xstrdup_ directly. Use the MONKEY_strdup 
macro.
+ * @param str string to duplicate
+ * @param filename where is this call being made (for debugging)
+ * @param linenumber line where this call is being made (for debugging)
+ * @return the duplicated string
+ */
+char *
+MONKEY_xstrdup_ (const char *str, const char *filename, int linenumber);
+
+/**
+ * Dup partially a string. Don't call MONKEY_xstrndup_ directly. Use the 
MONKEY_strndup macro.
+ *
+ * @param str string to duplicate
+ * @param len length of the string to duplicate
+ * @param filename where is this call being made (for debugging)
+ * @param linenumber line where this call is being made (for debugging)
+ * @return the duplicated string
+ */
+char *
+MONKEY_xstrndup_ (const char *str, size_t len, const char *filename,
+                  int linenumber);
+
+/**
+ * Grow an array, the new elements are zeroed out.
+ * Grows old by (*oldCount-newCount)*elementSize
+ * bytes and sets *oldCount to newCount.
+ *
+ * Don't call MONKEY_xgrow_ directly. Use the MONKEY_array_grow macro.
+ *
+ * @param old address of the pointer to the array
+ *        *old may be NULL
+ * @param elementSize the size of the elements of the array
+ * @param oldCount address of the number of elements in the *old array
+ * @param newCount number of elements in the new array, may be 0 (then *old 
will be NULL afterwards)
+ * @param filename where is this call being made (for debugging)
+ * @param linenumber line where this call is being made (for debugging)
+ */
+void
+MONKEY_xgrow_ (void **old, size_t elementSize, unsigned int *oldCount,
+               unsigned int newCount, const char *filename, int linenumber);
+
+
+
+
+#if __STDC_VERSION__ < 199901L
+#if __GNUC__ >= 2
+#define __func__ __FUNCTION__
+#else
+#define __func__ "<unknown>"
+#endif
+#endif
+
+#endif /* MONKEY_COMMON_H */

Added: monkey/branches/MonkeyBacktracking/monkey/src/include/mxml.h
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/include/mxml.h                
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/include/mxml.h        
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,329 @@
+/*
+ * "$Id: mxml.h 427 2011-01-03 02:03:29Z mike $"
+ *
+ * Header file for Mini-XML, a small XML-like file parsing library.
+ *
+ * Copyright 2003-2011 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ */
+
+/*
+ * Prevent multiple inclusion...
+ */
+
+#ifndef _mxml_h_
+#  define _mxml_h_
+
+/*
+ * Include necessary headers...
+ */
+
+#  include <stdio.h>
+#  include <stdlib.h>
+#  include <string.h>
+#  include <ctype.h>
+#  include <errno.h>
+
+
+/*
+ * Constants...
+ */
+
+#  define MXML_TAB             8       /* Tabs every N columns */
+
+#  define MXML_NO_CALLBACK     0       /* Don't use a type callback */
+#  define MXML_INTEGER_CALLBACK        mxml_integer_cb
+                                       /* Treat all data as integers */
+#  define MXML_OPAQUE_CALLBACK mxml_opaque_cb
+                                       /* Treat all data as opaque */
+#  define MXML_REAL_CALLBACK   mxml_real_cb
+                                       /* Treat all data as real numbers */
+#  define MXML_TEXT_CALLBACK   0       /* Treat all data as text */
+#  define MXML_IGNORE_CALLBACK mxml_ignore_cb
+                                       /* Ignore all non-element content */
+
+#  define MXML_NO_PARENT       0       /* No parent for the node */
+
+#  define MXML_DESCEND         1       /* Descend when finding/walking */
+#  define MXML_NO_DESCEND      0       /* Don't descend when finding/walking */
+#  define MXML_DESCEND_FIRST   -1      /* Descend for first find */
+
+#  define MXML_WS_BEFORE_OPEN  0       /* Callback for before open tag */
+#  define MXML_WS_AFTER_OPEN   1       /* Callback for after open tag */
+#  define MXML_WS_BEFORE_CLOSE 2       /* Callback for before close tag */
+#  define MXML_WS_AFTER_CLOSE  3       /* Callback for after close tag */
+
+#  define MXML_ADD_BEFORE      0       /* Add node before specified node */
+#  define MXML_ADD_AFTER       1       /* Add node after specified node */
+#  define MXML_ADD_TO_PARENT   NULL    /* Add node relative to parent */
+
+
+/*
+ * Data types...
+ */
+
+typedef enum mxml_sax_event_e          /**** SAX event type. ****/
+{
+  MXML_SAX_CDATA,                      /* CDATA node */
+  MXML_SAX_COMMENT,                    /* Comment node */
+  MXML_SAX_DATA,                       /* Data node */
+  MXML_SAX_DIRECTIVE,                  /* Processing directive node */
+  MXML_SAX_ELEMENT_CLOSE,              /* Element closed */
+  MXML_SAX_ELEMENT_OPEN                        /* Element opened */
+} mxml_sax_event_t;
+
+typedef enum mxml_type_e               /**** The XML node type. ****/
+{
+  MXML_IGNORE = -1,                    /* Ignore/throw away node @since 
Mini-XML 2.3@ */
+  MXML_ELEMENT,                                /* XML element with attributes 
*/
+  MXML_INTEGER,                                /* Integer value */
+  MXML_OPAQUE,                         /* Opaque string */
+  MXML_REAL,                           /* Real value */
+  MXML_TEXT,                           /* Text fragment */
+  MXML_CUSTOM                          /* Custom data @since Mini-XML 2.1@ */
+} mxml_type_t;
+
+typedef void (*mxml_custom_destroy_cb_t)(void *);
+                                       /**** Custom data destructor ****/
+
+typedef void (*mxml_error_cb_t)(const char *);  
+                                       /**** Error callback function ****/
+
+typedef struct mxml_attr_s             /**** An XML element attribute value. 
@private@ ****/
+{
+  char                 *name;          /* Attribute name */
+  char                 *value;         /* Attribute value */
+} mxml_attr_t;
+
+typedef struct mxml_element_s          /**** An XML element value. @private@ 
****/
+{
+  char                 *name;          /* Name of element */
+  int                  num_attrs;      /* Number of attributes */
+  mxml_attr_t          *attrs;         /* Attributes */
+} mxml_element_t;
+
+typedef struct mxml_text_s             /**** An XML text value. @private@ ****/
+{
+  int                  whitespace;     /* Leading whitespace? */
+  char                 *string;        /* Fragment string */
+} mxml_text_t;
+
+typedef struct mxml_custom_s           /**** An XML custom value. @private@ 
****/
+{
+  void                 *data;          /* Pointer to (allocated) custom data */
+  mxml_custom_destroy_cb_t destroy;    /* Pointer to destructor function */
+} mxml_custom_t;
+
+typedef union mxml_value_u             /**** An XML node value. @private@ ****/
+{
+  mxml_element_t       element;        /* Element */
+  int                  integer;        /* Integer number */
+  char                 *opaque;        /* Opaque string */
+  double               real;           /* Real number */
+  mxml_text_t          text;           /* Text fragment */
+  mxml_custom_t                custom;         /* Custom data @since Mini-XML 
2.1@ */
+} mxml_value_t;
+
+struct mxml_node_s                     /**** An XML node. @private@ ****/
+{
+  mxml_type_t          type;           /* Node type */
+  struct mxml_node_s   *next;          /* Next node under same parent */
+  struct mxml_node_s   *prev;          /* Previous node under same parent */
+  struct mxml_node_s   *parent;        /* Parent node */
+  struct mxml_node_s   *child;         /* First child node */
+  struct mxml_node_s   *last_child;    /* Last child node */
+  mxml_value_t         value;          /* Node value */
+  int                  ref_count;      /* Use count */
+  void                 *user_data;     /* User data */
+};
+
+typedef struct mxml_node_s mxml_node_t;        /**** An XML node. ****/
+
+struct mxml_index_s                     /**** An XML node index. @private@ 
****/
+{
+  char                 *attr;          /* Attribute used for indexing or NULL 
*/
+  int                  num_nodes;      /* Number of nodes in index */
+  int                  alloc_nodes;    /* Allocated nodes in index */
+  int                  cur_node;       /* Current node */
+  mxml_node_t          **nodes;        /* Node array */
+};
+
+typedef struct mxml_index_s mxml_index_t;
+                                       /**** An XML node index. ****/
+
+typedef int (*mxml_custom_load_cb_t)(mxml_node_t *, const char *);
+                                       /**** Custom data load callback 
function ****/
+
+typedef char *(*mxml_custom_save_cb_t)(mxml_node_t *);  
+                                       /**** Custom data save callback 
function ****/
+
+typedef int (*mxml_entity_cb_t)(const char *);
+                                       /**** Entity callback function */
+
+typedef mxml_type_t (*mxml_load_cb_t)(mxml_node_t *);
+                                       /**** Load callback function ****/
+
+typedef const char *(*mxml_save_cb_t)(mxml_node_t *, int);
+                                       /**** Save callback function ****/
+
+typedef void (*mxml_sax_cb_t)(mxml_node_t *, mxml_sax_event_t, void *);  
+                                       /**** SAX callback function ****/
+
+
+/*
+ * C++ support...
+ */
+
+#  ifdef __cplusplus
+extern "C" {
+#  endif /* __cplusplus */
+
+/*
+ * Prototypes...
+ */
+
+extern void            mxmlAdd(mxml_node_t *parent, int where,
+                               mxml_node_t *child, mxml_node_t *node);
+extern void            mxmlDelete(mxml_node_t *node);
+extern void            mxmlElementDeleteAttr(mxml_node_t *node,
+                                             const char *name);
+extern const char      *mxmlElementGetAttr(mxml_node_t *node, const char 
*name);
+extern void            mxmlElementSetAttr(mxml_node_t *node, const char *name,
+                                          const char *value);
+extern void            mxmlElementSetAttrf(mxml_node_t *node, const char *name,
+                                           const char *format, ...)
+#    ifdef __GNUC__
+__attribute__ ((__format__ (__printf__, 3, 4)))
+#    endif /* __GNUC__ */
+;
+extern int             mxmlEntityAddCallback(mxml_entity_cb_t cb);
+extern const char      *mxmlEntityGetName(int val);
+extern int             mxmlEntityGetValue(const char *name);
+extern void            mxmlEntityRemoveCallback(mxml_entity_cb_t cb);
+extern mxml_node_t     *mxmlFindElement(mxml_node_t *node, mxml_node_t *top,
+                                        const char *name, const char *attr,
+                                        const char *value, int descend);
+extern mxml_node_t     *mxmlFindPath(mxml_node_t *node, const char *path);
+extern const char      *mxmlGetCDATA(mxml_node_t *node);
+extern const void      *mxmlGetCustom(mxml_node_t *node);
+extern const char      *mxmlGetElement(mxml_node_t *node);
+extern mxml_node_t     *mxmlGetFirstChild(mxml_node_t *node);
+extern int             mxmlGetInteger(mxml_node_t *node);
+extern mxml_node_t     *mxmlGetLastChild(mxml_node_t *node);
+extern mxml_node_t     *mxmlGetNextSibling(mxml_node_t *node);
+extern const char      *mxmlGetOpaque(mxml_node_t *node);
+extern mxml_node_t     *mxmlGetParent(mxml_node_t *node);
+extern mxml_node_t     *mxmlGetPrevSibling(mxml_node_t *node);
+extern double          mxmlGetReal(mxml_node_t *node);
+extern int             mxmlGetRefCount(mxml_node_t *node);
+extern const char      *mxmlGetText(mxml_node_t *node, int *whitespace);
+extern mxml_type_t     mxmlGetType(mxml_node_t *node);
+extern void            *mxmlGetUserData(mxml_node_t *node);
+extern void            mxmlIndexDelete(mxml_index_t *ind);
+extern mxml_node_t     *mxmlIndexEnum(mxml_index_t *ind);
+extern mxml_node_t     *mxmlIndexFind(mxml_index_t *ind,
+                                      const char *element,
+                                      const char *value);
+extern int             mxmlIndexGetCount(mxml_index_t *ind);
+extern mxml_index_t    *mxmlIndexNew(mxml_node_t *node, const char *element,
+                                     const char *attr);
+extern mxml_node_t     *mxmlIndexReset(mxml_index_t *ind);
+extern mxml_node_t     *mxmlLoadFd(mxml_node_t *top, int fd,
+                                   mxml_type_t (*cb)(mxml_node_t *));
+extern mxml_node_t     *mxmlLoadFile(mxml_node_t *top, FILE *fp,
+                                     mxml_type_t (*cb)(mxml_node_t *));
+extern mxml_node_t     *mxmlLoadString(mxml_node_t *top, const char *s,
+                                       mxml_type_t (*cb)(mxml_node_t *));
+extern mxml_node_t     *mxmlNewCDATA(mxml_node_t *parent, const char *string);
+extern mxml_node_t     *mxmlNewCustom(mxml_node_t *parent, void *data,
+                                      mxml_custom_destroy_cb_t destroy);
+extern mxml_node_t     *mxmlNewElement(mxml_node_t *parent, const char *name);
+extern mxml_node_t     *mxmlNewInteger(mxml_node_t *parent, int integer);
+extern mxml_node_t     *mxmlNewOpaque(mxml_node_t *parent, const char *opaque);
+extern mxml_node_t     *mxmlNewReal(mxml_node_t *parent, double real);
+extern mxml_node_t     *mxmlNewText(mxml_node_t *parent, int whitespace,
+                                    const char *string);
+extern mxml_node_t     *mxmlNewTextf(mxml_node_t *parent, int whitespace,
+                                     const char *format, ...)
+#    ifdef __GNUC__
+__attribute__ ((__format__ (__printf__, 3, 4)))
+#    endif /* __GNUC__ */
+;
+extern mxml_node_t     *mxmlNewXML(const char *version);
+extern int             mxmlRelease(mxml_node_t *node);
+extern void            mxmlRemove(mxml_node_t *node);
+extern int             mxmlRetain(mxml_node_t *node);
+extern char            *mxmlSaveAllocString(mxml_node_t *node,
+                                            mxml_save_cb_t cb);
+extern int             mxmlSaveFd(mxml_node_t *node, int fd,
+                                  mxml_save_cb_t cb);
+extern int             mxmlSaveFile(mxml_node_t *node, FILE *fp,
+                                    mxml_save_cb_t cb);
+extern int             mxmlSaveString(mxml_node_t *node, char *buffer,
+                                      int bufsize, mxml_save_cb_t cb);
+extern mxml_node_t     *mxmlSAXLoadFd(mxml_node_t *top, int fd,
+                                      mxml_type_t (*cb)(mxml_node_t *),
+                                      mxml_sax_cb_t sax, void *sax_data);
+extern mxml_node_t     *mxmlSAXLoadFile(mxml_node_t *top, FILE *fp,
+                                        mxml_type_t (*cb)(mxml_node_t *),
+                                        mxml_sax_cb_t sax, void *sax_data);
+extern mxml_node_t     *mxmlSAXLoadString(mxml_node_t *top, const char *s,
+                                          mxml_type_t (*cb)(mxml_node_t *),
+                                          mxml_sax_cb_t sax, void *sax_data);
+extern int             mxmlSetCDATA(mxml_node_t *node, const char *data);
+extern int             mxmlSetCustom(mxml_node_t *node, void *data,
+                                     mxml_custom_destroy_cb_t destroy);
+extern void            mxmlSetCustomHandlers(mxml_custom_load_cb_t load,
+                                             mxml_custom_save_cb_t save);
+extern int             mxmlSetElement(mxml_node_t *node, const char *name);
+extern void            mxmlSetErrorCallback(mxml_error_cb_t cb);
+extern int             mxmlSetInteger(mxml_node_t *node, int integer);
+extern int             mxmlSetOpaque(mxml_node_t *node, const char *opaque);
+extern int             mxmlSetReal(mxml_node_t *node, double real);
+extern int             mxmlSetText(mxml_node_t *node, int whitespace,
+                                   const char *string);
+extern int             mxmlSetTextf(mxml_node_t *node, int whitespace,
+                                    const char *format, ...)
+#    ifdef __GNUC__
+__attribute__ ((__format__ (__printf__, 3, 4)))
+#    endif /* __GNUC__ */
+;
+extern int             mxmlSetUserData(mxml_node_t *node, void *data);
+extern void            mxmlSetWrapMargin(int column);
+extern mxml_node_t     *mxmlWalkNext(mxml_node_t *node, mxml_node_t *top,
+                                     int descend);
+extern mxml_node_t     *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top,
+                                     int descend);
+
+
+/*
+ * Semi-private functions...
+ */
+
+extern void            mxml_error(const char *format, ...);
+extern mxml_type_t     mxml_ignore_cb(mxml_node_t *node);
+extern mxml_type_t     mxml_integer_cb(mxml_node_t *node);
+extern mxml_type_t     mxml_opaque_cb(mxml_node_t *node);
+extern mxml_type_t     mxml_real_cb(mxml_node_t *node);
+
+
+/*
+ * C++ support...
+ */
+
+#  ifdef __cplusplus
+}
+#  endif /* __cplusplus */
+#endif /* !_mxml_h_ */
+
+
+/*
+ * End of "$Id: mxml.h 427 2011-01-03 02:03:29Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/include/mxml.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Modified: monkey/branches/MonkeyBacktracking/monkey/src/mi/Makefile.am
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/mi/Makefile.am        
2012-07-29 11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/src/mi/Makefile.am        
2012-07-29 17:41:22 UTC (rev 22954)
@@ -9,10 +9,9 @@
   XLIB = -lgcov
 endif
 
-lib_LTLIBRARIES = libmonkeymi.la
+lib_LTLIBRARIES = libmi.la
 
-libmonkeymi_la_SOURCES = \
-        gdbmi.h \
+libmi_la_SOURCES = \
         gdbmi_alloc.c \
         gdbmi_breakpoint.c \
         gdbmi_connect.c \

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/Makefile.am
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/Makefile.am           
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/Makefile.am   
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,27 @@
+INCLUDES = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include
+
+if MINGW
+ WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols 
+endif
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+  XLIB = -lgcov
+endif
+
+lib_LTLIBRARIES = libminixml.la
+
+libminixml_la_SOURCES = \
+        mxml-attr.c \
+        mxmldoc.c \
+        mxml-entity.c \
+        mxml-file.c \
+        mxml-get.c \
+        mxml-index.c \
+        mxml-node.c \
+        mxml-private.c \
+        mxml-private.h \
+        mxml-search.c \
+        mxml-set.c \
+        mxml-string.c \
+        config.h
\ No newline at end of file

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/config.h
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/config.h              
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/config.h      
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,95 @@
+/*
+ * "$Id: config.h.in 408 2010-09-19 05:26:46Z mike $"
+ *
+ * Configuration file for Mini-XML, a small XML-like file parsing library.
+ *
+ * Copyright 2003-2010 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+
+/*
+ * Version number...
+ */
+
+#define MXML_VERSION   ""
+
+
+/*
+ * Inline function support...
+ */
+
+#define inline
+
+
+/*
+ * Long long support...
+ */
+
+#undef HAVE_LONG_LONG
+
+
+/*
+ * Do we have the snprintf() and vsnprintf() functions?
+ */
+
+#undef HAVE_SNPRINTF
+#undef HAVE_VSNPRINTF
+
+
+/*
+ * Do we have the strXXX() functions?
+ */
+
+#undef HAVE_STRDUP
+
+
+/*
+ * Do we have threading support?
+ */
+
+#undef HAVE_PTHREAD_H
+
+
+/*
+ * Define prototypes for string functions as needed...
+ */
+
+#  ifndef HAVE_STRDUP
+extern char    *_mxml_strdup(const char *);
+#    define strdup _mxml_strdup
+#  endif /* !HAVE_STRDUP */
+
+extern char    *_mxml_strdupf(const char *, ...);
+extern char    *_mxml_vstrdupf(const char *, va_list);
+
+#  ifndef HAVE_SNPRINTF
+extern int     _mxml_snprintf(char *, size_t, const char *, ...);
+#    define snprintf _mxml_snprintf
+#  endif /* !HAVE_SNPRINTF */
+
+#  ifndef HAVE_VSNPRINTF
+extern int     _mxml_vsnprintf(char *, size_t, const char *, va_list);
+#    define vsnprintf _mxml_vsnprintf
+#  endif /* !HAVE_VSNPRINTF */
+
+/*
+ * End of "$Id: config.h.in 408 2010-09-19 05:26:46Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/config.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-attr.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-attr.c           
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-attr.c   
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,319 @@
+/*
+ * "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $"
+ *
+ * Attribute support code for Mini-XML, a small XML-like file parsing library.
+ *
+ * Copyright 2003-2010 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ *
+ * Contents:
+ *
+ *   mxmlElementDeleteAttr() - Delete an attribute.
+ *   mxmlElementGetAttr()    - Get an attribute.
+ *   mxmlElementSetAttr()    - Set an attribute.
+ *   mxmlElementSetAttrf()   - Set an attribute with a formatted value.
+ *   mxml_set_attr()         - Set or add an attribute name/value pair.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml.h"
+
+
+/*
+ * Local functions...
+ */
+
+static int     mxml_set_attr(mxml_node_t *node, const char *name,
+                             char *value);
+
+
+/*
+ * 'mxmlElementDeleteAttr()' - Delete an attribute.
+ *
+ * @since Mini-XML 2.4@
+ */
+
+void
+mxmlElementDeleteAttr(mxml_node_t *node,/* I - Element */
+                      const char  *name)/* I - Attribute name */
+{
+  int          i;                      /* Looping var */
+  mxml_attr_t  *attr;                  /* Cirrent attribute */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlElementDeleteAttr(node=%p, name=\"%s\")\n",
+          node, name ? name : "(null)");
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!node || node->type != MXML_ELEMENT || !name)
+    return;
+
+ /*
+  * Look for the attribute...
+  */
+
+  for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
+       i > 0;
+       i --, attr ++)
+  {
+#ifdef DEBUG
+    printf("    %s=\"%s\"\n", attr->name, attr->value);
+#endif /* DEBUG */
+
+    if (!strcmp(attr->name, name))
+    {
+     /*
+      * Delete this attribute...
+      */
+
+      free(attr->name);
+      free(attr->value);
+
+      i --;
+      if (i > 0)
+        memmove(attr, attr + 1, i * sizeof(mxml_attr_t));
+
+      node->value.element.num_attrs --;
+      return;
+    }
+  }
+}
+
+
+/*
+ * 'mxmlElementGetAttr()' - Get an attribute.
+ *
+ * This function returns NULL if the node is not an element or the
+ * named attribute does not exist.
+ */
+
+const char *                           /* O - Attribute value or NULL */
+mxmlElementGetAttr(mxml_node_t *node,  /* I - Element node */
+                   const char  *name)  /* I - Name of attribute */
+{
+  int          i;                      /* Looping var */
+  mxml_attr_t  *attr;                  /* Cirrent attribute */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlElementGetAttr(node=%p, name=\"%s\")\n",
+          node, name ? name : "(null)");
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!node || node->type != MXML_ELEMENT || !name)
+    return (NULL);
+
+ /*
+  * Look for the attribute...
+  */
+
+  for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
+       i > 0;
+       i --, attr ++)
+  {
+#ifdef DEBUG
+    printf("    %s=\"%s\"\n", attr->name, attr->value);
+#endif /* DEBUG */
+
+    if (!strcmp(attr->name, name))
+    {
+#ifdef DEBUG
+      printf("    Returning \"%s\"!\n", attr->value);
+#endif /* DEBUG */
+      return (attr->value);
+    }
+  }
+
+ /*
+  * Didn't find attribute, so return NULL...
+  */
+
+#ifdef DEBUG
+  puts("    Returning NULL!\n");
+#endif /* DEBUG */
+
+  return (NULL);
+}
+
+
+/*
+ * 'mxmlElementSetAttr()' - Set an attribute.
+ *
+ * If the named attribute already exists, the value of the attribute
+ * is replaced by the new string value. The string value is copied
+ * into the element node. This function does nothing if the node is
+ * not an element.
+ */
+
+void
+mxmlElementSetAttr(mxml_node_t *node,  /* I - Element node */
+                   const char  *name,  /* I - Name of attribute */
+                   const char  *value) /* I - Attribute value */
+{
+  char *valuec;                        /* Copy of value */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlElementSetAttr(node=%p, name=\"%s\", value=\"%s\")\n",
+          node, name ? name : "(null)", value ? value : "(null)");
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!node || node->type != MXML_ELEMENT || !name)
+    return;
+
+  if (value)
+    valuec = strdup(value);
+  else
+    valuec = NULL;
+
+  if (mxml_set_attr(node, name, valuec))
+    free(valuec);
+}
+
+
+/*
+ * 'mxmlElementSetAttrf()' - Set an attribute with a formatted value.
+ *
+ * If the named attribute already exists, the value of the attribute
+ * is replaced by the new formatted string. The formatted string value is
+ * copied into the element node. This function does nothing if the node
+ * is not an element.
+ *
+ * @since Mini-XML 2.3@
+ */
+
+void
+mxmlElementSetAttrf(mxml_node_t *node, /* I - Element node */
+                    const char  *name, /* I - Name of attribute */
+                    const char  *format,/* I - Printf-style attribute value */
+                   ...)                /* I - Additional arguments as needed */
+{
+  va_list      ap;                     /* Argument pointer */
+  char         *value;                 /* Value */
+
+
+#ifdef DEBUG
+  fprintf(stderr,
+          "mxmlElementSetAttrf(node=%p, name=\"%s\", format=\"%s\", ...)\n",
+          node, name ? name : "(null)", format ? format : "(null)");
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!node || node->type != MXML_ELEMENT || !name || !format)
+    return;
+
+ /*
+  * Format the value...
+  */
+
+  va_start(ap, format);
+  value = _mxml_vstrdupf(format, ap);
+  va_end(ap);
+
+  if (!value)
+    mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
+               name, node->value.element.name);
+  else if (mxml_set_attr(node, name, value))
+    free(value);
+}
+
+
+/*
+ * 'mxml_set_attr()' - Set or add an attribute name/value pair.
+ */
+
+static int                             /* O - 0 on success, -1 on failure */
+mxml_set_attr(mxml_node_t *node,       /* I - Element node */
+              const char  *name,       /* I - Attribute name */
+              char        *value)      /* I - Attribute value */
+{
+  int          i;                      /* Looping var */
+  mxml_attr_t  *attr;                  /* New attribute */
+
+
+ /*
+  * Look for the attribute...
+  */
+
+  for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
+       i > 0;
+       i --, attr ++)
+    if (!strcmp(attr->name, name))
+    {
+     /*
+      * Free the old value as needed...
+      */
+
+      if (attr->value)
+        free(attr->value);
+
+      attr->value = value;
+
+      return (0);
+    }
+
+ /*
+  * Add a new attribute...
+  */
+
+  if (node->value.element.num_attrs == 0)
+    attr = malloc(sizeof(mxml_attr_t));
+  else
+    attr = realloc(node->value.element.attrs,
+                   (node->value.element.num_attrs + 1) * sizeof(mxml_attr_t));
+
+  if (!attr)
+  {
+    mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
+               name, node->value.element.name);
+    return (-1);
+  }
+
+  node->value.element.attrs = attr;
+  attr += node->value.element.num_attrs;
+
+  if ((attr->name = strdup(name)) == NULL)
+  {
+    mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
+               name, node->value.element.name);
+    return (-1);
+  }
+
+  attr->value = value;
+
+  node->value.element.num_attrs ++;
+
+  return (0);
+}
+
+
+/*
+ * End of "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-attr.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-entity.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-entity.c         
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-entity.c 
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,460 @@
+/*
+ * "$Id: mxml-entity.c 408 2010-09-19 05:26:46Z mike $"
+ *
+ * Character entity support code for Mini-XML, a small XML-like
+ * file parsing library.
+ *
+ * Copyright 2003-2010 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ *
+ * Contents:
+ *
+ *   mxmlEntityAddCallback()    - Add a callback to convert entities to
+ *                                Unicode.
+ *   mxmlEntityGetName()        - Get the name that corresponds to the
+ *                                character value.
+ *   mxmlEntityGetValue()       - Get the character corresponding to a named
+ *                                entity.
+ *   mxmlEntityRemoveCallback() - Remove a callback.
+ *   _mxml_entity_cb()          - Lookup standard (X)HTML entities.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "mxml-private.h"
+
+
+/*
+ * 'mxmlEntityAddCallback()' - Add a callback to convert entities to Unicode.
+ */
+
+int                                    /* O - 0 on success, -1 on failure */
+mxmlEntityAddCallback(
+    mxml_entity_cb_t cb)               /* I - Callback function to add */
+{
+  _mxml_global_t *global = _mxml_global();
+                                       /* Global data */
+
+
+  if (global->num_entity_cbs < (int)(sizeof(global->entity_cbs) / 
sizeof(global->entity_cbs[0])))
+  {
+    global->entity_cbs[global->num_entity_cbs] = cb;
+    global->num_entity_cbs ++;
+
+    return (0);
+  }
+  else
+  {
+    mxml_error("Unable to add entity callback!");
+
+    return (-1);
+  }
+}
+
+
+/*
+ * 'mxmlEntityGetName()' - Get the name that corresponds to the character 
value.
+ *
+ * If val does not need to be represented by a named entity, NULL is returned.
+ */
+
+const char *                           /* O - Entity name or NULL */
+mxmlEntityGetName(int val)             /* I - Character value */
+{
+  switch (val)
+  {
+    case '&' :
+        return ("amp");
+
+    case '<' :
+        return ("lt");
+
+    case '>' :
+        return ("gt");
+
+    case '\"' :
+        return ("quot");
+
+    default :
+        return (NULL);
+  }
+}
+
+
+/*
+ * 'mxmlEntityGetValue()' - Get the character corresponding to a named entity.
+ *
+ * The entity name can also be a numeric constant. -1 is returned if the
+ * name is not known.
+ */
+
+int                                    /* O - Character value or -1 on error */
+mxmlEntityGetValue(const char *name)   /* I - Entity name */
+{
+  int          i;                      /* Looping var */
+  int          ch;                     /* Character value */
+  _mxml_global_t *global = _mxml_global();
+                                       /* Global data */
+
+
+  for (i = 0; i < global->num_entity_cbs; i ++)
+    if ((ch = (global->entity_cbs[i])(name)) >= 0)
+      return (ch);
+
+  return (-1);
+}
+
+
+/*
+ * 'mxmlEntityRemoveCallback()' - Remove a callback.
+ */
+
+void
+mxmlEntityRemoveCallback(
+    mxml_entity_cb_t cb)               /* I - Callback function to remove */
+{
+  int          i;                      /* Looping var */
+  _mxml_global_t *global = _mxml_global();
+                                       /* Global data */
+
+
+  for (i = 0; i < global->num_entity_cbs; i ++)
+    if (cb == global->entity_cbs[i])
+    {
+     /*
+      * Remove the callback...
+      */
+
+      global->num_entity_cbs --;
+
+      if (i < global->num_entity_cbs)
+        memmove(global->entity_cbs + i, global->entity_cbs + i + 1,
+               (global->num_entity_cbs - i) * sizeof(global->entity_cbs[0]));
+
+      return;
+    }
+}
+
+
+/*
+ * '_mxml_entity_cb()' - Lookup standard (X)HTML entities.
+ */
+
+int                                    /* O - Unicode value or -1 */
+_mxml_entity_cb(const char *name)      /* I - Entity name */
+{
+  int  diff,                           /* Difference between names */
+       current,                        /* Current entity in search */
+       first,                          /* First entity in search */
+       last;                           /* Last entity in search */
+  static const struct
+  {
+    const char *name;                  /* Entity name */
+    int                val;                    /* Character value */
+  }    entities[] =
+  {
+    { "AElig",         198 },
+    { "Aacute",                193 },
+    { "Acirc",         194 },
+    { "Agrave",                192 },
+    { "Alpha",         913 },
+    { "Aring",         197 },
+    { "Atilde",                195 },
+    { "Auml",          196 },
+    { "Beta",          914 },
+    { "Ccedil",                199 },
+    { "Chi",           935 },
+    { "Dagger",                8225 },
+    { "Delta",         916 },
+    { "Dstrok",                208 },
+    { "ETH",           208 },
+    { "Eacute",                201 },
+    { "Ecirc",         202 },
+    { "Egrave",                200 },
+    { "Epsilon",       917 },
+    { "Eta",           919 },
+    { "Euml",          203 },
+    { "Gamma",         915 },
+    { "Iacute",                205 },
+    { "Icirc",         206 },
+    { "Igrave",                204 },
+    { "Iota",          921 },
+    { "Iuml",          207 },
+    { "Kappa",         922 },
+    { "Lambda",                923 },
+    { "Mu",            924 },
+    { "Ntilde",                209 },
+    { "Nu",            925 },
+    { "OElig",         338 },
+    { "Oacute",                211 },
+    { "Ocirc",         212 },
+    { "Ograve",                210 },
+    { "Omega",         937 },
+    { "Omicron",       927 },
+    { "Oslash",                216 },
+    { "Otilde",                213 },
+    { "Ouml",          214 },
+    { "Phi",           934 },
+    { "Pi",            928 },
+    { "Prime",         8243 },
+    { "Psi",           936 },
+    { "Rho",           929 },
+    { "Scaron",                352 },
+    { "Sigma",         931 },
+    { "THORN",         222 },
+    { "Tau",           932 },
+    { "Theta",         920 },
+    { "Uacute",                218 },
+    { "Ucirc",         219 },
+    { "Ugrave",                217 },
+    { "Upsilon",       933 },
+    { "Uuml",          220 },
+    { "Xi",            926 },
+    { "Yacute",                221 },
+    { "Yuml",          376 },
+    { "Zeta",          918 },
+    { "aacute",                225 },
+    { "acirc",         226 },
+    { "acute",         180 },
+    { "aelig",         230 },
+    { "agrave",                224 },
+    { "alefsym",       8501 },
+    { "alpha",         945 },
+    { "amp",           '&' },
+    { "and",           8743 },
+    { "ang",           8736 },
+    { "apos",           '\'' },
+    { "aring",         229 },
+    { "asymp",         8776 },
+    { "atilde",                227 },
+    { "auml",          228 },
+    { "bdquo",         8222 },
+    { "beta",          946 },
+    { "brkbar",                166 },
+    { "brvbar",                166 },
+    { "bull",          8226 },
+    { "cap",           8745 },
+    { "ccedil",                231 },
+    { "cedil",         184 },
+    { "cent",          162 },
+    { "chi",           967 },
+    { "circ",          710 },
+    { "clubs",         9827 },
+    { "cong",          8773 },
+    { "copy",          169 },
+    { "crarr",         8629 },
+    { "cup",           8746 },
+    { "curren",                164 },
+    { "dArr",          8659 },
+    { "dagger",                8224 },
+    { "darr",          8595 },
+    { "deg",           176 },
+    { "delta",         948 },
+    { "diams",         9830 },
+    { "die",           168 },
+    { "divide",                247 },
+    { "eacute",                233 },
+    { "ecirc",         234 },
+    { "egrave",                232 },
+    { "empty",         8709 },
+    { "emsp",          8195 },
+    { "ensp",          8194 },
+    { "epsilon",       949 },
+    { "equiv",         8801 },
+    { "eta",           951 },
+    { "eth",           240 },
+    { "euml",          235 },
+    { "euro",          8364 },
+    { "exist",         8707 },
+    { "fnof",          402 },
+    { "forall",                8704 },
+    { "frac12",                189 },
+    { "frac14",                188 },
+    { "frac34",                190 },
+    { "frasl",         8260 },
+    { "gamma",         947 },
+    { "ge",            8805 },
+    { "gt",            '>' },
+    { "hArr",          8660 },
+    { "harr",          8596 },
+    { "hearts",                9829 },
+    { "hellip",                8230 },
+    { "hibar",         175 },
+    { "iacute",                237 },
+    { "icirc",         238 },
+    { "iexcl",         161 },
+    { "igrave",                236 },
+    { "image",         8465 },
+    { "infin",         8734 },
+    { "int",           8747 },
+    { "iota",          953 },
+    { "iquest",                191 },
+    { "isin",          8712 },
+    { "iuml",          239 },
+    { "kappa",         954 },
+    { "lArr",          8656 },
+    { "lambda",                955 },
+    { "lang",          9001 },
+    { "laquo",         171 },
+    { "larr",          8592 },
+    { "lceil",         8968 },
+    { "ldquo",         8220 },
+    { "le",            8804 },
+    { "lfloor",                8970 },
+    { "lowast",                8727 },
+    { "loz",           9674 },
+    { "lrm",           8206 },
+    { "lsaquo",                8249 },
+    { "lsquo",         8216 },
+    { "lt",            '<' },
+    { "macr",          175 },
+    { "mdash",         8212 },
+    { "micro",         181 },
+    { "middot",                183 },
+    { "minus",         8722 },
+    { "mu",            956 },
+    { "nabla",         8711 },
+    { "nbsp",          160 },
+    { "ndash",         8211 },
+    { "ne",            8800 },
+    { "ni",            8715 },
+    { "not",           172 },
+    { "notin",         8713 },
+    { "nsub",          8836 },
+    { "ntilde",                241 },
+    { "nu",            957 },
+    { "oacute",                243 },
+    { "ocirc",         244 },
+    { "oelig",         339 },
+    { "ograve",                242 },
+    { "oline",         8254 },
+    { "omega",         969 },
+    { "omicron",       959 },
+    { "oplus",         8853 },
+    { "or",            8744 },
+    { "ordf",          170 },
+    { "ordm",          186 },
+    { "oslash",                248 },
+    { "otilde",                245 },
+    { "otimes",                8855 },
+    { "ouml",          246 },
+    { "para",          182 },
+    { "part",          8706 },
+    { "permil",                8240 },
+    { "perp",          8869 },
+    { "phi",           966 },
+    { "pi",            960 },
+    { "piv",           982 },
+    { "plusmn",                177 },
+    { "pound",         163 },
+    { "prime",         8242 },
+    { "prod",          8719 },
+    { "prop",          8733 },
+    { "psi",           968 },
+    { "quot",          '\"' },
+    { "rArr",          8658 },
+    { "radic",         8730 },
+    { "rang",          9002 },
+    { "raquo",         187 },
+    { "rarr",          8594 },
+    { "rceil",         8969 },
+    { "rdquo",         8221 },
+    { "real",          8476 },
+    { "reg",           174 },
+    { "rfloor",                8971 },
+    { "rho",           961 },
+    { "rlm",           8207 },
+    { "rsaquo",                8250 },
+    { "rsquo",         8217 },
+    { "sbquo",         8218 },
+    { "scaron",                353 },
+    { "sdot",          8901 },
+    { "sect",          167 },
+    { "shy",           173 },
+    { "sigma",         963 },
+    { "sigmaf",                962 },
+    { "sim",           8764 },
+    { "spades",                9824 },
+    { "sub",           8834 },
+    { "sube",          8838 },
+    { "sum",           8721 },
+    { "sup",           8835 },
+    { "sup1",          185 },
+    { "sup2",          178 },
+    { "sup3",          179 },
+    { "supe",          8839 },
+    { "szlig",         223 },
+    { "tau",           964 },
+    { "there4",                8756 },
+    { "theta",         952 },
+    { "thetasym",      977 },
+    { "thinsp",                8201 },
+    { "thorn",         254 },
+    { "tilde",         732 },
+    { "times",         215 },
+    { "trade",         8482 },
+    { "uArr",          8657 },
+    { "uacute",                250 },
+    { "uarr",          8593 },
+    { "ucirc",         251 },
+    { "ugrave",                249 },
+    { "uml",           168 },
+    { "upsih",         978 },
+    { "upsilon",       965 },
+    { "uuml",          252 },
+    { "weierp",                8472 },
+    { "xi",            958 },
+    { "yacute",                253 },
+    { "yen",           165 },
+    { "yuml",          255 },
+    { "zeta",          950 },
+    { "zwj",           8205 },
+    { "zwnj",          8204 }
+  };
+
+
+ /*
+  * Do a binary search for the named entity...
+  */
+
+  first = 0;
+  last  = (int)(sizeof(entities) / sizeof(entities[0]) - 1);
+
+  while ((last - first) > 1)
+  {
+    current = (first + last) / 2;
+
+    if ((diff = strcmp(name, entities[current].name)) == 0)
+      return (entities[current].val);
+    else if (diff < 0)
+      last = current;
+    else
+      first = current;
+  }
+
+ /*
+  * If we get here, there is a small chance that there is still
+  * a match; check first and last...
+  */
+
+  if (!strcmp(name, entities[first].name))
+    return (entities[first].val);
+  else if (!strcmp(name, entities[last].name))
+    return (entities[last].val);
+  else
+    return (-1);
+}
+
+
+/*
+ * End of "$Id: mxml-entity.c 408 2010-09-19 05:26:46Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-entity.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-file.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-file.c           
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-file.c   
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,3080 @@
+/*
+ * "$Id: mxml-file.c 438 2011-03-24 05:47:51Z mike $"
+ *
+ * File loading code for Mini-XML, a small XML-like file parsing library.
+ *
+ * Copyright 2003-2011 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ *
+ * Contents:
+ *
+ *   mxmlLoadFd()            - Load a file descriptor into an XML node tree.
+ *   mxmlLoadFile()          - Load a file into an XML node tree.
+ *   mxmlLoadString()        - Load a string into an XML node tree.
+ *   mxmlSaveAllocString()   - Save an XML tree to an allocated string.
+ *   mxmlSaveFd()            - Save an XML tree to a file descriptor.
+ *   mxmlSaveFile()          - Save an XML tree to a file.
+ *   mxmlSaveString()        - Save an XML node tree to a string.
+ *   mxmlSAXLoadFd()         - Load a file descriptor into an XML node tree
+ *                             using a SAX callback.
+ *   mxmlSAXLoadFile()       - Load a file into an XML node tree
+ *                             using a SAX callback.
+ *   mxmlSAXLoadString()     - Load a string into an XML node tree
+ *                             using a SAX callback.
+ *   mxmlSetCustomHandlers() - Set the handling functions for custom data.
+ *   mxmlSetErrorCallback()  - Set the error message callback.
+ *   mxmlSetWrapMargin()     - Set the wrap margin when saving XML data.
+ *   mxml_add_char()         - Add a character to a buffer, expanding as 
needed.
+ *   mxml_fd_getc()          - Read a character from a file descriptor.
+ *   mxml_fd_putc()          - Write a character to a file descriptor.
+ *   mxml_fd_read()          - Read a buffer of data from a file descriptor.
+ *   mxml_fd_write()         - Write a buffer of data to a file descriptor.
+ *   mxml_file_getc()        - Get a character from a file.
+ *   mxml_file_putc()        - Write a character to a file.
+ *   mxml_get_entity()       - Get the character corresponding to an entity...
+ *   mxml_load_data()        - Load data into an XML node tree.
+ *   mxml_parse_element()    - Parse an element for any attributes...
+ *   mxml_string_getc()      - Get a character from a string.
+ *   mxml_string_putc()      - Write a character to a string.
+ *   mxml_write_name()       - Write a name string.
+ *   mxml_write_node()       - Save an XML node to a file.
+ *   mxml_write_string()     - Write a string, escaping & and < as needed.
+ *   mxml_write_ws()         - Do whitespace callback...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#ifndef WIN32
+#  include <unistd.h>
+#endif /* !WIN32 */
+#include "mxml-private.h"
+
+
+/*
+ * Character encoding...
+ */
+
+#define ENCODE_UTF8    0               /* UTF-8 */
+#define ENCODE_UTF16BE 1               /* UTF-16 Big-Endian */
+#define ENCODE_UTF16LE 2               /* UTF-16 Little-Endian */
+
+
+/*
+ * Macro to test for a bad XML character...
+ */
+
+#define mxml_bad_char(ch) ((ch) < ' ' && (ch) != '\n' && (ch) != '\r' && (ch) 
!= '\t')
+
+
+/*
+ * Types and structures...
+ */
+
+typedef int (*_mxml_getc_cb_t)(void *, int *);
+typedef int (*_mxml_putc_cb_t)(int, void *);
+
+typedef struct _mxml_fdbuf_s           /**** File descriptor buffer ****/
+{
+  int          fd;                     /* File descriptor */
+  unsigned char        *current,               /* Current position in buffer */
+               *end,                   /* End of buffer */
+               buffer[8192];           /* Character buffer */
+} _mxml_fdbuf_t;
+
+
+/*
+ * Local functions...
+ */
+
+static int             mxml_add_char(int ch, char **ptr, char **buffer,
+                                     int *bufsize);
+static int             mxml_fd_getc(void *p, int *encoding);
+static int             mxml_fd_putc(int ch, void *p);
+static int             mxml_fd_read(_mxml_fdbuf_t *buf);
+static int             mxml_fd_write(_mxml_fdbuf_t *buf);
+static int             mxml_file_getc(void *p, int *encoding);
+static int             mxml_file_putc(int ch, void *p);
+static int             mxml_get_entity(mxml_node_t *parent, void *p,
+                                       int *encoding,
+                                       _mxml_getc_cb_t getc_cb);
+static inline int      mxml_isspace(int ch)
+                       {
+                         return (ch == ' ' || ch == '\t' || ch == '\r' ||
+                                 ch == '\n');
+                       }
+static mxml_node_t     *mxml_load_data(mxml_node_t *top, void *p,
+                                       mxml_load_cb_t cb,
+                                       _mxml_getc_cb_t getc_cb,
+                                        mxml_sax_cb_t sax_cb, void *sax_data);
+static int             mxml_parse_element(mxml_node_t *node, void *p,
+                                          int *encoding,
+                                          _mxml_getc_cb_t getc_cb);
+static int             mxml_string_getc(void *p, int *encoding);
+static int             mxml_string_putc(int ch, void *p);
+static int             mxml_write_name(const char *s, void *p,
+                                       _mxml_putc_cb_t putc_cb);
+static int             mxml_write_node(mxml_node_t *node, void *p,
+                                       mxml_save_cb_t cb, int col,
+                                       _mxml_putc_cb_t putc_cb,
+                                       _mxml_global_t *global);
+static int             mxml_write_string(const char *s, void *p,
+                                         _mxml_putc_cb_t putc_cb);
+static int             mxml_write_ws(mxml_node_t *node, void *p, 
+                                     mxml_save_cb_t cb, int ws,
+                                     int col, _mxml_putc_cb_t putc_cb);
+
+
+/*
+ * 'mxmlLoadFd()' - Load a file descriptor into an XML node tree.
+ *
+ * The nodes in the specified file are added to the specified top node.
+ * If no top node is provided, the XML file MUST be well-formed with a
+ * single parent node like <?xml> for the entire file. The callback
+ * function returns the value type that should be used for child nodes.
+ * If MXML_NO_CALLBACK is specified then all child nodes will be either
+ * MXML_ELEMENT or MXML_TEXT nodes.
+ *
+ * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
+ * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
+ * child nodes of the specified type.
+ */
+
+mxml_node_t *                          /* O - First node or NULL if the file 
could not be read. */
+mxmlLoadFd(mxml_node_t    *top,                /* I - Top node */
+           int            fd,          /* I - File descriptor to read from */
+           mxml_load_cb_t cb)          /* I - Callback function or 
MXML_NO_CALLBACK */
+{
+  _mxml_fdbuf_t        buf;                    /* File descriptor buffer */
+
+
+ /*
+  * Initialize the file descriptor buffer...
+  */
+
+  buf.fd      = fd;
+  buf.current = buf.buffer;
+  buf.end     = buf.buffer;
+
+ /*
+  * Read the XML data...
+  */
+
+  return (mxml_load_data(top, &buf, cb, mxml_fd_getc, MXML_NO_CALLBACK, NULL));
+}
+
+
+/*
+ * 'mxmlLoadFile()' - Load a file into an XML node tree.
+ *
+ * The nodes in the specified file are added to the specified top node.
+ * If no top node is provided, the XML file MUST be well-formed with a
+ * single parent node like <?xml> for the entire file. The callback
+ * function returns the value type that should be used for child nodes.
+ * If MXML_NO_CALLBACK is specified then all child nodes will be either
+ * MXML_ELEMENT or MXML_TEXT nodes.
+ *
+ * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
+ * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
+ * child nodes of the specified type.
+ */
+
+mxml_node_t *                          /* O - First node or NULL if the file 
could not be read. */
+mxmlLoadFile(mxml_node_t    *top,      /* I - Top node */
+             FILE           *fp,       /* I - File to read from */
+             mxml_load_cb_t cb)                /* I - Callback function or 
MXML_NO_CALLBACK */
+{
+ /*
+  * Read the XML data...
+  */
+
+  return (mxml_load_data(top, fp, cb, mxml_file_getc, MXML_NO_CALLBACK, NULL));
+}
+
+
+/*
+ * 'mxmlLoadString()' - Load a string into an XML node tree.
+ *
+ * The nodes in the specified string are added to the specified top node.
+ * If no top node is provided, the XML string MUST be well-formed with a
+ * single parent node like <?xml> for the entire string. The callback
+ * function returns the value type that should be used for child nodes.
+ * If MXML_NO_CALLBACK is specified then all child nodes will be either
+ * MXML_ELEMENT or MXML_TEXT nodes.
+ *
+ * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
+ * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
+ * child nodes of the specified type.
+ */
+
+mxml_node_t *                          /* O - First node or NULL if the string 
has errors. */
+mxmlLoadString(mxml_node_t    *top,    /* I - Top node */
+               const char     *s,      /* I - String to load */
+               mxml_load_cb_t cb)      /* I - Callback function or 
MXML_NO_CALLBACK */
+{
+ /*
+  * Read the XML data...
+  */
+
+  return (mxml_load_data(top, (void *)&s, cb, mxml_string_getc, 
MXML_NO_CALLBACK,
+                         NULL));
+}
+
+
+/*
+ * 'mxmlSaveAllocString()' - Save an XML tree to an allocated string.
+ *
+ * This function returns a pointer to a string containing the textual
+ * representation of the XML node tree.  The string should be freed
+ * using the free() function when you are done with it.  NULL is returned
+ * if the node would produce an empty string or if the string cannot be
+ * allocated.
+ *
+ * The callback argument specifies a function that returns a whitespace
+ * string or NULL before and after each element. If MXML_NO_CALLBACK
+ * is specified, whitespace will only be added before MXML_TEXT nodes
+ * with leading whitespace and before attribute names inside opening
+ * element tags.
+ */
+
+char *                                 /* O - Allocated string or NULL */
+mxmlSaveAllocString(
+    mxml_node_t    *node,              /* I - Node to write */
+    mxml_save_cb_t cb)                 /* I - Whitespace callback or 
MXML_NO_CALLBACK */
+{
+  int  bytes;                          /* Required bytes */
+  char buffer[8192];                   /* Temporary buffer */
+  char *s;                             /* Allocated string */
+
+
+ /*
+  * Write the node to the temporary buffer...
+  */
+
+  bytes = mxmlSaveString(node, buffer, sizeof(buffer), cb);
+
+  if (bytes <= 0)
+    return (NULL);
+
+  if (bytes < (int)(sizeof(buffer) - 1))
+  {
+   /*
+    * Node fit inside the buffer, so just duplicate that string and
+    * return...
+    */
+
+    return (strdup(buffer));
+  }
+
+ /*
+  * Allocate a buffer of the required size and save the node to the
+  * new buffer...
+  */
+
+  if ((s = malloc(bytes + 1)) == NULL)
+    return (NULL);
+
+  mxmlSaveString(node, s, bytes + 1, cb);
+
+ /*
+  * Return the allocated string...
+  */
+
+  return (s);
+}
+
+
+/*
+ * 'mxmlSaveFd()' - Save an XML tree to a file descriptor.
+ *
+ * The callback argument specifies a function that returns a whitespace
+ * string or NULL before and after each element. If MXML_NO_CALLBACK
+ * is specified, whitespace will only be added before MXML_TEXT nodes
+ * with leading whitespace and before attribute names inside opening
+ * element tags.
+ */
+
+int                                    /* O - 0 on success, -1 on error. */
+mxmlSaveFd(mxml_node_t    *node,       /* I - Node to write */
+           int            fd,          /* I - File descriptor to write to */
+          mxml_save_cb_t cb)           /* I - Whitespace callback or 
MXML_NO_CALLBACK */
+{
+  int          col;                    /* Final column */
+  _mxml_fdbuf_t        buf;                    /* File descriptor buffer */
+  _mxml_global_t *global = _mxml_global();
+                                       /* Global data */
+
+
+ /*
+  * Initialize the file descriptor buffer...
+  */
+
+  buf.fd      = fd;
+  buf.current = buf.buffer;
+  buf.end     = buf.buffer + sizeof(buf.buffer);
+
+ /*
+  * Write the node...
+  */
+
+  if ((col = mxml_write_node(node, &buf, cb, 0, mxml_fd_putc, global)) < 0)
+    return (-1);
+
+  if (col > 0)
+    if (mxml_fd_putc('\n', &buf) < 0)
+      return (-1);
+
+ /*
+  * Flush and return...
+  */
+
+  return (mxml_fd_write(&buf));
+}
+
+
+/*
+ * 'mxmlSaveFile()' - Save an XML tree to a file.
+ *
+ * The callback argument specifies a function that returns a whitespace
+ * string or NULL before and after each element. If MXML_NO_CALLBACK
+ * is specified, whitespace will only be added before MXML_TEXT nodes
+ * with leading whitespace and before attribute names inside opening
+ * element tags.
+ */
+
+int                                    /* O - 0 on success, -1 on error. */
+mxmlSaveFile(mxml_node_t    *node,     /* I - Node to write */
+             FILE           *fp,       /* I - File to write to */
+            mxml_save_cb_t cb)         /* I - Whitespace callback or 
MXML_NO_CALLBACK */
+{
+  int  col;                            /* Final column */
+  _mxml_global_t *global = _mxml_global();
+                                       /* Global data */
+
+
+ /*
+  * Write the node...
+  */
+
+  if ((col = mxml_write_node(node, fp, cb, 0, mxml_file_putc, global)) < 0)
+    return (-1);
+
+  if (col > 0)
+    if (putc('\n', fp) < 0)
+      return (-1);
+
+ /*
+  * Return 0 (success)...
+  */
+
+  return (0);
+}
+
+
+/*
+ * 'mxmlSaveString()' - Save an XML node tree to a string.
+ *
+ * This function returns the total number of bytes that would be
+ * required for the string but only copies (bufsize - 1) characters
+ * into the specified buffer.
+ *
+ * The callback argument specifies a function that returns a whitespace
+ * string or NULL before and after each element. If MXML_NO_CALLBACK
+ * is specified, whitespace will only be added before MXML_TEXT nodes
+ * with leading whitespace and before attribute names inside opening
+ * element tags.
+ */
+
+int                                    /* O - Size of string */
+mxmlSaveString(mxml_node_t    *node,   /* I - Node to write */
+               char           *buffer, /* I - String buffer */
+               int            bufsize, /* I - Size of string buffer */
+               mxml_save_cb_t cb)      /* I - Whitespace callback or 
MXML_NO_CALLBACK */
+{
+  int  col;                            /* Final column */
+  char *ptr[2];                        /* Pointers for putc_cb */
+  _mxml_global_t *global = _mxml_global();
+                                       /* Global data */
+
+
+ /*
+  * Write the node...
+  */
+
+  ptr[0] = buffer;
+  ptr[1] = buffer + bufsize;
+
+  if ((col = mxml_write_node(node, ptr, cb, 0, mxml_string_putc, global)) < 0)
+    return (-1);
+
+  if (col > 0)
+    mxml_string_putc('\n', ptr);
+
+ /*
+  * Nul-terminate the buffer...
+  */
+
+  if (ptr[0] >= ptr[1])
+    buffer[bufsize - 1] = '\0';
+  else
+    ptr[0][0] = '\0';
+
+ /*
+  * Return the number of characters...
+  */
+
+  return (ptr[0] - buffer);
+}
+
+
+/*
+ * 'mxmlSAXLoadFd()' - Load a file descriptor into an XML node tree
+ *                     using a SAX callback.
+ *
+ * The nodes in the specified file are added to the specified top node.
+ * If no top node is provided, the XML file MUST be well-formed with a
+ * single parent node like <?xml> for the entire file. The callback
+ * function returns the value type that should be used for child nodes.
+ * If MXML_NO_CALLBACK is specified then all child nodes will be either
+ * MXML_ELEMENT or MXML_TEXT nodes.
+ *
+ * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
+ * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
+ * child nodes of the specified type.
+ *
+ * The SAX callback must call mxmlRetain() for any nodes that need to
+ * be kept for later use. Otherwise, nodes are deleted when the parent
+ * node is closed or after each data, comment, CDATA, or directive node.
+ *
+ * @since Mini-XML 2.3@
+ */
+
+mxml_node_t *                          /* O - First node or NULL if the file 
could not be read. */
+mxmlSAXLoadFd(mxml_node_t    *top,     /* I - Top node */
+              int            fd,       /* I - File descriptor to read from */
+              mxml_load_cb_t cb,       /* I - Callback function or 
MXML_NO_CALLBACK */
+              mxml_sax_cb_t  sax_cb,   /* I - SAX callback or MXML_NO_CALLBACK 
*/
+              void           *sax_data)        /* I - SAX user data */
+{
+  _mxml_fdbuf_t        buf;                    /* File descriptor buffer */
+
+
+ /*
+  * Initialize the file descriptor buffer...
+  */
+
+  buf.fd      = fd;
+  buf.current = buf.buffer;
+  buf.end     = buf.buffer;
+
+ /*
+  * Read the XML data...
+  */
+
+  return (mxml_load_data(top, &buf, cb, mxml_fd_getc, sax_cb, sax_data));
+}
+
+
+/*
+ * 'mxmlSAXLoadFile()' - Load a file into an XML node tree
+ *                       using a SAX callback.
+ *
+ * The nodes in the specified file are added to the specified top node.
+ * If no top node is provided, the XML file MUST be well-formed with a
+ * single parent node like <?xml> for the entire file. The callback
+ * function returns the value type that should be used for child nodes.
+ * If MXML_NO_CALLBACK is specified then all child nodes will be either
+ * MXML_ELEMENT or MXML_TEXT nodes.
+ *
+ * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
+ * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
+ * child nodes of the specified type.
+ *
+ * The SAX callback must call mxmlRetain() for any nodes that need to
+ * be kept for later use. Otherwise, nodes are deleted when the parent
+ * node is closed or after each data, comment, CDATA, or directive node.
+ *
+ * @since Mini-XML 2.3@
+ */
+
+mxml_node_t *                          /* O - First node or NULL if the file 
could not be read. */
+mxmlSAXLoadFile(
+    mxml_node_t    *top,               /* I - Top node */
+    FILE           *fp,                        /* I - File to read from */
+    mxml_load_cb_t cb,                 /* I - Callback function or 
MXML_NO_CALLBACK */
+    mxml_sax_cb_t  sax_cb,             /* I - SAX callback or MXML_NO_CALLBACK 
*/
+    void           *sax_data)          /* I - SAX user data */
+{
+ /*
+  * Read the XML data...
+  */
+
+  return (mxml_load_data(top, fp, cb, mxml_file_getc, sax_cb, sax_data));
+}
+
+
+/*
+ * 'mxmlSAXLoadString()' - Load a string into an XML node tree
+ *                         using a SAX callback.
+ *
+ * The nodes in the specified string are added to the specified top node.
+ * If no top node is provided, the XML string MUST be well-formed with a
+ * single parent node like <?xml> for the entire string. The callback
+ * function returns the value type that should be used for child nodes.
+ * If MXML_NO_CALLBACK is specified then all child nodes will be either
+ * MXML_ELEMENT or MXML_TEXT nodes.
+ *
+ * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
+ * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
+ * child nodes of the specified type.
+ *
+ * The SAX callback must call mxmlRetain() for any nodes that need to
+ * be kept for later use. Otherwise, nodes are deleted when the parent
+ * node is closed or after each data, comment, CDATA, or directive node.
+ *
+ * @since Mini-XML 2.3@
+ */
+
+mxml_node_t *                          /* O - First node or NULL if the string 
has errors. */
+mxmlSAXLoadString(
+    mxml_node_t    *top,               /* I - Top node */
+    const char     *s,                 /* I - String to load */
+    mxml_load_cb_t cb,                 /* I - Callback function or 
MXML_NO_CALLBACK */
+    mxml_sax_cb_t  sax_cb,             /* I - SAX callback or MXML_NO_CALLBACK 
*/
+    void           *sax_data)          /* I - SAX user data */
+{
+ /*
+  * Read the XML data...
+  */
+
+  return (mxml_load_data(top, (void *)&s, cb, mxml_string_getc, sax_cb, 
sax_data));
+}
+
+
+/*
+ * 'mxmlSetCustomHandlers()' - Set the handling functions for custom data.
+ *
+ * The load function accepts a node pointer and a data string and must
+ * return 0 on success and non-zero on error.
+ *
+ * The save function accepts a node pointer and must return a malloc'd
+ * string on success and NULL on error.
+ * 
+ */
+
+void
+mxmlSetCustomHandlers(
+    mxml_custom_load_cb_t load,                /* I - Load function */
+    mxml_custom_save_cb_t save)                /* I - Save function */
+{
+  _mxml_global_t *global = _mxml_global();
+                                       /* Global data */
+
+
+  global->custom_load_cb = load;
+  global->custom_save_cb = save;
+}
+
+
+/*
+ * 'mxmlSetErrorCallback()' - Set the error message callback.
+ */
+
+void
+mxmlSetErrorCallback(mxml_error_cb_t cb)/* I - Error callback function */
+{
+  _mxml_global_t *global = _mxml_global();
+                                       /* Global data */
+
+
+  global->error_cb = cb;
+}
+
+
+/*
+ * 'mxmlSetWrapMargin()' - Set the wrap margin when saving XML data.
+ *
+ * Wrapping is disabled when "column" is 0.
+ *
+ * @since Mini-XML 2.3@
+ */
+
+void
+mxmlSetWrapMargin(int column)          /* I - Column for wrapping, 0 to 
disable wrapping */
+{
+  _mxml_global_t *global = _mxml_global();
+                                       /* Global data */
+
+
+  global->wrap = column;
+}
+
+
+/*
+ * 'mxml_add_char()' - Add a character to a buffer, expanding as needed.
+ */
+
+static int                             /* O  - 0 on success, -1 on error */
+mxml_add_char(int  ch,                 /* I  - Character to add */
+              char **bufptr,           /* IO - Current position in buffer */
+             char **buffer,            /* IO - Current buffer */
+             int  *bufsize)            /* IO - Current buffer size */
+{
+  char *newbuffer;                     /* New buffer value */
+
+
+  if (*bufptr >= (*buffer + *bufsize - 4))
+  {
+   /*
+    * Increase the size of the buffer...
+    */
+
+    if (*bufsize < 1024)
+      (*bufsize) *= 2;
+    else
+      (*bufsize) += 1024;
+
+    if ((newbuffer = realloc(*buffer, *bufsize)) == NULL)
+    {
+      free(*buffer);
+
+      mxml_error("Unable to expand string buffer to %d bytes!", *bufsize);
+
+      return (-1);
+    }
+
+    *bufptr = newbuffer + (*bufptr - *buffer);
+    *buffer = newbuffer;
+  }
+
+  if (ch < 0x80)
+  {
+   /*
+    * Single byte ASCII...
+    */
+
+    *(*bufptr)++ = ch;
+  }
+  else if (ch < 0x800)
+  {
+   /*
+    * Two-byte UTF-8...
+    */
+
+    *(*bufptr)++ = 0xc0 | (ch >> 6);
+    *(*bufptr)++ = 0x80 | (ch & 0x3f);
+  }
+  else if (ch < 0x10000)
+  {
+   /*
+    * Three-byte UTF-8...
+    */
+
+    *(*bufptr)++ = 0xe0 | (ch >> 12);
+    *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
+    *(*bufptr)++ = 0x80 | (ch & 0x3f);
+  }
+  else
+  {
+   /*
+    * Four-byte UTF-8...
+    */
+
+    *(*bufptr)++ = 0xf0 | (ch >> 18);
+    *(*bufptr)++ = 0x80 | ((ch >> 12) & 0x3f);
+    *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
+    *(*bufptr)++ = 0x80 | (ch & 0x3f);
+  }
+
+  return (0);
+}
+
+
+/*
+ * 'mxml_fd_getc()' - Read a character from a file descriptor.
+ */
+
+static int                             /* O  - Character or EOF */
+mxml_fd_getc(void *p,                  /* I  - File descriptor buffer */
+             int  *encoding)           /* IO - Encoding */
+{
+  _mxml_fdbuf_t        *buf;                   /* File descriptor buffer */
+  int          ch,                     /* Current character */
+               temp;                   /* Temporary character */
+
+
+ /*
+  * Grab the next character in the buffer...
+  */
+
+  buf = (_mxml_fdbuf_t *)p;
+
+  if (buf->current >= buf->end)
+    if (mxml_fd_read(buf) < 0)
+      return (EOF);
+
+  ch = *(buf->current)++;
+
+  switch (*encoding)
+  {
+    case ENCODE_UTF8 :
+       /*
+       * Got a UTF-8 character; convert UTF-8 to Unicode and return...
+       */
+
+       if (!(ch & 0x80))
+       {
+#if DEBUG > 1
+          printf("mxml_fd_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
+#endif /* DEBUG > 1 */
+
+         if (mxml_bad_char(ch))
+         {
+           mxml_error("Bad control character 0x%02x not allowed by XML 
standard!",
+                      ch);
+           return (EOF);
+         }
+
+         return (ch);
+        }
+       else if (ch == 0xfe)
+       {
+        /*
+         * UTF-16 big-endian BOM?
+         */
+
+         if (buf->current >= buf->end)
+           if (mxml_fd_read(buf) < 0)
+             return (EOF);
+
+         ch = *(buf->current)++;
+          
+         if (ch != 0xff)
+           return (EOF);
+
+         *encoding = ENCODE_UTF16BE;
+
+         return (mxml_fd_getc(p, encoding));
+       }
+       else if (ch == 0xff)
+       {
+        /*
+         * UTF-16 little-endian BOM?
+         */
+
+         if (buf->current >= buf->end)
+           if (mxml_fd_read(buf) < 0)
+             return (EOF);
+
+         ch = *(buf->current)++;
+          
+         if (ch != 0xfe)
+           return (EOF);
+
+         *encoding = ENCODE_UTF16LE;
+
+         return (mxml_fd_getc(p, encoding));
+       }
+       else if ((ch & 0xe0) == 0xc0)
+       {
+        /*
+         * Two-byte value...
+         */
+
+         if (buf->current >= buf->end)
+           if (mxml_fd_read(buf) < 0)
+             return (EOF);
+
+         temp = *(buf->current)++;
+
+         if ((temp & 0xc0) != 0x80)
+           return (EOF);
+
+         ch = ((ch & 0x1f) << 6) | (temp & 0x3f);
+
+         if (ch < 0x80)
+         {
+           mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
+           return (EOF);
+         }
+       }
+       else if ((ch & 0xf0) == 0xe0)
+       {
+        /*
+         * Three-byte value...
+         */
+
+         if (buf->current >= buf->end)
+           if (mxml_fd_read(buf) < 0)
+             return (EOF);
+
+         temp = *(buf->current)++;
+
+         if ((temp & 0xc0) != 0x80)
+           return (EOF);
+
+         ch = ((ch & 0x0f) << 6) | (temp & 0x3f);
+
+         if (buf->current >= buf->end)
+           if (mxml_fd_read(buf) < 0)
+             return (EOF);
+
+         temp = *(buf->current)++;
+
+         if ((temp & 0xc0) != 0x80)
+           return (EOF);
+
+         ch = (ch << 6) | (temp & 0x3f);
+
+         if (ch < 0x800)
+         {
+           mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
+           return (EOF);
+         }
+
+         /*
+         * Ignore (strip) Byte Order Mark (BOM)...
+         */
+
+         if (ch == 0xfeff)
+           return (mxml_fd_getc(p, encoding));
+       }
+       else if ((ch & 0xf8) == 0xf0)
+       {
+        /*
+         * Four-byte value...
+         */
+
+         if (buf->current >= buf->end)
+           if (mxml_fd_read(buf) < 0)
+             return (EOF);
+
+         temp = *(buf->current)++;
+
+         if ((temp & 0xc0) != 0x80)
+           return (EOF);
+
+         ch = ((ch & 0x07) << 6) | (temp & 0x3f);
+
+         if (buf->current >= buf->end)
+           if (mxml_fd_read(buf) < 0)
+             return (EOF);
+
+         temp = *(buf->current)++;
+
+         if ((temp & 0xc0) != 0x80)
+           return (EOF);
+
+         ch = (ch << 6) | (temp & 0x3f);
+
+         if (buf->current >= buf->end)
+           if (mxml_fd_read(buf) < 0)
+             return (EOF);
+
+         temp = *(buf->current)++;
+
+         if ((temp & 0xc0) != 0x80)
+           return (EOF);
+
+         ch = (ch << 6) | (temp & 0x3f);
+
+         if (ch < 0x10000)
+         {
+           mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
+           return (EOF);
+         }
+       }
+       else
+         return (EOF);
+       break;
+
+    case ENCODE_UTF16BE :
+       /*
+        * Read UTF-16 big-endian char...
+       */
+
+       if (buf->current >= buf->end)
+         if (mxml_fd_read(buf) < 0)
+           return (EOF);
+
+       temp = *(buf->current)++;
+
+       ch = (ch << 8) | temp;
+
+       if (mxml_bad_char(ch))
+       {
+         mxml_error("Bad control character 0x%02x not allowed by XML 
standard!",
+                    ch);
+         return (EOF);
+       }
+        else if (ch >= 0xd800 && ch <= 0xdbff)
+       {
+        /*
+         * Multi-word UTF-16 char...
+         */
+
+          int lch;
+
+         if (buf->current >= buf->end)
+           if (mxml_fd_read(buf) < 0)
+             return (EOF);
+
+         lch = *(buf->current)++;
+
+         if (buf->current >= buf->end)
+           if (mxml_fd_read(buf) < 0)
+             return (EOF);
+
+         temp = *(buf->current)++;
+
+         lch = (lch << 8) | temp;
+
+          if (lch < 0xdc00 || lch >= 0xdfff)
+           return (EOF);
+
+          ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
+       }
+       break;
+
+    case ENCODE_UTF16LE :
+       /*
+        * Read UTF-16 little-endian char...
+       */
+
+       if (buf->current >= buf->end)
+         if (mxml_fd_read(buf) < 0)
+           return (EOF);
+
+       temp = *(buf->current)++;
+
+       ch |= (temp << 8);
+
+        if (mxml_bad_char(ch))
+       {
+         mxml_error("Bad control character 0x%02x not allowed by XML 
standard!",
+                    ch);
+         return (EOF);
+       }
+        else if (ch >= 0xd800 && ch <= 0xdbff)
+       {
+        /*
+         * Multi-word UTF-16 char...
+         */
+
+          int lch;
+
+         if (buf->current >= buf->end)
+           if (mxml_fd_read(buf) < 0)
+             return (EOF);
+
+         lch = *(buf->current)++;
+
+         if (buf->current >= buf->end)
+           if (mxml_fd_read(buf) < 0)
+             return (EOF);
+
+         temp = *(buf->current)++;
+
+         lch |= (temp << 8);
+
+          if (lch < 0xdc00 || lch >= 0xdfff)
+           return (EOF);
+
+          ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
+       }
+       break;
+  }
+
+#if DEBUG > 1
+  printf("mxml_fd_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
+#endif /* DEBUG > 1 */
+
+  return (ch);
+}
+
+
+/*
+ * 'mxml_fd_putc()' - Write a character to a file descriptor.
+ */
+
+static int                             /* O - 0 on success, -1 on error */
+mxml_fd_putc(int  ch,                  /* I - Character */
+             void *p)                  /* I - File descriptor buffer */
+{
+  _mxml_fdbuf_t        *buf;                   /* File descriptor buffer */
+
+
+ /*
+  * Flush the write buffer as needed...
+  */
+
+  buf = (_mxml_fdbuf_t *)p;
+
+  if (buf->current >= buf->end)
+    if (mxml_fd_write(buf) < 0)
+      return (-1);
+
+  *(buf->current)++ = ch;
+
+ /*
+  * Return successfully...
+  */
+
+  return (0);
+}
+
+
+/*
+ * 'mxml_fd_read()' - Read a buffer of data from a file descriptor.
+ */
+
+static int                             /* O - 0 on success, -1 on error */
+mxml_fd_read(_mxml_fdbuf_t *buf)               /* I - File descriptor buffer */
+{
+  int  bytes;                          /* Bytes read... */
+
+
+ /*
+  * Range check input...
+  */
+
+  if (!buf)
+    return (-1);
+
+ /*
+  * Read from the file descriptor...
+  */
+
+  while ((bytes = read(buf->fd, buf->buffer, sizeof(buf->buffer))) < 0)
+#ifdef EINTR
+    if (errno != EAGAIN && errno != EINTR)
+#else
+    if (errno != EAGAIN)
+#endif /* EINTR */
+      return (-1);
+
+  if (bytes == 0)
+    return (-1);
+
+ /*
+  * Update the pointers and return success...
+  */
+
+  buf->current = buf->buffer;
+  buf->end     = buf->buffer + bytes;
+
+  return (0);
+}
+
+
+/*
+ * 'mxml_fd_write()' - Write a buffer of data to a file descriptor.
+ */
+
+static int                             /* O - 0 on success, -1 on error */
+mxml_fd_write(_mxml_fdbuf_t *buf)      /* I - File descriptor buffer */
+{
+  int          bytes;                  /* Bytes written */
+  unsigned char        *ptr;                   /* Pointer into buffer */
+
+
+ /*
+  * Range check...
+  */
+
+  if (!buf)
+    return (-1);
+
+ /*
+  * Return 0 if there is nothing to write...
+  */
+
+  if (buf->current == buf->buffer)
+    return (0);
+
+ /*
+  * Loop until we have written everything...
+  */
+
+  for (ptr = buf->buffer; ptr < buf->current; ptr += bytes)
+    if ((bytes = write(buf->fd, ptr, buf->current - ptr)) < 0)
+      return (-1);
+
+ /*
+  * All done, reset pointers and return success...
+  */
+
+  buf->current = buf->buffer;
+
+  return (0);
+}
+
+
+/*
+ * 'mxml_file_getc()' - Get a character from a file.
+ */
+
+static int                             /* O  - Character or EOF */
+mxml_file_getc(void *p,                        /* I  - Pointer to file */
+               int  *encoding)         /* IO - Encoding */
+{
+  int  ch,                             /* Character from file */
+       temp;                           /* Temporary character */
+  FILE *fp;                            /* Pointer to file */
+
+
+ /*
+  * Read a character from the file and see if it is EOF or ASCII...
+  */
+
+  fp = (FILE *)p;
+  ch = getc(fp);
+
+  if (ch == EOF)
+    return (EOF);
+
+  switch (*encoding)
+  {
+    case ENCODE_UTF8 :
+       /*
+       * Got a UTF-8 character; convert UTF-8 to Unicode and return...
+       */
+
+       if (!(ch & 0x80))
+       {
+         if (mxml_bad_char(ch))
+         {
+           mxml_error("Bad control character 0x%02x not allowed by XML 
standard!",
+                      ch);
+           return (EOF);
+         }
+
+#if DEBUG > 1
+          printf("mxml_file_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
+#endif /* DEBUG > 1 */
+
+         return (ch);
+        }
+       else if (ch == 0xfe)
+       {
+        /*
+         * UTF-16 big-endian BOM?
+         */
+
+          ch = getc(fp);
+         if (ch != 0xff)
+           return (EOF);
+
+         *encoding = ENCODE_UTF16BE;
+
+         return (mxml_file_getc(p, encoding));
+       }
+       else if (ch == 0xff)
+       {
+        /*
+         * UTF-16 little-endian BOM?
+         */
+
+          ch = getc(fp);
+         if (ch != 0xfe)
+           return (EOF);
+
+         *encoding = ENCODE_UTF16LE;
+
+         return (mxml_file_getc(p, encoding));
+       }
+       else if ((ch & 0xe0) == 0xc0)
+       {
+        /*
+         * Two-byte value...
+         */
+
+         if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
+           return (EOF);
+
+         ch = ((ch & 0x1f) << 6) | (temp & 0x3f);
+
+         if (ch < 0x80)
+         {
+           mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
+           return (EOF);
+         }
+       }
+       else if ((ch & 0xf0) == 0xe0)
+       {
+        /*
+         * Three-byte value...
+         */
+
+         if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
+           return (EOF);
+
+         ch = ((ch & 0x0f) << 6) | (temp & 0x3f);
+
+         if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
+           return (EOF);
+
+         ch = (ch << 6) | (temp & 0x3f);
+
+         if (ch < 0x800)
+         {
+           mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
+           return (EOF);
+         }
+
+         /*
+         * Ignore (strip) Byte Order Mark (BOM)...
+         */
+
+         if (ch == 0xfeff)
+           return (mxml_file_getc(p, encoding));
+       }
+       else if ((ch & 0xf8) == 0xf0)
+       {
+        /*
+         * Four-byte value...
+         */
+
+         if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
+           return (EOF);
+
+         ch = ((ch & 0x07) << 6) | (temp & 0x3f);
+
+         if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
+           return (EOF);
+
+         ch = (ch << 6) | (temp & 0x3f);
+
+         if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
+           return (EOF);
+
+         ch = (ch << 6) | (temp & 0x3f);
+
+         if (ch < 0x10000)
+         {
+           mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
+           return (EOF);
+         }
+       }
+       else
+         return (EOF);
+       break;
+
+    case ENCODE_UTF16BE :
+       /*
+        * Read UTF-16 big-endian char...
+       */
+
+       ch = (ch << 8) | getc(fp);
+
+       if (mxml_bad_char(ch))
+       {
+         mxml_error("Bad control character 0x%02x not allowed by XML 
standard!",
+                    ch);
+         return (EOF);
+       }
+        else if (ch >= 0xd800 && ch <= 0xdbff)
+       {
+        /*
+         * Multi-word UTF-16 char...
+         */
+
+          int lch = (getc(fp) << 8) | getc(fp);
+
+          if (lch < 0xdc00 || lch >= 0xdfff)
+           return (EOF);
+
+          ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
+       }
+       break;
+
+    case ENCODE_UTF16LE :
+       /*
+        * Read UTF-16 little-endian char...
+       */
+
+       ch |= (getc(fp) << 8);
+
+        if (mxml_bad_char(ch))
+       {
+         mxml_error("Bad control character 0x%02x not allowed by XML 
standard!",
+                    ch);
+         return (EOF);
+       }
+        else if (ch >= 0xd800 && ch <= 0xdbff)
+       {
+        /*
+         * Multi-word UTF-16 char...
+         */
+
+          int lch = getc(fp) | (getc(fp) << 8);
+
+          if (lch < 0xdc00 || lch >= 0xdfff)
+           return (EOF);
+
+          ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
+       }
+       break;
+  }
+
+#if DEBUG > 1
+  printf("mxml_file_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
+#endif /* DEBUG > 1 */
+
+  return (ch);
+}
+
+
+/*
+ * 'mxml_file_putc()' - Write a character to a file.
+ */
+
+static int                             /* O - 0 on success, -1 on failure */
+mxml_file_putc(int  ch,                        /* I - Character to write */
+               void *p)                        /* I - Pointer to file */
+{
+  return (putc(ch, (FILE *)p) == EOF ? -1 : 0);
+}
+
+
+/*
+ * 'mxml_get_entity()' - Get the character corresponding to an entity...
+ */
+
+static int                             /* O  - Character value or EOF on error 
*/
+mxml_get_entity(mxml_node_t *parent,   /* I  - Parent node */
+               void        *p,         /* I  - Pointer to source */
+               int         *encoding,  /* IO - Character encoding */
+                int         (*getc_cb)(void *, int *))
+                                       /* I  - Get character function */
+{
+  int  ch;                             /* Current character */
+  char entity[64],                     /* Entity string */
+       *entptr;                        /* Pointer into entity */
+
+
+  entptr = entity;
+
+  while ((ch = (*getc_cb)(p, encoding)) != EOF)
+    if (ch > 126 || (!isalnum(ch) && ch != '#'))
+      break;
+    else if (entptr < (entity + sizeof(entity) - 1))
+      *entptr++ = ch;
+    else
+    {
+      mxml_error("Entity name too long under parent <%s>!",
+                parent ? parent->value.element.name : "null");
+      break;
+    }
+
+  *entptr = '\0';
+
+  if (ch != ';')
+  {
+    mxml_error("Character entity \"%s\" not terminated under parent <%s>!",
+              entity, parent ? parent->value.element.name : "null");
+    return (EOF);
+  }
+
+  if (entity[0] == '#')
+  {
+    if (entity[1] == 'x')
+      ch = strtol(entity + 2, NULL, 16);
+    else
+      ch = strtol(entity + 1, NULL, 10);
+  }
+  else if ((ch = mxmlEntityGetValue(entity)) < 0)
+    mxml_error("Entity name \"%s;\" not supported under parent <%s>!",
+              entity, parent ? parent->value.element.name : "null");
+
+  if (mxml_bad_char(ch))
+  {
+    mxml_error("Bad control character 0x%02x under parent <%s> not allowed by 
XML standard!",
+               ch, parent ? parent->value.element.name : "null");
+    return (EOF);
+  }
+
+  return (ch);
+}
+
+
+/*
+ * 'mxml_load_data()' - Load data into an XML node tree.
+ */
+
+static mxml_node_t *                   /* O - First node or NULL if the file 
could not be read. */
+mxml_load_data(
+    mxml_node_t     *top,              /* I - Top node */
+    void            *p,                        /* I - Pointer to data */
+    mxml_load_cb_t  cb,                        /* I - Callback function or 
MXML_NO_CALLBACK */
+    _mxml_getc_cb_t getc_cb,           /* I - Read function */
+    mxml_sax_cb_t   sax_cb,            /* I - SAX callback or MXML_NO_CALLBACK 
*/
+    void            *sax_data)         /* I - SAX user data */
+{
+  mxml_node_t  *node,                  /* Current node */
+               *first,                 /* First node added */
+               *parent;                /* Current parent node */
+  int          ch,                     /* Character from file */
+               whitespace;             /* Non-zero if whitespace seen */
+  char         *buffer,                /* String buffer */
+               *bufptr;                /* Pointer into buffer */
+  int          bufsize;                /* Size of buffer */
+  mxml_type_t  type;                   /* Current node type */
+  int          encoding;               /* Character encoding */
+  _mxml_global_t *global = _mxml_global();
+                                       /* Global data */
+  static const char * const types[] =  /* Type strings... */
+               {
+                 "MXML_ELEMENT",       /* XML element with attributes */
+                 "MXML_INTEGER",       /* Integer value */
+                 "MXML_OPAQUE",        /* Opaque string */
+                 "MXML_REAL",          /* Real value */
+                 "MXML_TEXT",          /* Text fragment */
+                 "MXML_CUSTOM"         /* Custom data */
+               };
+
+
+ /*
+  * Read elements and other nodes from the file...
+  */
+
+  if ((buffer = malloc(64)) == NULL)
+  {
+    mxml_error("Unable to allocate string buffer!");
+    return (NULL);
+  }
+
+  bufsize    = 64;
+  bufptr     = buffer;
+  parent     = top;
+  first      = NULL;
+  whitespace = 0;
+  encoding   = ENCODE_UTF8;
+
+  if (cb && parent)
+    type = (*cb)(parent);
+  else
+    type = MXML_TEXT;
+
+  while ((ch = (*getc_cb)(p, &encoding)) != EOF)
+  {
+    if ((ch == '<' ||
+         (mxml_isspace(ch) && type != MXML_OPAQUE && type != MXML_CUSTOM)) &&
+        bufptr > buffer)
+    {
+     /*
+      * Add a new value node...
+      */
+
+      *bufptr = '\0';
+
+      switch (type)
+      {
+       case MXML_INTEGER :
+            node = mxmlNewInteger(parent, strtol(buffer, &bufptr, 0));
+           break;
+
+       case MXML_OPAQUE :
+            node = mxmlNewOpaque(parent, buffer);
+           break;
+
+       case MXML_REAL :
+            node = mxmlNewReal(parent, strtod(buffer, &bufptr));
+           break;
+
+       case MXML_TEXT :
+            node = mxmlNewText(parent, whitespace, buffer);
+           break;
+
+       case MXML_CUSTOM :
+           if (global->custom_load_cb)
+           {
+            /*
+             * Use the callback to fill in the custom data...
+             */
+
+              node = mxmlNewCustom(parent, NULL, NULL);
+
+             if ((*global->custom_load_cb)(node, buffer))
+             {
+               mxml_error("Bad custom value '%s' in parent <%s>!",
+                          buffer, parent ? parent->value.element.name : 
"null");
+               mxmlDelete(node);
+               node = NULL;
+             }
+             break;
+           }
+
+        default : /* Ignore... */
+           node = NULL;
+           break;
+      }          
+
+      if (*bufptr)
+      {
+       /*
+        * Bad integer/real number value...
+       */
+
+        mxml_error("Bad %s value '%s' in parent <%s>!",
+                  type == MXML_INTEGER ? "integer" : "real", buffer,
+                  parent ? parent->value.element.name : "null");
+       break;
+      }
+
+      bufptr     = buffer;
+      whitespace = mxml_isspace(ch) && type == MXML_TEXT;
+
+      if (!node && type != MXML_IGNORE)
+      {
+       /*
+       * Print error and return...
+       */
+
+       mxml_error("Unable to add value node of type %s to parent <%s>!",
+                  types[type], parent ? parent->value.element.name : "null");
+       goto error;
+      }
+
+      if (sax_cb)
+      {
+        (*sax_cb)(node, MXML_SAX_DATA, sax_data);
+
+        if (!mxmlRelease(node))
+          node = NULL;
+      }
+
+      if (!first && node)
+        first = node;
+    }
+    else if (mxml_isspace(ch) && type == MXML_TEXT)
+      whitespace = 1;
+
+   /*
+    * Add lone whitespace node if we have an element and existing
+    * whitespace...
+    */
+
+    if (ch == '<' && whitespace && type == MXML_TEXT)
+    {
+      if (parent)
+      {
+       node = mxmlNewText(parent, whitespace, "");
+
+       if (sax_cb)
+       {
+         (*sax_cb)(node, MXML_SAX_DATA, sax_data);
+
+         if (!mxmlRelease(node))
+           node = NULL;
+       }
+
+       if (!first && node)
+         first = node;
+      }
+
+      whitespace = 0;
+    }
+
+    if (ch == '<')
+    {
+     /*
+      * Start of open/close tag...
+      */
+
+      bufptr = buffer;
+
+      while ((ch = (*getc_cb)(p, &encoding)) != EOF)
+        if (mxml_isspace(ch) || ch == '>' || (ch == '/' && bufptr > buffer))
+         break;
+       else if (ch == '<')
+       {
+         mxml_error("Bare < in element!");
+         goto error;
+       }
+       else if (ch == '&')
+       {
+         if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
+           goto error;
+
+         if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
+           goto error;
+       }
+       else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
+         goto error;
+       else if (((bufptr - buffer) == 1 && buffer[0] == '?') ||
+                ((bufptr - buffer) == 3 && !strncmp(buffer, "!--", 3)) ||
+                ((bufptr - buffer) == 8 && !strncmp(buffer, "![CDATA[", 8)))
+         break;
+
+      *bufptr = '\0';
+
+      if (!strcmp(buffer, "!--"))
+      {
+       /*
+        * Gather rest of comment...
+       */
+
+       while ((ch = (*getc_cb)(p, &encoding)) != EOF)
+       {
+         if (ch == '>' && bufptr > (buffer + 4) &&
+             bufptr[-3] != '-' && bufptr[-2] == '-' && bufptr[-1] == '-')
+           break;
+         else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
+           goto error;
+       }
+
+       /*
+        * Error out if we didn't get the whole comment...
+       */
+
+        if (ch != '>')
+       {
+        /*
+         * Print error and return...
+         */
+
+         mxml_error("Early EOF in comment node!");
+         goto error;
+       }
+
+
+       /*
+        * Otherwise add this as an element under the current parent...
+       */
+
+       *bufptr = '\0';
+
+        if (!parent && first)
+       {
+        /*
+         * There can only be one root element!
+         */
+
+         mxml_error("<%s> cannot be a second root node after <%s>", 
+                    buffer, first->value.element.name);
+          goto error;               
+       }
+
+       if ((node = mxmlNewElement(parent, buffer)) == NULL)
+       {
+        /*
+         * Just print error for now...
+         */
+
+         mxml_error("Unable to add comment node to parent <%s>!",
+                    parent ? parent->value.element.name : "null");
+         break;
+       }
+
+        if (sax_cb)
+        {
+          (*sax_cb)(node, MXML_SAX_COMMENT, sax_data);
+
+          if (!mxmlRelease(node))
+            node = NULL;
+        }
+
+       if (node && !first)
+         first = node;
+      }
+      else if (!strcmp(buffer, "![CDATA["))
+      {
+       /*
+        * Gather CDATA section...
+       */
+
+       while ((ch = (*getc_cb)(p, &encoding)) != EOF)
+       {
+         if (ch == '>' && !strncmp(bufptr - 2, "]]", 2))
+           break;
+         else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
+           goto error;
+       }
+
+       /*
+        * Error out if we didn't get the whole comment...
+       */
+
+        if (ch != '>')
+       {
+        /*
+         * Print error and return...
+         */
+
+         mxml_error("Early EOF in CDATA node!");
+         goto error;
+       }
+
+
+       /*
+        * Otherwise add this as an element under the current parent...
+       */
+
+       *bufptr = '\0';
+
+        if (!parent && first)
+       {
+        /*
+         * There can only be one root element!
+         */
+
+         mxml_error("<%s> cannot be a second root node after <%s>", 
+                    buffer, first->value.element.name);
+          goto error;               
+       }
+
+       if ((node = mxmlNewElement(parent, buffer)) == NULL)
+       {
+        /*
+         * Print error and return...
+         */
+
+         mxml_error("Unable to add CDATA node to parent <%s>!",
+                    parent ? parent->value.element.name : "null");
+         goto error;
+       }
+
+        if (sax_cb)
+        {
+          (*sax_cb)(node, MXML_SAX_CDATA, sax_data);
+
+          if (!mxmlRelease(node))
+            node = NULL;
+        }
+
+       if (node && !first)
+         first = node;
+      }
+      else if (buffer[0] == '?')
+      {
+       /*
+        * Gather rest of processing instruction...
+       */
+
+       while ((ch = (*getc_cb)(p, &encoding)) != EOF)
+       {
+         if (ch == '>' && bufptr > buffer && bufptr[-1] == '?')
+           break;
+         else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
+           goto error;
+       }
+
+       /*
+        * Error out if we didn't get the whole processing instruction...
+       */
+
+        if (ch != '>')
+       {
+        /*
+         * Print error and return...
+         */
+
+         mxml_error("Early EOF in processing instruction node!");
+         goto error;
+       }
+
+       /*
+        * Otherwise add this as an element under the current parent...
+       */
+
+       *bufptr = '\0';
+
+        if (!parent && first)
+       {
+        /*
+         * There can only be one root element!
+         */
+
+         mxml_error("<%s> cannot be a second root node after <%s>", 
+                    buffer, first->value.element.name);
+          goto error;               
+       }
+
+       if ((node = mxmlNewElement(parent, buffer)) == NULL)
+       {
+        /*
+         * Print error and return...
+         */
+
+         mxml_error("Unable to add processing instruction node to parent 
<%s>!",
+                    parent ? parent->value.element.name : "null");
+         goto error;
+       }
+
+        if (sax_cb)
+        {
+          (*sax_cb)(node, MXML_SAX_DIRECTIVE, sax_data);
+
+          if (!mxmlRelease(node))
+            node = NULL;
+        }
+
+        if (node)
+       {
+         if (!first)
+            first = node;
+
+         if (!parent)
+         {
+           parent = node;
+
+           if (cb)
+             type = (*cb)(parent);
+         }
+       }
+      }
+      else if (buffer[0] == '!')
+      {
+       /*
+        * Gather rest of declaration...
+       */
+
+       do
+       {
+         if (ch == '>')
+           break;
+         else
+         {
+            if (ch == '&')
+             if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
+               goto error;
+
+           if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
+             goto error;
+         }
+       }
+        while ((ch = (*getc_cb)(p, &encoding)) != EOF);
+
+       /*
+        * Error out if we didn't get the whole declaration...
+       */
+
+        if (ch != '>')
+       {
+        /*
+         * Print error and return...
+         */
+
+         mxml_error("Early EOF in declaration node!");
+         goto error;
+       }
+
+       /*
+        * Otherwise add this as an element under the current parent...
+       */
+
+       *bufptr = '\0';
+
+        if (!parent && first)
+       {
+        /*
+         * There can only be one root element!
+         */
+
+         mxml_error("<%s> cannot be a second root node after <%s>", 
+                    buffer, first->value.element.name);
+          goto error;               
+       }
+
+       if ((node = mxmlNewElement(parent, buffer)) == NULL)
+       {
+        /*
+         * Print error and return...
+         */
+
+         mxml_error("Unable to add declaration node to parent <%s>!",
+                    parent ? parent->value.element.name : "null");
+         goto error;
+       }
+
+        if (sax_cb)
+        {
+          (*sax_cb)(node, MXML_SAX_DIRECTIVE, sax_data);
+
+          if (!mxmlRelease(node))
+            node = NULL;
+        }
+
+        if (node)
+       {
+         if (!first)
+            first = node;
+
+         if (!parent)
+         {
+           parent = node;
+
+           if (cb)
+             type = (*cb)(parent);
+         }
+       }
+      }
+      else if (buffer[0] == '/')
+      {
+       /*
+        * Handle close tag...
+       */
+
+        if (!parent || strcmp(buffer + 1, parent->value.element.name))
+       {
+        /*
+         * Close tag doesn't match tree; print an error for now...
+         */
+
+         mxml_error("Mismatched close tag <%s> under parent <%s>!",
+                    buffer, parent ? parent->value.element.name : "(null)");
+          goto error;
+       }
+
+       /*
+        * Keep reading until we see >...
+       */
+
+        while (ch != '>' && ch != EOF)
+         ch = (*getc_cb)(p, &encoding);
+
+        node   = parent;
+        parent = parent->parent;
+
+        if (sax_cb)
+        {
+          (*sax_cb)(node, MXML_SAX_ELEMENT_CLOSE, sax_data);
+
+          if (!mxmlRelease(node) && first == node)
+           first = NULL;
+        }
+
+       /*
+       * Ascend into the parent and set the value type as needed...
+       */
+
+       if (cb && parent)
+         type = (*cb)(parent);
+      }
+      else
+      {
+       /*
+        * Handle open tag...
+       */
+
+        if (!parent && first)
+       {
+        /*
+         * There can only be one root element!
+         */
+
+         mxml_error("<%s> cannot be a second root node after <%s>", 
+                    buffer, first->value.element.name);
+          goto error;               
+       }
+
+        if ((node = mxmlNewElement(parent, buffer)) == NULL)
+       {
+        /*
+         * Just print error for now...
+         */
+
+         mxml_error("Unable to add element node to parent <%s>!",
+                    parent ? parent->value.element.name : "null");
+         goto error;
+       }
+
+        if (mxml_isspace(ch))
+        {
+         if ((ch = mxml_parse_element(node, p, &encoding, getc_cb)) == EOF)
+           goto error;
+        }
+        else if (ch == '/')
+       {
+         if ((ch = (*getc_cb)(p, &encoding)) != '>')
+         {
+           mxml_error("Expected > but got '%c' instead for element <%s/>!",
+                      ch, buffer);
+            mxmlDelete(node);
+            goto error;
+         }
+
+         ch = '/';
+       }
+
+        if (sax_cb)
+          (*sax_cb)(node, MXML_SAX_ELEMENT_OPEN, sax_data);
+
+        if (!first)
+         first = node;
+
+       if (ch == EOF)
+         break;
+
+        if (ch != '/')
+       {
+        /*
+         * Descend into this node, setting the value type as needed...
+         */
+
+         parent = node;
+
+         if (cb && parent)
+           type = (*cb)(parent);
+       }
+        else if (sax_cb)
+        {
+          (*sax_cb)(node, MXML_SAX_ELEMENT_CLOSE, sax_data);
+
+          if (!mxmlRelease(node) && first == node)
+            first = NULL;
+        }
+      }
+
+      bufptr  = buffer;
+    }
+    else if (ch == '&')
+    {
+     /*
+      * Add character entity to current buffer...
+      */
+
+      if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
+       goto error;
+
+      if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
+       goto error;
+    }
+    else if (type == MXML_OPAQUE || type == MXML_CUSTOM || !mxml_isspace(ch))
+    {
+     /*
+      * Add character to current buffer...
+      */
+
+      if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
+       goto error;
+    }
+  }
+
+ /*
+  * Free the string buffer - we don't need it anymore...
+  */
+
+  free(buffer);
+
+ /*
+  * Find the top element and return it...
+  */
+
+  if (parent)
+  {
+    node = parent;
+
+    while (parent->parent != top && parent->parent)
+      parent = parent->parent;
+
+    if (node != parent)
+    {
+      mxml_error("Missing close tag </%s> under parent <%s>!",
+                node->value.element.name,
+                node->parent ? node->parent->value.element.name : "(null)");
+
+      mxmlDelete(first);
+
+      return (NULL);
+    }
+  }
+
+  if (parent)
+    return (parent);
+  else
+    return (first);
+
+ /*
+  * Common error return...
+  */
+
+error:
+
+  mxmlDelete(first);
+
+  free(buffer);
+
+  return (NULL);
+}
+
+
+/*
+ * 'mxml_parse_element()' - Parse an element for any attributes...
+ */
+
+static int                             /* O  - Terminating character */
+mxml_parse_element(
+    mxml_node_t     *node,             /* I  - Element node */
+    void            *p,                        /* I  - Data to read from */
+    int             *encoding,         /* IO - Encoding */
+    _mxml_getc_cb_t getc_cb)           /* I  - Data callback */
+{
+  int  ch,                             /* Current character in file */
+       quote;                          /* Quoting character */
+  char *name,                          /* Attribute name */
+       *value,                         /* Attribute value */
+       *ptr;                           /* Pointer into name/value */
+  int  namesize,                       /* Size of name string */
+       valsize;                        /* Size of value string */
+
+
+ /*
+  * Initialize the name and value buffers...
+  */
+
+  if ((name = malloc(64)) == NULL)
+  {
+    mxml_error("Unable to allocate memory for name!");
+    return (EOF);
+  }
+
+  namesize = 64;
+
+  if ((value = malloc(64)) == NULL)
+  {
+    free(name);
+    mxml_error("Unable to allocate memory for value!");
+    return (EOF);
+  }
+
+  valsize = 64;
+
+ /*
+  * Loop until we hit a >, /, ?, or EOF...
+  */
+
+  while ((ch = (*getc_cb)(p, encoding)) != EOF)
+  {
+#if DEBUG > 1
+    fprintf(stderr, "parse_element: ch='%c'\n", ch);
+#endif /* DEBUG > 1 */
+
+   /*
+    * Skip leading whitespace...
+    */
+
+    if (mxml_isspace(ch))
+      continue;
+
+   /*
+    * Stop at /, ?, or >...
+    */
+
+    if (ch == '/' || ch == '?')
+    {
+     /*
+      * Grab the > character and print an error if it isn't there...
+      */
+
+      quote = (*getc_cb)(p, encoding);
+
+      if (quote != '>')
+      {
+        mxml_error("Expected '>' after '%c' for element %s, but got '%c'!",
+                  ch, node->value.element.name, quote);
+        goto error;
+      }
+
+      break;
+    }
+    else if (ch == '<')
+    {
+      mxml_error("Bare < in element %s!", node->value.element.name);
+      goto error;
+    }
+    else if (ch == '>')
+      break;
+
+   /*
+    * Read the attribute name...
+    */
+
+    name[0] = ch;
+    ptr     = name + 1;
+
+    if (ch == '\"' || ch == '\'')
+    {
+     /*
+      * Name is in quotes, so get a quoted string...
+      */
+
+      quote = ch;
+
+      while ((ch = (*getc_cb)(p, encoding)) != EOF)
+      {
+        if (ch == '&')
+         if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
+           goto error;
+
+       if (mxml_add_char(ch, &ptr, &name, &namesize))
+         goto error;
+
+       if (ch == quote)
+          break;
+      }
+    }
+    else
+    {
+     /*
+      * Grab an normal, non-quoted name...
+      */
+
+      while ((ch = (*getc_cb)(p, encoding)) != EOF)
+       if (mxml_isspace(ch) || ch == '=' || ch == '/' || ch == '>' ||
+           ch == '?')
+          break;
+       else
+       {
+          if (ch == '&')
+           if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
+             goto error;
+
+         if (mxml_add_char(ch, &ptr, &name, &namesize))
+           goto error;
+       }
+    }
+
+    *ptr = '\0';
+
+    if (mxmlElementGetAttr(node, name))
+      goto error;
+
+    while (ch != EOF && mxml_isspace(ch))
+      ch = (*getc_cb)(p, encoding);
+
+    if (ch == '=')
+    {
+     /*
+      * Read the attribute value...
+      */
+
+      while ((ch = (*getc_cb)(p, encoding)) != EOF && mxml_isspace(ch));
+
+      if (ch == EOF)
+      {
+        mxml_error("Missing value for attribute '%s' in element %s!",
+                  name, node->value.element.name);
+        goto error;
+      }
+
+      if (ch == '\'' || ch == '\"')
+      {
+       /*
+        * Read quoted value...
+       */
+
+        quote = ch;
+       ptr   = value;
+
+        while ((ch = (*getc_cb)(p, encoding)) != EOF)
+         if (ch == quote)
+           break;
+         else
+         {
+           if (ch == '&')
+             if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
+               goto error;
+             
+           if (mxml_add_char(ch, &ptr, &value, &valsize))
+             goto error;
+         }
+
+        *ptr = '\0';
+      }
+      else
+      {
+       /*
+        * Read unquoted value...
+       */
+
+       value[0] = ch;
+       ptr      = value + 1;
+
+       while ((ch = (*getc_cb)(p, encoding)) != EOF)
+         if (mxml_isspace(ch) || ch == '=' || ch == '/' || ch == '>')
+            break;
+         else
+         {
+           if (ch == '&')
+             if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
+               goto error;
+             
+           if (mxml_add_char(ch, &ptr, &value, &valsize))
+             goto error;
+         }
+
+        *ptr = '\0';
+      }
+
+     /*
+      * Set the attribute with the given string value...
+      */
+
+      mxmlElementSetAttr(node, name, value);
+    }
+    else
+    {
+      mxml_error("Missing value for attribute '%s' in element %s!",
+                name, node->value.element.name);
+      goto error;
+    }
+
+   /*
+    * Check the end character...
+    */
+
+    if (ch == '/' || ch == '?')
+    {
+     /*
+      * Grab the > character and print an error if it isn't there...
+      */
+
+      quote = (*getc_cb)(p, encoding);
+
+      if (quote != '>')
+      {
+        mxml_error("Expected '>' after '%c' for element %s, but got '%c'!",
+                  ch, node->value.element.name, quote);
+        ch = EOF;
+      }
+
+      break;
+    }
+    else if (ch == '>')
+      break;
+  }
+
+ /*
+  * Free the name and value buffers and return...
+  */
+
+  free(name);
+  free(value);
+
+  return (ch);
+
+ /*
+  * Common error return point...
+  */
+
+error:
+
+  free(name);
+  free(value);
+
+  return (EOF);
+}
+
+
+/*
+ * 'mxml_string_getc()' - Get a character from a string.
+ */
+
+static int                             /* O  - Character or EOF */
+mxml_string_getc(void *p,              /* I  - Pointer to file */
+                 int  *encoding)       /* IO - Encoding */
+{
+  int          ch;                     /* Character */
+  const char   **s;                    /* Pointer to string pointer */
+
+
+  s = (const char **)p;
+
+  if ((ch = (*s)[0] & 255) != 0 || *encoding == ENCODE_UTF16LE)
+  {
+   /*
+    * Got character; convert UTF-8 to integer and return...
+    */
+
+    (*s)++;
+
+    switch (*encoding)
+    {
+      case ENCODE_UTF8 :
+         if (!(ch & 0x80))
+         {
+#if DEBUG > 1
+            printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
+#endif /* DEBUG > 1 */
+
+           if (mxml_bad_char(ch))
+           {
+             mxml_error("Bad control character 0x%02x not allowed by XML 
standard!",
+                        ch);
+             return (EOF);
+           }
+
+           return (ch);
+          }
+         else if (ch == 0xfe)
+         {
+          /*
+           * UTF-16 big-endian BOM?
+           */
+
+            if (((*s)[0] & 255) != 0xff)
+             return (EOF);
+
+           *encoding = ENCODE_UTF16BE;
+           (*s)++;
+
+           return (mxml_string_getc(p, encoding));
+         }
+         else if (ch == 0xff)
+         {
+          /*
+           * UTF-16 little-endian BOM?
+           */
+
+            if (((*s)[0] & 255) != 0xfe)
+             return (EOF);
+
+           *encoding = ENCODE_UTF16LE;
+           (*s)++;
+
+           return (mxml_string_getc(p, encoding));
+         }
+         else if ((ch & 0xe0) == 0xc0)
+         {
+          /*
+           * Two-byte value...
+           */
+
+           if (((*s)[0] & 0xc0) != 0x80)
+              return (EOF);
+
+           ch = ((ch & 0x1f) << 6) | ((*s)[0] & 0x3f);
+
+           (*s)++;
+
+           if (ch < 0x80)
+           {
+             mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
+             return (EOF);
+           }
+
+#if DEBUG > 1
+            printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
+#endif /* DEBUG > 1 */
+
+           return (ch);
+         }
+         else if ((ch & 0xf0) == 0xe0)
+         {
+          /*
+           * Three-byte value...
+           */
+
+           if (((*s)[0] & 0xc0) != 0x80 ||
+               ((*s)[1] & 0xc0) != 0x80)
+              return (EOF);
+
+           ch = ((((ch & 0x0f) << 6) | ((*s)[0] & 0x3f)) << 6) | ((*s)[1] & 
0x3f);
+
+           (*s) += 2;
+
+           if (ch < 0x800)
+           {
+             mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
+             return (EOF);
+           }
+
+          /*
+           * Ignore (strip) Byte Order Mark (BOM)...
+           */
+
+           if (ch == 0xfeff)
+             return (mxml_string_getc(p, encoding));
+
+#if DEBUG > 1
+            printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
+#endif /* DEBUG > 1 */
+
+           return (ch);
+         }
+         else if ((ch & 0xf8) == 0xf0)
+         {
+          /*
+           * Four-byte value...
+           */
+
+           if (((*s)[0] & 0xc0) != 0x80 ||
+               ((*s)[1] & 0xc0) != 0x80 ||
+               ((*s)[2] & 0xc0) != 0x80)
+              return (EOF);
+
+           ch = ((((((ch & 0x07) << 6) | ((*s)[0] & 0x3f)) << 6) |
+                  ((*s)[1] & 0x3f)) << 6) | ((*s)[2] & 0x3f);
+
+           (*s) += 3;
+
+           if (ch < 0x10000)
+           {
+             mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
+             return (EOF);
+           }
+
+#if DEBUG > 1
+            printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
+#endif /* DEBUG > 1 */
+
+           return (ch);
+         }
+         else
+           return (EOF);
+
+      case ENCODE_UTF16BE :
+        /*
+          * Read UTF-16 big-endian char...
+         */
+
+         ch = (ch << 8) | ((*s)[0] & 255);
+         (*s) ++;
+
+          if (mxml_bad_char(ch))
+         {
+           mxml_error("Bad control character 0x%02x not allowed by XML 
standard!",
+                      ch);
+           return (EOF);
+         }
+          else if (ch >= 0xd800 && ch <= 0xdbff)
+         {
+          /*
+           * Multi-word UTF-16 char...
+           */
+
+            int lch;                   /* Lower word */
+
+
+            if (!(*s)[0])
+             return (EOF);
+
+            lch = (((*s)[0] & 255) << 8) | ((*s)[1] & 255);
+           (*s) += 2;
+
+            if (lch < 0xdc00 || lch >= 0xdfff)
+             return (EOF);
+
+            ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
+         }
+
+#if DEBUG > 1
+          printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
+#endif /* DEBUG > 1 */
+
+         return (ch);
+
+      case ENCODE_UTF16LE :
+        /*
+          * Read UTF-16 little-endian char...
+         */
+
+         ch = ch | (((*s)[0] & 255) << 8);
+
+         if (!ch)
+         {
+           (*s) --;
+           return (EOF);
+         }
+
+         (*s) ++;
+
+          if (mxml_bad_char(ch))
+         {
+           mxml_error("Bad control character 0x%02x not allowed by XML 
standard!",
+                      ch);
+           return (EOF);
+         }
+          else if (ch >= 0xd800 && ch <= 0xdbff)
+         {
+          /*
+           * Multi-word UTF-16 char...
+           */
+
+            int lch;                   /* Lower word */
+
+
+            if (!(*s)[1])
+             return (EOF);
+
+            lch = (((*s)[1] & 255) << 8) | ((*s)[0] & 255);
+           (*s) += 2;
+
+            if (lch < 0xdc00 || lch >= 0xdfff)
+             return (EOF);
+
+            ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
+         }
+
+#if DEBUG > 1
+          printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
+#endif /* DEBUG > 1 */
+
+         return (ch);
+    }
+  }
+
+  return (EOF);
+}
+
+
+/*
+ * 'mxml_string_putc()' - Write a character to a string.
+ */
+
+static int                             /* O - 0 on success, -1 on failure */
+mxml_string_putc(int  ch,              /* I - Character to write */
+                 void *p)              /* I - Pointer to string pointers */
+{
+  char **pp;                           /* Pointer to string pointers */
+
+
+  pp = (char **)p;
+
+  if (pp[0] < pp[1])
+    pp[0][0] = ch;
+
+  pp[0] ++;
+
+  return (0);
+}
+
+
+/*
+ * 'mxml_write_name()' - Write a name string.
+ */
+
+static int                             /* O - 0 on success, -1 on failure */
+mxml_write_name(const char *s,         /* I - Name to write */
+                void       *p,         /* I - Write pointer */
+               int        (*putc_cb)(int, void *))
+                                       /* I - Write callback */
+{
+  char         quote;                  /* Quote character */
+  const char   *name;                  /* Entity name */
+
+
+  if (*s == '\"' || *s == '\'')
+  {
+   /*
+    * Write a quoted name string...
+    */
+
+    if ((*putc_cb)(*s, p) < 0)
+      return (-1);
+
+    quote = *s++;
+
+    while (*s && *s != quote)
+    {
+      if ((name = mxmlEntityGetName(*s)) != NULL)
+      {
+       if ((*putc_cb)('&', p) < 0)
+          return (-1);
+
+        while (*name)
+       {
+         if ((*putc_cb)(*name, p) < 0)
+            return (-1);
+
+          name ++;
+       }
+
+       if ((*putc_cb)(';', p) < 0)
+          return (-1);
+      }
+      else if ((*putc_cb)(*s, p) < 0)
+       return (-1);
+
+      s ++;
+    }
+
+   /*
+    * Write the end quote...
+    */
+
+    if ((*putc_cb)(quote, p) < 0)
+      return (-1);
+  }
+  else
+  {
+   /*
+    * Write a non-quoted name string...
+    */
+
+    while (*s)
+    {
+      if ((*putc_cb)(*s, p) < 0)
+       return (-1);
+
+      s ++;
+    }
+  }
+
+  return (0);
+}
+
+
+/*
+ * 'mxml_write_node()' - Save an XML node to a file.
+ */
+
+static int                             /* O - Column or -1 on error */
+mxml_write_node(mxml_node_t     *node, /* I - Node to write */
+                void            *p,    /* I - File to write to */
+               mxml_save_cb_t  cb,     /* I - Whitespace callback */
+               int             col,    /* I - Current column */
+               _mxml_putc_cb_t putc_cb,/* I - Output callback */
+               _mxml_global_t  *global)/* I - Global data */
+{
+  int          i,                      /* Looping var */
+               width;                  /* Width of attr + value */
+  mxml_attr_t  *attr;                  /* Current attribute */
+  char         s[255];                 /* Temporary string */
+
+
+ /*
+  * Print the node value...
+  */
+
+  switch (node->type)
+  {
+    case MXML_ELEMENT :
+       col = mxml_write_ws(node, p, cb, MXML_WS_BEFORE_OPEN, col, putc_cb);
+
+       if ((*putc_cb)('<', p) < 0)
+         return (-1);
+       if (node->value.element.name[0] == '?' ||
+           !strncmp(node->value.element.name, "!--", 3) ||
+           !strncmp(node->value.element.name, "![CDATA[", 8))
+       {
+        /*
+         * Comments, CDATA, and processing instructions do not
+         * use character entities.
+         */
+
+         const char    *ptr;           /* Pointer into name */
+
+
+         for (ptr = node->value.element.name; *ptr; ptr ++)
+           if ((*putc_cb)(*ptr, p) < 0)
+             return (-1);
+       }
+       else if (mxml_write_name(node->value.element.name, p, putc_cb) < 0)
+         return (-1);
+
+       col += strlen(node->value.element.name) + 1;
+
+       for (i = node->value.element.num_attrs, attr = 
node->value.element.attrs;
+            i > 0;
+            i --, attr ++)
+       {
+         width = strlen(attr->name);
+
+         if (attr->value)
+           width += strlen(attr->value) + 3;
+
+         if (global->wrap > 0 && (col + width) > global->wrap)
+         {
+           if ((*putc_cb)('\n', p) < 0)
+             return (-1);
+
+           col = 0;
+         }
+         else
+         {
+           if ((*putc_cb)(' ', p) < 0)
+             return (-1);
+
+           col ++;
+         }
+
+         if (mxml_write_name(attr->name, p, putc_cb) < 0)
+           return (-1);
+
+         if (attr->value)
+         {
+           if ((*putc_cb)('=', p) < 0)
+             return (-1);
+           if ((*putc_cb)('\"', p) < 0)
+             return (-1);
+           if (mxml_write_string(attr->value, p, putc_cb) < 0)
+             return (-1);
+           if ((*putc_cb)('\"', p) < 0)
+             return (-1);
+         }
+
+         col += width;
+       }
+
+       if (node->child)
+       {
+        /*
+         * Write children...
+         */
+
+         mxml_node_t *child;           /* Current child */
+
+
+         if ((*putc_cb)('>', p) < 0)
+           return (-1);
+         else
+           col ++;
+
+         col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
+
+          for (child = node->child; child; child = child->next)
+         {
+           if ((col = mxml_write_node(child, p, cb, col, putc_cb, global)) < 0)
+             return (-1);
+         }
+
+        /*
+         * The ? and ! elements are special-cases and have no end tags...
+         */
+
+         if (node->value.element.name[0] != '!' &&
+             node->value.element.name[0] != '?')
+         {
+           col = mxml_write_ws(node, p, cb, MXML_WS_BEFORE_CLOSE, col, 
putc_cb);
+
+           if ((*putc_cb)('<', p) < 0)
+             return (-1);
+           if ((*putc_cb)('/', p) < 0)
+             return (-1);
+           if (mxml_write_string(node->value.element.name, p, putc_cb) < 0)
+             return (-1);
+           if ((*putc_cb)('>', p) < 0)
+             return (-1);
+
+           col += strlen(node->value.element.name) + 3;
+
+           col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_CLOSE, col, putc_cb);
+         }
+       }
+       else if (node->value.element.name[0] == '!' ||
+                node->value.element.name[0] == '?')
+       {
+        /*
+         * The ? and ! elements are special-cases...
+         */
+
+         if ((*putc_cb)('>', p) < 0)
+           return (-1);
+         else
+           col ++;
+
+         col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
+       }
+       else
+       {
+         if ((*putc_cb)(' ', p) < 0)
+           return (-1);
+         if ((*putc_cb)('/', p) < 0)
+           return (-1);
+         if ((*putc_cb)('>', p) < 0)
+           return (-1);
+
+         col += 3;
+
+         col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
+       }
+       break;
+
+    case MXML_INTEGER :
+       if (node->prev)
+       {
+         if (global->wrap > 0 && col > global->wrap)
+         {
+           if ((*putc_cb)('\n', p) < 0)
+             return (-1);
+
+           col = 0;
+         }
+         else if ((*putc_cb)(' ', p) < 0)
+           return (-1);
+         else
+           col ++;
+       }
+
+       sprintf(s, "%d", node->value.integer);
+       if (mxml_write_string(s, p, putc_cb) < 0)
+         return (-1);
+
+       col += strlen(s);
+       break;
+
+    case MXML_OPAQUE :
+       if (mxml_write_string(node->value.opaque, p, putc_cb) < 0)
+         return (-1);
+
+       col += strlen(node->value.opaque);
+       break;
+
+    case MXML_REAL :
+       if (node->prev)
+       {
+         if (global->wrap > 0 && col > global->wrap)
+         {
+           if ((*putc_cb)('\n', p) < 0)
+             return (-1);
+
+           col = 0;
+         }
+         else if ((*putc_cb)(' ', p) < 0)
+           return (-1);
+         else
+           col ++;
+       }
+
+       sprintf(s, "%f", node->value.real);
+       if (mxml_write_string(s, p, putc_cb) < 0)
+         return (-1);
+
+       col += strlen(s);
+       break;
+
+    case MXML_TEXT :
+       if (node->value.text.whitespace && col > 0)
+       {
+         if (global->wrap > 0 && col > global->wrap)
+         {
+           if ((*putc_cb)('\n', p) < 0)
+             return (-1);
+
+           col = 0;
+         }
+         else if ((*putc_cb)(' ', p) < 0)
+           return (-1);
+         else
+           col ++;
+       }
+
+       if (mxml_write_string(node->value.text.string, p, putc_cb) < 0)
+         return (-1);
+
+       col += strlen(node->value.text.string);
+       break;
+
+    case MXML_CUSTOM :
+       if (global->custom_save_cb)
+       {
+         char  *data;          /* Custom data string */
+         const char    *newline;       /* Last newline in string */
+
+
+         if ((data = (*global->custom_save_cb)(node)) == NULL)
+           return (-1);
+
+         if (mxml_write_string(data, p, putc_cb) < 0)
+           return (-1);
+
+         if ((newline = strrchr(data, '\n')) == NULL)
+           col += strlen(data);
+         else
+           col = strlen(newline);
+
+         free(data);
+         break;
+       }
+
+    default : /* Should never happen */
+       return (-1);
+  }
+
+  return (col);
+}
+
+
+/*
+ * 'mxml_write_string()' - Write a string, escaping & and < as needed.
+ */
+
+static int                             /* O - 0 on success, -1 on failure */
+mxml_write_string(
+    const char      *s,                        /* I - String to write */
+    void            *p,                        /* I - Write pointer */
+    _mxml_putc_cb_t putc_cb)           /* I - Write callback */
+{
+  const char   *name;                  /* Entity name, if any */
+
+
+  while (*s)
+  {
+    if ((name = mxmlEntityGetName(*s)) != NULL)
+    {
+      if ((*putc_cb)('&', p) < 0)
+        return (-1);
+
+      while (*name)
+      {
+       if ((*putc_cb)(*name, p) < 0)
+          return (-1);
+        name ++;
+      }
+
+      if ((*putc_cb)(';', p) < 0)
+        return (-1);
+    }
+    else if ((*putc_cb)(*s, p) < 0)
+      return (-1);
+
+    s ++;
+  }
+
+  return (0);
+}
+
+
+/*
+ * 'mxml_write_ws()' - Do whitespace callback...
+ */
+
+static int                             /* O - New column */
+mxml_write_ws(mxml_node_t     *node,   /* I - Current node */
+              void            *p,      /* I - Write pointer */
+              mxml_save_cb_t  cb,      /* I - Callback function */
+             int             ws,       /* I - Where value */
+             int             col,      /* I - Current column */
+              _mxml_putc_cb_t putc_cb) /* I - Write callback */
+{
+  const char   *s;                     /* Whitespace string */
+
+
+  if (cb && (s = (*cb)(node, ws)) != NULL)
+  {
+    while (*s)
+    {
+      if ((*putc_cb)(*s, p) < 0)
+       return (-1);
+      else if (*s == '\n')
+       col = 0;
+      else if (*s == '\t')
+      {
+       col += MXML_TAB;
+       col = col - (col % MXML_TAB);
+      }
+      else
+       col ++;
+
+      s ++;
+    }
+  }
+
+  return (col);
+}
+
+
+/*
+ * End of "$Id: mxml-file.c 438 2011-03-24 05:47:51Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-file.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-get.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-get.c            
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-get.c    
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,471 @@
+/*
+ * "$Id: mxml-get.c 427 2011-01-03 02:03:29Z mike $"
+ *
+ * Node get functions for Mini-XML, a small XML-like file parsing library.
+ *
+ * Copyright 2011 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ *
+ * Contents:
+ *
+ *   mxmlGetCDATA()       - Get the value for a CDATA node.
+ *   mxmlGetCustom()      - Get the value for a custom node.
+ *   mxmlGetElement()     - Get the name for an element node.
+ *   mxmlGetFirstChild()  - Get the first child of an element node.
+ *   mxmlGetInteger()     - Get the integer value from the specified node or 
its
+ *                          first child.
+ *   mxmlGetLastChild()   - Get the last child of an element node.
+ *   mxmlGetNextSibling() - Get the next node for the current parent.
+ *   mxmlGetOpaque()      - Get an opaque string value for a node or its first
+ *                          child.
+ *   mxmlGetParent()      - Get the parent node.
+ *   mxmlGetPrevSibling() - Get the previous node for the current parent.
+ *   mxmlGetReal()        - Get the real value for a node or its first child.
+ *   mxmlGetText()        - Get the text value for a node or its first child.
+ *   mxmlGetType()        - Get the node type.
+ *   mxmlGetUserData()    - Get the user data pointer for a node.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml.h"
+
+
+/*
+ * 'mxmlGetCDATA()' - Get the value for a CDATA node.
+ *
+ * @code NULL@ is returned if the node is not a CDATA element.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+const char *                           /* O - CDATA value or NULL */
+mxmlGetCDATA(mxml_node_t *node)                /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node || node->type != MXML_ELEMENT ||
+      strncmp(node->value.element.name, "![CDATA[", 8))
+    return (NULL);
+
+ /*
+  * Return the text following the CDATA declaration...
+  */
+
+  return (node->value.element.name + 8);
+}
+
+
+/*
+ * 'mxmlGetCustom()' - Get the value for a custom node.
+ *
+ * @code NULL@ is returned if the node (or its first child) is not a custom
+ * value node.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+const void *                           /* O - Custom value or NULL */
+mxmlGetCustom(mxml_node_t *node)       /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+    return (NULL);
+
+ /*
+  * Return the integer value...
+  */
+
+  if (node->type == MXML_CUSTOM)
+    return (node->value.custom.data);
+  else if (node->type == MXML_ELEMENT &&
+           node->child &&
+          node->child->type == MXML_CUSTOM)
+    return (node->child->value.custom.data);
+  else
+    return (NULL);
+}
+
+
+/*
+ * 'mxmlGetElement()' - Get the name for an element node.
+ *
+ * @code NULL@ is returned if the node is not an element node.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+const char *                           /* O - Element name or NULL */
+mxmlGetElement(mxml_node_t *node)      /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node || node->type != MXML_ELEMENT)
+    return (NULL);
+
+ /*
+  * Return the element name...
+  */
+
+  return (node->value.element.name);
+}
+
+
+/*
+ * 'mxmlGetFirstChild()' - Get the first child of an element node.
+ *
+ * @code NULL@ is returned if the node is not an element node or if the node
+ * has no children.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+mxml_node_t *                          /* O - First child or NULL */
+mxmlGetFirstChild(mxml_node_t *node)   /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node || node->type != MXML_ELEMENT)
+    return (NULL);
+
+ /*
+  * Return the first child node...
+  */
+
+  return (node->child);
+}
+
+
+/*
+ * 'mxmlGetInteger()' - Get the integer value from the specified node or its
+ *                      first child.
+ *
+ * 0 is returned if the node (or its first child) is not an integer value node.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+int                                    /* O - Integer value or 0 */
+mxmlGetInteger(mxml_node_t *node)      /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+    return (0);
+
+ /*
+  * Return the integer value...
+  */
+
+  if (node->type == MXML_INTEGER)
+    return (node->value.integer);
+  else if (node->type == MXML_ELEMENT &&
+           node->child &&
+          node->child->type == MXML_INTEGER)
+    return (node->child->value.integer);
+  else
+    return (0);
+}
+
+
+/*
+ * 'mxmlGetLastChild()' - Get the last child of an element node.
+ *
+ * @code NULL@ is returned if the node is not an element node or if the node
+ * has no children.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+mxml_node_t *                          /* O - Last child or NULL */
+mxmlGetLastChild(mxml_node_t *node)    /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node || node->type != MXML_ELEMENT)
+    return (NULL);
+
+ /*
+  * Return the node type...
+  */
+
+  return (node->last_child);
+}
+
+
+/*
+ * 'mxmlGetNextSibling()' - Get the next node for the current parent.
+ *
+ * @code NULL@ is returned if this is the last child for the current parent.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+mxml_node_t *
+mxmlGetNextSibling(mxml_node_t *node)  /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+    return (NULL);
+
+ /*
+  * Return the node type...
+  */
+
+  return (node->next);
+}
+
+
+/*
+ * 'mxmlGetOpaque()' - Get an opaque string value for a node or its first 
child.
+ *
+ * @code NULL@ is returned if the node (or its first child) is not an opaque
+ * value node.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+const char *                           /* O - Opaque string or NULL */
+mxmlGetOpaque(mxml_node_t *node)       /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+    return (NULL);
+
+ /*
+  * Return the integer value...
+  */
+
+  if (node->type == MXML_OPAQUE)
+    return (node->value.opaque);
+  else if (node->type == MXML_ELEMENT &&
+           node->child &&
+          node->child->type == MXML_OPAQUE)
+    return (node->child->value.opaque);
+  else
+    return (NULL);
+}
+
+
+/*
+ * 'mxmlGetParent()' - Get the parent node.
+ *
+ * @code NULL@ is returned for a root node.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+mxml_node_t *                          /* O - Parent node or NULL */
+mxmlGetParent(mxml_node_t *node)       /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+    return (NULL);
+
+ /*
+  * Return the node type...
+  */
+
+  return (node->parent);
+}
+
+
+/*
+ * 'mxmlGetPrevSibling()' - Get the previous node for the current parent.
+ *
+ * @code NULL@ is returned if this is the first child for the current parent.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+mxml_node_t *                          /* O - Previous node or NULL */
+mxmlGetPrevSibling(mxml_node_t *node)  /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+    return (NULL);
+
+ /*
+  * Return the node type...
+  */
+
+  return (node->prev);
+}
+
+
+/*
+ * 'mxmlGetReal()' - Get the real value for a node or its first child.
+ *
+ * 0.0 is returned if the node (or its first child) is not a real value node.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+double                                 /* O - Real value or 0.0 */
+mxmlGetReal(mxml_node_t *node)         /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+    return (0.0);
+
+ /*
+  * Return the integer value...
+  */
+
+  if (node->type == MXML_REAL)
+    return (node->value.real);
+  else if (node->type == MXML_ELEMENT &&
+           node->child &&
+          node->child->type == MXML_REAL)
+    return (node->child->value.real);
+  else
+    return (0.0);
+}
+
+
+/*
+ * 'mxmlGetText()' - Get the text value for a node or its first child.
+ *
+ * @code NULL@ is returned if the node (or its first child) is not a text node.
+ * The "whitespace" argument can be NULL.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+const char *                           /* O - Text string or NULL */
+mxmlGetText(mxml_node_t *node,         /* I - Node to get */
+            int         *whitespace)   /* O - 1 if string is preceded by 
whitespace, 0 otherwise */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+  {
+    if (whitespace)
+      *whitespace = 0;
+
+    return (NULL);
+  }
+
+ /*
+  * Return the integer value...
+  */
+
+  if (node->type == MXML_TEXT)
+  {
+    if (whitespace)
+      *whitespace = node->value.text.whitespace;
+
+    return (node->value.text.string);
+  }
+  else if (node->type == MXML_ELEMENT &&
+           node->child &&
+          node->child->type == MXML_TEXT)
+  {
+    if (whitespace)
+      *whitespace = node->child->value.text.whitespace;
+
+    return (node->child->value.text.string);
+  }
+  else
+  {
+    if (whitespace)
+      *whitespace = 0;
+
+    return (NULL);
+  }
+}
+
+
+/*
+ * 'mxmlGetType()' - Get the node type.
+ *
+ * @code MXML_IGNORE@ is returned if "node" is @code address@hidden
+ *
+ * @since Mini-XML 2.7@
+ */
+
+mxml_type_t                            /* O - Type of node */
+mxmlGetType(mxml_node_t *node)         /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+    return (MXML_IGNORE);
+
+ /*
+  * Return the node type...
+  */
+
+  return (node->type);
+}
+
+
+/*
+ * 'mxmlGetUserData()' - Get the user data pointer for a node.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+void *                                 /* O - User data pointer */
+mxmlGetUserData(mxml_node_t *node)     /* I - Node to get */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+    return (NULL);
+
+ /*
+  * Return the user data pointer...
+  */
+
+  return (node->user_data);
+}
+
+
+/*
+ * End of "$Id: mxml-get.c 427 2011-01-03 02:03:29Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-get.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-index.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-index.c          
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-index.c  
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,662 @@
+/*
+ * "$Id: mxml-index.c 426 2011-01-01 23:42:17Z mike $"
+ *
+ * Index support code for Mini-XML, a small XML-like file parsing library.
+ *
+ * Copyright 2003-2011 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ *
+ * Contents:
+ *
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml.h"
+
+
+/*
+ * Sort functions...
+ */
+
+static int     index_compare(mxml_index_t *ind, mxml_node_t *first,
+                             mxml_node_t *second);
+static int     index_find(mxml_index_t *ind, const char *element,
+                          const char *value, mxml_node_t *node);
+static void    index_sort(mxml_index_t *ind, int left, int right);
+
+
+/*
+ * 'mxmlIndexDelete()' - Delete an index.
+ */
+
+void
+mxmlIndexDelete(mxml_index_t *ind)     /* I - Index to delete */
+{
+ /*
+  * Range check input..
+  */
+
+  if (!ind)
+    return;
+
+ /*
+  * Free memory...
+  */
+
+  if (ind->attr)
+    free(ind->attr);
+
+  if (ind->alloc_nodes)
+    free(ind->nodes);
+
+  free(ind);
+}
+
+
+/*
+ * 'mxmlIndexEnum()' - Return the next node in the index.
+ *
+ * Nodes are returned in the sorted order of the index.
+ */
+
+mxml_node_t *                          /* O - Next node or NULL if there is 
none */
+mxmlIndexEnum(mxml_index_t *ind)       /* I - Index to enumerate */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!ind)
+    return (NULL);
+
+ /*
+  * Return the next node...
+  */
+
+  if (ind->cur_node < ind->num_nodes)
+    return (ind->nodes[ind->cur_node ++]);
+  else
+    return (NULL);
+}
+
+
+/*
+ * 'mxmlIndexFind()' - Find the next matching node.
+ *
+ * You should call mxmlIndexReset() prior to using this function for
+ * the first time with a particular set of "element" and "value"
+ * strings. Passing NULL for both "element" and "value" is equivalent
+ * to calling mxmlIndexEnum().
+ */
+
+mxml_node_t *                          /* O - Node or NULL if none found */
+mxmlIndexFind(mxml_index_t *ind,       /* I - Index to search */
+              const char   *element,   /* I - Element name to find, if any */
+             const char   *value)      /* I - Attribute value, if any */
+{
+  int          diff,                   /* Difference between names */
+               current,                /* Current entity in search */
+               first,                  /* First entity in search */
+               last;                   /* Last entity in search */
+
+
+#ifdef DEBUG
+  printf("mxmlIndexFind(ind=%p, element=\"%s\", value=\"%s\")\n",
+         ind, element ? element : "(null)", value ? value : "(null)");
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!ind || (!ind->attr && value))
+  {
+#ifdef DEBUG
+    puts("    returning NULL...");
+    printf("    ind->attr=\"%s\"\n", ind->attr ? ind->attr : "(null)");
+#endif /* DEBUG */
+
+    return (NULL);
+  }
+
+ /*
+  * If both element and value are NULL, just enumerate the nodes in the
+  * index...
+  */
+
+  if (!element && !value)
+    return (mxmlIndexEnum(ind));
+
+ /*
+  * If there are no nodes in the index, return NULL...
+  */
+
+  if (!ind->num_nodes)
+  {
+#ifdef DEBUG
+    puts("    returning NULL...");
+    puts("    no nodes!");
+#endif /* DEBUG */
+
+    return (NULL);
+  }
+
+ /*
+  * If cur_node == 0, then find the first matching node...
+  */
+
+  if (ind->cur_node == 0)
+  {
+   /*
+    * Find the first node using a modified binary search algorithm...
+    */
+
+    first = 0;
+    last  = ind->num_nodes - 1;
+
+#ifdef DEBUG
+    printf("    find first time, num_nodes=%d...\n", ind->num_nodes);
+#endif /* DEBUG */
+
+    while ((last - first) > 1)
+    {
+      current = (first + last) / 2;
+
+#ifdef DEBUG
+      printf("    first=%d, last=%d, current=%d\n", first, last, current);
+#endif /* DEBUG */
+
+      if ((diff = index_find(ind, element, value, ind->nodes[current])) == 0)
+      {
+       /*
+        * Found a match, move back to find the first...
+       */
+
+#ifdef DEBUG
+        puts("    match!");
+#endif /* DEBUG */
+
+        while (current > 0 &&
+              !index_find(ind, element, value, ind->nodes[current - 1]))
+         current --;
+
+#ifdef DEBUG
+        printf("    returning first match=%d\n", current);
+#endif /* DEBUG */
+
+       /*
+        * Return the first match and save the index to the next...
+       */
+
+        ind->cur_node = current + 1;
+
+       return (ind->nodes[current]);
+      }
+      else if (diff < 0)
+       last = current;
+      else
+       first = current;
+
+#ifdef DEBUG
+      printf("    diff=%d\n", diff);
+#endif /* DEBUG */
+    }
+
+   /*
+    * If we get this far, then we found exactly 0 or 1 matches...
+    */
+
+    for (current = first; current <= last; current ++)
+      if (!index_find(ind, element, value, ind->nodes[current]))
+      {
+       /*
+       * Found exactly one (or possibly two) match...
+       */
+
+#ifdef DEBUG
+       printf("    returning only match %d...\n", current);
+#endif /* DEBUG */
+
+       ind->cur_node = current + 1;
+
+       return (ind->nodes[current]);
+      }
+
+   /*
+    * No matches...
+    */
+
+    ind->cur_node = ind->num_nodes;
+
+#ifdef DEBUG
+    puts("    returning NULL...");
+#endif /* DEBUG */
+
+    return (NULL);
+  }
+  else if (ind->cur_node < ind->num_nodes &&
+           !index_find(ind, element, value, ind->nodes[ind->cur_node]))
+  {
+   /*
+    * Return the next matching node...
+    */
+
+#ifdef DEBUG
+    printf("    returning next match %d...\n", ind->cur_node);
+#endif /* DEBUG */
+
+    return (ind->nodes[ind->cur_node ++]);
+  }
+
+ /*
+  * If we get this far, then we have no matches...
+  */
+
+  ind->cur_node = ind->num_nodes;
+
+#ifdef DEBUG
+  puts("    returning NULL...");
+#endif /* DEBUG */
+
+  return (NULL);
+}
+
+
+/*
+ * 'mxmlIndexGetCount()' - Get the number of nodes in an index.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+int                                    /* I - Number of nodes in index */
+mxmlIndexGetCount(mxml_index_t *ind)   /* I - Index of nodes */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!ind)
+    return (0);
+
+ /*
+  * Return the number of nodes in the index...
+  */
+
+  return (ind->num_nodes);
+}
+
+
+/*
+ * 'mxmlIndexNew()' - Create a new index.
+ *
+ * The index will contain all nodes that contain the named element and/or
+ * attribute. If both "element" and "attr" are NULL, then the index will
+ * contain a sorted list of the elements in the node tree.  Nodes are
+ * sorted by element name and optionally by attribute value if the "attr"
+ * argument is not NULL.
+ */
+
+mxml_index_t *                         /* O - New index */
+mxmlIndexNew(mxml_node_t *node,                /* I - XML node tree */
+             const char  *element,     /* I - Element to index or NULL for all 
*/
+             const char  *attr)                /* I - Attribute to index or 
NULL for none */
+{
+  mxml_index_t *ind;                   /* New index */
+  mxml_node_t  *current,               /* Current node in index */
+               **temp;                 /* Temporary node pointer array */
+
+
+ /*
+  * Range check input...
+  */
+
+#ifdef DEBUG
+  printf("mxmlIndexNew(node=%p, element=\"%s\", attr=\"%s\")\n",
+         node, element ? element : "(null)", attr ? attr : "(null)");
+#endif /* DEBUG */
+
+  if (!node)
+    return (NULL);
+
+ /*
+  * Create a new index...
+  */
+
+  if ((ind = calloc(1, sizeof(mxml_index_t))) == NULL)
+  {
+    mxml_error("Unable to allocate %d bytes for index - %s",
+               sizeof(mxml_index_t), strerror(errno));
+    return (NULL);
+  }
+
+  if (attr)
+    ind->attr = strdup(attr);
+
+  if (!element && !attr)
+    current = node;
+  else
+    current = mxmlFindElement(node, node, element, attr, NULL, MXML_DESCEND);
+
+  while (current)
+  {
+    if (ind->num_nodes >= ind->alloc_nodes)
+    {
+      if (!ind->alloc_nodes)
+        temp = malloc(64 * sizeof(mxml_node_t *));
+      else
+        temp = realloc(ind->nodes, (ind->alloc_nodes + 64) * 
sizeof(mxml_node_t *));
+
+      if (!temp)
+      {
+       /*
+        * Unable to allocate memory for the index, so abort...
+       */
+
+        mxml_error("Unable to allocate %d bytes for index: %s",
+                  (ind->alloc_nodes + 64) * sizeof(mxml_node_t *),
+                  strerror(errno));
+
+        mxmlIndexDelete(ind);
+       return (NULL);
+      }
+
+      ind->nodes       = temp;
+      ind->alloc_nodes += 64;
+    }
+
+    ind->nodes[ind->num_nodes ++] = current;
+
+    current = mxmlFindElement(current, node, element, attr, NULL, 
MXML_DESCEND);
+  }
+
+ /*
+  * Sort nodes based upon the search criteria...
+  */
+
+#ifdef DEBUG
+  {
+    int i;                             /* Looping var */
+
+
+    printf("%d node(s) in index.\n\n", ind->num_nodes);
+
+    if (attr)
+    {
+      printf("Node      Address   Element         %s\n", attr);
+      puts("--------  --------  --------------  
------------------------------");
+
+      for (i = 0; i < ind->num_nodes; i ++)
+       printf("%8d  %-8p  %-14.14s  %s\n", i, ind->nodes[i],
+              ind->nodes[i]->value.element.name,
+              mxmlElementGetAttr(ind->nodes[i], attr));
+    }
+    else
+    {
+      puts("Node      Address   Element");
+      puts("--------  --------  --------------");
+
+      for (i = 0; i < ind->num_nodes; i ++)
+       printf("%8d  %-8p  %s\n", i, ind->nodes[i],
+              ind->nodes[i]->value.element.name);
+    }
+
+    putchar('\n');
+  }
+#endif /* DEBUG */
+
+  if (ind->num_nodes > 1)
+    index_sort(ind, 0, ind->num_nodes - 1);
+
+#ifdef DEBUG
+  {
+    int i;                             /* Looping var */
+
+
+    puts("After sorting:\n");
+
+    if (attr)
+    {
+      printf("Node      Address   Element         %s\n", attr);
+      puts("--------  --------  --------------  
------------------------------");
+
+      for (i = 0; i < ind->num_nodes; i ++)
+       printf("%8d  %-8p  %-14.14s  %s\n", i, ind->nodes[i],
+              ind->nodes[i]->value.element.name,
+              mxmlElementGetAttr(ind->nodes[i], attr));
+    }
+    else
+    {
+      puts("Node      Address   Element");
+      puts("--------  --------  --------------");
+
+      for (i = 0; i < ind->num_nodes; i ++)
+       printf("%8d  %-8p  %s\n", i, ind->nodes[i],
+              ind->nodes[i]->value.element.name);
+    }
+
+    putchar('\n');
+  }
+#endif /* DEBUG */
+
+ /*
+  * Return the new index...
+  */
+
+  return (ind);
+}
+
+
+/*
+ * 'mxmlIndexReset()' - Reset the enumeration/find pointer in the index and
+ *                      return the first node in the index.
+ *
+ * This function should be called prior to using mxmlIndexEnum() or
+ * mxmlIndexFind() for the first time.
+ */
+
+mxml_node_t *                          /* O - First node or NULL if there is 
none */
+mxmlIndexReset(mxml_index_t *ind)      /* I - Index to reset */
+{
+#ifdef DEBUG
+  printf("mxmlIndexReset(ind=%p)\n", ind);
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!ind)
+    return (NULL);
+
+ /*
+  * Set the index to the first element...
+  */
+
+  ind->cur_node = 0;
+
+ /*
+  * Return the first node...
+  */
+
+  if (ind->num_nodes)
+    return (ind->nodes[0]);
+  else
+    return (NULL);
+}
+
+
+/*
+ * 'index_compare()' - Compare two nodes.
+ */
+
+static int                             /* O - Result of comparison */
+index_compare(mxml_index_t *ind,       /* I - Index */
+              mxml_node_t  *first,     /* I - First node */
+              mxml_node_t  *second)    /* I - Second node */
+{
+  int  diff;                           /* Difference */
+
+
+ /*
+  * Check the element name...
+  */
+
+  if ((diff = strcmp(first->value.element.name,
+                     second->value.element.name)) != 0)
+    return (diff);
+
+ /*
+  * Check the attribute value...
+  */
+
+  if (ind->attr)
+  {
+    if ((diff = strcmp(mxmlElementGetAttr(first, ind->attr),
+                       mxmlElementGetAttr(second, ind->attr))) != 0)
+      return (diff);
+  }
+
+ /*
+  * No difference, return 0...
+  */
+
+  return (0);
+}
+
+
+/*
+ * 'index_find()' - Compare a node with index values.
+ */
+
+static int                             /* O - Result of comparison */
+index_find(mxml_index_t *ind,          /* I - Index */
+           const char   *element,      /* I - Element name or NULL */
+          const char   *value,         /* I - Attribute value or NULL */
+           mxml_node_t  *node)         /* I - Node */
+{
+  int  diff;                           /* Difference */
+
+
+ /*
+  * Check the element name...
+  */
+
+  if (element)
+  {
+    if ((diff = strcmp(element, node->value.element.name)) != 0)
+      return (diff);
+  }
+
+ /*
+  * Check the attribute value...
+  */
+
+  if (value)
+  {
+    if ((diff = strcmp(value, mxmlElementGetAttr(node, ind->attr))) != 0)
+      return (diff);
+  }
+
+ /*
+  * No difference, return 0...
+  */
+
+  return (0);
+}
+
+
+/*
+ * 'index_sort()' - Sort the nodes in the index...
+ *
+ * This function implements the classic quicksort algorithm...
+ */
+
+static void
+index_sort(mxml_index_t *ind,          /* I - Index to sort */
+           int          left,          /* I - Left node in partition */
+          int          right)          /* I - Right node in partition */
+{
+  mxml_node_t  *pivot,                 /* Pivot node */
+               *temp;                  /* Swap node */
+  int          templ,                  /* Temporary left node */
+               tempr;                  /* Temporary right node */
+
+
+ /*
+  * Loop until we have sorted all the way to the right...
+  */
+
+  do
+  {
+   /*
+    * Sort the pivot in the current partition...
+    */
+
+    pivot = ind->nodes[left];
+
+    for (templ = left, tempr = right; templ < tempr;)
+    {
+     /*
+      * Move left while left node <= pivot node...
+      */
+
+      while ((templ < right) &&
+             index_compare(ind, ind->nodes[templ], pivot) <= 0)
+       templ ++;
+
+     /*
+      * Move right while right node > pivot node...
+      */
+
+      while ((tempr > left) &&
+             index_compare(ind, ind->nodes[tempr], pivot) > 0)
+       tempr --;
+
+     /*
+      * Swap nodes if needed...
+      */
+
+      if (templ < tempr)
+      {
+       temp              = ind->nodes[templ];
+       ind->nodes[templ] = ind->nodes[tempr];
+       ind->nodes[tempr] = temp;
+      }
+    }
+
+   /*
+    * When we get here, the right (tempr) node is the new position for the
+    * pivot node...
+    */
+
+    if (index_compare(ind, pivot, ind->nodes[tempr]) > 0)
+    {
+      ind->nodes[left]  = ind->nodes[tempr];
+      ind->nodes[tempr] = pivot;
+    }
+
+   /*
+    * Recursively sort the left partition as needed...
+    */
+
+    if (left < (tempr - 1))
+      index_sort(ind, left, tempr - 1);
+  }
+  while (right > (left = tempr + 1));
+}
+
+
+/*
+ * End of "$Id: mxml-index.c 426 2011-01-01 23:42:17Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-index.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-node.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-node.c           
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-node.c   
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,807 @@
+/*
+ * "$Id: mxml-node.c 436 2011-01-22 01:02:05Z mike $"
+ *
+ * Node support code for Mini-XML, a small XML-like file parsing library.
+ *
+ * Copyright 2003-2011 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ *
+ * Contents:
+ *
+ *   mxmlAdd()         - Add a node to a tree.
+ *   mxmlDelete()      - Delete a node and all of its children.
+ *   mxmlGetRefCount() - Get the current reference (use) count for a node.
+ *   mxmlNewCDATA()    - Create a new CDATA node.
+ *   mxmlNewCustom()   - Create a new custom data node.
+ *   mxmlNewElement()  - Create a new element node.
+ *   mxmlNewInteger()  - Create a new integer node.
+ *   mxmlNewOpaque()   - Create a new opaque string.
+ *   mxmlNewReal()     - Create a new real number node.
+ *   mxmlNewText()     - Create a new text fragment node.
+ *   mxmlNewTextf()    - Create a new formatted text fragment node.
+ *   mxmlRemove()      - Remove a node from its parent.
+ *   mxmlNewXML()      - Create a new XML document tree.
+ *   mxmlRelease()     - Release a node.
+ *   mxmlRetain()      - Retain a node.
+ *   mxml_new()        - Create a new node.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml.h"
+
+
+/*
+ * Local functions...
+ */
+
+static mxml_node_t     *mxml_new(mxml_node_t *parent, mxml_type_t type);
+
+
+/*
+ * 'mxmlAdd()' - Add a node to a tree.
+ *
+ * Adds the specified node to the parent. If the child argument is not
+ * NULL, puts the new node before or after the specified child depending
+ * on the value of the where argument. If the child argument is NULL,
+ * puts the new node at the beginning of the child list (MXML_ADD_BEFORE)
+ * or at the end of the child list (MXML_ADD_AFTER). The constant
+ * MXML_ADD_TO_PARENT can be used to specify a NULL child pointer.
+ */
+
+void
+mxmlAdd(mxml_node_t *parent,           /* I - Parent node */
+        int         where,             /* I - Where to add, MXML_ADD_BEFORE or 
MXML_ADD_AFTER */
+        mxml_node_t *child,            /* I - Child node for where or 
MXML_ADD_TO_PARENT */
+       mxml_node_t *node)              /* I - Node to add */
+{
+#ifdef DEBUG
+  fprintf(stderr, "mxmlAdd(parent=%p, where=%d, child=%p, node=%p)\n", parent,
+          where, child, node);
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!parent || !node)
+    return;
+
+#if DEBUG > 1
+  fprintf(stderr, "    BEFORE: node->parent=%p\n", node->parent);
+  if (parent)
+  {
+    fprintf(stderr, "    BEFORE: parent->child=%p\n", parent->child);
+    fprintf(stderr, "    BEFORE: parent->last_child=%p\n", parent->last_child);
+    fprintf(stderr, "    BEFORE: parent->prev=%p\n", parent->prev);
+    fprintf(stderr, "    BEFORE: parent->next=%p\n", parent->next);
+  }
+#endif /* DEBUG > 1 */
+
+ /*
+  * Remove the node from any existing parent...
+  */
+
+  if (node->parent)
+    mxmlRemove(node);
+
+ /*
+  * Reset pointers...
+  */
+
+  node->parent = parent;
+
+  switch (where)
+  {
+    case MXML_ADD_BEFORE :
+        if (!child || child == parent->child || child->parent != parent)
+       {
+        /*
+         * Insert as first node under parent...
+         */
+
+         node->next = parent->child;
+
+         if (parent->child)
+           parent->child->prev = node;
+         else
+           parent->last_child = node;
+
+         parent->child = node;
+       }
+       else
+       {
+        /*
+         * Insert node before this child...
+         */
+
+         node->next = child;
+         node->prev = child->prev;
+
+         if (child->prev)
+           child->prev->next = node;
+         else
+           parent->child = node;
+
+         child->prev = node;
+       }
+        break;
+
+    case MXML_ADD_AFTER :
+        if (!child || child == parent->last_child || child->parent != parent)
+       {
+        /*
+         * Insert as last node under parent...
+         */
+
+         node->parent = parent;
+         node->prev   = parent->last_child;
+
+         if (parent->last_child)
+           parent->last_child->next = node;
+         else
+           parent->child = node;
+
+         parent->last_child = node;
+        }
+       else
+       {
+        /*
+         * Insert node after this child...
+         */
+
+         node->prev = child;
+         node->next = child->next;
+
+         if (child->next)
+           child->next->prev = node;
+         else
+           parent->last_child = node;
+
+         child->next = node;
+       }
+        break;
+  }
+
+#if DEBUG > 1
+  fprintf(stderr, "    AFTER: node->parent=%p\n", node->parent);
+  if (parent)
+  {
+    fprintf(stderr, "    AFTER: parent->child=%p\n", parent->child);
+    fprintf(stderr, "    AFTER: parent->last_child=%p\n", parent->last_child);
+    fprintf(stderr, "    AFTER: parent->prev=%p\n", parent->prev);
+    fprintf(stderr, "    AFTER: parent->next=%p\n", parent->next);
+  }
+#endif /* DEBUG > 1 */
+}
+
+
+/*
+ * 'mxmlDelete()' - Delete a node and all of its children.
+ *
+ * If the specified node has a parent, this function first removes the
+ * node from its parent using the mxmlRemove() function.
+ */
+
+void
+mxmlDelete(mxml_node_t *node)          /* I - Node to delete */
+{
+  int  i;                              /* Looping var */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlDelete(node=%p)\n", node);
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+    return;
+
+ /*
+  * Remove the node from its parent, if any...
+  */
+
+  mxmlRemove(node);
+
+ /*
+  * Delete children...
+  */
+
+  while (node->child)
+    mxmlDelete(node->child);
+
+ /*
+  * Now delete any node data...
+  */
+
+  switch (node->type)
+  {
+    case MXML_ELEMENT :
+        if (node->value.element.name)
+         free(node->value.element.name);
+
+       if (node->value.element.num_attrs)
+       {
+         for (i = 0; i < node->value.element.num_attrs; i ++)
+         {
+           if (node->value.element.attrs[i].name)
+             free(node->value.element.attrs[i].name);
+           if (node->value.element.attrs[i].value)
+             free(node->value.element.attrs[i].value);
+         }
+
+          free(node->value.element.attrs);
+       }
+        break;
+    case MXML_INTEGER :
+       /* Nothing to do */
+        break;
+    case MXML_OPAQUE :
+        if (node->value.opaque)
+         free(node->value.opaque);
+        break;
+    case MXML_REAL :
+       /* Nothing to do */
+        break;
+    case MXML_TEXT :
+        if (node->value.text.string)
+         free(node->value.text.string);
+        break;
+    case MXML_CUSTOM :
+        if (node->value.custom.data &&
+           node->value.custom.destroy)
+         (*(node->value.custom.destroy))(node->value.custom.data);
+       break;
+    default :
+        break;
+  }
+
+ /*
+  * Free this node...
+  */
+
+  free(node);
+}
+
+
+/*
+ * 'mxmlGetRefCount()' - Get the current reference (use) count for a node.
+ *
+ * The initial reference count of new nodes is 1. Use the @link mxmlRetain@
+ * and @link mxmlRelease@ functions to increment and decrement a node's
+ * reference count.
+ *
+ * @since Mini-XML address@hidden
+ */
+
+int                                    /* O - Reference count */
+mxmlGetRefCount(mxml_node_t *node)     /* I - Node */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+    return (0);
+
+ /*
+  * Return the reference count...
+  */
+
+  return (node->ref_count);
+}
+
+
+/*
+ * 'mxmlNewCDATA()' - Create a new CDATA node.
+ *
+ * The new CDATA node is added to the end of the specified parent's child
+ * list. The constant MXML_NO_PARENT can be used to specify that the new
+ * CDATA node has no parent. The data string must be nul-terminated and
+ * is copied into the new node. CDATA nodes use the MXML_ELEMENT type.
+ *
+ * @since Mini-XML 2.3@
+ */
+
+mxml_node_t *                          /* O - New node */
+mxmlNewCDATA(mxml_node_t *parent,      /* I - Parent node or MXML_NO_PARENT */
+            const char  *data)         /* I - Data string */
+{
+  mxml_node_t  *node;                  /* New node */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlNewCDATA(parent=%p, data=\"%s\")\n",
+          parent, data ? data : "(null)");
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!data)
+    return (NULL);
+
+ /*
+  * Create the node and set the name value...
+  */
+
+  if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL)
+    node->value.element.name = _mxml_strdupf("![CDATA[%s]]", data);
+
+  return (node);
+}
+
+
+/*
+ * 'mxmlNewCustom()' - Create a new custom data node.
+ *
+ * The new custom node is added to the end of the specified parent's child
+ * list. The constant MXML_NO_PARENT can be used to specify that the new
+ * element node has no parent. NULL can be passed when the data in the
+ * node is not dynamically allocated or is separately managed.
+ *
+ * @since Mini-XML 2.1@
+ */
+
+mxml_node_t *                          /* O - New node */
+mxmlNewCustom(
+    mxml_node_t              *parent,  /* I - Parent node or MXML_NO_PARENT */
+    void                     *data,    /* I - Pointer to data */
+    mxml_custom_destroy_cb_t destroy)  /* I - Function to destroy data */
+{
+  mxml_node_t  *node;                  /* New node */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlNewCustom(parent=%p, data=%p, destroy=%p)\n", parent,
+          data, destroy);
+#endif /* DEBUG */
+
+ /*
+  * Create the node and set the value...
+  */
+
+  if ((node = mxml_new(parent, MXML_CUSTOM)) != NULL)
+  {
+    node->value.custom.data    = data;
+    node->value.custom.destroy = destroy;
+  }
+
+  return (node);
+}
+
+
+/*
+ * 'mxmlNewElement()' - Create a new element node.
+ *
+ * The new element node is added to the end of the specified parent's child
+ * list. The constant MXML_NO_PARENT can be used to specify that the new
+ * element node has no parent.
+ */
+
+mxml_node_t *                          /* O - New node */
+mxmlNewElement(mxml_node_t *parent,    /* I - Parent node or MXML_NO_PARENT */
+               const char  *name)      /* I - Name of element */
+{
+  mxml_node_t  *node;                  /* New node */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlNewElement(parent=%p, name=\"%s\")\n", parent,
+          name ? name : "(null)");
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!name)
+    return (NULL);
+
+ /*
+  * Create the node and set the element name...
+  */
+
+  if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL)
+    node->value.element.name = strdup(name);
+
+  return (node);
+}
+
+
+/*
+ * 'mxmlNewInteger()' - Create a new integer node.
+ *
+ * The new integer node is added to the end of the specified parent's child
+ * list. The constant MXML_NO_PARENT can be used to specify that the new
+ * integer node has no parent.
+ */
+
+mxml_node_t *                          /* O - New node */
+mxmlNewInteger(mxml_node_t *parent,    /* I - Parent node or MXML_NO_PARENT */
+               int         integer)    /* I - Integer value */
+{
+  mxml_node_t  *node;                  /* New node */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlNewInteger(parent=%p, integer=%d)\n", parent, integer);
+#endif /* DEBUG */
+
+ /*
+  * Create the node and set the element name...
+  */
+
+  if ((node = mxml_new(parent, MXML_INTEGER)) != NULL)
+    node->value.integer = integer;
+
+  return (node);
+}
+
+
+/*
+ * 'mxmlNewOpaque()' - Create a new opaque string.
+ *
+ * The new opaque node is added to the end of the specified parent's child
+ * list. The constant MXML_NO_PARENT can be used to specify that the new
+ * opaque node has no parent. The opaque string must be nul-terminated and
+ * is copied into the new node.
+ */
+
+mxml_node_t *                          /* O - New node */
+mxmlNewOpaque(mxml_node_t *parent,     /* I - Parent node or MXML_NO_PARENT */
+              const char  *opaque)     /* I - Opaque string */
+{
+  mxml_node_t  *node;                  /* New node */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlNewOpaque(parent=%p, opaque=\"%s\")\n", parent,
+          opaque ? opaque : "(null)");
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!opaque)
+    return (NULL);
+
+ /*
+  * Create the node and set the element name...
+  */
+
+  if ((node = mxml_new(parent, MXML_OPAQUE)) != NULL)
+    node->value.opaque = strdup(opaque);
+
+  return (node);
+}
+
+
+/*
+ * 'mxmlNewReal()' - Create a new real number node.
+ *
+ * The new real number node is added to the end of the specified parent's
+ * child list. The constant MXML_NO_PARENT can be used to specify that
+ * the new real number node has no parent.
+ */
+
+mxml_node_t *                          /* O - New node */
+mxmlNewReal(mxml_node_t *parent,       /* I - Parent node or MXML_NO_PARENT */
+            double      real)          /* I - Real number value */
+{
+  mxml_node_t  *node;                  /* New node */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlNewReal(parent=%p, real=%g)\n", parent, real);
+#endif /* DEBUG */
+
+ /*
+  * Create the node and set the element name...
+  */
+
+  if ((node = mxml_new(parent, MXML_REAL)) != NULL)
+    node->value.real = real;
+
+  return (node);
+}
+
+
+/*
+ * 'mxmlNewText()' - Create a new text fragment node.
+ *
+ * The new text node is added to the end of the specified parent's child
+ * list. The constant MXML_NO_PARENT can be used to specify that the new
+ * text node has no parent. The whitespace parameter is used to specify
+ * whether leading whitespace is present before the node. The text
+ * string must be nul-terminated and is copied into the new node.  
+ */
+
+mxml_node_t *                          /* O - New node */
+mxmlNewText(mxml_node_t *parent,       /* I - Parent node or MXML_NO_PARENT */
+            int         whitespace,    /* I - 1 = leading whitespace, 0 = no 
whitespace */
+           const char  *string)        /* I - String */
+{
+  mxml_node_t  *node;                  /* New node */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlNewText(parent=%p, whitespace=%d, string=\"%s\")\n",
+          parent, whitespace, string ? string : "(null)");
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!string)
+    return (NULL);
+
+ /*
+  * Create the node and set the text value...
+  */
+
+  if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
+  {
+    node->value.text.whitespace = whitespace;
+    node->value.text.string     = strdup(string);
+  }
+
+  return (node);
+}
+
+
+/*
+ * 'mxmlNewTextf()' - Create a new formatted text fragment node.
+ *
+ * The new text node is added to the end of the specified parent's child
+ * list. The constant MXML_NO_PARENT can be used to specify that the new
+ * text node has no parent. The whitespace parameter is used to specify
+ * whether leading whitespace is present before the node. The format
+ * string must be nul-terminated and is formatted into the new node.  
+ */
+
+mxml_node_t *                          /* O - New node */
+mxmlNewTextf(mxml_node_t *parent,      /* I - Parent node or MXML_NO_PARENT */
+             int         whitespace,   /* I - 1 = leading whitespace, 0 = no 
whitespace */
+            const char  *format,       /* I - Printf-style frmat string */
+            ...)                       /* I - Additional args as needed */
+{
+  mxml_node_t  *node;                  /* New node */
+  va_list      ap;                     /* Pointer to arguments */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlNewTextf(parent=%p, whitespace=%d, format=\"%s\", 
...)\n",
+          parent, whitespace, format ? format : "(null)");
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!format)
+    return (NULL);
+
+ /*
+  * Create the node and set the text value...
+  */
+
+  if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
+  {
+    va_start(ap, format);
+
+    node->value.text.whitespace = whitespace;
+    node->value.text.string     = _mxml_vstrdupf(format, ap);
+
+    va_end(ap);
+  }
+
+  return (node);
+}
+
+
+/*
+ * 'mxmlRemove()' - Remove a node from its parent.
+ *
+ * Does not free memory used by the node - use mxmlDelete() for that.
+ * This function does nothing if the node has no parent.
+ */
+
+void
+mxmlRemove(mxml_node_t *node)          /* I - Node to remove */
+{
+#ifdef DEBUG
+  fprintf(stderr, "mxmlRemove(node=%p)\n", node);
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!node || !node->parent)
+    return;
+
+ /*
+  * Remove from parent...
+  */
+
+#if DEBUG > 1
+  fprintf(stderr, "    BEFORE: node->parent=%p\n", node->parent);
+  if (node->parent)
+  {
+    fprintf(stderr, "    BEFORE: node->parent->child=%p\n", 
node->parent->child);
+    fprintf(stderr, "    BEFORE: node->parent->last_child=%p\n", 
node->parent->last_child);
+  }
+  fprintf(stderr, "    BEFORE: node->child=%p\n", node->child);
+  fprintf(stderr, "    BEFORE: node->last_child=%p\n", node->last_child);
+  fprintf(stderr, "    BEFORE: node->prev=%p\n", node->prev);
+  fprintf(stderr, "    BEFORE: node->next=%p\n", node->next);
+#endif /* DEBUG > 1 */
+
+  if (node->prev)
+    node->prev->next = node->next;
+  else
+    node->parent->child = node->next;
+
+  if (node->next)
+    node->next->prev = node->prev;
+  else
+    node->parent->last_child = node->prev;
+
+  node->parent = NULL;
+  node->prev   = NULL;
+  node->next   = NULL;
+
+#if DEBUG > 1
+  fprintf(stderr, "    AFTER: node->parent=%p\n", node->parent);
+  if (node->parent)
+  {
+    fprintf(stderr, "    AFTER: node->parent->child=%p\n", 
node->parent->child);
+    fprintf(stderr, "    AFTER: node->parent->last_child=%p\n", 
node->parent->last_child);
+  }
+  fprintf(stderr, "    AFTER: node->child=%p\n", node->child);
+  fprintf(stderr, "    AFTER: node->last_child=%p\n", node->last_child);
+  fprintf(stderr, "    AFTER: node->prev=%p\n", node->prev);
+  fprintf(stderr, "    AFTER: node->next=%p\n", node->next);
+#endif /* DEBUG > 1 */
+}
+
+
+/*
+ * 'mxmlNewXML()' - Create a new XML document tree.
+ *
+ * The "version" argument specifies the version number to put in the
+ * ?xml element node. If NULL, version 1.0 is assumed.
+ *
+ * @since Mini-XML 2.3@
+ */
+
+mxml_node_t *                          /* O - New ?xml node */
+mxmlNewXML(const char *version)                /* I - Version number to use */
+{
+  char element[1024];                  /* Element text */
+
+
+  snprintf(element, sizeof(element), "?xml version=\"%s\" encoding=\"utf-8\"?",
+           version ? version : "1.0");
+
+  return (mxmlNewElement(NULL, element));
+}
+
+
+/*
+ * 'mxmlRelease()' - Release a node.
+ *
+ * When the reference count reaches zero, the node (and any children)
+ * is deleted via mxmlDelete().
+ *
+ * @since Mini-XML 2.3@
+ */
+
+int                                    /* O - New reference count */
+mxmlRelease(mxml_node_t *node)         /* I - Node */
+{
+  if (node)
+  {
+    if ((-- node->ref_count) <= 0)
+    {
+      mxmlDelete(node);
+      return (0);
+    }
+    else
+      return (node->ref_count);
+  }
+  else
+    return (-1);
+}
+
+
+/*
+ * 'mxmlRetain()' - Retain a node.
+ *
+ * @since Mini-XML 2.3@
+ */
+
+int                                    /* O - New reference count */
+mxmlRetain(mxml_node_t *node)          /* I - Node */
+{
+  if (node)
+    return (++ node->ref_count);
+  else
+    return (-1);
+}
+
+
+/*
+ * 'mxml_new()' - Create a new node.
+ */
+
+static mxml_node_t *                   /* O - New node */
+mxml_new(mxml_node_t *parent,          /* I - Parent node */
+         mxml_type_t type)             /* I - Node type */
+{
+  mxml_node_t  *node;                  /* New node */
+
+
+#if DEBUG > 1
+  fprintf(stderr, "mxml_new(parent=%p, type=%d)\n", parent, type);
+#endif /* DEBUG > 1 */
+
+ /*
+  * Allocate memory for the node...
+  */
+
+  if ((node = calloc(1, sizeof(mxml_node_t))) == NULL)
+  {
+#if DEBUG > 1
+    fputs("    returning NULL\n", stderr);
+#endif /* DEBUG > 1 */
+
+    return (NULL);
+  }
+
+#if DEBUG > 1
+  fprintf(stderr, "    returning %p\n", node);
+#endif /* DEBUG > 1 */
+
+ /*
+  * Set the node type...
+  */
+
+  node->type      = type;
+  node->ref_count = 1;
+
+ /*
+  * Add to the parent if present...
+  */
+
+  if (parent)
+    mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
+
+ /*
+  * Return the new node...
+  */
+
+  return (node);
+}
+
+
+/*
+ * End of "$Id: mxml-node.c 436 2011-01-22 01:02:05Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-node.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-private.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-private.c        
                        (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-private.c        
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,331 @@
+/*
+ * "$Id: mxml-private.c 422 2010-11-07 22:55:11Z mike $"
+ *
+ * Private functions for Mini-XML, a small XML-like file parsing library.
+ *
+ * Copyright 2003-2010 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ *
+ * Contents:
+ *
+ *   mxml_error()      - Display an error message.
+ *   mxml_integer_cb() - Default callback for integer values.
+ *   mxml_opaque_cb()  - Default callback for opaque values.
+ *   mxml_real_cb()    - Default callback for real number values.
+ *   _mxml_global()    - Get global data.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "mxml-private.h"
+
+
+/*
+ * Some crazy people think that unloading a shared object is a good or safe
+ * thing to do.  Unfortunately, most objects are simply *not* safe to unload
+ * and bad things *will* happen.
+ *
+ * The following mess of conditional code allows us to provide a destructor
+ * function in Mini-XML for our thread-global storage so that it can possibly
+ * be unloaded safely, although since there is no standard way to do so I
+ * can't even provide any guarantees that you can do it safely on all 
platforms.
+ *
+ * This code currently supports AIX, HP-UX, Linux, Mac OS X, Solaris, and
+ * Windows.  It might work on the BSDs and IRIX, but I haven't tested that.
+ */
+
+#if defined(__sun) || defined(_AIX)
+#  pragma fini(_mxml_fini)
+#  define _MXML_FINI _mxml_fini
+#elif defined(__hpux)
+#  pragma FINI _mxml_fini
+#  define _MXML_FINI _mxml_fini
+#elif defined(__GNUC__) /* Linux and Mac OS X */
+#  define _MXML_FINI __attribute((destructor)) _mxml_fini
+#else
+#  define _MXML_FINI _fini
+#endif /* __sun */
+
+
+/*
+ * 'mxml_error()' - Display an error message.
+ */
+
+void
+mxml_error(const char *format,         /* I - Printf-style format string */
+           ...)                                /* I - Additional arguments as 
needed */
+{
+  va_list      ap;                     /* Pointer to arguments */
+  char         s[1024];                /* Message string */
+  _mxml_global_t *global = _mxml_global();
+                                       /* Global data */
+
+
+ /*
+  * Range check input...
+  */
+
+  if (!format)
+    return;
+
+ /*
+  * Format the error message string...
+  */
+
+  va_start(ap, format);
+
+  vsnprintf(s, sizeof(s), format, ap);
+
+  va_end(ap);
+
+ /*
+  * And then display the error message...
+  */
+
+  if (global->error_cb)
+    (*global->error_cb)(s);
+  else
+    fprintf(stderr, "mxml: %s\n", s);
+}
+
+
+/*
+ * 'mxml_ignore_cb()' - Default callback for ignored values.
+ */
+
+mxml_type_t                            /* O - Node type */
+mxml_ignore_cb(mxml_node_t *node)      /* I - Current node */
+{
+  (void)node;
+
+  return (MXML_IGNORE);
+}
+
+
+/*
+ * 'mxml_integer_cb()' - Default callback for integer values.
+ */
+
+mxml_type_t                            /* O - Node type */
+mxml_integer_cb(mxml_node_t *node)     /* I - Current node */
+{
+  (void)node;
+
+  return (MXML_INTEGER);
+}
+
+
+/*
+ * 'mxml_opaque_cb()' - Default callback for opaque values.
+ */
+
+mxml_type_t                            /* O - Node type */
+mxml_opaque_cb(mxml_node_t *node)      /* I - Current node */
+{
+  (void)node;
+
+  return (MXML_OPAQUE);
+}
+
+
+/*
+ * 'mxml_real_cb()' - Default callback for real number values.
+ */
+
+mxml_type_t                            /* O - Node type */
+mxml_real_cb(mxml_node_t *node)                /* I - Current node */
+{
+  (void)node;
+
+  return (MXML_REAL);
+}
+
+
+#ifdef HAVE_PTHREAD_H                  /**** POSIX threading ****/
+#  include <pthread.h>
+
+static pthread_key_t   _mxml_key = -1; /* Thread local storage key */
+static pthread_once_t  _mxml_key_once = PTHREAD_ONCE_INIT;
+                                       /* One-time initialization object */
+static void            _mxml_init(void);
+static void            _mxml_destructor(void *g);
+
+
+/*
+ * '_mxml_destructor()' - Free memory used for globals...
+ */
+
+static void
+_mxml_destructor(void *g)              /* I - Global data */
+{
+  free(g);
+}
+
+
+/*
+ * '_mxml_fini()' - Clean up when unloaded.
+ */
+
+static void
+_MXML_FINI(void)
+{
+  _mxml_global_t       *global;        /* Global data */
+
+
+  if (_mxml_key != -1)
+  {
+    if ((global = (_mxml_global_t *)pthread_getspecific(_mxml_key)) != NULL)
+      _mxml_destructor(global);
+
+    pthread_key_delete(_mxml_key);
+    _mxml_key = -1;
+  }
+}
+
+
+/*
+ * '_mxml_global()' - Get global data.
+ */
+
+_mxml_global_t *                       /* O - Global data */
+_mxml_global(void)
+{
+  _mxml_global_t       *global;        /* Global data */
+
+
+  pthread_once(&_mxml_key_once, _mxml_init);
+
+  if ((global = (_mxml_global_t *)pthread_getspecific(_mxml_key)) == NULL)
+  {
+    global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
+    pthread_setspecific(_mxml_key, global);
+
+    global->num_entity_cbs = 1;
+    global->entity_cbs[0]  = _mxml_entity_cb;
+    global->wrap           = 72;
+  }
+
+  return (global);
+}
+
+
+/*
+ * '_mxml_init()' - Initialize global data...
+ */
+
+static void
+_mxml_init(void)
+{
+  pthread_key_create(&_mxml_key, _mxml_destructor);
+}
+
+
+#elif defined(WIN32) && defined(MXML1_EXPORTS) /**** WIN32 threading ****/
+#  include <windows.h>
+
+static DWORD _mxml_tls_index;          /* Index for global storage */
+
+
+/*
+ * 'DllMain()' - Main entry for library.
+ */
+ 
+BOOL WINAPI                            /* O - Success/failure */
+DllMain(HINSTANCE hinst,               /* I - DLL module handle */
+        DWORD     reason,              /* I - Reason */
+        LPVOID    reserved)            /* I - Unused */
+{
+  _mxml_global_t       *global;        /* Global data */
+
+
+  (void)hinst;
+  (void)reserved;
+
+  switch (reason) 
+  { 
+    case DLL_PROCESS_ATTACH :          /* Called on library initialization */
+        if ((_mxml_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) 
+          return (FALSE); 
+        break; 
+
+    case DLL_THREAD_DETACH :           /* Called when a thread terminates */
+        if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
+          free(global);
+        break; 
+
+    case DLL_PROCESS_DETACH :          /* Called when library is unloaded */
+        if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
+          free(global);
+
+        TlsFree(_mxml_tls_index); 
+        break; 
+
+    default: 
+        break; 
+  } 
+
+  return (TRUE);
+}
+
+
+/*
+ * '_mxml_global()' - Get global data.
+ */
+
+_mxml_global_t *                       /* O - Global data */
+_mxml_global(void)
+{
+  _mxml_global_t       *global;        /* Global data */
+
+
+  if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) == NULL)
+  {
+    global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
+
+    global->num_entity_cbs = 1;
+    global->entity_cbs[0]  = _mxml_entity_cb;
+    global->wrap           = 72;
+
+    TlsSetValue(_mxml_tls_index, (LPVOID)global); 
+  }
+
+  return (global);
+}
+
+
+#else                                  /**** No threading ****/
+/*
+ * '_mxml_global()' - Get global data.
+ */
+
+_mxml_global_t *                       /* O - Global data */
+_mxml_global(void)
+{
+  static _mxml_global_t        global =        /* Global data */
+  {
+    NULL,                              /* error_cb */
+    1,                                 /* num_entity_cbs */
+    { _mxml_entity_cb },               /* entity_cbs */
+    72,                                        /* wrap */
+    NULL,                              /* custom_load_cb */
+    NULL                               /* custom_save_cb */
+  };
+
+
+  return (&global);
+}
+#endif /* HAVE_PTHREAD_H */
+
+
+/*
+ * End of "$Id: mxml-private.c 422 2010-11-07 22:55:11Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-private.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-private.h
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-private.h        
                        (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-private.h        
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,50 @@
+/*
+ * "$Id: mxml-private.h 408 2010-09-19 05:26:46Z mike $"
+ *
+ * Private definitions for Mini-XML, a small XML-like file parsing library.
+ *
+ * Copyright 2003-2010 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml.h"
+
+
+/*
+ * Global, per-thread data...
+ */
+
+typedef struct _mxml_global_s
+{
+  void (*error_cb)(const char *);
+  int  num_entity_cbs;
+  int  (*entity_cbs[100])(const char *name);
+  int  wrap;
+  mxml_custom_load_cb_t        custom_load_cb;
+  mxml_custom_save_cb_t        custom_save_cb;
+} _mxml_global_t;
+
+
+/*
+ * Functions...
+ */
+
+extern _mxml_global_t  *_mxml_global(void);
+extern int             _mxml_entity_cb(const char *name);
+
+
+/*
+ * End of "$Id: mxml-private.h 408 2010-09-19 05:26:46Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-private.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-search.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-search.c         
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-search.c 
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,287 @@
+/*
+ * "$Id: mxml-search.c 427 2011-01-03 02:03:29Z mike $"
+ *
+ * Search/navigation functions for Mini-XML, a small XML-like file
+ * parsing library.
+ *
+ * Copyright 2003-2010 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ *
+ * Contents:
+ *
+ *   mxmlFindElement() - Find the named element.
+ *   mxmlFindValue()   - Find a value with the given path.
+ *   mxmlWalkNext()    - Walk to the next logical node in the tree.
+ *   mxmlWalkPrev()    - Walk to the previous logical node in the tree.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml.h"
+
+
+/*
+ * 'mxmlFindElement()' - Find the named element.
+ *
+ * The search is constrained by the name, attribute name, and value; any
+ * NULL names or values are treated as wildcards, so different kinds of
+ * searches can be implemented by looking for all elements of a given name
+ * or all elements with a specific attribute. The descend argument determines
+ * whether the search descends into child nodes; normally you will use
+ * MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find
+ * additional direct descendents of the node. The top node argument
+ * constrains the search to a particular node's children.
+ */
+
+mxml_node_t *                          /* O - Element node or NULL */
+mxmlFindElement(mxml_node_t *node,     /* I - Current node */
+                mxml_node_t *top,      /* I - Top node */
+                const char  *name,     /* I - Element name or NULL for any */
+               const char  *attr,      /* I - Attribute name, or NULL for none 
*/
+               const char  *value,     /* I - Attribute value, or NULL for any 
*/
+               int         descend)    /* I - Descend into tree - 
MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
+{
+  const char   *temp;                  /* Current attribute value */
+
+
+ /*
+  * Range check input...
+  */
+
+  if (!node || !top || (!attr && value))
+    return (NULL);
+
+ /*
+  * Start with the next node...
+  */
+
+  node = mxmlWalkNext(node, top, descend);
+
+ /*
+  * Loop until we find a matching element...
+  */
+
+  while (node != NULL)
+  {
+   /*
+    * See if this node matches...
+    */
+
+    if (node->type == MXML_ELEMENT &&
+        node->value.element.name &&
+       (!name || !strcmp(node->value.element.name, name)))
+    {
+     /*
+      * See if we need to check for an attribute...
+      */
+
+      if (!attr)
+        return (node);                 /* No attribute search, return it... */
+
+     /*
+      * Check for the attribute...
+      */
+
+      if ((temp = mxmlElementGetAttr(node, attr)) != NULL)
+      {
+       /*
+        * OK, we have the attribute, does it match?
+       */
+
+       if (!value || !strcmp(value, temp))
+         return (node);                /* Yes, return it... */
+      }
+    }
+
+   /*
+    * No match, move on to the next node...
+    */
+
+    if (descend == MXML_DESCEND)
+      node = mxmlWalkNext(node, top, MXML_DESCEND);
+    else
+      node = node->next;
+  }
+
+  return (NULL);
+}
+
+
+/*
+ * 'mxmlFindPath()' - Find a node with the given path.
+ *
+ * The "path" is a slash-separated list of element names. The name "*" is
+ * considered a wildcard for one or more levels of elements.  For example,
+ * "foo/one/two", "bar/two/one", "*\/one", and so forth.
+ *
+ * The first child node of the found node is returned if the given node has
+ * children and the first child is a value node.
+ * 
+ * @since Mini-XML 2.7@
+ */
+
+mxml_node_t *                          /* O - Found node or NULL */
+mxmlFindPath(mxml_node_t *top,         /* I - Top node */
+            const char  *path)         /* I - Path to element */
+{
+  mxml_node_t  *node;                  /* Current node */
+  char         element[256];           /* Current element name */
+  const char   *pathsep;               /* Separator in path */
+  int          descend;                /* mxmlFindElement option */
+
+
+ /*
+  * Range check input...
+  */
+
+  if (!top || !path || !*path)
+    return (NULL);
+
+ /*
+  * Search each element in the path...
+  */
+
+  node = top;
+  while (*path)
+  {
+   /*
+    * Handle wildcards...
+    */
+
+    if (!strncmp(path, "*/", 2))
+    {
+      path += 2;
+      descend = MXML_DESCEND;
+    }
+    else
+      descend = MXML_DESCEND_FIRST;
+
+   /*
+    * Get the next element in the path...
+    */
+
+    if ((pathsep = strchr(path, '/')) == NULL)
+      pathsep = path + strlen(path);
+
+    if (pathsep == path || (pathsep - path) >= sizeof(element))
+      return (NULL);
+
+    memcpy(element, path, pathsep - path);
+    element[pathsep - path] = '\0';
+
+    if (*pathsep)
+      path = pathsep + 1;
+    else
+      path = pathsep;
+
+   /*
+    * Search for the element...
+    */
+
+    if ((node = mxmlFindElement(node, node, element, NULL, NULL,
+                                descend)) == NULL)
+      return (NULL);
+  }
+
+ /*
+  * If we get this far, return the node or its first child...
+  */
+
+  if (node->child && node->child->type != MXML_ELEMENT)
+    return (node->child);
+  else
+    return (node);
+}
+
+
+/*
+ * 'mxmlWalkNext()' - Walk to the next logical node in the tree.
+ *
+ * The descend argument controls whether the first child is considered
+ * to be the next node. The top node argument constrains the walk to
+ * the node's children.
+ */
+
+mxml_node_t *                          /* O - Next node or NULL */
+mxmlWalkNext(mxml_node_t *node,                /* I - Current node */
+             mxml_node_t *top,         /* I - Top node */
+             int         descend)      /* I - Descend into tree - 
MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
+{
+  if (!node)
+    return (NULL);
+  else if (node->child && descend)
+    return (node->child);
+  else if (node == top)
+    return (NULL);
+  else if (node->next)
+    return (node->next);
+  else if (node->parent && node->parent != top)
+  {
+    node = node->parent;
+
+    while (!node->next)
+      if (node->parent == top || !node->parent)
+        return (NULL);
+      else
+        node = node->parent;
+
+    return (node->next);
+  }
+  else
+    return (NULL);
+}
+
+
+/*
+ * 'mxmlWalkPrev()' - Walk to the previous logical node in the tree.
+ *
+ * The descend argument controls whether the previous node's last child
+ * is considered to be the previous node. The top node argument constrains
+ * the walk to the node's children.
+ */
+
+mxml_node_t *                          /* O - Previous node or NULL */
+mxmlWalkPrev(mxml_node_t *node,                /* I - Current node */
+             mxml_node_t *top,         /* I - Top node */
+             int         descend)      /* I - Descend into tree - 
MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
+{
+  if (!node || node == top)
+    return (NULL);
+  else if (node->prev)
+  {
+    if (node->prev->last_child && descend)
+    {
+     /*
+      * Find the last child under the previous node...
+      */
+
+      node = node->prev->last_child;
+
+      while (node->last_child)
+        node = node->last_child;
+
+      return (node);
+    }
+    else
+      return (node->prev);
+  }
+  else if (node->parent != top)
+    return (node->parent);
+  else
+    return (NULL);
+}
+
+
+/*
+ * End of "$Id: mxml-search.c 427 2011-01-03 02:03:29Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-search.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-set.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-set.c            
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-set.c    
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,349 @@
+/*
+ * "$Id: mxml-set.c 441 2011-12-09 23:49:00Z mike $"
+ *
+ * Node set functions for Mini-XML, a small XML-like file parsing library.
+ *
+ * Copyright 2003-2011 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ *
+ * Contents:
+ *
+ *   mxmlSetCDATA()    - Set the element name of a CDATA node.
+ *   mxmlSetCustom()   - Set the data and destructor of a custom data node.
+ *   mxmlSetElement()  - Set the name of an element node.
+ *   mxmlSetInteger()  - Set the value of an integer node.
+ *   mxmlSetOpaque()   - Set the value of an opaque node.
+ *   mxmlSetReal()     - Set the value of a real number node.
+ *   mxmlSetText()     - Set the value of a text node.
+ *   mxmlSetTextf()    - Set the value of a text node to a formatted string.
+ *   mxmlSetUserData() - Set the user data pointer for a node.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml.h"
+
+
+/*
+ * 'mxmlSetCDATA()' - Set the element name of a CDATA node.
+ *
+ * The node is not changed if it (or its first child) is not a CDATA element 
node.
+ *
+ * @since Mini-XML 2.3@
+ */
+
+int                                    /* O - 0 on success, -1 on failure */
+mxmlSetCDATA(mxml_node_t *node,                /* I - Node to set */
+             const char  *data)                /* I - New data string */
+{
+ /*
+  * Range check input...
+  */
+
+  if (node && node->type == MXML_ELEMENT &&
+      strncmp(node->value.element.name, "![CDATA[", 8) &&
+      node->child && node->child->type == MXML_ELEMENT &&
+      !strncmp(node->child->value.element.name, "![CDATA[", 8))
+    node = node->child;
+
+  if (!node || node->type != MXML_ELEMENT || !data ||
+      strncmp(node->value.element.name, "![CDATA[", 8))
+    return (-1);
+
+ /*
+  * Free any old element value and set the new value...
+  */
+
+  if (node->value.element.name)
+    free(node->value.element.name);
+
+  node->value.element.name = _mxml_strdupf("![CDATA[%s]]", data);
+
+  return (0);
+}
+
+
+/*
+ * 'mxmlSetCustom()' - Set the data and destructor of a custom data node.
+ *
+ * The node is not changed if it (or its first child) is not a custom node.
+ *
+ * @since Mini-XML 2.1@
+ */
+
+int                                    /* O - 0 on success, -1 on failure */
+mxmlSetCustom(
+    mxml_node_t              *node,    /* I - Node to set */
+    void                     *data,    /* I - New data pointer */
+    mxml_custom_destroy_cb_t destroy)  /* I - New destructor function */
+{
+ /*
+  * Range check input...
+  */
+
+  if (node && node->type == MXML_ELEMENT &&
+      node->child && node->child->type == MXML_CUSTOM)
+    node = node->child;
+
+  if (!node || node->type != MXML_CUSTOM)
+    return (-1);
+
+ /*
+  * Free any old element value and set the new value...
+  */
+
+  if (node->value.custom.data && node->value.custom.destroy)
+    (*(node->value.custom.destroy))(node->value.custom.data);
+
+  node->value.custom.data    = data;
+  node->value.custom.destroy = destroy;
+
+  return (0);
+}
+
+
+/*
+ * 'mxmlSetElement()' - Set the name of an element node.
+ *
+ * The node is not changed if it is not an element node.
+ */
+
+int                                    /* O - 0 on success, -1 on failure */
+mxmlSetElement(mxml_node_t *node,      /* I - Node to set */
+               const char  *name)      /* I - New name string */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node || node->type != MXML_ELEMENT || !name)
+    return (-1);
+
+ /*
+  * Free any old element value and set the new value...
+  */
+
+  if (node->value.element.name)
+    free(node->value.element.name);
+
+  node->value.element.name = strdup(name);
+
+  return (0);
+}
+
+
+/*
+ * 'mxmlSetInteger()' - Set the value of an integer node.
+ *
+ * The node is not changed if it (or its first child) is not an integer node.
+ */
+
+int                                    /* O - 0 on success, -1 on failure */
+mxmlSetInteger(mxml_node_t *node,      /* I - Node to set */
+               int         integer)    /* I - Integer value */
+{
+ /*
+  * Range check input...
+  */
+
+  if (node && node->type == MXML_ELEMENT &&
+      node->child && node->child->type == MXML_INTEGER)
+    node = node->child;
+
+  if (!node || node->type != MXML_INTEGER)
+    return (-1);
+
+ /*
+  * Set the new value and return...
+  */
+
+  node->value.integer = integer;
+
+  return (0);
+}
+
+
+/*
+ * 'mxmlSetOpaque()' - Set the value of an opaque node.
+ *
+ * The node is not changed if it (or its first child) is not an opaque node.
+ */
+
+int                                    /* O - 0 on success, -1 on failure */
+mxmlSetOpaque(mxml_node_t *node,       /* I - Node to set */
+              const char  *opaque)     /* I - Opaque string */
+{
+ /*
+  * Range check input...
+  */
+
+  if (node && node->type == MXML_ELEMENT &&
+      node->child && node->child->type == MXML_OPAQUE)
+    node = node->child;
+
+  if (!node || node->type != MXML_OPAQUE || !opaque)
+    return (-1);
+
+ /*
+  * Free any old opaque value and set the new value...
+  */
+
+  if (node->value.opaque)
+    free(node->value.opaque);
+
+  node->value.opaque = strdup(opaque);
+
+  return (0);
+}
+
+
+/*
+ * 'mxmlSetReal()' - Set the value of a real number node.
+ *
+ * The node is not changed if it (or its first child) is not a real number 
node.
+ */
+
+int                                    /* O - 0 on success, -1 on failure */
+mxmlSetReal(mxml_node_t *node,         /* I - Node to set */
+            double      real)          /* I - Real number value */
+{
+ /*
+  * Range check input...
+  */
+
+  if (node && node->type == MXML_ELEMENT &&
+      node->child && node->child->type == MXML_REAL)
+    node = node->child;
+
+  if (!node || node->type != MXML_REAL)
+    return (-1);
+
+ /*
+  * Set the new value and return...
+  */
+
+  node->value.real = real;
+
+  return (0);
+}
+
+
+/*
+ * 'mxmlSetText()' - Set the value of a text node.
+ *
+ * The node is not changed if it (or its first child) is not a text node.
+ */
+
+int                                    /* O - 0 on success, -1 on failure */
+mxmlSetText(mxml_node_t *node,         /* I - Node to set */
+            int         whitespace,    /* I - 1 = leading whitespace, 0 = no 
whitespace */
+           const char  *string)        /* I - String */
+{
+ /*
+  * Range check input...
+  */
+
+  if (node && node->type == MXML_ELEMENT &&
+      node->child && node->child->type == MXML_TEXT)
+    node = node->child;
+
+  if (!node || node->type != MXML_TEXT || !string)
+    return (-1);
+
+ /*
+  * Free any old string value and set the new value...
+  */
+
+  if (node->value.text.string)
+    free(node->value.text.string);
+
+  node->value.text.whitespace = whitespace;
+  node->value.text.string     = strdup(string);
+
+  return (0);
+}
+
+
+/*
+ * 'mxmlSetTextf()' - Set the value of a text node to a formatted string.
+ *
+ * The node is not changed if it (or its first child) is not a text node.
+ */
+
+int                                    /* O - 0 on success, -1 on failure */
+mxmlSetTextf(mxml_node_t *node,                /* I - Node to set */
+             int         whitespace,   /* I - 1 = leading whitespace, 0 = no 
whitespace */
+             const char  *format,      /* I - Printf-style format string */
+            ...)                       /* I - Additional arguments as needed */
+{
+  va_list      ap;                     /* Pointer to arguments */
+
+
+ /*
+  * Range check input...
+  */
+
+  if (node && node->type == MXML_ELEMENT &&
+      node->child && node->child->type == MXML_TEXT)
+    node = node->child;
+
+  if (!node || node->type != MXML_TEXT || !format)
+    return (-1);
+
+ /*
+  * Free any old string value and set the new value...
+  */
+
+  if (node->value.text.string)
+    free(node->value.text.string);
+
+  va_start(ap, format);
+
+  node->value.text.whitespace = whitespace;
+  node->value.text.string     = _mxml_strdupf(format, ap);
+
+  va_end(ap);
+
+  return (0);
+}
+
+
+/*
+ * 'mxmlSetUserData()' - Set the user data pointer for a node.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+int                                    /* O - 0 on success, -1 on failure */
+mxmlSetUserData(mxml_node_t *node,     /* I - Node to set */
+                void        *data)     /* I - User data pointer */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!node)
+    return (-1);
+
+ /*
+  * Set the user data pointer and return...
+  */
+
+  node->user_data = data;
+  return (0);
+}
+
+
+/*
+ * End of "$Id: mxml-set.c 441 2011-12-09 23:49:00Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-set.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-string.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-string.c         
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-string.c 
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,476 @@
+/*
+ * "$Id: mxml-string.c 424 2010-12-25 16:21:50Z mike $"
+ *
+ * String functions for Mini-XML, a small XML-like file parsing library.
+ *
+ * Copyright 2003-2010 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ *
+ * Contents:
+ *
+ *   _mxml_snprintf()  - Format a string.
+ *   _mxml_strdup()    - Duplicate a string.
+ *   _mxml_strdupf()   - Format and duplicate a string.
+ *   _mxml_vsnprintf() - Format a string into a fixed size buffer.
+ *   _mxml_vstrdupf()  - Format and duplicate a string.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+
+
+/*
+ * The va_copy macro is part of C99, but many compilers don't implement it.
+ * Provide a "direct assignment" implmentation when va_copy isn't defined...
+ */
+
+#ifndef va_copy
+#  ifdef __va_copy
+#    define va_copy(dst,src) __va_copy(dst,src)
+#  else
+#    define va_copy(dst,src) memcpy(&dst, &src, sizeof(va_list))
+#  endif /* __va_copy */
+#endif /* va_copy */
+
+
+#ifndef HAVE_SNPRINTF
+/*
+ * '_mxml_snprintf()' - Format a string.
+ */
+
+int                                    /* O - Number of bytes formatted */
+_mxml_snprintf(char       *buffer,     /* I - Output buffer */
+               size_t     bufsize,     /* I - Size of output buffer */
+              const char *format,      /* I - Printf-style format string */
+              ...)                     /* I - Additional arguments as needed */
+{
+  va_list      ap;                     /* Argument list */
+  int          bytes;                  /* Number of bytes formatted */
+
+
+  va_start(ap, format);
+  bytes = vsnprintf(buffer, bufsize, format, ap);
+  va_end(ap);
+
+  return (bytes);
+}
+#endif /* !HAVE_SNPRINTF */
+
+
+/*
+ * '_mxml_strdup()' - Duplicate a string.
+ */
+
+#ifndef HAVE_STRDUP
+char *                                 /* O - New string pointer */
+_mxml_strdup(const char *s)            /* I - String to duplicate */
+{
+  char *t;                             /* New string pointer */
+
+
+  if (s == NULL)
+    return (NULL);
+
+  if ((t = malloc(strlen(s) + 1)) == NULL)
+    return (NULL);
+
+  return (strcpy(t, s));
+}
+#endif /* !HAVE_STRDUP */
+
+
+/*
+ * '_mxml_strdupf()' - Format and duplicate a string.
+ */
+
+char *                                 /* O - New string pointer */
+_mxml_strdupf(const char *format,      /* I - Printf-style format string */
+              ...)                     /* I - Additional arguments as needed */
+{
+  va_list      ap;                     /* Pointer to additional arguments */
+  char         *s;                     /* Pointer to formatted string */
+
+
+ /*
+  * Get a pointer to the additional arguments, format the string,
+  * and return it...
+  */
+
+  va_start(ap, format);
+  s = _mxml_vstrdupf(format, ap);
+  va_end(ap);
+
+  return (s);
+}
+
+
+#ifndef HAVE_VSNPRINTF
+/*
+ * '_mxml_vsnprintf()' - Format a string into a fixed size buffer.
+ */
+
+int                                    /* O - Number of bytes formatted */
+_mxml_vsnprintf(char       *buffer,    /* O - Output buffer */
+                size_t     bufsize,    /* O - Size of output buffer */
+               const char *format,     /* I - Printf-style format string */
+               va_list    ap)          /* I - Pointer to additional arguments 
*/
+{
+  char         *bufptr,                /* Pointer to position in buffer */
+               *bufend,                /* Pointer to end of buffer */
+               sign,                   /* Sign of format width */
+               size,                   /* Size character (h, l, L) */
+               type;                   /* Format type character */
+  int          width,                  /* Width of field */
+               prec;                   /* Number of characters of precision */
+  char         tformat[100],           /* Temporary format string for 
sprintf() */
+               *tptr,                  /* Pointer into temporary format */
+               temp[1024];             /* Buffer for formatted numbers */
+  char         *s;                     /* Pointer to string */
+  int          slen;                   /* Length of string */
+  int          bytes;                  /* Total number of bytes needed */
+
+
+ /*
+  * Loop through the format string, formatting as needed...
+  */
+
+  bufptr = buffer;
+  bufend = buffer + bufsize - 1;
+  bytes  = 0;
+
+  while (*format)
+  {
+    if (*format == '%')
+    {
+      tptr = tformat;
+      *tptr++ = *format++;
+
+      if (*format == '%')
+      {
+        if (bufptr && bufptr < bufend) *bufptr++ = *format;
+        bytes ++;
+        format ++;
+       continue;
+      }
+      else if (strchr(" -+#\'", *format))
+      {
+        *tptr++ = *format;
+        sign = *format++;
+      }
+      else
+        sign = 0;
+
+      if (*format == '*')
+      {
+       /*
+        * Get width from argument...
+       */
+
+       format ++;
+       width = va_arg(ap, int);
+
+       snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width);
+       tptr += strlen(tptr);
+      }
+      else
+      {
+       width = 0;
+
+       while (isdigit(*format & 255))
+       {
+         if (tptr < (tformat + sizeof(tformat) - 1))
+           *tptr++ = *format;
+
+         width = width * 10 + *format++ - '0';
+       }
+      }
+
+      if (*format == '.')
+      {
+       if (tptr < (tformat + sizeof(tformat) - 1))
+         *tptr++ = *format;
+
+        format ++;
+
+        if (*format == '*')
+       {
+         /*
+         * Get precision from argument...
+         */
+
+         format ++;
+         prec = va_arg(ap, int);
+
+         snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec);
+         tptr += strlen(tptr);
+       }
+       else
+       {
+         prec = 0;
+
+         while (isdigit(*format & 255))
+         {
+           if (tptr < (tformat + sizeof(tformat) - 1))
+             *tptr++ = *format;
+
+           prec = prec * 10 + *format++ - '0';
+         }
+       }
+      }
+      else
+        prec = -1;
+
+      if (*format == 'l' && format[1] == 'l')
+      {
+        size = 'L';
+
+       if (tptr < (tformat + sizeof(tformat) - 2))
+       {
+         *tptr++ = 'l';
+         *tptr++ = 'l';
+       }
+
+       format += 2;
+      }
+      else if (*format == 'h' || *format == 'l' || *format == 'L')
+      {
+       if (tptr < (tformat + sizeof(tformat) - 1))
+         *tptr++ = *format;
+
+        size = *format++;
+      }
+
+      if (!*format)
+        break;
+
+      if (tptr < (tformat + sizeof(tformat) - 1))
+        *tptr++ = *format;
+
+      type  = *format++;
+      *tptr = '\0';
+
+      switch (type)
+      {
+       case 'E' : /* Floating point formats */
+       case 'G' :
+       case 'e' :
+       case 'f' :
+       case 'g' :
+           if ((width + 2) > sizeof(temp))
+             break;
+
+           sprintf(temp, tformat, va_arg(ap, double));
+
+            bytes += strlen(temp);
+
+            if (bufptr)
+           {
+             if ((bufptr + strlen(temp)) > bufend)
+             {
+               strncpy(bufptr, temp, (size_t)(bufend - bufptr));
+               bufptr = bufend;
+             }
+             else
+             {
+               strcpy(bufptr, temp);
+               bufptr += strlen(temp);
+             }
+           }
+           break;
+
+        case 'B' : /* Integer formats */
+       case 'X' :
+       case 'b' :
+        case 'd' :
+       case 'i' :
+       case 'o' :
+       case 'u' :
+       case 'x' :
+           if ((width + 2) > sizeof(temp))
+             break;
+
+#ifdef HAVE_LONG_LONG
+           if (size == 'L')
+             sprintf(temp, tformat, va_arg(ap, long long));
+           else
+#endif /* HAVE_LONG_LONG */
+           sprintf(temp, tformat, va_arg(ap, int));
+
+            bytes += strlen(temp);
+
+           if (bufptr)
+           {
+             if ((bufptr + strlen(temp)) > bufend)
+             {
+               strncpy(bufptr, temp, (size_t)(bufend - bufptr));
+               bufptr = bufend;
+             }
+             else
+             {
+               strcpy(bufptr, temp);
+               bufptr += strlen(temp);
+             }
+           }
+           break;
+
+       case 'p' : /* Pointer value */
+           if ((width + 2) > sizeof(temp))
+             break;
+
+           sprintf(temp, tformat, va_arg(ap, void *));
+
+            bytes += strlen(temp);
+
+           if (bufptr)
+           {
+             if ((bufptr + strlen(temp)) > bufend)
+             {
+               strncpy(bufptr, temp, (size_t)(bufend - bufptr));
+               bufptr = bufend;
+             }
+             else
+             {
+               strcpy(bufptr, temp);
+               bufptr += strlen(temp);
+             }
+           }
+           break;
+
+        case 'c' : /* Character or character array */
+           bytes += width;
+
+           if (bufptr)
+           {
+             if (width <= 1)
+               *bufptr++ = va_arg(ap, int);
+             else
+             {
+               if ((bufptr + width) > bufend)
+                 width = bufend - bufptr;
+
+               memcpy(bufptr, va_arg(ap, char *), (size_t)width);
+               bufptr += width;
+             }
+           }
+           break;
+
+       case 's' : /* String */
+           if ((s = va_arg(ap, char *)) == NULL)
+             s = "(null)";
+
+           slen = strlen(s);
+           if (slen > width && prec != width)
+             width = slen;
+
+            bytes += width;
+
+           if (bufptr)
+           {
+             if ((bufptr + width) > bufend)
+               width = bufend - bufptr;
+
+              if (slen > width)
+               slen = width;
+
+             if (sign == '-')
+             {
+               strncpy(bufptr, s, (size_t)slen);
+               memset(bufptr + slen, ' ', (size_t)(width - slen));
+             }
+             else
+             {
+               memset(bufptr, ' ', (size_t)(width - slen));
+               strncpy(bufptr + width - slen, s, (size_t)slen);
+             }
+
+             bufptr += width;
+           }
+           break;
+
+       case 'n' : /* Output number of chars so far */
+           *(va_arg(ap, int *)) = bytes;
+           break;
+      }
+    }
+    else
+    {
+      bytes ++;
+
+      if (bufptr && bufptr < bufend)
+        *bufptr++ = *format;
+
+      format ++;
+    }
+  }
+
+ /*
+  * Nul-terminate the string and return the number of characters needed.
+  */
+
+  *bufptr = '\0';
+
+  return (bytes);
+}
+#endif /* !HAVE_VSNPRINTF */
+
+
+/*
+ * '_mxml_vstrdupf()' - Format and duplicate a string.
+ */
+
+char *                                 /* O - New string pointer */
+_mxml_vstrdupf(const char *format,     /* I - Printf-style format string */
+               va_list    ap)          /* I - Pointer to additional arguments 
*/
+{
+  int          bytes;                  /* Number of bytes required */
+  char         *buffer,                /* String buffer */
+               temp[256];              /* Small buffer for first vsnprintf */
+  va_list      apcopy;                 /* Copy of argument list */
+
+
+ /*
+  * First format with a tiny buffer; this will tell us how many bytes are
+  * needed...
+  */
+
+  va_copy(apcopy, ap);
+  bytes = vsnprintf(temp, sizeof(temp), format, apcopy);
+
+  if (bytes < sizeof(temp))
+  {
+   /*
+    * Hey, the formatted string fits in the tiny buffer, so just dup that...
+    */
+
+    return (strdup(temp));
+  }
+
+ /*
+  * Allocate memory for the whole thing and reformat to the new, larger
+  * buffer...
+  */
+
+  if ((buffer = calloc(1, bytes + 1)) != NULL)
+    vsnprintf(buffer, bytes + 1, format, ap);
+
+ /*
+  * Return the new string...
+  */
+
+  return (buffer);
+}
+
+
+/*
+ * End of "$Id: mxml-string.c 424 2010-12-25 16:21:50Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxml-string.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxmldoc.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxmldoc.c             
                (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxmldoc.c     
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,5809 @@
+/*#define DEBUG 1*/
+/*
+ * "$Id: mxmldoc.c 440 2011-08-11 18:51:26Z mike $"
+ *
+ * Documentation generator using Mini-XML, a small XML-like file parsing
+ * library.
+ *
+ * Copyright 2003-2011 by Michael R Sweet.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Michael R Sweet and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "COPYING"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at:
+ *
+ *     http://www.minixml.org/
+ *
+ * Contents:
+ *
+ *   main()              - Main entry for test program.
+ *   add_variable()      - Add a variable or argument.
+ *   find_public()       - Find a public function, type, etc.
+ *   get_comment_info()  - Get info from comment.
+ *   get_text()          - Get the text for a node.
+ *   load_cb()           - Set the type of child nodes.
+ *   new_documentation() - Create a new documentation tree.
+ *   remove_directory()  - Remove a directory.
+ *   safe_strcpy()       - Copy a string allowing for overlapping strings.
+ *   scan_file()         - Scan a source file.
+ *   sort_node()         - Insert a node sorted into a tree.
+ *   update_comment()    - Update a comment node.
+ *   usage()             - Show program usage...
+ *   write_description() - Write the description text.
+ *   write_element()     - Write an element's text nodes.
+ *   write_file()        - Copy a file to the output.
+ *   write_function()    - Write documentation for a function.
+ *   write_html()        - Write HTML documentation.
+ *   write_html_head()   - Write the standard HTML header.
+ *   write_man()         - Write manpage documentation.
+ *   write_scu()         - Write a structure, class, or union.
+ *   write_string()      - Write a string, quoting HTML special chars as 
needed.
+ *   write_toc()         - Write a table-of-contents.
+ *   write_tokens()      - Write <Token> nodes for all APIs.
+ *   ws_cb()             - Whitespace callback for saving.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml.h"
+#include <time.h>
+#include <sys/stat.h>
+#ifndef WIN32
+#  include <dirent.h>
+#  include <unistd.h>
+#endif /* !WIN32 */
+#ifdef __APPLE__
+#  include <spawn.h>
+#  include <sys/wait.h>
+extern char **environ;
+#endif /* __APPLE__ */
+
+
+/*
+ * 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:
+ *
+ * <?xml version="1.0"?>
+ * <mxmldoc xmlns="http://www.easysw.com";
+ *  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+ *  xsi:schemaLocation="http://www.minixml.org/mxmldoc.xsd";>
+ *
+ *   <namespace name="">                        [optional...]
+ *     <constant name="">
+ *       <description>descriptive text</description>
+ *     </constant>
+ *
+ *     <enumeration name="">
+ *       <description>descriptive text</description>
+ *       <constant name="">...</constant>
+ *     </enumeration>
+ *
+ *     <typedef name="">
+ *       <description>descriptive text</description>
+ *       <type>type string</type>
+ *     </typedef>
+ *
+ *     <function name="" scope="">
+ *       <description>descriptive text</description>
+ *       <argument name="" direction="I|O|IO" default="">
+ *         <description>descriptive text</description>
+ *         <type>type string</type>
+ *       </argument>
+ *       <returnvalue>
+ *         <description>descriptive text</description>
+ *         <type>type string</type>
+ *       </returnvalue>
+ *       <seealso>function names separated by spaces</seealso>
+ *     </function>
+ *
+ *     <variable name="" scope="">
+ *       <description>descriptive text</description>
+ *       <type>type string</type>
+ *     </variable>
+ *
+ *     <struct name="">
+ *       <description>descriptive text</description>
+ *       <variable name="">...</variable>
+ *       <function name="">...</function>
+ *     </struct>
+ *
+ *     <union name="">
+ *       <description>descriptive text</description>
+ *       <variable name="">...</variable>
+ *     </union>
+ *
+ *     <class name="" parent="">
+ *       <description>descriptive text</description>
+ *       <class name="">...</class>
+ *       <enumeration name="">...</enumeration>
+ *       <function name="">...</function>
+ *       <struct name="">...</struct>
+ *       <variable name="">...</variable>
+ *     </class>
+ *   </namespace>
+ * </mxmldoc>
+ */
+
+
+/*
+ * 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 */
+
+
+/*
+ * Output modes...
+ */
+
+#define OUTPUT_NONE            0       /* No output */
+#define OUTPUT_HTML            1       /* Output HTML */
+#define OUTPUT_XML             2       /* Output XML */
+#define OUTPUT_MAN             3       /* Output nroff/man */
+#define OUTPUT_TOKENS          4       /* Output docset Tokens.xml file */
+
+
+/*
+ * Local functions...
+ */
+
+static mxml_node_t     *add_variable(mxml_node_t *parent, const char *name,
+                                     mxml_node_t *type);
+static mxml_node_t     *find_public(mxml_node_t *node, mxml_node_t *top,
+                                    const char *name);
+static char            *get_comment_info(mxml_node_t *description);
+static char            *get_text(mxml_node_t *node, char *buffer, int buflen);
+static mxml_type_t     load_cb(mxml_node_t *node);
+static mxml_node_t     *new_documentation(mxml_node_t **mxmldoc);
+static int             remove_directory(const char *path);
+static void            safe_strcpy(char *dst, const char *src);
+static int             scan_file(const char *filename, FILE *fp,
+                                 mxml_node_t *doc);
+static void            sort_node(mxml_node_t *tree, mxml_node_t *func);
+static void            update_comment(mxml_node_t *parent,
+                                      mxml_node_t *comment);
+static void            usage(const char *option);
+static void            write_description(FILE *out, mxml_node_t *description,
+                                         const char *element, int summary);
+static void            write_element(FILE *out, mxml_node_t *doc,
+                                     mxml_node_t *element, int mode);
+static void            write_file(FILE *out, const char *file);
+static void            write_function(FILE *out, mxml_node_t *doc,
+                                      mxml_node_t *function, int level);
+static void            write_html(const char *section, const char *title,
+                                  const char *footerfile,
+                                  const char *headerfile,
+                                  const char *introfile, const char *cssfile,
+                                  const char *framefile,
+                                  const char *docset, const char *docversion,
+                                  const char *feedname, const char *feedurl,
+                                  mxml_node_t *doc);
+static void            write_html_head(FILE *out, const char *section,
+                                       const char *title, const char *cssfile);
+static void            write_man(const char *man_name, const char *section,
+                                 const char *title, const char *headerfile,
+                                 const char *footerfile, const char *introfile,
+                                 mxml_node_t *doc);
+static void            write_scu(FILE *out, mxml_node_t *doc,
+                                 mxml_node_t *scut);
+static void            write_string(FILE *out, const char *s, int mode);
+static void            write_toc(FILE *out, mxml_node_t *doc,
+                                 const char *introfile, const char *target,
+                                 int xml);
+static void            write_tokens(FILE *out, mxml_node_t *doc,
+                                    const char *path);
+static const char      *ws_cb(mxml_node_t *node, int where);
+
+
+/*
+ * '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 */
+{
+  int          i;                      /* Looping var */
+  int          len;                    /* Length of argument */
+  FILE         *fp;                    /* File to read */
+  mxml_node_t  *doc;                   /* XML documentation tree */
+  mxml_node_t  *mxmldoc;               /* mxmldoc node */
+  const char   *cssfile,               /* CSS stylesheet file */
+               *docset,                /* Documentation set directory */
+               *docversion,            /* Documentation set version */
+               *feedname,              /* Feed name for documentation set */
+               *feedurl,               /* Feed URL for documentation set */
+               *footerfile,            /* Footer file */
+               *framefile,             /* Framed HTML basename */
+               *headerfile,            /* Header file */
+               *introfile,             /* Introduction file */
+               *name,                  /* Name of manpage */
+               *path,                  /* Path to help file for tokens */
+               *section,               /* Section/keywords of documentation */
+               *title,                 /* Title of documentation */
+               *xmlfile;               /* XML file */
+  int          mode,                   /* Output mode */
+               update;                 /* Updated XML file */
+
+
+ /*
+  * Check arguments...
+  */
+
+  cssfile     = NULL;
+  doc         = NULL;
+  docset      = NULL;
+  docversion  = NULL;
+  feedname    = NULL;
+  feedurl     = NULL;
+  footerfile  = NULL;
+  framefile   = NULL;
+  headerfile  = NULL;
+  introfile   = NULL;
+  mode        = OUTPUT_HTML;
+  mxmldoc     = NULL;
+  name        = NULL;
+  path        = NULL;
+  section     = NULL;
+  title       = NULL;
+  update      = 0;
+  xmlfile     = NULL;
+
+  for (i = 1; i < argc; i ++)
+    if (!strcmp(argv[i], "--help"))
+    {
+     /*
+      * Show help...
+      */
+
+      usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--version"))
+    {
+     /*
+      * Show version...
+      */
+
+      puts(MXML_VERSION + 10);
+      return (0);
+    }
+    else if (!strcmp(argv[i], "--css") && !cssfile)
+    {
+     /*
+      * Set CSS stylesheet file...
+      */
+
+      i ++;
+      if (i < argc)
+        cssfile = argv[i];
+      else
+        usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--docset") && !docset)
+    {
+     /*
+      * Set documentation set directory...
+      */
+
+      i ++;
+      if (i < argc)
+        docset = argv[i];
+      else
+        usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--docversion") && !docversion)
+    {
+     /*
+      * Set documentation set directory...
+      */
+
+      i ++;
+      if (i < argc)
+        docversion = argv[i];
+      else
+        usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--footer") && !footerfile)
+    {
+     /*
+      * Set footer file...
+      */
+
+      i ++;
+      if (i < argc)
+        footerfile = argv[i];
+      else
+        usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--feedname") && !feedname)
+    {
+     /*
+      * Set documentation set feed name...
+      */
+
+      i ++;
+      if (i < argc)
+        feedname = argv[i];
+      else
+        usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--feedurl") && !feedurl)
+    {
+     /*
+      * Set documentation set feed name...
+      */
+
+      i ++;
+      if (i < argc)
+        feedurl = argv[i];
+      else
+        usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--framed") && !framefile)
+    {
+     /*
+      * Set base filename for framed HTML output...
+      */
+
+      i ++;
+      if (i < argc)
+        framefile = argv[i];
+      else
+        usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--header") && !headerfile)
+    {
+     /*
+      * Set header file...
+      */
+
+      i ++;
+      if (i < argc)
+        headerfile = argv[i];
+      else
+        usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--intro") && !introfile)
+    {
+     /*
+      * Set intro file...
+      */
+
+      i ++;
+      if (i < argc)
+        introfile = argv[i];
+      else
+        usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--man") && !name)
+    {
+     /*
+      * Output manpage...
+      */
+
+      i ++;
+      if (i < argc)
+      {
+        mode = OUTPUT_MAN;
+        name = argv[i];
+      }
+      else
+        usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--no-output"))
+      mode = OUTPUT_NONE;
+    else if (!strcmp(argv[i], "--section") && !section)
+    {
+     /*
+      * Set section/keywords...
+      */
+
+      i ++;
+      if (i < argc)
+        section = argv[i];
+      else
+        usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--title") && !title)
+    {
+     /*
+      * Set title...
+      */
+
+      i ++;
+      if (i < argc)
+        title = argv[i];
+      else
+        usage(NULL);
+    }
+    else if (!strcmp(argv[i], "--tokens"))
+    {
+     /*
+      * Output Tokens.xml file...
+      */
+
+      mode = OUTPUT_TOKENS;
+
+      i ++;
+      if (i < argc)
+        path = argv[i];
+      else
+        usage(NULL);
+    }
+    else if (argv[i][0] == '-')
+    {
+     /*
+      * Unknown/bad option...
+      */
+
+      usage(argv[i]);
+    }
+    else
+    {
+     /*
+      * Process XML or source file...
+      */
+
+      len = (int)strlen(argv[i]);
+      if (len > 4 && !strcmp(argv[i] + len - 4, ".xml"))
+      {
+       /*
+        * Set XML file...
+       */
+
+        if (xmlfile)
+         usage(NULL);
+
+        xmlfile = argv[i];
+
+        if (!doc)
+       {
+         if ((fp = fopen(argv[i], "r")) != NULL)
+         {
+          /*
+           * Read the existing XML file...
+           */
+
+           doc = mxmlLoadFile(NULL, fp, load_cb);
+
+           fclose(fp);
+
+           if (!doc)
+           {
+             mxmldoc = NULL;
+
+             fprintf(stderr,
+                     "mxmldoc: Unable to read the XML documentation file "
+                     "\"%s\"!\n", argv[i]);
+           }
+           else if ((mxmldoc = mxmlFindElement(doc, doc, "mxmldoc", NULL,
+                                               NULL, MXML_DESCEND)) == NULL)
+           {
+             fprintf(stderr,
+                     "mxmldoc: XML documentation file \"%s\" is missing "
+                     "<mxmldoc> node!!\n", argv[i]);
+
+             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);
+      }
+    }
+
+  if (update && xmlfile)
+  {
+   /*
+    * Save the updated XML documentation file...
+    */
+
+    if ((fp = fopen(xmlfile, "w")) != NULL)
+    {
+     /*
+      * Write over the existing XML file...
+      */
+
+      mxmlSetWrapMargin(0);
+
+      if (mxmlSaveFile(doc, fp, ws_cb))
+      {
+       fprintf(stderr,
+               "mxmldoc: Unable to write the XML documentation file \"%s\": "
+               "%s!\n", xmlfile, strerror(errno));
+       fclose(fp);
+       mxmlDelete(doc);
+       return (1);
+      }
+
+      fclose(fp);
+    }
+    else
+    {
+      fprintf(stderr,
+              "mxmldoc: Unable to create the XML documentation file \"%s\": "
+             "%s!\n", xmlfile, strerror(errno));
+      mxmlDelete(doc);
+      return (1);
+    }
+  }
+
+  switch (mode)
+  {
+    case OUTPUT_HTML :
+       /*
+        * Write HTML documentation...
+        */
+
+        write_html(section, title ? title : "Documentation", footerfile,
+                  headerfile, introfile, cssfile, framefile, docset,
+                  docversion, feedname, feedurl, mxmldoc);
+        break;
+
+    case OUTPUT_MAN :
+       /*
+        * Write manpage documentation...
+        */
+
+        write_man(name, section, title, footerfile, headerfile, introfile,
+                 mxmldoc);
+        break;
+
+    case OUTPUT_TOKENS :
+       fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+             "<Tokens version=\"1.0\">\n", stdout);
+
+       write_tokens(stdout, mxmldoc, path);
+
+       fputs("</Tokens>\n", stdout);
+        break;
+  }
+
+ /*
+  * Delete the tree and return...
+  */
+
+  mxmlDelete(doc);
+
+  return (0);
+}
+
+
+/*
+ * 'add_variable()' - Add a variable or argument.
+ */
+
+static mxml_node_t *                   /* O - New variable/argument */
+add_variable(mxml_node_t *parent,      /* I - Parent node */
+             const char  *name,                /* I - "argument" or "variable" 
*/
+             mxml_node_t *type)                /* I - Type nodes */
+{
+  mxml_node_t  *variable,              /* New variable */
+               *node,                  /* Current node */
+               *next;                  /* Next node */
+  char         buffer[16384],          /* String buffer */
+               *bufptr;                /* Pointer into buffer */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "add_variable(parent=%p, name=\"%s\", type=%p)\n",
+          parent, name, type);
+#endif /* DEBUG */
+
+ /*
+  * Range check input...
+  */
+
+  if (!type || !type->child)
+    return (NULL);
+
+ /*
+  * Create the variable/argument node...
+  */
+
+  variable = mxmlNewElement(parent, name);
+
+ /*
+  * Check for a default value...
+  */
+
+  for (node = type->child; node; node = node->next)
+    if (!strcmp(node->value.text.string, "="))
+      break;
+
+  if (node)
+  {
+   /*
+    * Default value found, copy it and add as a "default" attribute...
+    */
+
+    for (bufptr = buffer; node; bufptr += strlen(bufptr))
+    {
+      if (node->value.text.whitespace && bufptr > buffer)
+       *bufptr++ = ' ';
+
+      strcpy(bufptr, node->value.text.string);
+
+      next = node->next;
+      mxmlDelete(node);
+      node = next;
+    }
+
+    mxmlElementSetAttr(variable, "default", buffer);
+  }
+
+ /*
+  * Extract the argument/variable name...
+  */
+
+  if (type->last_child->value.text.string[0] == ')')
+  {
+   /*
+    * Handle "type (*name)(args)"...
+    */
+
+    for (node = type->child; node; node = node->next)
+      if (node->value.text.string[0] == '(')
+       break;
+
+    for (bufptr = buffer; node; bufptr += strlen(bufptr))
+    {
+      if (node->value.text.whitespace && bufptr > buffer)
+       *bufptr++ = ' ';
+
+      strcpy(bufptr, node->value.text.string);
+
+      next = node->next;
+      mxmlDelete(node);
+      node = next;
+    }
+  }
+  else
+  {
+   /*
+    * Handle "type name"...
+    */
+
+    strcpy(buffer, type->last_child->value.text.string);
+    mxmlDelete(type->last_child);
+  }
+
+ /*
+  * Set the name...
+  */
+
+  mxmlElementSetAttr(variable, "name", buffer);
+
+ /*
+  * Add the remaining type information to the variable node...
+  */
+
+  mxmlAdd(variable, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
+
+ /*
+  * Add new new variable node...
+  */
+
+  return (variable);
+}
+
+
+/*
+ * 'find_public()' - Find a public function, type, etc.
+ */
+
+static mxml_node_t *                   /* I - Found node or NULL */
+find_public(mxml_node_t *node,         /* I - Current node */
+            mxml_node_t *top,          /* I - Top node */
+            const char  *name)         /* I - Name of element */
+{
+  mxml_node_t  *description,           /* Description node */
+               *comment;               /* Comment node */
+
+
+  for (node = mxmlFindElement(node, top, name, NULL, NULL,
+                              node == top ? MXML_DESCEND_FIRST :
+                                           MXML_NO_DESCEND);
+       node;
+       node = mxmlFindElement(node, top, name, NULL, NULL, MXML_NO_DESCEND))
+  {
+   /*
+    * Get the description for this node...
+    */
+
+    description = mxmlFindElement(node, node, "description", NULL, NULL,
+                                  MXML_DESCEND_FIRST);
+
+   /*
+    * A missing or empty description signals a private node...
+    */
+
+    if (!description)
+      continue;
+
+   /*
+    * Look for @private@ in the comment text...
+    */
+
+    for (comment = description->child; comment; comment = comment->next)
+      if ((comment->type == MXML_TEXT &&
+           strstr(comment->value.text.string, "@private@")) ||
+          (comment->type == MXML_OPAQUE &&
+           strstr(comment->value.opaque, "@private@")))
+        break;
+
+    if (!comment)
+    {
+     /*
+      * No @private@, so return this node...
+      */
+
+      return (node);
+    }
+  }
+
+ /*
+  * If we get here, there are no (more) public nodes...
+  */
+
+  return (NULL);
+}
+
+
+/*
+ * 'get_comment_info()' - Get info from comment.
+ */
+
+static char *                          /* O - Info from comment */
+get_comment_info(
+    mxml_node_t *description)          /* I - Description node */
+{
+  char         text[10240],            /* Description text */
+               since[255],             /* @since value */
+               *ptr;                   /* Pointer into text */
+  static char  info[1024];             /* Info string */
+
+
+  if (!description)
+    return ("");
+
+  get_text(description, text, sizeof(text));
+
+  for (ptr = strchr(text, '@'); ptr; ptr = strchr(ptr + 1, '@'))
+  {
+    if (!strncmp(ptr, "@deprecated@", 12))
+      return ("<span class=\"info\">&nbsp;DEPRECATED&nbsp;</span>");
+    else if (!strncmp(ptr, "@since ", 7))
+    {
+      strncpy(since, ptr + 7, sizeof(since) - 1);
+      since[sizeof(since) - 1] = '\0';
+
+      if ((ptr = strchr(since, '@')) != NULL)
+        *ptr = '\0';
+
+      snprintf(info, sizeof(info), "<span 
class=\"info\">&nbsp;%s&nbsp;</span>", since);
+      return (info);
+    }
+  }
+
+  return ("");
+}
+
+
+/*
+ * 'get_text()' - Get the text for a node.
+ */
+
+static char *                          /* O - Text in node */
+get_text(mxml_node_t *node,            /* I - Node to get */
+         char        *buffer,          /* I - Buffer */
+        int         buflen)            /* I - Size of buffer */
+{
+  char         *ptr,                   /* Pointer into buffer */
+               *end;                   /* End of buffer */
+  int          len;                    /* Length of node */
+  mxml_node_t  *current;               /* Current node */
+
+
+  ptr = buffer;
+  end = buffer + buflen - 1;
+
+  for (current = node->child; current && ptr < end; current = current->next)
+  {
+    if (current->type == MXML_TEXT)
+    {
+      if (current->value.text.whitespace)
+        *ptr++ = ' ';
+
+      len = (int)strlen(current->value.text.string);
+      if (len > (int)(end - ptr))
+        len = (int)(end - ptr);
+
+      memcpy(ptr, current->value.text.string, len);
+      ptr += len;
+    }
+    else if (current->type == MXML_OPAQUE)
+    {
+      len = (int)strlen(current->value.opaque);
+      if (len > (int)(end - ptr))
+        len = (int)(end - ptr);
+
+      memcpy(ptr, current->value.opaque, len);
+      ptr += len;
+    }
+  }
+
+  *ptr = '\0';
+
+  return (buffer);
+}
+
+
+/*
+ * 'load_cb()' - Set the type of child nodes.
+ */
+
+static mxml_type_t                     /* O - Node type */
+load_cb(mxml_node_t *node)             /* I - Node */
+{
+  if (!strcmp(node->value.element.name, "description"))
+    return (MXML_OPAQUE);
+  else
+    return (MXML_TEXT);
+}
+
+
+/*
+ * '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 = mxmlNewXML(NULL);
+
+  *mxmldoc = mxmlNewElement(doc, "mxmldoc");
+
+  mxmlElementSetAttr(*mxmldoc, "xmlns", "http://www.easysw.com";);
+  mxmlElementSetAttr(*mxmldoc, "xmlns:xsi",
+                     "http://www.w3.org/2001/XMLSchema-instance";);
+  mxmlElementSetAttr(*mxmldoc, "xsi:schemaLocation",
+                     "http://www.minixml.org/mxmldoc.xsd";);
+
+  return (doc);
+}
+
+
+/*
+ * 'remove_directory()' - Remove a directory.
+ */
+
+static int                             /* O - 1 on success, 0 on failure */
+remove_directory(const char *path)     /* I - Directory to remove */
+{
+#ifdef WIN32
+  /* TODO: Add Windows directory removal code */
+
+#else
+  DIR          *dir;                   /* Directory */
+  struct dirent        *dent;                  /* Current directory entry */
+  char         filename[1024];         /* Current filename */
+  struct stat  fileinfo;               /* File information */
+
+
+  if ((dir = opendir(path)) == NULL)
+  {
+    fprintf(stderr, "mxmldoc: Unable to open directory \"%s\": %s\n", path,
+            strerror(errno));
+    return (0);
+  }
+
+  while ((dent = readdir(dir)) != NULL)
+  {
+   /*
+    * Skip "." and ".."...
+    */
+
+    if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
+      continue;
+
+   /*
+    * See if we have a file or directory...
+    */
+
+    snprintf(filename, sizeof(filename), "%s/%s", path, dent->d_name);
+
+    if (stat(filename, &fileinfo))
+    {
+      fprintf(stderr, "mxmldoc: Unable to stat \"%s\": %s\n", filename,
+             strerror(errno));
+      closedir(dir);
+      return (0);
+    }
+
+    if (S_ISDIR(fileinfo.st_mode))
+    {
+      if (!remove_directory(filename))
+      {
+        closedir(dir);
+       return (0);
+      }
+    }
+    else if (unlink(filename))
+    {
+      fprintf(stderr, "mxmldoc: Unable to remove \"%s\": %s\n", filename,
+             strerror(errno));
+      closedir(dir);
+      return (0);
+    }
+  }
+
+  closedir(dir);
+
+  if (rmdir(path))
+  {
+    fprintf(stderr, "mxmldoc: Unable to remove directory \"%s\": %s\n", path,
+            strerror(errno));
+    return (0);
+  }
+#endif /* WIN32 */
+
+  return (1);
+}
+
+
+/*
+ * 'safe_strcpy()' - Copy a string allowing for overlapping strings.
+ */
+
+static void
+safe_strcpy(char       *dst,           /* I - Destination string */
+            const char *src)           /* I - Source string */
+{
+  while (*src)
+    *dst++ = *src++;
+
+  *dst = '\0';
+}
+
+
+/*
+ * '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 */
+{
+  int          state,                  /* Current parser state */
+               braces,                 /* Number of braces active */
+               parens;                 /* Number of active parenthesis */
+  int          ch;                     /* Current character */
+  char         buffer[65536],          /* String buffer */
+               *bufptr;                /* Pointer into buffer */
+  const char   *scope;                 /* Current variable/function scope */
+  mxml_node_t  *comment,               /* <comment> node */
+               *constant,              /* <constant> node */
+               *enumeration,           /* <enumeration> node */
+               *function,              /* <function> node */
+               *fstructclass,          /* function struct/class node */
+               *structclass,           /* <struct> or <class> node */
+               *typedefnode,           /* <typedef> node */
+               *variable,              /* <variable> or <argument> node */
+               *returnvalue,           /* <returnvalue> node */
+               *type,                  /* <type> node */
+               *description,           /* <description> node */
+               *node,                  /* Current node */
+               *next;                  /* Next node */
+#if DEBUG > 1
+  mxml_node_t  *temp;                  /* Temporary node */
+  int          oldstate,               /* Previous state */
+               oldch;                  /* Old character */
+  static const char *states[] =                /* State strings */
+               {
+                 "STATE_NONE",
+                 "STATE_PREPROCESSOR",
+                 "STATE_C_COMMENT",
+                 "STATE_CXX_COMMENT",
+                 "STATE_STRING",
+                 "STATE_CHARACTER",
+                 "STATE_IDENTIFIER"
+               };
+#endif /* DEBUG > 1 */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "scan_file(filename=\"%s\", fp=%p, tree=%p)\n", filename,
+          fp, tree);
+#endif /* DEBUG */
+
+ /*
+  * Initialize the finite state machine...
+  */
+
+  state        = STATE_NONE;
+  braces       = 0;
+  parens       = 0;
+  bufptr       = buffer;
+
+  comment      = mxmlNewElement(MXML_NO_PARENT, "temp");
+  constant     = NULL;
+  enumeration  = NULL;
+  function     = NULL;
+  variable     = NULL;
+  returnvalue  = NULL;
+  type         = NULL;
+  description  = NULL;
+  typedefnode  = NULL;
+  structclass  = NULL;
+  fstructclass = NULL;
+
+  if (!strcmp(tree->value.element.name, "class"))
+    scope = "private";
+  else
+    scope = NULL;
+
+ /*
+  * Read until end-of-file...
+  */
+
+  while ((ch = getc(fp)) != EOF)
+  {
+#if DEBUG > 1
+    oldstate = state;
+    oldch    = ch;
+#endif /* DEBUG > 1 */
+
+    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);
+
+                 if (type)
+                 {
+#ifdef DEBUG
+                    fputs("Identifier: <<<< / >>>\n", stderr);
+#endif /* DEBUG */
+                    ch = type->last_child->value.text.string[0];
+                   mxmlNewText(type, isalnum(ch) || ch == '_', "/");
+                 }
+               }
+               break;
+
+           case '#' :                  /* Preprocessor */
+#ifdef DEBUG
+               fputs("    #preprocessor...\n", stderr);
+#endif /* DEBUG */
+               state = STATE_PREPROCESSOR;
+               break;
+
+            case '\'' :                        /* Character constant */
+               state = STATE_CHARACTER;
+               bufptr = buffer;
+               *bufptr++ = ch;
+               break;
+
+            case '\"' :                        /* String constant */
+               state = STATE_STRING;
+               bufptr = buffer;
+               *bufptr++ = ch;
+               break;
+
+            case '{' :
+#ifdef DEBUG
+               fprintf(stderr, "    open brace, function=%p, type=%p...\n",
+                       function, type);
+                if (type)
+                  fprintf(stderr, "    type->child=\"%s\"...\n",
+                         type->child->value.text.string);
+#endif /* DEBUG */
+
+               if (function)
+               {
+                 if (fstructclass)
+                 {
+                   sort_node(fstructclass, function);
+                   fstructclass = NULL;
+                 }
+                 else
+                   sort_node(tree, function);
+
+                 function = NULL;
+               }
+               else if (type && type->child &&
+                        ((!strcmp(type->child->value.text.string, "typedef") &&
+                          type->child->next &&
+                          (!strcmp(type->child->next->value.text.string, 
"struct") ||
+                           !strcmp(type->child->next->value.text.string, 
"union") ||
+                           !strcmp(type->child->next->value.text.string, 
"class"))) ||
+                         !strcmp(type->child->value.text.string, "union") ||
+                         !strcmp(type->child->value.text.string, "struct") ||
+                         !strcmp(type->child->value.text.string, "class")))
+               {
+                /*
+                 * Start of a class or structure...
+                 */
+
+                 if (!strcmp(type->child->value.text.string, "typedef"))
+                 {
+#ifdef DEBUG
+                    fputs("    starting typedef...\n", stderr);
+#endif /* DEBUG */
+
+                   typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
+                   mxmlDelete(type->child);
+                 }
+                 else
+                   typedefnode = NULL;
+
+                 structclass = mxmlNewElement(MXML_NO_PARENT,
+                                              type->child->value.text.string);
+
+#ifdef DEBUG
+                  fprintf(stderr, "%c%s: <<<< %s >>>\n",
+                         toupper(type->child->value.text.string[0]),
+                         type->child->value.text.string + 1,
+                         type->child->next ?
+                             type->child->next->value.text.string : 
"(noname)");
+
+                  fputs("    type =", stderr);
+                  for (node = type->child; node; node = node->next)
+                   fprintf(stderr, " \"%s\"", node->value.text.string);
+                 putc('\n', stderr);
+
+                  fprintf(stderr, "    scope = %s\n", scope ? scope : 
"(null)");
+#endif /* DEBUG */
+
+                  if (type->child->next)
+                 {
+                   mxmlElementSetAttr(structclass, "name",
+                                      type->child->next->value.text.string);
+                   sort_node(tree, structclass);
+                 }
+
+                  if (typedefnode && type->child)
+                   type->child->value.text.whitespace = 0;
+                  else if (structclass && type->child &&
+                          type->child->next && type->child->next->next)
+                 {
+                   for (bufptr = buffer, node = type->child->next->next;
+                        node;
+                        bufptr += strlen(bufptr))
+                   {
+                     if (node->value.text.whitespace && bufptr > buffer)
+                       *bufptr++ = ' ';
+
+                     strcpy(bufptr, node->value.text.string);
+
+                     next = node->next;
+                     mxmlDelete(node);
+                     node = next;
+                   }
+
+                   mxmlElementSetAttr(structclass, "parent", buffer);
+
+                   mxmlDelete(type);
+                   type = NULL;
+                 }
+                 else
+                 {
+                   mxmlDelete(type);
+                   type = NULL;
+                 }
+
+                 if (typedefnode && comment->last_child)
+                 {
+                  /*
+                   * 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
+                   fprintf(stderr,
+                           "    duplicating comment %p/%p for typedef...\n",
+                           comment->last_child, comment->child);
+#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 %p/%p to %s...\n",
+                         comment->last_child, comment->child,
+                         structclass->value.element.name);
+#endif /* DEBUG */
+                 update_comment(structclass, comment->last_child);
+                 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
+                         comment->last_child);
+
+                  if (scan_file(filename, fp, structclass))
+                 {
+                   mxmlDelete(comment);
+                   return (-1);
+                 }
+
+#ifdef DEBUG
+                  fputs("    ended typedef...\n", stderr);
+#endif /* DEBUG */
+                  structclass = NULL;
+                  break;
+                }
+               else if (type && type->child && type->child->next &&
+                        (!strcmp(type->child->value.text.string, "enum") ||
+                         (!strcmp(type->child->value.text.string, "typedef") &&
+                          !strcmp(type->child->next->value.text.string, 
"enum"))))
+                {
+                /*
+                 * Enumeration type...
+                 */
+
+                 if (!strcmp(type->child->value.text.string, "typedef"))
+                 {
+#ifdef DEBUG
+                    fputs("    starting typedef...\n", stderr);
+#endif /* DEBUG */
+
+                   typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
+                   mxmlDelete(type->child);
+                 }
+                 else
+                   typedefnode = NULL;
+
+                 enumeration = mxmlNewElement(MXML_NO_PARENT, "enumeration");
+
+#ifdef DEBUG
+                  fprintf(stderr, "Enumeration: <<<< %s >>>\n",
+                         type->child->next ?
+                             type->child->next->value.text.string : 
"(noname)");
+#endif /* DEBUG */
+
+                  if (type->child->next)
+                 {
+                   mxmlElementSetAttr(enumeration, "name",
+                                      type->child->next->value.text.string);
+                   sort_node(tree, enumeration);
+                 }
+
+                  if (typedefnode && type->child)
+                   type->child->value.text.whitespace = 0;
+                  else
+                 {
+                   mxmlDelete(type);
+                   type = NULL;
+                 }
+
+                 if (typedefnode && comment->last_child)
+                 {
+                  /*
+                   * 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
+                   fprintf(stderr,
+                           "    duplicating comment %p/%p for typedef...\n",
+                           comment->last_child, comment->child);
+#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
+                 fprintf(stderr, "    adding comment %p/%p to 
enumeration...\n",
+                         comment->last_child, comment->child);
+#endif /* DEBUG */
+                 update_comment(enumeration, comment->last_child);
+                 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
+                         comment->last_child);
+               }
+               else if (type && type->child &&
+                        !strcmp(type->child->value.text.string, "extern"))
+                {
+                  if (scan_file(filename, fp, tree))
+                 {
+                   mxmlDelete(comment);
+                   return (-1);
+                 }
+                }
+               else if (type)
+               {
+                 mxmlDelete(type);
+                 type = NULL;
+               }
+
+               braces ++;
+               function = NULL;
+               variable = NULL;
+               break;
+
+            case '}' :
+#ifdef DEBUG
+               fputs("    close brace...\n", stderr);
+#endif /* DEBUG */
+
+                if (structclass)
+                 scope = NULL;
+
+                if (!typedefnode)
+                 enumeration = NULL;
+
+               constant    = NULL;
+               structclass = NULL;
+
+               if (braces > 0)
+                 braces --;
+               else
+               {
+                 mxmlDelete(comment);
+                 return (0);
+               }
+               break;
+
+            case '(' :
+               if (type)
+               {
+#ifdef DEBUG
+                  fputs("Identifier: <<<< ( >>>\n", stderr);
+#endif /* DEBUG */
+                 mxmlNewText(type, 0, "(");
+               }
+
+               parens ++;
+               break;
+
+            case ')' :
+               if (type && parens)
+               {
+#ifdef DEBUG
+                  fputs("Identifier: <<<< ) >>>\n", stderr);
+#endif /* DEBUG */
+                 mxmlNewText(type, 0, ")");
+               }
+
+                if (function && type && !parens)
+               {
+                /*
+                 * Check for "void" argument...
+                 */
+
+                 if (type->child && type->child->next)
+                   variable = add_variable(function, "argument", type);
+                 else
+                   mxmlDelete(type);
+
+                 type = NULL;
+               }
+
+               if (parens > 0)
+                 parens --;
+               break;
+
+           case ';' :
+#ifdef DEBUG
+                fputs("Identifier: <<<< ; >>>\n", stderr);
+               fprintf(stderr, "    enumeration=%p, function=%p, type=%p, 
type->child=%p, typedefnode=%p\n",
+                       enumeration, function, type, type ? type->child : NULL, 
typedefnode);
+#endif /* DEBUG */
+
+               if (function)
+               {
+                 if (!strcmp(tree->value.element.name, "class"))
+                 {
+#ifdef DEBUG
+                   fputs("    ADDING FUNCTION TO CLASS\n", stderr);
+#endif /* DEBUG */
+                   sort_node(tree, function);
+                 }
+                 else
+                   mxmlDelete(function);
+
+                 function = NULL;
+                 variable = NULL;
+               }
+
+               if (type)
+               {
+                /*
+                 * See if we have a typedef...
+                 */
+
+                 if (type->child &&
+                     !strcmp(type->child->value.text.string, "typedef"))
+                 {
+                  /*
+                   * Yes, add it!
+                   */
+
+                   typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
+
+                   for (node = type->child->next; node; node = node->next)
+                     if (!strcmp(node->value.text.string, "("))
+                       break;
+
+                    if (node)
+                   {
+                     for (node = node->next; node; node = node->next)
+                       if (strcmp(node->value.text.string, "*"))
+                         break;
+                    }
+
+                    if (!node)
+                     node = type->last_child;
+
+#ifdef DEBUG
+                   fprintf(stderr, "    ADDING TYPEDEF FOR %p(%s)...\n",
+                           node, node->value.text.string);
+#endif /* DEBUG */
+
+                   mxmlElementSetAttr(typedefnode, "name",
+                                      node->value.text.string);
+                   sort_node(tree, typedefnode);
+
+                    if (type->child != node)
+                     mxmlDelete(type->child);
+
+                   mxmlDelete(node);
+
+                   if (type->child)
+                     type->child->value.text.whitespace = 0;
+
+                   mxmlAdd(typedefnode, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
+                           type);
+                   type = NULL;
+                   break;
+                 }
+                 else if (typedefnode && enumeration)
+                 {
+                  /*
+                   * Add enum typedef...
+                   */
+
+                    node = type->child;
+
+#ifdef DEBUG
+                   fprintf(stderr, "    ADDING TYPEDEF FOR %p(%s)...\n",
+                           node, node->value.text.string);
+#endif /* DEBUG */
+
+                   mxmlElementSetAttr(typedefnode, "name",
+                                      node->value.text.string);
+                   sort_node(tree, typedefnode);
+                   mxmlDelete(type);
+
+                   type = mxmlNewElement(typedefnode, "type");
+                    mxmlNewText(type, 0, "enum");
+                   mxmlNewText(type, 1,
+                               mxmlElementGetAttr(enumeration, "name"));
+                   enumeration = NULL;
+                   type = NULL;
+                   break;
+                 }
+
+                 mxmlDelete(type);
+                 type = NULL;
+               }
+               break;
+
+           case ':' :
+               if (type)
+               {
+#ifdef DEBUG
+                  fputs("Identifier: <<<< : >>>\n", stderr);
+#endif /* DEBUG */
+                 mxmlNewText(type, 1, ":");
+               }
+               break;
+
+           case '*' :
+               if (type)
+               {
+#ifdef DEBUG
+                  fputs("Identifier: <<<< * >>>\n", stderr);
+#endif /* DEBUG */
+                  ch = type->last_child->value.text.string[0];
+                 mxmlNewText(type, isalnum(ch) || ch == '_', "*");
+               }
+               break;
+
+           case ',' :
+               if (type && !enumeration)
+               {
+#ifdef DEBUG
+                  fputs("Identifier: <<<< , >>>\n", stderr);
+#endif /* DEBUG */
+                 mxmlNewText(type, 0, ",");
+               }
+               break;
+
+           case '&' :
+               if (type)
+               {
+#ifdef DEBUG
+                  fputs("Identifier: <<<< & >>>\n", stderr);
+#endif /* DEBUG */
+                 mxmlNewText(type, 1, "&");
+               }
+               break;
+
+           case '+' :
+               if (type)
+               {
+#ifdef DEBUG
+                  fputs("Identifier: <<<< + >>>\n", stderr);
+#endif /* DEBUG */
+                  ch = type->last_child->value.text.string[0];
+                 mxmlNewText(type, isalnum(ch) || ch == '_', "+");
+               }
+               break;
+
+           case '-' :
+               if (type)
+               {
+#ifdef DEBUG
+                  fputs("Identifier: <<<< - >>>\n", stderr);
+#endif /* DEBUG */
+                  ch = type->last_child->value.text.string[0];
+                 mxmlNewText(type, isalnum(ch) || ch == '_', "-");
+               }
+               break;
+
+           case '=' :
+               if (type)
+               {
+#ifdef DEBUG
+                  fputs("Identifier: <<<< = >>>\n", stderr);
+#endif /* DEBUG */
+                  ch = type->last_child->value.text.string[0];
+                 mxmlNewText(type, isalnum(ch) || ch == '_', "=");
+               }
+               break;
+
+            default :                  /* Other */
+               if (isalnum(ch) || ch == '_' || ch == '.' || ch == ':' || ch == 
'~')
+               {
+                 state     = STATE_IDENTIFIER;
+                 bufptr    = buffer;
+                 *bufptr++ = ch;
+               }
+               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->child != comment->last_child)
+                     {
+#ifdef DEBUG
+                       fprintf(stderr, "    removing comment %p(%20.20s), last 
comment %p(%20.20s)...\n",
+                               comment->child,
+                               comment->child ? 
comment->child->value.text.string : "",
+                               comment->last_child,
+                               comment->last_child ? 
comment->last_child->value.text.string : "");
+#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, typedefnode=%p, tree=\"%s\"\n",
+                             variable, constant, typedefnode,
+                             tree->value.element.name);
+#endif /* DEBUG */
+
+                     if (variable)
+                     {
+                       if (strstr(buffer, "@private@"))
+                       {
+                        /*
+                         * Delete private variables...
+                         */
+
+                         mxmlDelete(variable);
+                       }
+                       else
+                       {
+                         description = mxmlNewElement(variable, "description");
+#ifdef DEBUG
+                         fprintf(stderr,
+                                 "    adding comment %p/%p to variable...\n",
+                                 comment->last_child, comment->child);
+#endif /* DEBUG */
+                         mxmlNewText(comment, 0, buffer);
+                         update_comment(variable,
+                                        mxmlNewText(description, 0, buffer));
+                        }
+
+                       variable = NULL;
+                     }
+                     else if (constant)
+                     {
+                       if (strstr(buffer, "@private@"))
+                       {
+                        /*
+                         * Delete private constants...
+                         */
+
+                         mxmlDelete(constant);
+                       }
+                       else
+                       {
+                         description = mxmlNewElement(constant, "description");
+#ifdef DEBUG
+                         fprintf(stderr,
+                                 "    adding comment %p/%p to constant...\n",
+                                 comment->last_child, comment->child);
+#endif /* DEBUG */
+                         mxmlNewText(comment, 0, buffer);
+                         update_comment(constant,
+                                        mxmlNewText(description, 0, buffer));
+                       }
+
+                       constant = NULL;
+                     }
+                     else if (typedefnode)
+                     {
+                       if (strstr(buffer, "@private@"))
+                       {
+                        /*
+                         * Delete private typedefs...
+                         */
+
+                         mxmlDelete(typedefnode);
+
+                         if (structclass)
+                         {
+                           mxmlDelete(structclass);
+                           structclass = NULL;
+                         }
+
+                         if (enumeration)
+                         {
+                           mxmlDelete(enumeration);
+                           enumeration = NULL;
+                         }
+                       }
+                       else
+                       {
+                         description = mxmlNewElement(typedefnode, 
"description");
+#ifdef DEBUG
+                         fprintf(stderr,
+                                 "    adding comment %p/%p to typedef %s...\n",
+                                 comment->last_child, comment->child,
+                                 mxmlElementGetAttr(typedefnode, "name"));
+#endif /* DEBUG */
+                         mxmlNewText(comment, 0, buffer);
+                         update_comment(typedefnode,
+                                        mxmlNewText(description, 0, buffer));
+
+                         if (structclass)
+                         {
+                           description = mxmlNewElement(structclass, 
"description");
+                           update_comment(structclass,
+                                          mxmlNewText(description, 0, buffer));
+                         }
+                         else if (enumeration)
+                         {
+                           description = mxmlNewElement(enumeration, 
"description");
+                           update_comment(enumeration,
+                                          mxmlNewText(description, 0, buffer));
+                         }
+                       }
+
+                       typedefnode = NULL;
+                     }
+                     else if (strcmp(tree->value.element.name, "mxmldoc") &&
+                              !mxmlFindElement(tree, tree, "description",
+                                               NULL, NULL, MXML_DESCEND_FIRST))
+                      {
+                       description = mxmlNewElement(tree, "description");
+#ifdef DEBUG
+                       fprintf(stderr, "    adding comment %p/%p to 
parent...\n",
+                               comment->last_child, comment->child);
+#endif /* DEBUG */
+                       mxmlNewText(comment, 0, buffer);
+                       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 */
+
+                     state = STATE_NONE;
+                     break;
+                   }
+                   else
+                     ungetc(ch, fp);
+                 }
+                 else if (ch == '\n' && bufptr > buffer &&
+                          bufptr < (buffer + sizeof(buffer) - 1))
+                   *bufptr++ = ch;
+                 else if (!isspace(ch))
+                   break;
+
+               if (ch != EOF)
+                 ungetc(ch, fp);
+
+                if (bufptr > buffer && bufptr < (buffer + sizeof(buffer) - 1))
+                 *bufptr++ = '\n';
+               break;
+
+           case '/' :
+               if (ch == '/' && bufptr > buffer && bufptr[-1] == '*')
+               {
+                 while (bufptr > buffer &&
+                        (bufptr[-1] == '*' || isspace(bufptr[-1] & 255)))
+                   bufptr --;
+                 *bufptr = '\0';
+
+                 if (comment->child != comment->last_child)
+                 {
+#ifdef DEBUG
+                   fprintf(stderr, "    removing comment %p(%20.20s), last 
comment %p(%20.20s)...\n",
+                           comment->child,
+                           comment->child ? comment->child->value.text.string 
: "",
+                           comment->last_child,
+                           comment->last_child ? 
comment->last_child->value.text.string : "");
+#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, typedefnode=%p, tree=\"%s\"\n",
+                         variable, constant, typedefnode,
+                         tree->value.element.name);
+#endif /* DEBUG */
+
+                 if (variable)
+                 {
+                   if (strstr(buffer, "@private@"))
+                   {
+                    /*
+                     * Delete private variables...
+                     */
+
+                     mxmlDelete(variable);
+                   }
+                   else
+                   {
+                     description = mxmlNewElement(variable, "description");
+#ifdef DEBUG
+                     fprintf(stderr, "    adding comment %p/%p to 
variable...\n",
+                             comment->last_child, comment->child);
+#endif /* DEBUG */
+                     mxmlNewText(comment, 0, buffer);
+                     update_comment(variable,
+                                    mxmlNewText(description, 0, buffer));
+                    }
+
+                   variable = NULL;
+                 }
+                 else if (constant)
+                 {
+                   if (strstr(buffer, "@private@"))
+                   {
+                    /*
+                     * Delete private constants...
+                     */
+
+                     mxmlDelete(constant);
+                   }
+                   else
+                   {
+                     description = mxmlNewElement(constant, "description");
+#ifdef DEBUG
+                     fprintf(stderr, "    adding comment %p/%p to 
constant...\n",
+                             comment->last_child, comment->child);
+#endif /* DEBUG */
+                     mxmlNewText(comment, 0, buffer);
+                     update_comment(constant,
+                                    mxmlNewText(description, 0, buffer));
+                   }
+
+                   constant = NULL;
+                 }
+                 else if (typedefnode)
+                 {
+                   if (strstr(buffer, "@private@"))
+                   {
+                    /*
+                     * Delete private typedefs...
+                     */
+
+                     mxmlDelete(typedefnode);
+
+                     if (structclass)
+                     {
+                       mxmlDelete(structclass);
+                       structclass = NULL;
+                     }
+
+                     if (enumeration)
+                     {
+                       mxmlDelete(enumeration);
+                       enumeration = NULL;
+                     }
+                   }
+                   else
+                   {
+                     description = mxmlNewElement(typedefnode, "description");
+#ifdef DEBUG
+                     fprintf(stderr,
+                             "    adding comment %p/%p to typedef %s...\n",
+                             comment->last_child, comment->child,
+                             mxmlElementGetAttr(typedefnode, "name"));
+#endif /* DEBUG */
+                     mxmlNewText(comment, 0, buffer);
+                     update_comment(typedefnode,
+                                    mxmlNewText(description, 0, buffer));
+
+                     if (structclass)
+                     {
+                       description = mxmlNewElement(structclass, 
"description");
+                       update_comment(structclass,
+                                      mxmlNewText(description, 0, buffer));
+                     }
+                     else if (enumeration)
+                     {
+                       description = mxmlNewElement(enumeration, 
"description");
+                       update_comment(enumeration,
+                                      mxmlNewText(description, 0, buffer));
+                     }
+                   }
+
+                   typedefnode = NULL;
+                 }
+                 else if (strcmp(tree->value.element.name, "mxmldoc") &&
+                          !mxmlFindElement(tree, tree, "description",
+                                           NULL, NULL, MXML_DESCEND_FIRST))
+                  {
+                   description = mxmlNewElement(tree, "description");
+#ifdef DEBUG
+                   fprintf(stderr, "    adding comment %p/%p to parent...\n",
+                           comment->last_child, comment->child);
+#endif /* DEBUG */
+                   mxmlNewText(comment, 0, buffer);
+                   update_comment(tree,
+                                  mxmlNewText(description, 0, buffer));
+                 }
+                 else
+                   mxmlNewText(comment, 0, buffer);
+
+#ifdef DEBUG
+                 fprintf(stderr, "C comment: <<<< %s >>>\n", buffer);
+#endif /* DEBUG */
+
+                 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')
+         {
+           state = STATE_NONE;
+           *bufptr = '\0';
+
+            if (comment->child != comment->last_child)
+           {
+#ifdef DEBUG
+             fprintf(stderr, "    removing comment %p(%20.20s), last comment 
%p(%20.20s)...\n",
+                     comment->child,
+                     comment->child ? comment->child->value.text.string : "",
+                     comment->last_child,
+                     comment->last_child ? 
comment->last_child->value.text.string : "");
+#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)
+           {
+             if (strstr(buffer, "@private@"))
+             {
+              /*
+               * Delete private variables...
+               */
+
+               mxmlDelete(variable);
+             }
+             else
+             {
+               description = mxmlNewElement(variable, "description");
+#ifdef DEBUG
+               fprintf(stderr, "    adding comment %p/%p to variable...\n",
+                       comment->last_child, comment->child);
+#endif /* DEBUG */
+               mxmlNewText(comment, 0, buffer);
+               update_comment(variable,
+                              mxmlNewText(description, 0, buffer));
+              }
+
+             variable = NULL;
+           }
+           else if (constant)
+           {
+             if (strstr(buffer, "@private@"))
+             {
+              /*
+               * Delete private constants...
+               */
+
+               mxmlDelete(constant);
+             }
+             else
+             {
+               description = mxmlNewElement(constant, "description");
+#ifdef DEBUG
+               fprintf(stderr, "    adding comment %p/%p to constant...\n",
+                       comment->last_child, comment->child);
+#endif /* DEBUG */
+               mxmlNewText(comment, 0, buffer);
+               update_comment(constant,
+                              mxmlNewText(description, 0, buffer));
+              }
+
+             constant = NULL;
+           }
+           else if (typedefnode)
+           {
+             if (strstr(buffer, "@private@"))
+             {
+              /*
+               * Delete private typedefs...
+               */
+
+               mxmlDelete(typedefnode);
+               typedefnode = NULL;
+
+               if (structclass)
+               {
+                 mxmlDelete(structclass);
+                 structclass = NULL;
+               }
+
+               if (enumeration)
+               {
+                 mxmlDelete(enumeration);
+                 enumeration = NULL;
+               }
+             }
+             else
+             {
+               description = mxmlNewElement(typedefnode, "description");
+#ifdef DEBUG
+               fprintf(stderr, "    adding comment %p/%p to typedef %s...\n",
+                       comment->last_child, comment->child,
+                       mxmlElementGetAttr(typedefnode, "name"));
+#endif /* DEBUG */
+               mxmlNewText(comment, 0, buffer);
+               update_comment(typedefnode,
+                              mxmlNewText(description, 0, buffer));
+
+               if (structclass)
+               {
+                 description = mxmlNewElement(structclass, "description");
+                 update_comment(structclass,
+                                mxmlNewText(description, 0, buffer));
+               }
+               else if (enumeration)
+               {
+                 description = mxmlNewElement(enumeration, "description");
+                 update_comment(enumeration,
+                                mxmlNewText(description, 0, buffer));
+               }
+              }
+           }
+           else if (strcmp(tree->value.element.name, "mxmldoc") &&
+                    !mxmlFindElement(tree, tree, "description",
+                                     NULL, NULL, MXML_DESCEND_FIRST))
+            {
+              description = mxmlNewElement(tree, "description");
+#ifdef DEBUG
+             fprintf(stderr, "    adding comment %p/%p to parent...\n",
+                     comment->last_child, comment->child);
+#endif /* DEBUG */
+             mxmlNewText(comment, 0, buffer);
+             update_comment(tree,
+                            mxmlNewText(description, 0, buffer));
+           }
+           else
+              mxmlNewText(comment, 0, buffer);
+
+#ifdef DEBUG
+           fprintf(stderr, "C++ comment: <<<< %s >>>\n", buffer);
+#endif /* DEBUG */
+         }
+         else if (ch == ' ' && bufptr == buffer)
+           break;
+         else if (bufptr < (buffer + sizeof(buffer) - 1))
+           *bufptr++ = ch;
+          break;
+
+      case STATE_STRING :              /* Inside a string constant */
+         *bufptr++ = ch;
+
+          if (ch == '\\')
+           *bufptr++ = getc(fp);
+         else if (ch == '\"')
+         {
+           *bufptr = '\0';
+
+           if (type)
+             mxmlNewText(type, type->child != NULL, buffer);
+
+           state = STATE_NONE;
+         }
+          break;
+
+      case STATE_CHARACTER :           /* Inside a character constant */
+         *bufptr++ = ch;
+
+          if (ch == '\\')
+           *bufptr++ = getc(fp);
+         else if (ch == '\'')
+         {
+           *bufptr = '\0';
+
+           if (type)
+             mxmlNewText(type, type->child != NULL, buffer);
+
+           state = STATE_NONE;
+         }
+          break;
+
+      case STATE_IDENTIFIER :          /* Inside a keyword or identifier */
+         if (isalnum(ch) || ch == '_' || ch == '[' || ch == ']' ||
+             (ch == ',' && (parens > 1 || (type && !enumeration && 
!function))) ||
+             ch == ':' || ch == '.' || ch == '~')
+         {
+           if (bufptr < (buffer + sizeof(buffer) - 1))
+             *bufptr++ = ch;
+         }
+         else
+         {
+           ungetc(ch, fp);
+           *bufptr = '\0';
+           state   = STATE_NONE;
+
+#ifdef DEBUG
+            fprintf(stderr, "    braces=%d, type=%p, type->child=%p, 
buffer=\"%s\"\n",
+                   braces, type, type ? type->child : NULL, buffer);
+#endif /* DEBUG */
+
+            if (!braces)
+           {
+             if (!type || !type->child)
+             {
+               if (!strcmp(tree->value.element.name, "class"))
+               {
+                 if (!strcmp(buffer, "public") ||
+                     !strcmp(buffer, "public:"))
+                 {
+                   scope = "public";
+#ifdef DEBUG
+                   fputs("    scope = public\n", stderr);
+#endif /* DEBUG */
+                   break;
+                 }
+                 else if (!strcmp(buffer, "private") ||
+                          !strcmp(buffer, "private:"))
+                 {
+                   scope = "private";
+#ifdef DEBUG
+                   fputs("    scope = private\n", stderr);
+#endif /* DEBUG */
+                   break;
+                 }
+                 else if (!strcmp(buffer, "protected") ||
+                          !strcmp(buffer, "protected:"))
+                 {
+                   scope = "protected";
+#ifdef DEBUG
+                   fputs("    scope = protected\n", stderr);
+#endif /* DEBUG */
+                   break;
+                 }
+               }
+             }
+
+             if (!type)
+                type = mxmlNewElement(MXML_NO_PARENT, "type");
+
+#ifdef DEBUG
+              fprintf(stderr, "    function=%p (%s), type->child=%p, ch='%c', 
parens=%d\n",
+                     function,
+                     function ? mxmlElementGetAttr(function, "name") : "null",
+                     type->child, ch, parens);
+#endif /* DEBUG */
+
+              if (!function && ch == '(')
+             {
+               if (type->child &&
+                   !strcmp(type->child->value.text.string, "extern"))
+               {
+                /*
+                 * Remove external declarations...
+                 */
+
+                 mxmlDelete(type);
+                 type = NULL;
+                 break;
+               }
+
+               if (type->child &&
+                   !strcmp(type->child->value.text.string, "static") &&
+                   !strcmp(tree->value.element.name, "mxmldoc"))
+               {
+                /*
+                 * Remove static functions...
+                 */
+
+                 mxmlDelete(type);
+                 type = NULL;
+                 break;
+               }
+
+               function = mxmlNewElement(MXML_NO_PARENT, "function");
+               if ((bufptr = strchr(buffer, ':')) != NULL && bufptr[1] == ':')
+               {
+                 *bufptr = '\0';
+                 bufptr += 2;
+
+                 if ((fstructclass =
+                          mxmlFindElement(tree, tree, "class", "name", buffer,
+                                          MXML_DESCEND_FIRST)) == NULL)
+                   fstructclass =
+                       mxmlFindElement(tree, tree, "struct", "name", buffer,
+                                       MXML_DESCEND_FIRST);
+               }
+               else
+                 bufptr = buffer;
+
+               mxmlElementSetAttr(function, "name", bufptr);
+
+               if (scope)
+                 mxmlElementSetAttr(function, "scope", scope);
+
+#ifdef DEBUG
+                fprintf(stderr, "function: %s\n", buffer);
+               fprintf(stderr, "    scope = %s\n", scope ? scope : "(null)");
+               fprintf(stderr, "    comment = %p\n", comment);
+               fprintf(stderr, "    child = (%p) %s\n",
+                       comment->child,
+                       comment->child ?
+                           comment->child->value.text.string : "(null)");
+               fprintf(stderr, "    last_child = (%p) %s\n",
+                       comment->last_child,
+                       comment->last_child ?
+                           comment->last_child->value.text.string : "(null)");
+#endif /* DEBUG */
+
+                if (type->last_child &&
+                   strcmp(type->last_child->value.text.string, "void"))
+               {
+                  returnvalue = mxmlNewElement(function, "returnvalue");
+
+                 mxmlAdd(returnvalue, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, 
type);
+
+                 description = mxmlNewElement(returnvalue, "description");
+#ifdef DEBUG
+                 fprintf(stderr, "    adding comment %p/%p to 
returnvalue...\n",
+                         comment->last_child, comment->child);
+#endif /* DEBUG */
+                 update_comment(returnvalue, comment->last_child);
+                 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
+                         comment->last_child);
+                }
+               else
+                 mxmlDelete(type);
+
+               description = mxmlNewElement(function, "description");
+#ifdef DEBUG
+                 fprintf(stderr, "    adding comment %p/%p to function...\n",
+                         comment->last_child, comment->child);
+#endif /* DEBUG */
+               update_comment(function, comment->last_child);
+               mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
+                       comment->last_child);
+
+               type = NULL;
+             }
+             else if (function && ((ch == ')' && parens == 1) || ch == ','))
+             {
+              /*
+               * Argument definition...
+               */
+
+                if (strcmp(buffer, "void"))
+               {
+                 mxmlNewText(type, type->child != NULL &&
+                                   type->last_child->value.text.string[0] != 
'(' &&
+                                   type->last_child->value.text.string[0] != 
'*',
+                             buffer);
+
+#ifdef DEBUG
+                  fprintf(stderr, "Argument: <<<< %s >>>\n", buffer);
+#endif /* DEBUG */
+
+                 variable = add_variable(function, "argument", type);
+               }
+               else
+                 mxmlDelete(type);
+
+               type = NULL;
+             }
+              else if (type->child && !function && (ch == ';' || ch == ','))
+             {
+#ifdef DEBUG
+               fprintf(stderr, "    got semicolon, typedefnode=%p, 
structclass=%p\n",
+                       typedefnode, structclass);
+#endif /* DEBUG */
+
+               if (typedefnode || structclass)
+               {
+#ifdef DEBUG
+                  fprintf(stderr, "Typedef/struct/class: <<<< %s >>>>\n", 
buffer);
+#endif /* DEBUG */
+
+                 if (typedefnode)
+                 {
+                   mxmlElementSetAttr(typedefnode, "name", buffer);
+
+                    sort_node(tree, typedefnode);
+                 }
+
+                 if (structclass && !mxmlElementGetAttr(structclass, "name"))
+                 {
+#ifdef DEBUG
+                   fprintf(stderr, "setting struct/class name to %s!\n",
+                           type->last_child->value.text.string);
+#endif /* DEBUG */
+                   mxmlElementSetAttr(structclass, "name", buffer);
+
+                   sort_node(tree, structclass);
+                   structclass = NULL;
+                 }
+
+                 if (typedefnode)
+                   mxmlAdd(typedefnode, MXML_ADD_BEFORE, MXML_ADD_TO_PARENT,
+                           type);
+                  else
+                   mxmlDelete(type);
+
+                 type        = NULL;
+                 typedefnode = NULL;
+               }
+               else if (type->child &&
+                        !strcmp(type->child->value.text.string, "typedef"))
+               {
+                /*
+                 * Simple typedef...
+                 */
+
+#ifdef DEBUG
+                  fprintf(stderr, "Typedef: <<<< %s >>>\n", buffer);
+#endif /* DEBUG */
+
+                 typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
+                 mxmlElementSetAttr(typedefnode, "name", buffer);
+                 mxmlDelete(type->child);
+
+                  sort_node(tree, typedefnode);
+
+                  if (type->child)
+                   type->child->value.text.whitespace = 0;
+
+                 mxmlAdd(typedefnode, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, 
type);
+                 type = NULL;
+               }
+               else if (!parens)
+               {
+                /*
+                 * Variable definition...
+                 */
+
+                 if (type->child &&
+                     !strcmp(type->child->value.text.string, "static") &&
+                     !strcmp(tree->value.element.name, "mxmldoc"))
+                 {
+                  /*
+                   * Remove static functions...
+                   */
+
+                   mxmlDelete(type);
+                   type = NULL;
+                   break;
+                 }
+
+                 mxmlNewText(type, type->child != NULL &&
+                                   type->last_child->value.text.string[0] != 
'(' &&
+                                   type->last_child->value.text.string[0] != 
'*',
+                             buffer);
+
+#ifdef DEBUG
+                  fprintf(stderr, "Variable: <<<< %s >>>>\n", buffer);
+                  fprintf(stderr, "    scope = %s\n", scope ? scope : 
"(null)");
+#endif /* DEBUG */
+
+                 variable = add_variable(MXML_NO_PARENT, "variable", type);
+                 type     = NULL;
+
+                 sort_node(tree, variable);
+
+                 if (scope)
+                   mxmlElementSetAttr(variable, "scope", scope);
+               }
+              }
+             else
+              {
+#ifdef DEBUG
+                fprintf(stderr, "Identifier: <<<< %s >>>>\n", buffer);
+#endif /* DEBUG */
+
+               mxmlNewText(type, type->child != NULL &&
+                                 type->last_child->value.text.string[0] != '(' 
&&
+                                 type->last_child->value.text.string[0] != '*',
+                           buffer);
+             }
+           }
+           else if (enumeration && !isdigit(buffer[0] & 255))
+           {
+#ifdef DEBUG
+             fprintf(stderr, "Constant: <<<< %s >>>\n", buffer);
+#endif /* DEBUG */
+
+             constant = mxmlNewElement(MXML_NO_PARENT, "constant");
+             mxmlElementSetAttr(constant, "name", buffer);
+             sort_node(enumeration, constant);
+           }
+           else if (type)
+           {
+             mxmlDelete(type);
+             type = NULL;
+           }
+         }
+          break;
+    }
+
+#if DEBUG > 1
+    if (state != oldstate)
+    {
+      fprintf(stderr, "    changed states from %s to %s on receipt of 
character '%c'...\n",
+              states[oldstate], states[state], oldch);
+      fprintf(stderr, "    variable = %p\n", variable);
+      if (type)
+      {
+        fputs("    type =", stderr);
+        for (temp = type->child; temp; temp = temp->next)
+         fprintf(stderr, " \"%s\"", temp->value.text.string);
+       fputs("\n", stderr);
+      }
+    }
+#endif /* DEBUG > 1 */
+  }
+
+  mxmlDelete(comment);
+
+ /*
+  * All done, return with no errors...
+  */
+
+  return (0);
+}
+
+
+/*
+ * 'sort_node()' - Insert a node sorted into a tree.
+ */
+
+static void
+sort_node(mxml_node_t *tree,           /* I - Tree to sort into */
+          mxml_node_t *node)           /* I - Node to add */
+{
+  mxml_node_t  *temp;                  /* Current node */
+  const char   *tempname,              /* Name of current node */
+               *nodename,              /* Name of node */
+               *scope;                 /* Scope */
+
+
+#if DEBUG > 1
+  fprintf(stderr, "    sort_node(tree=%p, node=%p)\n", tree, node);
+#endif /* DEBUG > 1 */
+
+ /*
+  * Range check input...
+  */
+
+  if (!tree || !node || node->parent == tree)
+    return;
+
+ /*
+  * Get the node name...
+  */
+
+  if ((nodename = mxmlElementGetAttr(node, "name")) == NULL)
+    return;
+
+  if (nodename[0] == '_')
+    return;                            /* Hide private names */
+
+#if DEBUG > 1
+  fprintf(stderr, "        nodename=%p (\"%s\")\n", nodename, nodename);
+#endif /* DEBUG > 1 */
+
+ /*
+  * Delete any existing definition at this level, if one exists...
+  */
+
+  if ((temp = mxmlFindElement(tree, tree, node->value.element.name,
+                              "name", nodename, MXML_DESCEND_FIRST)) != NULL)
+  {
+   /*
+    * Copy the scope if needed...
+    */
+
+    if ((scope = mxmlElementGetAttr(temp, "scope")) != NULL &&
+        mxmlElementGetAttr(node, "scope") == NULL)
+    {
+#ifdef DEBUG
+      fprintf(stderr, "    copying scope %s for %s\n", scope, nodename);
+#endif /* DEBUG */
+
+      mxmlElementSetAttr(node, "scope", scope);
+    }
+
+    mxmlDelete(temp);
+  }
+
+ /*
+  * Add the node into the tree at the proper place...
+  */
+
+  for (temp = tree->child; temp; temp = temp->next)
+  {
+#if DEBUG > 1
+    fprintf(stderr, "        temp=%p\n", temp);
+#endif /* DEBUG > 1 */
+
+    if ((tempname = mxmlElementGetAttr(temp, "name")) == NULL)
+      continue;
+
+#if DEBUG > 1
+    fprintf(stderr, "        tempname=%p (\"%s\")\n", tempname, tempname);
+#endif /* DEBUG > 1 */
+
+    if (strcmp(nodename, tempname) < 0)
+      break;
+  }
+
+  if (temp)
+    mxmlAdd(tree, MXML_ADD_BEFORE, temp, node);
+  else
+    mxmlAdd(tree, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
+}
+
+
+/*
+ * 'update_comment()' - Update a comment node.
+ */
+
+static void
+update_comment(mxml_node_t *parent,    /* I - Parent node */
+               mxml_node_t *comment)   /* I - Comment 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...
+  */
+
+  if (!parent || !comment)
+    return;
+
+ /*
+  * Convert "\/" to "/"...
+  */
+
+  for (ptr = strstr(comment->value.text.string, "\\/");
+       ptr;
+       ptr = strstr(ptr, "\\/"))
+    safe_strcpy(ptr, ptr + 1);
+
+ /*
+  * Update the comment...
+  */
+
+  ptr = comment->value.text.string;
+
+  if (*ptr == '\'')
+  {
+   /*
+    * Convert "'name()' - description" to "description".
+    */
+
+    for (ptr ++; *ptr && *ptr != '\''; ptr ++);
+
+    if (*ptr == '\'')
+    {
+      ptr ++;
+      while (isspace(*ptr & 255))
+        ptr ++;
+
+      if (*ptr == '-')
+        ptr ++;
+
+      while (isspace(*ptr & 255))
+        ptr ++;
+
+      safe_strcpy(comment->value.text.string, ptr);
+    }
+  }
+  else if (!strncmp(ptr, "I ", 2) || !strncmp(ptr, "O ", 2) ||
+           !strncmp(ptr, "IO ", 3))
+  {
+   /*
+    * 'Convert "I - description", "IO - description", or "O - description"
+    * to description + direction attribute.
+    */
+
+    ptr = strchr(ptr, ' ');
+    *ptr++ = '\0';
+
+    if (!strcmp(parent->value.element.name, "argument"))
+      mxmlElementSetAttr(parent, "direction", comment->value.text.string);
+
+    while (isspace(*ptr & 255))
+      ptr ++;
+
+    if (*ptr == '-')
+      ptr ++;
+
+    while (isspace(*ptr & 255))
+      ptr ++;
+
+    safe_strcpy(comment->value.text.string, ptr);
+  }
+
+ /*
+  * Eliminate leading and trailing *'s...
+  */
+
+  for (ptr = comment->value.text.string; *ptr == '*'; ptr ++);
+  for (; isspace(*ptr & 255); ptr ++);
+  if (ptr > comment->value.text.string)
+    safe_strcpy(comment->value.text.string, ptr);
+
+  for (ptr = comment->value.text.string + strlen(comment->value.text.string) - 
1;
+       ptr > comment->value.text.string && *ptr == '*';
+       ptr --)
+    *ptr = '\0';
+  for (; ptr > comment->value.text.string && isspace(*ptr & 255); ptr --)
+    *ptr = '\0';
+
+#ifdef DEBUG
+  fprintf(stderr, "    updated comment = %s\n", comment->value.text.string);
+#endif /* DEBUG */
+}
+
+
+/*
+ * '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("    --css filename.css         Set CSS stylesheet file");
+  puts("    --docset bundleid.docset   Generate documentation set");
+  puts("    --docversion version       Set documentation version");
+  puts("    --feedname name            Set documentation set feed name");
+  puts("    --feedurl url              Set documentation set feed URL");
+  puts("    --footer footerfile        Set footer file");
+  puts("    --framed basename          Generate framed HTML to 
basename*.html");
+  puts("    --header headerfile        Set header file");
+  puts("    --intro introfile          Set introduction file");
+  puts("    --man name                 Generate man page");
+  puts("    --no-output                Do no generate documentation file");
+  puts("    --section section          Set section name");
+  puts("    --title title              Set documentation title");
+  puts("    --tokens path              Generate Xcode docset Tokens.xml file");
+  puts("    --version                  Show mxmldoc/Mini-XML version");
+
+  exit(1);
+}
+
+
+/*
+ * 'write_description()' - Write the description text.
+ */
+
+static void
+write_description(
+    FILE        *out,                  /* I - Output file */
+    mxml_node_t *description,          /* I - Description node */
+    const char  *element,              /* I - HTML element, if any */
+    int         summary)               /* I - Show summary */
+{
+  char text[10240],                    /* Text for description */
+        *start,                                /* Start of code/link */
+       *ptr;                           /* Pointer into text */
+  int  col;                            /* Current column */
+
+
+  if (!description)
+    return;
+
+  get_text(description, text, sizeof(text));
+
+  ptr = strstr(text, "\n\n");
+
+  if (summary)
+  {
+    if (ptr)
+      *ptr = '\0';
+
+    ptr = text;
+  }
+  else if (!ptr || !ptr[2])
+    return;
+  else
+    ptr += 2;
+
+  if (element && *element)
+    fprintf(out, "<%s class=\"%s\">", element,
+            summary ? "description" : "discussion");
+  else if (!summary)
+    fputs(".PP\n", out);
+
+  for (col = 0; *ptr; ptr ++)
+  {
+    if (*ptr == '@' &&
+        (!strncmp(ptr + 1, "deprecated@", 11) ||
+         !strncmp(ptr + 1, "since ", 6)))
+    {
+      ptr ++;
+      while (*ptr && *ptr != '@')
+        ptr ++;
+
+      if (!*ptr)
+        return;
+    }
+    else if (!strncmp(ptr, "@code ", 6))
+    {
+      for (ptr += 6; isspace(*ptr & 255); ptr ++);
+
+      for (start = ptr, ptr ++; *ptr && *ptr != '@'; ptr ++);
+
+      if (*ptr)
+        *ptr = '\0';
+      else
+        ptr --;
+
+      if (element && *element)
+        fprintf(out, "<code>%s</code>", start);
+      else if (element)
+        fputs(start, out);
+      else
+        fprintf(out, "\\fB%s\\fR", start);
+    }
+    else if (!strncmp(ptr, "@link ", 6))
+    {
+      for (ptr += 6; isspace(*ptr & 255); ptr ++);
+
+      for (start = ptr, ptr ++; *ptr && *ptr != '@'; ptr ++);
+
+      if (*ptr)
+        *ptr = '\0';
+      else
+        ptr --;
+
+      if (element && *element)
+        fprintf(out, "<a href=\"#%s\"><code>%s</code></a>", start, start);
+      else if (element)
+        fputs(start, out);
+      else
+        fprintf(out, "\\fI%s\\fR", start);
+    }
+    else if (element)
+    {
+      if (*ptr == '&')
+        fputs("&amp;", out);
+      else if (*ptr == '<')
+        fputs("&lt;", out);
+      else if (*ptr == '>')
+        fputs("&gt;", out);
+      else if (*ptr == '\"')
+        fputs("&quot;", out);
+      else if (*ptr & 128)
+      {
+       /*
+        * Convert UTF-8 to Unicode constant...
+        */
+
+        int    ch;                     /* Unicode character */
+
+
+        ch = *ptr & 255;
+
+        if ((ch & 0xe0) == 0xc0)
+        {
+          ch = ((ch & 0x1f) << 6) | (ptr[1] & 0x3f);
+         ptr ++;
+        }
+        else if ((ch & 0xf0) == 0xe0)
+        {
+          ch = ((((ch * 0x0f) << 6) | (ptr[1] & 0x3f)) << 6) | (ptr[2] & 0x3f);
+         ptr += 2;
+        }
+
+        if (ch == 0xa0)
+        {
+         /*
+          * Handle non-breaking space as-is...
+         */
+
+          fputs("&nbsp;", out);
+        }
+        else
+          fprintf(out, "&#x%x;", ch);
+      }
+      else if (*ptr == '\n' && ptr[1] == '\n' && ptr[2] && ptr[2] != '@')
+      {
+        fputs("<br>\n<br>\n", out);
+        ptr ++;
+      }
+      else
+        putc(*ptr, out);
+    }
+    else if (*ptr == '\n' && ptr[1] == '\n' && ptr[2] && ptr[2] != '@')
+    {
+      fputs("\n.PP\n", out);
+      ptr ++;
+    }
+    else
+    {
+      if (*ptr == '\\' || (*ptr == '.' && col == 0))
+        putc('\\', out);
+
+      putc(*ptr, out);
+
+      if (*ptr == '\n')
+        col = 0;
+      else
+        col ++;
+    }
+  }
+
+  if (element && *element)
+    fprintf(out, "</%s>\n", element);
+  else if (!element)
+    putc('\n', out);
+}
+
+
+/*
+ * 'write_element()' - Write an element's text nodes.
+ */
+
+static void
+write_element(FILE        *out,                /* I - Output file */
+              mxml_node_t *doc,                /* I - Document tree */
+              mxml_node_t *element,    /* I - Element to write */
+              int         mode)                /* I - Output mode */
+{
+  mxml_node_t  *node;                  /* Current node */
+
+
+  if (!element)
+    return;
+
+  for (node = element->child;
+       node;
+       node = mxmlWalkNext(node, element, MXML_NO_DESCEND))
+    if (node->type == MXML_TEXT)
+    {
+      if (node->value.text.whitespace)
+       putc(' ', out);
+
+      if (mode == OUTPUT_HTML &&
+          (mxmlFindElement(doc, doc, "class", "name", node->value.text.string,
+                           MXML_DESCEND) ||
+          mxmlFindElement(doc, doc, "enumeration", "name",
+                          node->value.text.string, MXML_DESCEND) ||
+          mxmlFindElement(doc, doc, "struct", "name", node->value.text.string,
+                           MXML_DESCEND) ||
+          mxmlFindElement(doc, doc, "typedef", "name", node->value.text.string,
+                           MXML_DESCEND) ||
+          mxmlFindElement(doc, doc, "union", "name", node->value.text.string,
+                           MXML_DESCEND)))
+      {
+        fputs("<a href=\"#", out);
+        write_string(out, node->value.text.string, mode);
+       fputs("\">", out);
+        write_string(out, node->value.text.string, mode);
+       fputs("</a>", out);
+      }
+      else
+        write_string(out, node->value.text.string, mode);
+    }
+
+  if (!strcmp(element->value.element.name, "type") &&
+      element->last_child->value.text.string[0] != '*')
+    putc(' ', out);
+}
+
+
+/*
+ * 'write_file()' - Copy a file to the output.
+ */
+
+static void
+write_file(FILE       *out,            /* I - Output file */
+           const char *file)           /* I - File to copy */
+{
+  FILE         *fp;                    /* Copy file */
+  char         line[8192];             /* Line from file */
+
+
+  if ((fp = fopen(file, "r")) == NULL)
+  {
+    fprintf(stderr, "mxmldoc: Unable to open \"%s\": %s\n", file,
+            strerror(errno));
+    return;
+  }
+
+  while (fgets(line, sizeof(line), fp))
+    fputs(line, out);
+
+  fclose(fp);
+}
+
+
+/*
+ * 'write_function()' - Write documentation for a function.
+ */
+
+static void
+write_function(FILE        *out,       /* I - Output file */
+               mxml_node_t *doc,       /* I - Document */
+               mxml_node_t *function,  /* I - Function */
+              int         level)       /* I - Base heading level */
+{
+  mxml_node_t  *arg,                   /* Current argument */
+               *adesc,                 /* Description of argument */
+               *description,           /* Description of function */
+               *type,                  /* Type for argument */
+               *node;                  /* Node in description */
+  const char   *name,                  /* Name of function/type */
+               *defval;                /* Default value */
+  char         prefix;                 /* Prefix character */
+  char         *sep;                   /* Newline separator */
+
+
+  name        = mxmlElementGetAttr(function, "name");
+  description = mxmlFindElement(function, function, "description", NULL,
+                               NULL, MXML_DESCEND_FIRST);
+
+  fprintf(out, "<h%d class=\"%s\">%s<a name=\"%s\">%s</a></h%d>\n",
+         level, level == 3 ? "function" : "method",
+         get_comment_info(description), name, name, level);
+
+  if (description)
+    write_description(out, description, "p", 1);
+
+  fputs("<p class=\"code\">\n", out);
+
+  arg = mxmlFindElement(function, function, "returnvalue", NULL,
+                       NULL, MXML_DESCEND_FIRST);
+
+  if (arg)
+    write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                           NULL, MXML_DESCEND_FIRST),
+                 OUTPUT_HTML);
+  else
+    fputs("void ", out);
+
+  fprintf(out, "%s ", name);
+  for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
+                            MXML_DESCEND_FIRST), prefix = '(';
+       arg;
+       arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
+                            MXML_NO_DESCEND), prefix = ',')
+  {
+    type = mxmlFindElement(arg, arg, "type", NULL, NULL,
+                          MXML_DESCEND_FIRST);
+
+    fprintf(out, "%c<br>\n&nbsp;&nbsp;&nbsp;&nbsp;", prefix);
+    if (type->child)
+      write_element(out, doc, type, OUTPUT_HTML);
+
+    fputs(mxmlElementGetAttr(arg, "name"), out);
+    if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
+      fprintf(out, " %s", defval);
+  }
+
+  if (prefix == '(')
+    fputs("(void);</p>\n", out);
+  else
+  {
+    fprintf(out,
+            "<br>\n);</p>\n"
+           "<h%d class=\"parameters\">Parameters</h%d>\n"
+           "<dl>\n", level + 1, level + 1);
+
+    for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
+                              MXML_DESCEND_FIRST);
+        arg;
+        arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
+                              MXML_NO_DESCEND))
+    {
+      fprintf(out, "<dt>%s</dt>\n", mxmlElementGetAttr(arg, "name"));
+
+      adesc = mxmlFindElement(arg, arg, "description", NULL, NULL,
+                             MXML_DESCEND_FIRST);
+
+      write_description(out, adesc, "dd", 1);
+      write_description(out, adesc, "dd", 0);
+    }
+
+    fputs("</dl>\n", out);
+  }
+
+  arg = mxmlFindElement(function, function, "returnvalue", NULL,
+                       NULL, MXML_DESCEND_FIRST);
+
+  if (arg)
+  {
+    fprintf(out, "<h%d class=\"returnvalue\">Return Value</h%d>\n", level + 1,
+            level + 1);
+
+    adesc = mxmlFindElement(arg, arg, "description", NULL, NULL,
+                           MXML_DESCEND_FIRST);
+
+    write_description(out, adesc, "p", 1);
+    write_description(out, adesc, "p", 0);
+  }
+
+  if (description)
+  {
+    for (node = description->child; node; node = node->next)
+      if (node->value.text.string &&
+         (sep = strstr(node->value.text.string, "\n\n")) != NULL)
+      {
+       sep += 2;
+       if (*sep && strncmp(sep, "@since ", 7) &&
+           strncmp(sep, "@deprecated@", 12))
+         break;
+      }
+
+    if (node)
+    {
+      fprintf(out, "<h%d class=\"discussion\">Discussion</h%d>\n", level + 1,
+             level + 1);
+      write_description(out, description, "p", 0);
+    }
+  }
+}
+
+
+/*
+ * 'write_html()' - Write HTML documentation.
+ */
+
+static void
+write_html(const char  *section,       /* I - Section */
+          const char  *title,          /* I - Title */
+          const char  *footerfile,     /* I - Footer file */
+          const char  *headerfile,     /* I - Header file */
+          const char  *introfile,      /* I - Intro file */
+          const char  *cssfile,        /* I - Stylesheet file */
+          const char  *framefile,      /* I - Framed HTML basename */
+          const char  *docset,         /* I - Documentation set directory */
+          const char  *docversion,     /* I - Documentation set version */
+          const char  *feedname,       /* I - Feed name for doc set */
+          const char  *feedurl,        /* I - Feed URL for doc set */
+          mxml_node_t *doc)            /* I - XML documentation */
+{
+  FILE         *out;                   /* Output file */
+  mxml_node_t  *function,              /* Current function */
+               *scut,                  /* Struct/class/union/typedef */
+               *arg,                   /* Current argument */
+               *description,           /* Description of function/var */
+               *type;                  /* Type for argument */
+  const char   *name,                  /* Name of function/type */
+               *defval,                /* Default value */
+               *basename;              /* Base filename for framed output */
+  char         filename[1024];         /* Current output filename */
+
+
+  if (framefile)
+  {
+   /*
+    * Get the basename of the frame file...
+    */
+
+    if ((basename = strrchr(framefile, '/')) != NULL)
+      basename ++;
+    else
+      basename = framefile;
+
+    if (strstr(basename, ".html"))
+      fputs("mxmldoc: Frame base name should not contain .html extension!\n",
+            stderr);
+
+   /*
+    * Create the container HTML file for the frames...
+    */
+
+    snprintf(filename, sizeof(filename), "%s.html", framefile);
+
+    if ((out = fopen(filename, "w")) == NULL)
+    {
+      fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
+              strerror(errno));
+      return;
+    }
+
+    fputs("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" "
+          "\"http://www.w3.org/TR/html4/frameset.dtd\";>\n"
+         "<html>\n"
+         "<head>\n"
+         "\t<title>", out);
+    write_string(out, title, OUTPUT_HTML);
+    fputs("</title>\n", out);
+
+    if (section)
+      fprintf(out, "\t<meta name=\"keywords\" content=\"%s\">\n", section);
+
+    fputs("\t<meta http-equiv=\"Content-Type\" "
+          "content=\"text/html;charset=utf-8\">\n"
+         "\t<meta name=\"creator\" content=\"" MXML_VERSION "\">\n"
+          "</head>\n", out);
+
+    fputs("<frameset cols=\"250,*\">\n", out);
+    fprintf(out, "<frame src=\"%s-toc.html\">\n", basename);
+    fprintf(out, "<frame name=\"body\" src=\"%s-body.html\">\n", basename);
+    fputs("</frameset>\n"
+          "<noframes>\n"
+         "<h1>", out);
+    write_string(out, title, OUTPUT_HTML);
+    fprintf(out,
+            "</h1>\n"
+            "<ul>\n"
+           "\t<li><a href=\"%s-toc.html\">Table of Contents</a></li>\n"
+           "\t<li><a href=\"%s-body.html\">Body</a></li>\n"
+           "</ul>\n", basename, basename);
+    fputs("</noframes>\n"
+          "</html>\n", out);
+    fclose(out);
+
+   /*
+    * Write the table-of-contents file...
+    */
+
+    snprintf(filename, sizeof(filename), "%s-toc.html", framefile);
+
+    if ((out = fopen(filename, "w")) == NULL)
+    {
+      fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
+              strerror(errno));
+      return;
+    }
+
+    write_html_head(out, section, title, cssfile);
+
+    snprintf(filename, sizeof(filename), "%s-body.html", basename);
+
+    fputs("<div class=\"contents\">\n", out);
+    fprintf(out, "<h1 class=\"title\"><a href=\"%s\" target=\"body\">",
+            filename);
+    write_string(out, title, OUTPUT_HTML);
+    fputs("</a></h1>\n", out);
+
+    write_toc(out, doc, introfile, filename, 0);
+
+    fputs("</div>\n"
+          "</body>\n"
+          "</html>\n", out);
+    fclose(out);
+
+   /*
+    * Finally, open the body file...
+    */
+
+    snprintf(filename, sizeof(filename), "%s-body.html", framefile);
+
+    if ((out = fopen(filename, "w")) == NULL)
+    {
+      fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
+              strerror(errno));
+      return;
+    }
+  }
+  else if (docset)
+  {
+   /*
+    * Create an Xcode documentation set - start by removing any existing
+    * output directory...
+    */
+
+#ifdef __APPLE__
+    const char *id;                    /* Identifier */
+
+
+    if (!access(docset, 0) && !remove_directory(docset))
+      return;
+
+   /*
+    * Then make the Apple standard bundle directory structure...
+    */
+
+    if (mkdir(docset, 0755))
+    {
+      fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", docset,
+              strerror(errno));
+      return;
+    }
+
+    snprintf(filename, sizeof(filename), "%s/Contents", docset);
+    if (mkdir(filename, 0755))
+    {
+      fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
+              strerror(errno));
+      return;
+    }
+
+    snprintf(filename, sizeof(filename), "%s/Contents/Resources", docset);
+    if (mkdir(filename, 0755))
+    {
+      fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
+              strerror(errno));
+      return;
+    }
+
+    snprintf(filename, sizeof(filename), "%s/Contents/Resources/Documentation",
+             docset);
+    if (mkdir(filename, 0755))
+    {
+      fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
+              strerror(errno));
+      return;
+    }
+
+   /*
+    * The Info.plist file, which describes the documentation set...
+    */
+
+    if ((id = strrchr(docset, '/')) != NULL)
+      id ++;
+    else
+      id = docset;
+
+    snprintf(filename, sizeof(filename), "%s/Contents/Info.plist", docset);
+    if ((out = fopen(filename, "w")) == NULL)
+    {
+      fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
+              strerror(errno));
+      return;
+    }
+
+    fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+          "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" 
\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\";>\n"
+          "<plist version=\"1.0\">\n"
+          "<dict>\n"
+         "\t<key>CFBundleIdentifier</key>\n"
+         "\t<string>", out);
+    write_string(out, id, OUTPUT_HTML);
+    fputs("</string>\n"
+          "\t<key>CFBundleName</key>\n"
+         "\t<string>", out);
+    write_string(out, title, OUTPUT_HTML);
+    fputs("</string>\n"
+          "\t<key>CFBundleVersion</key>\n"
+         "\t<string>", out);
+    write_string(out, docversion ? docversion : "0.0", OUTPUT_HTML);
+    fputs("</string>\n"
+          "\t<key>CFBundleShortVersionString</key>\n"
+         "\t<string>", out);
+    write_string(out, docversion ? docversion : "0.0", OUTPUT_HTML);
+    fputs("</string>\n", out);
+
+    if (feedname)
+    {
+      fputs("\t<key>DocSetFeedName</key>\n"
+           "\t<string>", out);
+      write_string(out, feedname ? feedname : title, OUTPUT_HTML);
+      fputs("</string>\n", out);
+    }
+
+    if (feedurl)
+    {
+      fputs("\t<key>DocSetFeedURL</key>\n"
+           "\t<string>", out);
+      write_string(out, feedurl, OUTPUT_HTML);
+      fputs("</string>\n", out);
+    }
+
+    fputs("</dict>\n"
+          "</plist>\n", out);
+
+    fclose(out);
+
+   /*
+    * Next the Nodes.xml file...
+    */
+
+    snprintf(filename, sizeof(filename), "%s/Contents/Resources/Nodes.xml",
+             docset);
+    if ((out = fopen(filename, "w")) == NULL)
+    {
+      fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
+              strerror(errno));
+      return;
+    }
+
+    fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+          "<DocSetNodes version=\"1.0\">\n"
+         "<TOC>\n"
+         "<Node id=\"0\">\n"
+         "<Name>", out);
+    write_string(out, title, OUTPUT_HTML);
+    fputs("</Name>\n"
+          "<Path>Documentation/index.html</Path>\n"
+         "<Subnodes>\n", out);
+
+    write_toc(out, doc, introfile, NULL, 1);
+
+    fputs("</Subnodes>\n"
+          "</Node>\n"
+          "</TOC>\n"
+          "</DocSetNodes>\n", out);
+
+    fclose(out);
+
+   /*
+    * Then the Tokens.xml file...
+    */
+
+    snprintf(filename, sizeof(filename), "%s/Contents/Resources/Tokens.xml",
+             docset);
+    if ((out = fopen(filename, "w")) == NULL)
+    {
+      fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
+              strerror(errno));
+      return;
+    }
+
+    fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+          "<Tokens version=\"1.0\">\n", out);
+
+    write_tokens(out, doc, "index.html");
+
+    fputs("</Tokens>\n", out);
+
+    fclose(out);
+
+   /*
+    * Finally the HTML file...
+    */
+
+    snprintf(filename, sizeof(filename),
+             "%s/Contents/Resources/Documentation/index.html",
+             docset);
+    if ((out = fopen(filename, "w")) == NULL)
+    {
+      fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
+              strerror(errno));
+      return;
+    }
+
+#else
+    fputs("mxmldoc: Xcode documentation sets can only be created on "
+          "Mac OS X.\n", stderr);
+    return;
+#endif /* __APPLE__ */
+  }
+  else
+    out = stdout;
+
+ /*
+  * Standard header...
+  */
+
+  write_html_head(out, section, title, cssfile);
+
+  fputs("<div class='body'>\n", out);
+
+ /*
+  * Header...
+  */
+
+  if (headerfile)
+  {
+   /*
+    * Use custom header...
+    */
+
+    write_file(out, headerfile);
+  }
+  else
+  {
+   /*
+    * Use standard header...
+    */
+
+    fputs("<h1 class=\"title\">", out);
+    write_string(out, title, OUTPUT_HTML);
+    fputs("</h1>\n", out);
+  }
+
+ /*
+  * Table of contents...
+  */
+
+  if (!framefile)
+    write_toc(out, doc, introfile, NULL, 0);
+
+ /*
+  * Intro...
+  */
+
+  if (introfile)
+    write_file(out, introfile);
+
+ /*
+  * List of classes...
+  */
+
+  if ((scut = find_public(doc, doc, "class")) != NULL)
+  {
+    fputs("<h2 class=\"title\"><a name=\"CLASSES\">Classes</a></h2>\n", out);
+
+    while (scut)
+    {
+      write_scu(out, doc, scut);
+
+      scut = find_public(scut, doc, "class");
+    }
+  }
+
+ /*
+  * List of functions...
+  */
+
+  if ((function = find_public(doc, doc, "function")) != NULL)
+  {
+    fputs("<h2 class=\"title\"><a name=\"FUNCTIONS\">Functions</a></h2>\n", 
out);
+
+    while (function)
+    {
+      write_function(out, doc, function, 3);
+
+      function = find_public(function, doc, "function");
+    }
+  }
+
+ /*
+  * List of types...
+  */
+
+  if ((scut = find_public(doc, doc, "typedef")) != NULL)
+  {
+    fputs("<h2 class=\"title\"><a name=\"TYPES\">Data Types</a></h2>\n", out);
+
+    while (scut)
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description", NULL,
+                                    NULL, MXML_DESCEND_FIRST);
+      fprintf(out, "<h3 class=\"typedef\">%s<a name=\"%s\">%s</a></h3>\n",
+             get_comment_info(description), name, name);
+
+      if (description)
+       write_description(out, description, "p", 1);
+
+      fputs("<p class=\"code\">\n"
+           "typedef ", out);
+
+      type = mxmlFindElement(scut, scut, "type", NULL, NULL,
+                             MXML_DESCEND_FIRST);
+
+      for (type = type->child; type; type = type->next)
+        if (!strcmp(type->value.text.string, "("))
+         break;
+       else
+       {
+         if (type->value.text.whitespace)
+           putc(' ', out);
+
+         if (mxmlFindElement(doc, doc, "class", "name",
+                             type->value.text.string, MXML_DESCEND) ||
+             mxmlFindElement(doc, doc, "enumeration", "name",
+                             type->value.text.string, MXML_DESCEND) ||
+             mxmlFindElement(doc, doc, "struct", "name",
+                             type->value.text.string, MXML_DESCEND) ||
+             mxmlFindElement(doc, doc, "typedef", "name",
+                             type->value.text.string, MXML_DESCEND) ||
+             mxmlFindElement(doc, doc, "union", "name",
+                             type->value.text.string, MXML_DESCEND))
+         {
+            fputs("<a href=\"#", out);
+            write_string(out, type->value.text.string, OUTPUT_HTML);
+           fputs("\">", out);
+            write_string(out, type->value.text.string, OUTPUT_HTML);
+           fputs("</a>", out);
+         }
+         else
+            write_string(out, type->value.text.string, OUTPUT_HTML);
+        }
+
+      if (type)
+      {
+       /*
+        * Output function type...
+       */
+
+        if (type->prev && type->prev->value.text.string[0] != '*')
+         putc(' ', out);
+
+        fprintf(out, "(*%s", name);
+
+       for (type = type->next->next; type; type = type->next)
+       {
+         if (type->value.text.whitespace)
+           putc(' ', out);
+
+         if (mxmlFindElement(doc, doc, "class", "name",
+                             type->value.text.string, MXML_DESCEND) ||
+             mxmlFindElement(doc, doc, "enumeration", "name",
+                             type->value.text.string, MXML_DESCEND) ||
+             mxmlFindElement(doc, doc, "struct", "name",
+                             type->value.text.string, MXML_DESCEND) ||
+             mxmlFindElement(doc, doc, "typedef", "name",
+                             type->value.text.string, MXML_DESCEND) ||
+             mxmlFindElement(doc, doc, "union", "name",
+                             type->value.text.string, MXML_DESCEND))
+         {
+            fputs("<a href=\"#", out);
+            write_string(out, type->value.text.string, OUTPUT_HTML);
+           fputs("\">", out);
+            write_string(out, type->value.text.string, OUTPUT_HTML);
+           fputs("</a>", out);
+         }
+         else
+            write_string(out, type->value.text.string, OUTPUT_HTML);
+        }
+
+        fputs(";\n", out);
+      }
+      else
+      {
+       type = mxmlFindElement(scut, scut, "type", NULL, NULL,
+                              MXML_DESCEND_FIRST);
+        if (type->last_child->value.text.string[0] != '*')
+         putc(' ', out);
+
+       fprintf(out, "%s;\n", name);
+      }
+
+      fputs("</p>\n", out);
+
+      scut = find_public(scut, doc, "typedef");
+    }
+  }
+
+ /*
+  * List of structures...
+  */
+
+  if ((scut = find_public(doc, doc, "struct")) != NULL)
+  {
+    fputs("<h2 class=\"title\"><a name=\"STRUCTURES\">Structures</a></h2>\n",
+          out);
+
+    while (scut)
+    {
+      write_scu(out, doc, scut);
+
+      scut = find_public(scut, doc, "struct");
+    }
+  }
+
+ /*
+  * List of unions...
+  */
+
+  if ((scut = find_public(doc, doc, "union")) != NULL)
+  {
+    fputs("<h2 class=\"title\"><a name=\"UNIONS\">Unions</a></h2>\n", out);
+
+    while (scut)
+    {
+      write_scu(out, doc, scut);
+
+      scut = find_public(scut, doc, "union");
+    }
+  }
+
+ /*
+  * Variables...
+  */
+
+  if ((arg = find_public(doc, doc, "variable")) != NULL)
+  {
+    fputs("<h2 class=\"title\"><a name=\"VARIABLES\">Variables</a></h2>\n",
+          out);
+
+    while (arg)
+    {
+      name        = mxmlElementGetAttr(arg, "name");
+      description = mxmlFindElement(arg, arg, "description", NULL,
+                                    NULL, MXML_DESCEND_FIRST);
+      fprintf(out, "<h3 class=\"variable\">%s<a name=\"%s\">%s</a></h3>\n",
+             get_comment_info(description), name, name);
+
+      if (description)
+       write_description(out, description, "p", 1);
+
+      fputs("<p class=\"code\">", out);
+
+      write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                              NULL, MXML_DESCEND_FIRST),
+                    OUTPUT_HTML);
+      fputs(mxmlElementGetAttr(arg, "name"), out);
+      if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
+       fprintf(out, " %s", defval);
+      fputs(";</p>\n", out);
+
+      arg = find_public(arg, doc, "variable");
+    }
+  }
+
+ /*
+  * List of enumerations...
+  */
+
+  if ((scut = find_public(doc, doc, "enumeration")) != NULL)
+  {
+    fputs("<h2 class=\"title\"><a name=\"ENUMERATIONS\">Constants</a></h2>\n",
+          out);
+
+    while (scut)
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description", NULL,
+                                    NULL, MXML_DESCEND_FIRST);
+      fprintf(out, "<h3 class=\"enumeration\">%s<a name=\"%s\">%s</a></h3>\n",
+              get_comment_info(description), name, name);
+
+      if (description)
+       write_description(out, description, "p", 1);
+
+      fputs("<h4 class=\"constants\">Constants</h4>\n"
+            "<dl>\n", out);
+
+      for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL,
+                                MXML_DESCEND_FIRST);
+          arg;
+          arg = mxmlFindElement(arg, scut, "constant", NULL, NULL,
+                                MXML_NO_DESCEND))
+      {
+       description = mxmlFindElement(arg, arg, "description", NULL,
+                                      NULL, MXML_DESCEND_FIRST);
+       fprintf(out, "<dt>%s %s</dt>\n",
+               mxmlElementGetAttr(arg, "name"), get_comment_info(description));
+
+       write_description(out, description, "dd", 1);
+       write_description(out, description, "dd", 0);
+      }
+
+      fputs("</dl>\n", out);
+
+      scut = find_public(scut, doc, "enumeration");
+    }
+  }
+
+ /*
+  * Footer...
+  */
+
+  if (footerfile)
+  {
+   /*
+    * Use custom footer...
+    */
+
+    write_file(out, footerfile);
+  }
+
+  fputs("</div>\n"
+        "</body>\n"
+        "</html>\n", out);
+
+ /*
+  * Close output file as needed...
+  */
+
+  if (out != stdout)
+    fclose(out);
+
+#ifdef __APPLE__
+ /*
+  * When generating document sets, run the docsetutil program to index it...
+  */
+
+  if (docset)
+  {
+    const char *args[4];               /* Argument array */
+    pid_t      pid;                    /* Process ID */
+    int                status;                 /* Exit status */
+
+
+    args[0] = "/Developer/usr/bin/docsetutil";
+    args[1] = "index";
+    args[2] = docset;
+    args[3] = NULL;
+
+    if (posix_spawn(&pid, args[0], NULL, NULL, (char **)args, environ))
+    {
+      fprintf(stderr, "mxmldoc: Unable to index documentation set \"%s\": 
%s\n",
+              docset, strerror(errno));
+    }
+    else
+    {
+      while (wait(&status) != pid);
+
+      if (status)
+      {
+        if (WIFEXITED(status))
+         fprintf(stderr, "mxmldoc: docsetutil exited with status %d\n",
+                 WEXITSTATUS(status));
+        else
+         fprintf(stderr, "mxmldoc: docsetutil crashed with signal %d\n",
+                 WTERMSIG(status));
+      }
+      else
+      {
+       /*
+        * Remove unneeded temporary XML files...
+       */
+
+       snprintf(filename, sizeof(filename), "%s/Contents/Resources/Nodes.xml",
+                docset);
+        unlink(filename);
+
+       snprintf(filename, sizeof(filename), "%s/Contents/Resources/Tokens.xml",
+                docset);
+        unlink(filename);
+      }
+    }
+  }
+#endif /* __APPLE__ */
+}
+
+
+/*
+ * 'write_html_head()' - Write the standard HTML header.
+ */
+
+static void
+write_html_head(FILE       *out,       /* I - Output file */
+                const char *section,   /* I - Section */
+                const char *title,     /* I - Title */
+               const char *cssfile)    /* I - Stylesheet */
+{
+  fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" "
+        "\"http://www.w3.org/TR/html4/loose.dtd\";>\n"
+        "<html>\n", out);
+
+  if (section)
+    fprintf(out, "<!-- SECTION: %s -->\n", section);
+
+  fputs("<head>\n"
+        "\t<title>", out);
+  write_string(out, title, OUTPUT_HTML);
+  fputs("\t</title>\n", out);
+
+  if (section)
+    fprintf(out, "\t<meta name=\"keywords\" content=\"%s\">\n", section);
+
+  fputs("\t<meta http-equiv=\"Content-Type\" "
+       "content=\"text/html;charset=utf-8\">\n"
+       "\t<meta name=\"creator\" content=\"" MXML_VERSION "\">\n"
+        "<style type=\"text/css\"><!--\n", out);
+
+  if (cssfile)
+  {
+   /*
+    * Use custom stylesheet file...
+    */
+
+    write_file(out, cssfile);
+  }
+  else
+  {
+   /*
+    * Use standard stylesheet...
+    */
+
+    fputs("body, p, h1, h2, h3, h4 {\n"
+         "  font-family: \"lucida grande\", geneva, helvetica, arial, "
+         "sans-serif;\n"
+         "}\n"
+         "div.body h1 {\n"
+         "  font-size: 250%;\n"
+         "  font-weight: bold;\n"
+         "  margin: 0;\n"
+         "}\n"
+         "div.body h2 {\n"
+         "  font-size: 250%;\n"
+         "  margin-top: 1.5em;\n"
+         "}\n"
+         "div.body h3 {\n"
+         "  font-size: 150%;\n"
+         "  margin-bottom: 0.5em;\n"
+         "  margin-top: 1.5em;\n"
+         "}\n"
+         "div.body h4 {\n"
+         "  font-size: 110%;\n"
+         "  margin-bottom: 0.5em;\n"
+         "  margin-top: 1.5em;\n"
+         "}\n"
+         "div.body h5 {\n"
+         "  font-size: 100%;\n"
+         "  margin-bottom: 0.5em;\n"
+         "  margin-top: 1.5em;\n"
+         "}\n"
+         "div.contents {\n"
+         "  background: #e8e8e8;\n"
+         "  border: solid thin black;\n"
+         "  padding: 10px;\n"
+         "}\n"
+         "div.contents h1 {\n"
+         "  font-size: 110%;\n"
+         "}\n"
+         "div.contents h2 {\n"
+         "  font-size: 100%;\n"
+         "}\n"
+         "div.contents ul.contents {\n"
+         "  font-size: 80%;\n"
+         "}\n"
+         ".class {\n"
+         "  border-bottom: solid 2px gray;\n"
+         "}\n"
+         ".constants {\n"
+         "}\n"
+         ".description {\n"
+         "  margin-top: 0.5em;\n"
+         "}\n"
+         ".discussion {\n"
+         "}\n"
+         ".enumeration {\n"
+         "  border-bottom: solid 2px gray;\n"
+         "}\n"
+         ".function {\n"
+         "  border-bottom: solid 2px gray;\n"
+         "  margin-bottom: 0;\n"
+         "}\n"
+         ".members {\n"
+         "}\n"
+         ".method {\n"
+         "}\n"
+         ".parameters {\n"
+         "}\n"
+         ".returnvalue {\n"
+         "}\n"
+         ".struct {\n"
+         "  border-bottom: solid 2px gray;\n"
+         "}\n"
+         ".typedef {\n"
+         "  border-bottom: solid 2px gray;\n"
+         "}\n"
+         ".union {\n"
+         "  border-bottom: solid 2px gray;\n"
+         "}\n"
+         ".variable {\n"
+         "}\n"
+         "code, p.code, pre, ul.code li {\n"
+         "  font-family: monaco, courier, monospace;\n"
+         "  font-size: 90%;\n"
+         "}\n"
+         "a:link, a:visited {\n"
+         "  text-decoration: none;\n"
+         "}\n"
+         "span.info {\n"
+         "  background: black;\n"
+         "  border: solid thin black;\n"
+         "  color: white;\n"
+         "  font-size: 80%;\n"
+         "  font-style: italic;\n"
+         "  font-weight: bold;\n"
+         "  white-space: nowrap;\n"
+         "}\n"
+         "h3 span.info, h4 span.info {\n"
+         "  float: right;\n"
+         "  font-size: 100%;\n"
+         "}\n"
+         "ul.code, ul.contents, ul.subcontents {\n"
+         "  list-style-type: none;\n"
+         "  margin: 0;\n"
+         "  padding-left: 0;\n"
+         "}\n"
+         "ul.code li {\n"
+         "  margin: 0;\n"
+         "}\n"
+         "ul.contents > li {\n"
+         "  margin-top: 1em;\n"
+         "}\n"
+         "ul.contents li ul.code, ul.contents li ul.subcontents {\n"
+         "  padding-left: 2em;\n"
+         "}\n"
+         "div.body dl {\n"
+         "  margin-top: 0;\n"
+         "}\n"
+         "div.body dt {\n"
+         "  font-style: italic;\n"
+         "  margin-top: 0;\n"
+         "}\n"
+         "div.body dd {\n"
+         "  margin-bottom: 0.5em;\n"
+         "}\n"
+         "h1.title {\n"
+         "}\n"
+         "h2.title {\n"
+         "  border-bottom: solid 2px black;\n"
+         "}\n"
+         "h3.title {\n"
+         "  border-bottom: solid 2px black;\n"
+         "}\n", out);
+  }
+
+  fputs("--></style>\n"
+        "</head>\n"
+        "<body>\n", out);
+}
+
+
+/*
+ * 'write_man()' - Write manpage documentation.
+ */
+
+static void
+write_man(const char  *man_name,       /* I - Name of manpage */
+         const char  *section,         /* I - Section */
+         const char  *title,           /* I - Title */
+         const char  *footerfile,      /* I - Footer file */
+         const char  *headerfile,      /* I - Header file */
+         const char  *introfile,       /* I - Intro file */
+         mxml_node_t *doc)             /* I - XML documentation */
+{
+  int          i;                      /* Looping var */
+  mxml_node_t  *function,              /* Current function */
+               *scut,                  /* Struct/class/union/typedef */
+               *arg,                   /* Current argument */
+               *description,           /* Description of function/var */
+               *type;                  /* Type for argument */
+  const char   *name,                  /* Name of function/type */
+               *cname,                 /* Class name */
+               *defval,                /* Default value */
+               *parent;                /* Parent class */
+  int          inscope;                /* Variable/method scope */
+  char         prefix;                 /* Prefix character */
+  time_t       curtime;                /* Current time */
+  struct tm    *curdate;               /* Current date */
+  char         buffer[1024];           /* String buffer */
+  static const char * const scopes[] = /* Scope strings */
+               {
+                 "private",
+                 "protected",
+                 "public"
+               };
+
+
+ /*
+  * Standard man page...
+  */
+
+  curtime = time(NULL);
+  curdate = localtime(&curtime);
+  strftime(buffer, sizeof(buffer), "%x", curdate);
+
+  printf(".TH %s %s \"%s\" \"%s\" \"%s\"\n", man_name, section ? section : "3",
+         title ? title : "", buffer, title ? title : "");
+
+ /*
+  * Header...
+  */
+
+  if (headerfile)
+  {
+   /*
+    * Use custom header...
+    */
+
+    write_file(stdout, headerfile);
+  }
+  else
+  {
+   /*
+    * Use standard header...
+    */
+
+    puts(".SH NAME");
+    printf("%s \\- %s\n", man_name, title ? title : man_name);
+  }
+
+ /*
+  * Intro...
+  */
+
+  if (introfile)
+    write_file(stdout, introfile);
+
+ /*
+  * List of classes...
+  */
+
+  if (find_public(doc, doc, "class"))
+  {
+    puts(".SH CLASSES");
+
+    for (scut = find_public(doc, doc, "class");
+        scut;
+        scut = find_public(scut, doc, "class"))
+    {
+      cname       = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description", NULL,
+                                    NULL, MXML_DESCEND_FIRST);
+      printf(".SS %s\n", cname);
+
+      write_description(stdout, description, NULL, 1);
+
+      printf(".PP\n"
+             ".nf\n"
+             "class %s", cname);
+      if ((parent = mxmlElementGetAttr(scut, "parent")) != NULL)
+        printf(" %s", parent);
+      puts("\n{");
+
+      for (i = 0; i < 3; i ++)
+      {
+        inscope = 0;
+
+       for (arg = mxmlFindElement(scut, scut, "variable", "scope", scopes[i],
+                                  MXML_DESCEND_FIRST);
+            arg;
+            arg = mxmlFindElement(arg, scut, "variable", "scope", scopes[i],
+                                  MXML_NO_DESCEND))
+       {
+          if (!inscope)
+         {
+           inscope = 1;
+           printf("  %s:\n", scopes[i]);
+         }
+
+         printf("    ");
+         write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                                     NULL, MXML_DESCEND_FIRST),
+                        OUTPUT_MAN);
+         printf("%s;\n", mxmlElementGetAttr(arg, "name"));
+       }
+
+       for (function = mxmlFindElement(scut, scut, "function", "scope",
+                                       scopes[i], MXML_DESCEND_FIRST);
+            function;
+            function = mxmlFindElement(function, scut, "function", "scope",
+                                       scopes[i], MXML_NO_DESCEND))
+       {
+          if (!inscope)
+         {
+           inscope = 1;
+           printf("  %s:\n", scopes[i]);
+         }
+
+          name = mxmlElementGetAttr(function, "name");
+
+          printf("    ");
+
+         arg = mxmlFindElement(function, function, "returnvalue", NULL,
+                               NULL, MXML_DESCEND_FIRST);
+
+         if (arg)
+           write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                                       NULL, 
MXML_DESCEND_FIRST),
+                          OUTPUT_MAN);
+         else if (strcmp(cname, name) && strcmp(cname, name + 1))
+           fputs("void ", stdout);
+
+         printf("%s", name);
+
+         for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
+                                    MXML_DESCEND_FIRST), prefix = '(';
+              arg;
+              arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
+                                    MXML_NO_DESCEND), prefix = ',')
+         {
+           type = mxmlFindElement(arg, arg, "type", NULL, NULL,
+                                  MXML_DESCEND_FIRST);
+
+           putchar(prefix);
+           if (prefix == ',')
+             putchar(' ');
+
+           if (type->child)
+             write_element(stdout, doc, type, OUTPUT_MAN);
+           fputs(mxmlElementGetAttr(arg, "name"), stdout);
+            if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
+             printf(" %s", defval);
+         }
+
+         if (prefix == '(')
+           puts("(void);");
+         else
+           puts(");");
+       }
+      }
+
+      puts("};\n"
+           ".fi");
+
+      write_description(stdout, description, NULL, 0);
+    }
+  }
+
+ /*
+  * List of enumerations...
+  */
+
+  if (find_public(doc, doc, "enumeration"))
+  {
+    puts(".SH ENUMERATIONS");
+
+    for (scut = find_public(doc, doc, "enumeration");
+        scut;
+        scut = find_public(scut, doc, "enumeration"))
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description", NULL,
+                                    NULL, MXML_DESCEND_FIRST);
+      printf(".SS %s\n", name);
+
+      write_description(stdout, description, NULL, 1);
+      write_description(stdout, description, NULL, 0);
+
+      for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL,
+                                MXML_DESCEND_FIRST);
+          arg;
+          arg = mxmlFindElement(arg, scut, "constant", NULL, NULL,
+                                MXML_NO_DESCEND))
+      {
+       description = mxmlFindElement(arg, arg, "description", NULL,
+                                      NULL, MXML_DESCEND_FIRST);
+       printf(".TP 5\n%s\n.br\n", mxmlElementGetAttr(arg, "name"));
+       write_description(stdout, description, NULL, 1);
+      }
+    }
+  }
+
+ /*
+  * List of functions...
+  */
+
+  if (find_public(doc, doc, "function"))
+  {
+    puts(".SH FUNCTIONS");
+
+    for (function = find_public(doc, doc, "function");
+        function;
+        function = find_public(function, doc, "function"))
+    {
+      name        = mxmlElementGetAttr(function, "name");
+      description = mxmlFindElement(function, function, "description", NULL,
+                                    NULL, MXML_DESCEND_FIRST);
+      printf(".SS %s\n", name);
+
+      write_description(stdout, description, NULL, 1);
+
+      puts(".PP\n"
+           ".nf");
+
+      arg = mxmlFindElement(function, function, "returnvalue", NULL,
+                            NULL, MXML_DESCEND_FIRST);
+
+      if (arg)
+       write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                                   NULL, MXML_DESCEND_FIRST),
+                      OUTPUT_MAN);
+      else
+       fputs("void", stdout);
+
+      printf(" %s ", name);
+      for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
+                                MXML_DESCEND_FIRST), prefix = '(';
+          arg;
+          arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
+                                MXML_NO_DESCEND), prefix = ',')
+      {
+        type = mxmlFindElement(arg, arg, "type", NULL, NULL,
+                              MXML_DESCEND_FIRST);
+
+       printf("%c\n    ", prefix);
+       if (type->child)
+         write_element(stdout, doc, type, OUTPUT_MAN);
+       fputs(mxmlElementGetAttr(arg, "name"), stdout);
+        if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
+         printf(" %s", defval);
+      }
+
+      if (prefix == '(')
+       puts("(void);");
+      else
+       puts("\n);");
+
+      puts(".fi");
+
+      write_description(stdout, description, NULL, 0);
+    }
+  }
+
+ /*
+  * List of structures...
+  */
+
+  if (find_public(doc, doc, "struct"))
+  {
+    puts(".SH STRUCTURES");
+
+    for (scut = find_public(doc, doc, "struct");
+        scut;
+        scut = find_public(scut, doc, "struct"))
+    {
+      cname       = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description", NULL,
+                                    NULL, MXML_DESCEND_FIRST);
+      printf(".SS %s\n", cname);
+
+      write_description(stdout, description, NULL, 1);
+
+      printf(".PP\n"
+             ".nf\n"
+            "struct %s\n{\n", cname);
+      for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
+                                MXML_DESCEND_FIRST);
+          arg;
+          arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
+                                MXML_NO_DESCEND))
+      {
+       printf("  ");
+       write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                                   NULL, MXML_DESCEND_FIRST),
+                      OUTPUT_MAN);
+       printf("%s;\n", mxmlElementGetAttr(arg, "name"));
+      }
+
+      for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
+                                      MXML_DESCEND_FIRST);
+          function;
+          function = mxmlFindElement(function, scut, "function", NULL, NULL,
+                                      MXML_NO_DESCEND))
+      {
+        name = mxmlElementGetAttr(function, "name");
+
+        printf("  ");
+
+       arg = mxmlFindElement(function, function, "returnvalue", NULL,
+                              NULL, MXML_DESCEND_FIRST);
+
+       if (arg)
+         write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                                     NULL, MXML_DESCEND_FIRST),
+                        OUTPUT_MAN);
+       else if (strcmp(cname, name) && strcmp(cname, name + 1))
+         fputs("void ", stdout);
+
+       fputs(name, stdout);
+
+       for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
+                                  MXML_DESCEND_FIRST), prefix = '(';
+            arg;
+            arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
+                                  MXML_NO_DESCEND), prefix = ',')
+       {
+         type = mxmlFindElement(arg, arg, "type", NULL, NULL,
+                                MXML_DESCEND_FIRST);
+
+         putchar(prefix);
+         if (prefix == ',')
+           putchar(' ');
+
+         if (type->child)
+           write_element(stdout, doc, type, OUTPUT_MAN);
+         fputs(mxmlElementGetAttr(arg, "name"), stdout);
+          if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
+           printf(" %s", defval);
+       }
+
+       if (prefix == '(')
+         puts("(void);");
+       else
+         puts(");");
+      }
+
+      puts("};\n"
+           ".fi");
+
+      write_description(stdout, description, NULL, 0);
+    }
+  }
+
+ /*
+  * List of types...
+  */
+
+  if (find_public(doc, doc, "typedef"))
+  {
+    puts(".SH TYPES");
+
+    for (scut = find_public(doc, doc, "typedef");
+        scut;
+        scut = find_public(scut, doc, "typedef"))
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description", NULL,
+                                    NULL, MXML_DESCEND_FIRST);
+      printf(".SS %s\n", name);
+
+      write_description(stdout, description, NULL, 1);
+
+      fputs(".PP\n"
+            ".nf\n"
+           "typedef ", stdout);
+
+      type = mxmlFindElement(scut, scut, "type", NULL, NULL,
+                             MXML_DESCEND_FIRST);
+
+      for (type = type->child; type; type = type->next)
+        if (!strcmp(type->value.text.string, "("))
+         break;
+       else
+       {
+         if (type->value.text.whitespace)
+           putchar(' ');
+
+          write_string(stdout, type->value.text.string, OUTPUT_MAN);
+        }
+
+      if (type)
+      {
+       /*
+        * Output function type...
+       */
+
+        printf(" (*%s", name);
+
+       for (type = type->next->next; type; type = type->next)
+       {
+         if (type->value.text.whitespace)
+           putchar(' ');
+
+          write_string(stdout, type->value.text.string, OUTPUT_MAN);
+        }
+
+        puts(";");
+      }
+      else
+       printf(" %s;\n", name);
+
+      puts(".fi");
+
+      write_description(stdout, description, NULL, 0);
+    }
+  }
+
+ /*
+  * List of unions...
+  */
+
+  if (find_public(doc, doc, "union"))
+  {
+    puts(".SH UNIONS");
+
+    for (scut = find_public(doc, doc, "union");
+        scut;
+        scut = find_public(scut, doc, "union"))
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description", NULL,
+                                    NULL, MXML_DESCEND_FIRST);
+      printf(".SS %s\n", name);
+
+      write_description(stdout, description, NULL, 1);
+
+      printf(".PP\n"
+             ".nf\n"
+            "union %s\n{\n", name);
+      for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
+                                MXML_DESCEND_FIRST);
+          arg;
+          arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
+                                MXML_NO_DESCEND))
+      {
+       printf("  ");
+       write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                                   NULL, MXML_DESCEND_FIRST),
+                      OUTPUT_MAN);
+       printf("%s;\n", mxmlElementGetAttr(arg, "name"));
+      }
+
+      puts("};\n"
+           ".fi");
+
+      write_description(stdout, description, NULL, 0);
+    }
+  }
+
+ /*
+  * Variables...
+  */
+
+  if (find_public(doc, doc, "variable"))
+  {
+    puts(".SH VARIABLES");
+
+    for (arg = find_public(doc, doc, "variable");
+        arg;
+        arg = find_public(arg, doc, "variable"))
+    {
+      name        = mxmlElementGetAttr(arg, "name");
+      description = mxmlFindElement(arg, arg, "description", NULL,
+                                    NULL, MXML_DESCEND_FIRST);
+      printf(".SS %s\n", name);
+
+      write_description(stdout, description, NULL, 1);
+
+      puts(".PP\n"
+           ".nf");
+
+      write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                                 NULL, MXML_DESCEND_FIRST),
+                    OUTPUT_MAN);
+      fputs(mxmlElementGetAttr(arg, "name"), stdout);
+      if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
+       printf(" %s", defval);
+      puts(";\n"
+           ".fi");
+
+      write_description(stdout, description, NULL, 0);
+    }
+  }
+
+  if (footerfile)
+  {
+   /*
+    * Use custom footer...
+    */
+
+    write_file(stdout, footerfile);
+  }
+}
+
+
+/*
+ * 'write_scu()' - Write a structure, class, or union.
+ */
+
+static void
+write_scu(FILE        *out,    /* I - Output file */
+          mxml_node_t *doc,    /* I - Document */
+          mxml_node_t *scut)   /* I - Structure, class, or union */
+{
+  int          i;                      /* Looping var */
+  mxml_node_t  *function,              /* Current function */
+               *arg,                   /* Current argument */
+               *description,           /* Description of function/var */
+               *type;                  /* Type for argument */
+  const char   *name,                  /* Name of function/type */
+               *cname,                 /* Class name */
+               *defval,                /* Default value */
+               *parent,                /* Parent class */
+               *scope;                 /* Scope for variable/function */
+  int          inscope,                /* Variable/method scope */
+               maxscope;               /* Maximum scope */
+  char         prefix;                 /* Prefix character */
+  static const char * const scopes[] = /* Scope strings */
+               {
+                 "private",
+                 "protected",
+                 "public"
+               };
+
+
+  cname       = mxmlElementGetAttr(scut, "name");
+  description = mxmlFindElement(scut, scut, "description", NULL,
+                               NULL, MXML_DESCEND_FIRST);
+
+  fprintf(out, "<h3 class=\"%s\">%s<a name=\"%s\">%s</a></h3>\n",
+         scut->value.element.name, get_comment_info(description), cname,
+         cname);
+
+  if (description)
+    write_description(out, description, "p", 1);
+
+  fprintf(out, "<p class=\"code\">%s %s", scut->value.element.name, cname);
+  if ((parent = mxmlElementGetAttr(scut, "parent")) != NULL)
+    fprintf(out, " %s", parent);
+  fputs(" {<br>\n", out);
+
+  maxscope = !strcmp(scut->value.element.name, "class") ? 3 : 1;
+
+  for (i = 0; i < maxscope; i ++)
+  {
+    inscope = maxscope == 1;
+
+    for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
+                              MXML_DESCEND_FIRST);
+        arg;
+        arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
+                              MXML_NO_DESCEND))
+    {
+      if (maxscope > 1 &&
+          ((scope = mxmlElementGetAttr(arg, "scope")) == NULL ||
+          strcmp(scope, scopes[i])))
+       continue;
+
+      if (!inscope)
+      {
+       inscope = 1;
+       fprintf(out, "&nbsp;&nbsp;%s:<br>\n", scopes[i]);
+      }
+
+      fputs("&nbsp;&nbsp;&nbsp;&nbsp;", out);
+      write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                             NULL, MXML_DESCEND_FIRST),
+                   OUTPUT_HTML);
+      fprintf(out, "%s;<br>\n", mxmlElementGetAttr(arg, "name"));
+    }
+
+    for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
+                                    MXML_DESCEND_FIRST);
+        function;
+        function = mxmlFindElement(function, scut, "function", NULL, NULL,
+                                   MXML_NO_DESCEND))
+    {
+      if (maxscope > 1 &&
+          ((scope = mxmlElementGetAttr(arg, "scope")) == NULL ||
+          strcmp(scope, scopes[i])))
+       continue;
+
+      if (!inscope)
+      {
+       inscope = 1;
+       fprintf(out, "&nbsp;&nbsp;%s:<br>\n", scopes[i]);
+      }
+
+      name = mxmlElementGetAttr(function, "name");
+
+      fputs("&nbsp;&nbsp;&nbsp;&nbsp;", out);
+
+      arg = mxmlFindElement(function, function, "returnvalue", NULL,
+                           NULL, MXML_DESCEND_FIRST);
+
+      if (arg)
+       write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                               NULL, MXML_DESCEND_FIRST),
+                     OUTPUT_HTML);
+      else if (strcmp(cname, name) && strcmp(cname, name + 1))
+       fputs("void ", out);
+
+      fprintf(out, "<a href=\"#%s.%s\">%s</a>", cname, name, name);
+
+      for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
+                                MXML_DESCEND_FIRST), prefix = '(';
+          arg;
+          arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
+                                MXML_NO_DESCEND), prefix = ',')
+      {
+       type = mxmlFindElement(arg, arg, "type", NULL, NULL,
+                              MXML_DESCEND_FIRST);
+
+       putc(prefix, out);
+       if (prefix == ',')
+         putc(' ', out);
+
+       if (type->child)
+         write_element(out, doc, type, OUTPUT_HTML);
+
+       fputs(mxmlElementGetAttr(arg, "name"), out);
+       if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
+         fprintf(out, " %s", defval);
+      }
+
+      if (prefix == '(')
+       fputs("(void);<br>\n", out);
+      else
+       fputs(");<br>\n", out);
+    }
+  }
+
+  fputs("};</p>\n"
+       "<h4 class=\"members\">Members</h4>\n"
+       "<dl>\n", out);
+
+  for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
+                            MXML_DESCEND_FIRST);
+       arg;
+       arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
+                            MXML_NO_DESCEND))
+  {
+    description = mxmlFindElement(arg, arg, "description", NULL,
+                                 NULL, MXML_DESCEND_FIRST);
+
+    fprintf(out, "<dt>%s %s</dt>\n",
+           mxmlElementGetAttr(arg, "name"), get_comment_info(description));
+
+    write_description(out, description, "dd", 1);
+    write_description(out, description, "dd", 0);
+  }
+
+  fputs("</dl>\n", out);
+
+  for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
+                                 MXML_DESCEND_FIRST);
+       function;
+       function = mxmlFindElement(function, scut, "function", NULL, NULL,
+                                 MXML_NO_DESCEND))
+  {
+    write_function(out, doc, function, 4);
+  }
+}
+
+
+/*
+ * 'write_string()' - Write a string, quoting HTML special chars as needed.
+ */
+
+static void
+write_string(FILE       *out,          /* I - Output file */
+             const char *s,            /* I - String to write */
+             int        mode)          /* I - Output mode */
+{
+  switch (mode)
+  {
+    case OUTPUT_HTML :
+    case OUTPUT_XML :
+        while (*s)
+        {
+          if (*s == '&')
+            fputs("&amp;", out);
+          else if (*s == '<')
+            fputs("&lt;", out);
+          else if (*s == '>')
+            fputs("&gt;", out);
+          else if (*s == '\"')
+            fputs("&quot;", out);
+          else if (*s & 128)
+          {
+           /*
+            * Convert UTF-8 to Unicode constant...
+            */
+
+            int        ch;                     /* Unicode character */
+
+
+            ch = *s & 255;
+
+            if ((ch & 0xe0) == 0xc0)
+            {
+              ch = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
+             s ++;
+            }
+            else if ((ch & 0xf0) == 0xe0)
+            {
+              ch = ((((ch * 0x0f) << 6) | (s[1] & 0x3f)) << 6) | (s[2] & 0x3f);
+             s += 2;
+            }
+
+            if (ch == 0xa0)
+            {
+             /*
+              * Handle non-breaking space as-is...
+             */
+
+              fputs("&nbsp;", out);
+            }
+            else
+              fprintf(out, "&#x%x;", ch);
+          }
+          else
+            putc(*s, out);
+
+          s ++;
+        }
+        break;
+
+    case OUTPUT_MAN :
+        while (*s)
+        {
+          if (*s == '\\' || *s == '-')
+            putc('\\', out);
+
+          putc(*s++, out);
+        }
+        break;
+  }
+}
+
+
+/*
+ * 'write_toc()' - Write a table-of-contents.
+ */
+
+static void
+write_toc(FILE        *out,            /* I - Output file */
+          mxml_node_t *doc,            /* I - Document */
+          const char  *introfile,      /* I - Introduction file */
+         const char  *target,          /* I - Target name */
+         int         xml)              /* I - Write XML nodes? */
+{
+  FILE         *fp;                    /* Intro file */
+  mxml_node_t  *function,              /* Current function */
+               *scut,                  /* Struct/class/union/typedef */
+               *arg,                   /* Current argument */
+               *description;           /* Description of function/var */
+  const char   *name,                  /* Name of function/type */
+               *targetattr;            /* Target attribute, if any */
+  int          xmlid = 1;              /* Current XML node ID */
+
+
+ /*
+  * If target is set, it is the frame file that contains the body.
+  * Otherwise, we are creating a single-file...
+  */
+
+  if (target)
+    targetattr = " target=\"body\"";
+  else
+    targetattr = "";
+
+ /*
+  * The table-of-contents is a nested unordered list.  Start by
+  * reading any intro file to see if there are any headings there.
+  */
+
+  if (!xml)
+    fputs("<h2 class=\"title\">Contents</h2>\n"
+          "<ul class=\"contents\">\n", out);
+
+  if (introfile && (fp = fopen(introfile, "r")) != NULL)
+  {
+    char       line[8192],             /* Line from file */
+               *ptr,                   /* Pointer in line */
+               *end,                   /* End of line */
+               *anchor,                /* Anchor name */
+               quote,                  /* Quote character for value */
+               level = '2',            /* Current heading level */
+               newlevel;               /* New heading level */
+    int                inelement;              /* In an element? */
+
+
+    while (fgets(line, sizeof(line), fp))
+    {
+     /*
+      * See if this line has a heading...
+      */
+
+      if ((ptr = strstr(line, "<h")) == NULL &&
+          (ptr = strstr(line, "<H")) == NULL)
+       continue;
+
+      if (ptr[2] != '2' && ptr[2] != '3')
+        continue;
+
+      newlevel = ptr[2];
+
+     /*
+      * Make sure we have the whole heading...
+      */
+
+      while (!strstr(line, "</h") && !strstr(line, "</H"))
+      {
+        end = line + strlen(line);
+
+       if (end == (line + sizeof(line) - 1) ||
+           !fgets(end, (int)(sizeof(line) - (end - line)), fp))
+         break;
+      }
+
+     /*
+      * Convert newlines and tabs to spaces...
+      */
+
+      for (ptr = line; *ptr; ptr ++)
+        if (isspace(*ptr & 255))
+         *ptr = ' ';
+
+     /*
+      * Find the anchor and text...
+      */
+
+      for (ptr = strchr(line, '<'); ptr; ptr = strchr(ptr + 1, '<'))
+        if (!strncmp(ptr, "<A NAME=", 8) || !strncmp(ptr, "<a name=", 8))
+         break;
+
+      if (!ptr)
+        continue;
+
+      ptr += 8;
+      inelement = 1;
+
+      if (*ptr == '\'' || *ptr == '\"')
+      {
+       /*
+        * Quoted anchor...
+       */
+
+        quote  = *ptr++;
+       anchor = ptr;
+
+       while (*ptr && *ptr != quote)
+         ptr ++;
+
+        if (!*ptr)
+         continue;
+
+        *ptr++ = '\0';
+      }
+      else
+      {
+       /*
+        * Non-quoted anchor...
+       */
+
+        anchor = ptr;
+
+       while (*ptr && *ptr != '>' && !isspace(*ptr & 255))
+         ptr ++;
+
+        if (!*ptr)
+         continue;
+
+        if (*ptr == '>')
+         inelement = 0;
+
+       *ptr++ = '\0';
+      }
+
+     /*
+      * Write text until we see "</A>"...
+      */
+
+      if (xml)
+      {
+       if (newlevel < level)
+         fputs("</Node>\n"
+               "</Subnodes></Node>\n", out);
+       else if (newlevel > level && newlevel == '3')
+         fputs("<Subnodes>\n", out);
+       else if (xmlid > 1)
+         fputs("</Node>\n", out);
+
+       level = newlevel;
+
+       fprintf(out, "<Node id=\"%d\">\n"
+                     "<Path>Documentation/index.html</Path>\n"
+                    "<Anchor>%s</Anchor>\n"
+                    "<Name>", xmlid ++, anchor);
+
+       quote = 0;
+
+       while (*ptr)
+       {
+         if (inelement)
+         {
+           if (*ptr == quote)
+             quote = 0;
+           else if (*ptr == '>')
+             inelement = 0;
+           else if (*ptr == '\'' || *ptr == '\"')
+             quote = *ptr;
+         }
+         else if (*ptr == '<')
+         {
+           if (!strncmp(ptr, "</A>", 4) || !strncmp(ptr, "</a>", 4))
+             break;
+
+           inelement = 1;
+         }
+         else
+           putc(*ptr, out);
+
+         ptr ++;
+       }
+
+       fputs("</Name>\n", out);
+      }
+      else
+      {
+       if (newlevel < level)
+         fputs("</li>\n"
+               "</ul></li>\n", out);
+       else if (newlevel > level)
+         fputs("<ul class=\"subcontents\">\n", out);
+       else if (xmlid > 1)
+         fputs("</li>\n", out);
+
+       level = newlevel;
+       xmlid ++;
+
+       fprintf(out, "%s<li><a href=\"%s#%s\"%s>", level > '2' ? "\t" : "",
+               target ? target : "", anchor, targetattr);
+
+       quote = 0;
+
+       while (*ptr)
+       {
+         if (inelement)
+         {
+           if (*ptr == quote)
+             quote = 0;
+           else if (*ptr == '>')
+             inelement = 0;
+           else if (*ptr == '\'' || *ptr == '\"')
+             quote = *ptr;
+         }
+         else if (*ptr == '<')
+         {
+           if (!strncmp(ptr, "</A>", 4) || !strncmp(ptr, "</a>", 4))
+             break;
+
+           inelement = 1;
+         }
+         else
+           putc(*ptr, out);
+
+         ptr ++;
+       }
+
+       fputs("</a>", out);
+      }
+    }
+
+    if (level > '1')
+    {
+      if (xml)
+      {
+       fputs("</Node>\n", out);
+
+       if (level == '3')
+         fputs("</Subnodes></Node>\n", out);
+      }
+      else
+      {
+       fputs("</li>\n", out);
+
+       if (level == '3')
+         fputs("</ul></li>\n", out);
+      }
+    }
+
+    fclose(fp);
+  }
+
+ /*
+  * Next the classes...
+  */
+
+  if ((scut = find_public(doc, doc, "class")) != NULL)
+  {
+    if (xml)
+      fprintf(out, "<Node id=\"%d\">\n"
+                  "<Path>Documentation/index.html</Path>\n"
+                  "<Anchor>CLASSES</Anchor>\n"
+                  "<Name>Classes</Name>\n"
+                  "<Subnodes>\n", xmlid ++);
+    else
+      fprintf(out, "<li><a href=\"%s#CLASSES\"%s>Classes</a>"
+                  "<ul class=\"code\">\n",
+             target ? target : "", targetattr);
+
+    while (scut)
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      if (xml)
+      {
+       fprintf(out, "<Node id=\"%d\">\n"
+                    "<Path>Documentation/index.html</Path>\n"
+                    "<Anchor>%s</Anchor>\n"
+                    "<Name>%s</Name>\n"
+                    "</Node>\n", xmlid ++, name, name);
+      }
+      else
+      {
+       fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
+               target ? target : "", name, targetattr);
+       write_description(out, description, "", 1);
+       fprintf(out, "\">%s</a></li>\n", name);
+      }
+
+      scut = find_public(scut, doc, "class");
+    }
+
+    if (xml)
+      fputs("</Subnodes></Node>\n", out);
+    else
+      fputs("</ul></li>\n", out);
+  }
+
+ /*
+  * Functions...
+  */
+
+  if ((function = find_public(doc, doc, "function")) != NULL)
+  {
+    if (xml)
+      fprintf(out, "<Node id=\"%d\">\n"
+                  "<Path>Documentation/index.html</Path>\n"
+                  "<Anchor>FUNCTIONS</Anchor>\n"
+                  "<Name>Functions</Name>\n"
+                  "<Subnodes>\n", xmlid ++);
+    else
+      fprintf(out, "<li><a href=\"%s#FUNCTIONS\"%s>Functions</a>"
+                  "<ul class=\"code\">\n", target ? target : "", targetattr);
+
+    while (function)
+    {
+      name        = mxmlElementGetAttr(function, "name");
+      description = mxmlFindElement(function, function, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      if (xml)
+      {
+       fprintf(out, "<Node id=\"%d\">\n"
+                    "<Path>Documentation/index.html</Path>\n"
+                    "<Anchor>%s</Anchor>\n"
+                    "<Name>%s</Name>\n"
+                    "</Node>\n", xmlid ++, name, name);
+      }
+      else
+      {
+       fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
+               target ? target : "", name, targetattr);
+       write_description(out, description, "", 1);
+       fprintf(out, "\">%s</a></li>\n", name);
+      }
+
+      function = find_public(function, doc, "function");
+    }
+
+    if (xml)
+      fputs("</Subnodes></Node>\n", out);
+    else
+      fputs("</ul></li>\n", out);
+  }
+
+ /*
+  * Data types...
+  */
+
+  if ((scut = find_public(doc, doc, "typedef")) != NULL)
+  {
+    if (xml)
+      fprintf(out, "<Node id=\"%d\">\n"
+                  "<Path>Documentation/index.html</Path>\n"
+                  "<Anchor>TYPES</Anchor>\n"
+                  "<Name>Data Types</Name>\n"
+                  "<Subnodes>\n", xmlid ++);
+    else
+      fprintf(out, "<li><a href=\"%s#TYPES\"%s>Data Types</a>"
+                  "<ul class=\"code\">\n", target ? target : "", targetattr);
+
+    while (scut)
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      if (xml)
+      {
+       fprintf(out, "<Node id=\"%d\">\n"
+                    "<Path>Documentation/index.html</Path>\n"
+                    "<Anchor>%s</Anchor>\n"
+                    "<Name>%s</Name>\n"
+                    "</Node>\n", xmlid ++, name, name);
+      }
+      else
+      {
+       fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
+               target ? target : "", name, targetattr);
+       write_description(out, description, "", 1);
+       fprintf(out, "\">%s</a></li>\n", name);
+      }
+
+      scut = find_public(scut, doc, "typedef");
+    }
+
+    if (xml)
+      fputs("</Subnodes></Node>\n", out);
+    else
+      fputs("</ul></li>\n", out);
+  }
+
+ /*
+  * Structures...
+  */
+
+  if ((scut = find_public(doc, doc, "struct")) != NULL)
+  {
+    if (xml)
+      fprintf(out, "<Node id=\"%d\">\n"
+                  "<Path>Documentation/index.html</Path>\n"
+                  "<Anchor>STRUCTURES</Anchor>\n"
+                  "<Name>Structures</Name>\n"
+                  "<Subnodes>\n", xmlid ++);
+    else
+      fprintf(out, "<li><a href=\"%s#STRUCTURES\"%s>Structures</a>"
+                  "<ul class=\"code\">\n", target ? target : "", targetattr);
+
+    while (scut)
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      if (xml)
+      {
+       fprintf(out, "<Node id=\"%d\">\n"
+                    "<Path>Documentation/index.html</Path>\n"
+                    "<Anchor>%s</Anchor>\n"
+                    "<Name>%s</Name>\n"
+                    "</Node>\n", xmlid ++, name, name);
+      }
+      else
+      {
+       fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
+               target ? target : "", name, targetattr);
+       write_description(out, description, "", 1);
+       fprintf(out, "\">%s</a></li>\n", name);
+      }
+
+      scut = find_public(scut, doc, "struct");
+    }
+
+    if (xml)
+      fputs("</Subnodes></Node>\n", out);
+    else
+      fputs("</ul></li>\n", out);
+  }
+
+ /*
+  * Unions...
+  */
+
+  if ((scut = find_public(doc, doc, "union")) != NULL)
+  {
+    if (xml)
+      fprintf(out, "<Node id=\"%d\">\n"
+                  "<Path>Documentation/index.html</Path>\n"
+                  "<Anchor>UNIONS</Anchor>\n"
+                  "<Name>Unions</Name>\n"
+                  "<Subnodes>\n", xmlid ++);
+    else
+      fprintf(out,
+              "<li><a href=\"%s#UNIONS\"%s>Unions</a><ul class=\"code\">\n",
+             target ? target : "", targetattr);
+
+    while (scut)
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      if (xml)
+      {
+       fprintf(out, "<Node id=\"%d\">\n"
+                    "<Path>Documentation/index.html</Path>\n"
+                    "<Anchor>%s</Anchor>\n"
+                    "<Name>%s</Name>\n"
+                    "</Node>\n", xmlid ++, name, name);
+      }
+      else
+      {
+       fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
+               target ? target : "", name, targetattr);
+       write_description(out, description, "", 1);
+       fprintf(out, "\">%s</a></li>\n", name);
+      }
+
+      scut = find_public(scut, doc, "union");
+    }
+
+    if (xml)
+      fputs("</Subnodes></Node>\n", out);
+    else
+      fputs("</ul></li>\n", out);
+  }
+
+ /*
+  * Globals variables...
+  */
+
+  if ((arg = find_public(doc, doc, "variable")) != NULL)
+  {
+    if (xml)
+      fprintf(out, "<Node id=\"%d\">\n"
+                  "<Path>Documentation/index.html</Path>\n"
+                  "<Anchor>VARIABLES</Anchor>\n"
+                  "<Name>Variables</Name>\n"
+                  "<Subnodes>\n", xmlid ++);
+    else
+      fprintf(out, "<li><a href=\"%s#VARIABLES\"%s>Variables</a>"
+                  "<ul class=\"code\">\n", target ? target : "", targetattr);
+
+    while (arg)
+    {
+      name        = mxmlElementGetAttr(arg, "name");
+      description = mxmlFindElement(arg, arg, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      if (xml)
+      {
+       fprintf(out, "<Node id=\"%d\">\n"
+                    "<Path>Documentation/index.html</Path>\n"
+                    "<Anchor>%s</Anchor>\n"
+                    "<Name>%s</Name>\n"
+                    "</Node>\n", xmlid ++, name, name);
+      }
+      else
+      {
+       fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
+               target ? target : "", name, targetattr);
+       write_description(out, description, "", 1);
+       fprintf(out, "\">%s</a></li>\n", name);
+      }
+
+      arg = find_public(arg, doc, "variable");
+    }
+
+    if (xml)
+      fputs("</Subnodes></Node>\n", out);
+    else
+      fputs("</ul></li>\n", out);
+  }
+
+ /*
+  * Enumerations/constants...
+  */
+
+  if ((scut = find_public(doc, doc, "enumeration")) != NULL)
+  {
+    if (xml)
+      fprintf(out, "<Node id=\"%d\">\n"
+                  "<Path>Documentation/index.html</Path>\n"
+                  "<Anchor>ENUMERATIONS</Anchor>\n"
+                  "<Name>Constants</Name>\n"
+                  "<Subnodes>\n", xmlid ++);
+    else
+      fprintf(out, "<li><a href=\"%s#ENUMERATIONS\"%s>Constants</a>"
+                  "<ul class=\"code\">\n", target ? target : "", targetattr);
+
+    while (scut)
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      if (xml)
+      {
+       fprintf(out, "<Node id=\"%d\">\n"
+                    "<Path>Documentation/index.html</Path>\n"
+                    "<Anchor>%s</Anchor>\n"
+                    "<Name>%s</Name>\n"
+                    "</Node>\n", xmlid ++, name, name);
+      }
+      else
+      {
+       fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
+               target ? target : "", name, targetattr);
+       write_description(out, description, "", 1);
+       fprintf(out, "\">%s</a></li>\n", name);
+      }
+
+      scut = find_public(scut, doc, "enumeration");
+    }
+
+    if (xml)
+      fputs("</Subnodes></Node>\n", out);
+    else
+      fputs("</ul></li>\n", out);
+  }
+
+ /*
+  * Close out the HTML table-of-contents list as needed...
+  */
+
+  if (!xml)
+    fputs("</ul>\n", out);
+}
+
+
+/*
+ * 'write_tokens()' - Write <Token> nodes for all APIs.
+ */
+
+static void
+write_tokens(FILE        *out,         /* I - Output file */
+             mxml_node_t *doc,         /* I - Document */
+            const char  *path)         /* I - Path to help file */
+{
+  mxml_node_t  *function,              /* Current function */
+               *scut,                  /* Struct/class/union/typedef */
+               *arg,                   /* Current argument */
+               *description,           /* Description of function/var */
+               *type,                  /* Type node */
+               *node;                  /* Current child node */
+  const char   *name,                  /* Name of function/type */
+               *cename,                /* Current class/enum name */
+               *defval;                /* Default value for argument */
+  char         prefix;                 /* Prefix for declarations */
+
+
+ /*
+  * Classes...
+  */
+
+  if ((scut = find_public(doc, doc, "class")) != NULL)
+  {
+    while (scut)
+    {
+      cename      = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      fprintf(out, "<Token>\n"
+                  "<Path>Documentation/%s</Path>\n"
+                  "<Anchor>%s</Anchor>\n"
+                  "<TokenIdentifier>//apple_ref/cpp/cl/%s</TokenIdentifier>\n"
+                  "<Abstract>", path, cename, cename);
+      write_description(out, description, "", 1);
+      fputs("</Abstract>\n"
+            "</Token>\n", out);
+
+      if ((function = find_public(scut, scut, "function")) != NULL)
+      {
+       while (function)
+       {
+         name        = mxmlElementGetAttr(function, "name");
+         description = mxmlFindElement(function, function, "description",
+                                       NULL, NULL, MXML_DESCEND_FIRST);
+
+         fprintf(out, "<Token>\n"
+                      "<Path>Documentation/%s</Path>\n"
+                      "<Anchor>%s.%s</Anchor>\n"
+                      "<TokenIdentifier>//apple_ref/cpp/clm/%s/%s", path,
+                 cename, name, cename, name);
+
+         arg = mxmlFindElement(function, function, "returnvalue", NULL,
+                               NULL, MXML_DESCEND_FIRST);
+
+         if (arg && (type = mxmlFindElement(arg, arg, "type", NULL,
+                                            NULL, MXML_DESCEND_FIRST)) != NULL)
+          {
+           for (node = type->child; node; node = node->next)
+             fputs(node->value.text.string, out);
+         }
+         else if (strcmp(cename, name) && strcmp(cename, name + 1))
+           fputs("void", out);
+
+         fputs("/", out);
+
+         for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
+                                    MXML_DESCEND_FIRST), prefix = '(';
+              arg;
+              arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
+                                    MXML_NO_DESCEND), prefix = ',')
+         {
+           type = mxmlFindElement(arg, arg, "type", NULL, NULL,
+                                  MXML_DESCEND_FIRST);
+
+           putc(prefix, out);
+
+           for (node = type->child; node; node = node->next)
+             fputs(node->value.text.string, out);
+
+           fputs(mxmlElementGetAttr(arg, "name"), out);
+         }
+
+         if (prefix == '(')
+           fputs("(void", out);
+
+         fputs(")</TokenIdentifier>\n"
+               "<Abstract>", out);
+         write_description(out, description, "", 1);
+         fputs("</Abstract>\n"
+               "<Declaration>", out);
+
+         arg = mxmlFindElement(function, function, "returnvalue", NULL,
+                               NULL, MXML_DESCEND_FIRST);
+
+         if (arg)
+           write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                                   NULL, MXML_DESCEND_FIRST),
+                         OUTPUT_XML);
+         else if (strcmp(cename, name) && strcmp(cename, name + 1))
+           fputs("void ", out);
+
+         fputs(name, out);
+
+         for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
+                                    MXML_DESCEND_FIRST), prefix = '(';
+              arg;
+              arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
+                                    MXML_NO_DESCEND), prefix = ',')
+         {
+           type = mxmlFindElement(arg, arg, "type", NULL, NULL,
+                                  MXML_DESCEND_FIRST);
+
+           putc(prefix, out);
+           if (prefix == ',')
+             putc(' ', out);
+
+           if (type->child)
+             write_element(out, doc, type, OUTPUT_XML);
+
+           fputs(mxmlElementGetAttr(arg, "name"), out);
+           if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
+             fprintf(out, " %s", defval);
+         }
+
+         if (prefix == '(')
+           fputs("(void);", out);
+         else
+           fputs(");", out);
+
+         fputs("</Declaration>\n"
+               "</Token>\n", out);
+
+         function = find_public(function, doc, "function");
+       }
+      }
+      scut = find_public(scut, doc, "class");
+    }
+  }
+
+ /*
+  * Functions...
+  */
+
+  if ((function = find_public(doc, doc, "function")) != NULL)
+  {
+    while (function)
+    {
+      name        = mxmlElementGetAttr(function, "name");
+      description = mxmlFindElement(function, function, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      fprintf(out, "<Token>\n"
+                  "<Path>Documentation/%s</Path>\n"
+                  "<Anchor>%s</Anchor>\n"
+                  "<TokenIdentifier>//apple_ref/c/func/%s</TokenIdentifier>\n"
+                  "<Abstract>", path, name, name);
+      write_description(out, description, "", 1);
+      fputs("</Abstract>\n"
+            "<Declaration>", out);
+
+      arg = mxmlFindElement(function, function, "returnvalue", NULL,
+                           NULL, MXML_DESCEND_FIRST);
+
+      if (arg)
+       write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
+                                               NULL, MXML_DESCEND_FIRST),
+                     OUTPUT_XML);
+      else // if (strcmp(cname, name) && strcmp(cname, name + 1))
+       fputs("void ", out);
+
+      fputs(name, out);
+
+      for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
+                                MXML_DESCEND_FIRST), prefix = '(';
+          arg;
+          arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
+                                MXML_NO_DESCEND), prefix = ',')
+      {
+       type = mxmlFindElement(arg, arg, "type", NULL, NULL,
+                              MXML_DESCEND_FIRST);
+
+       putc(prefix, out);
+       if (prefix == ',')
+         putc(' ', out);
+
+       if (type->child)
+         write_element(out, doc, type, OUTPUT_XML);
+
+       fputs(mxmlElementGetAttr(arg, "name"), out);
+       if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
+         fprintf(out, " %s", defval);
+      }
+
+      if (prefix == '(')
+       fputs("(void);", out);
+      else
+       fputs(");", out);
+
+      fputs("</Declaration>\n"
+            "</Token>\n", out);
+
+      function = find_public(function, doc, "function");
+    }
+  }
+
+ /*
+  * Data types...
+  */
+
+  if ((scut = find_public(doc, doc, "typedef")) != NULL)
+  {
+    while (scut)
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      fprintf(out, "<Token>\n"
+                  "<Path>Documentation/%s</Path>\n"
+                  "<Anchor>%s</Anchor>\n"
+                  "<TokenIdentifier>//apple_ref/c/tdef/%s</TokenIdentifier>\n"
+                  "<Abstract>", path, name, name);
+      write_description(out, description, "", 1);
+      fputs("</Abstract>\n"
+            "</Token>\n", out);
+
+      scut = find_public(scut, doc, "typedef");
+    }
+  }
+
+ /*
+  * Structures...
+  */
+
+  if ((scut = find_public(doc, doc, "struct")) != NULL)
+  {
+    while (scut)
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      fprintf(out, "<Token>\n"
+                  "<Path>Documentation/%s</Path>\n"
+                  "<Anchor>%s</Anchor>\n"
+                  "<TokenIdentifier>//apple_ref/c/tag/%s</TokenIdentifier>\n"
+                  "<Abstract>", path, name, name);
+      write_description(out, description, "", 1);
+      fputs("</Abstract>\n"
+            "</Token>\n", out);
+
+      scut = find_public(scut, doc, "struct");
+    }
+  }
+
+ /*
+  * Unions...
+  */
+
+  if ((scut = find_public(doc, doc, "union")) != NULL)
+  {
+    while (scut)
+    {
+      name        = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      fprintf(out, "<Token>\n"
+                  "<Path>Documentation/%s</Path>\n"
+                  "<Anchor>%s</Anchor>\n"
+                  "<TokenIdentifier>//apple_ref/c/tag/%s</TokenIdentifier>\n"
+                  "<Abstract>", path, name, name);
+      write_description(out, description, "", 1);
+      fputs("</Abstract>\n"
+            "</Token>\n", out);
+
+      scut = find_public(scut, doc, "union");
+    }
+  }
+
+ /*
+  * Globals variables...
+  */
+
+  if ((arg = find_public(doc, doc, "variable")) != NULL)
+  {
+    while (arg)
+    {
+      name        = mxmlElementGetAttr(arg, "name");
+      description = mxmlFindElement(arg, arg, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      fprintf(out, "<Token>\n"
+                  "<Path>Documentation/%s</Path>\n"
+                  "<Anchor>%s</Anchor>\n"
+                  "<TokenIdentifier>//apple_ref/c/data/%s</TokenIdentifier>\n"
+                  "<Abstract>", path, name, name);
+      write_description(out, description, "", 1);
+      fputs("</Abstract>\n"
+            "</Token>\n", out);
+
+      arg = find_public(arg, doc, "variable");
+    }
+  }
+
+ /*
+  * Enumerations/constants...
+  */
+
+  if ((scut = find_public(doc, doc, "enumeration")) != NULL)
+  {
+    while (scut)
+    {
+      cename      = mxmlElementGetAttr(scut, "name");
+      description = mxmlFindElement(scut, scut, "description",
+                                   NULL, NULL, MXML_DESCEND_FIRST);
+
+      fprintf(out, "<Token>\n"
+                  "<Path>Documentation/%s</Path>\n"
+                  "<Anchor>%s</Anchor>\n"
+                  "<TokenIdentifier>//apple_ref/c/tag/%s</TokenIdentifier>\n"
+                  "<Abstract>", path, cename, cename);
+      write_description(out, description, "", 1);
+      fputs("</Abstract>\n"
+            "</Token>\n", out);
+
+      for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL,
+                                MXML_DESCEND_FIRST);
+          arg;
+          arg = mxmlFindElement(arg, scut, "constant", NULL, NULL,
+                                MXML_NO_DESCEND))
+      {
+        name        = mxmlElementGetAttr(arg, "name");
+       description = mxmlFindElement(arg, arg, "description", NULL,
+                                      NULL, MXML_DESCEND_FIRST);
+       fprintf(out, "<Token>\n"
+                    "<Path>Documentation/%s</Path>\n"
+                    "<Anchor>%s</Anchor>\n"
+                    
"<TokenIdentifier>//apple_ref/c/econst/%s</TokenIdentifier>\n"
+                    "<Abstract>", path, cename, name);
+       write_description(out, description, "", 1);
+       fputs("</Abstract>\n"
+             "</Token>\n", out);
+      }
+
+      scut = find_public(scut, doc, "enumeration");
+    }
+  }
+}
+
+
+/*
+ * 'ws_cb()' - Whitespace callback for saving.
+ */
+
+static const char *                    /* O - Whitespace string or NULL for 
none */
+ws_cb(mxml_node_t *node,               /* I - Element node */
+      int         where)               /* I - Where value */
+{
+  const char *name;                    /* Name of element */
+  int  depth;                          /* Depth of node */
+  static const char *spaces = "                                        ";
+                                       /* Whitespace (40 spaces) for indent */
+
+
+  name = node->value.element.name;
+
+  switch (where)
+  {
+    case MXML_WS_BEFORE_CLOSE :
+        if (strcmp(name, "argument") &&
+           strcmp(name, "class") &&
+           strcmp(name, "constant") &&
+           strcmp(name, "enumeration") &&
+           strcmp(name, "function") &&
+           strcmp(name, "mxmldoc") &&
+           strcmp(name, "namespace") &&
+           strcmp(name, "returnvalue") &&
+           strcmp(name, "struct") &&
+           strcmp(name, "typedef") &&
+           strcmp(name, "union") &&
+           strcmp(name, "variable"))
+         return (NULL);
+
+       for (depth = -4; node; node = node->parent, depth += 2);
+       if (depth > 40)
+         return (spaces);
+       else if (depth < 2)
+         return (NULL);
+       else
+         return (spaces + 40 - depth);
+
+    case MXML_WS_AFTER_CLOSE :
+       return ("\n");
+
+    case MXML_WS_BEFORE_OPEN :
+       for (depth = -4; node; node = node->parent, depth += 2);
+       if (depth > 40)
+         return (spaces);
+       else if (depth < 2)
+         return (NULL);
+       else
+         return (spaces + 40 - depth);
+
+    default :
+    case MXML_WS_AFTER_OPEN :
+        if (strcmp(name, "argument") &&
+           strcmp(name, "class") &&
+           strcmp(name, "constant") &&
+           strcmp(name, "enumeration") &&
+           strcmp(name, "function") &&
+           strcmp(name, "mxmldoc") &&
+           strcmp(name, "namespace") &&
+           strcmp(name, "returnvalue") &&
+           strcmp(name, "struct") &&
+           strcmp(name, "typedef") &&
+           strcmp(name, "union") &&
+           strcmp(name, "variable") &&
+           strncmp(name, "?xml", 4))
+         return (NULL);
+       else
+          return ("\n");
+  }
+}
+
+
+/*
+ * End of "$Id: mxmldoc.c 440 2011-08-11 18:51:26Z mike $".
+ */


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/minixml/mxmldoc.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Modified: monkey/branches/MonkeyBacktracking/monkey/src/pathologist/Makefile.am
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/pathologist/Makefile.am       
2012-07-29 11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/src/pathologist/Makefile.am       
2012-07-29 17:41:22 UTC (rev 22954)
@@ -15,34 +15,34 @@
 if HAVE_OPENSSL
 
 
-lib_LTLIBRARIES = libmonkeyedb.la \
-                                 libmonkeyaction.la \
-                                 libmonkeyxml.la
+lib_LTLIBRARIES = libpathologistedb.la \
+                                 libpathologistaction.la \
+                                 libpathologistxml.la
 
-libmonkeyedb_la_SOURCES = \
+libpathologistedb_la_SOURCES = \
   edb_api.c \
-  monkey_edb.h
+  pathologist_edb.h
 
-libmonkeyedb_la_LIBADD = \
-  $(top_builddir)/src/util/libmonkeyutil.la \
+libpathologistedb_la_LIBADD = \
+  $(top_builddir)/src/util/libpathologistutil.la \
   -lsqlite3 \
   $(XLIB)  
 
-libmonkeyaction_la_SOURCES = \
+libpathologistaction_la_SOURCES = \
   action_api.c \
-  monkey_action.h
+  pathologist_action.h
 
-libmonkeyaction_la_LIBADD = \
-  $(top_builddir)/src/mi/libmonkeymi.la \
-  $(top_builddir)/src/util/libmonkeyutil.la \
+libpathologistaction_la_LIBADD = \
+  $(top_builddir)/src/mi/libmi.la \
+  $(top_builddir)/src/util/libpathologistutil.la \
   $(XLIB)
 
-libmonkeyxml_la_SOURCES = \
+libpathologistxml_la_SOURCES = \
   xml_writer.c \
-  monkey_xml_writer.h
+  pathologist_xml_writer.h
   
-libmonkeyxml_la_LIBADD = \
-  $(top_builddir)/src/util/libmonkeyutil.la \
+libpathologistxml_la_LIBADD = \
+  $(top_builddir)/src/util/libpathologistutil.la \
   $(XLIB)
    
 bin_PROGRAMS = \
@@ -53,35 +53,30 @@
  mail_sender.c
 
 pathologist_LDADD = \
-  $(top_builddir)/src/mi/libmonkeymi.la \
-  $(top_builddir)/src/util/libmonkeyutil.la \
-  $(top_builddir)/src/pathologist/libmonkeyedb.la \
-  $(top_builddir)/src/pathologist/libmonkeyaction.la \
-  $(top_builddir)/src/pathologist/libmonkeyxml.la \
+  $(top_builddir)/src/mi/libmi.la \
+  $(top_builddir)/src/util/libpathologistutil.la \
+  $(top_builddir)/src/pathologist/libpathologistedb.la \
+  $(top_builddir)/src/pathologist/libpathologistaction.la \
+  $(top_builddir)/src/pathologist/libpathologistxml.la \
   -lesmtp \
   $(GN_LIBINTL)
-  
-check_PROGRAMS = \
-    #test_monkey_edb
-    #test_monkey       
 
 if ENABLE_TEST_RUN
-# TESTS = $(check_SCRIPTS)
-TESTS = $(check_PROGRAMS)
+       TESTS = $(check_PROGRAMS)
 endif
+  
+check_PROGRAMS = \
+    test_pathologist   
 
+test_pathologist_SOURCES = \
+ test_pathologist.c
+test_pathologist_LDADD = \
+  $(top_builddir)/src/minixml/libminixml.la
+  
+EXTRA_DIST = \
+  ../../refs  
 
-#test_monkey_SOURCES = \
- #test_monkey.c
-#test_monkey_LDADD = \
-  $(top_builddir)/src/util/libmonkeyutil.la
-
-check_SCRIPTS = \
-  #test_monkey.sh \
-  #test_monkey_npe.sh
-    
-#$(check_SCRIPTS) 
-
+  
 endif
 endif
 endif

Modified: monkey/branches/MonkeyBacktracking/monkey/src/pathologist/action_api.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/pathologist/action_api.c      
2012-07-29 11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/src/pathologist/action_api.c      
2012-07-29 17:41:22 UTC (rev 22954)
@@ -3,10 +3,10 @@
  * @brief Monkey API for actions taken by Monkey while debugging
  */
 
-#include "monkey_action.h"
-#include "monkey_edb.h"
-#include "monkey_xml_writer.h"
 #include "monkey_common.h"
+#include "pathologist_action.h"
+#include "pathologist_edb.h"
+#include "pathologist_xml_writer.h"
 #include <libesmtp.h>
 #include <string.h>
 #include <stdio.h>

Modified: monkey/branches/MonkeyBacktracking/monkey/src/pathologist/edb_api.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/pathologist/edb_api.c 
2012-07-29 11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/src/pathologist/edb_api.c 
2012-07-29 17:41:22 UTC (rev 22954)
@@ -7,7 +7,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <sqlite3.h>
-#include <monkey_edb.h>
+#include "pathologist_edb.h"
 
 
 /**

Deleted: 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_action.h
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_action.h   
2012-07-29 11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_action.h   
2012-07-29 17:41:22 UTC (rev 22954)
@@ -1,98 +0,0 @@
-/**
- * @file monkey/MONKEY_action.h
- * @brief Monkey API for actions taken by Monkey while debugging
- */
-
-#ifndef MONKEY_ACTION_H
-#define MONKEY_ACTION_H
-
-#include "gdbmi.h"
-#include "monkey_xml_writer.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                          /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-
-/* Debug constants */
-#define DEBUG_MODE_GDB 0
-#define GDB_STATE_STOPPED 1
-#define GDB_STATE_EXIT_NORMALLY 2
-#define GDB_STATE_ERROR 3
-#define GDB_SAFETY_COUNT 2
-#define DEBUG_MODE_VALGRIND 4
-#define DEBUG_MODE_REPORT_READY 5
-#define BUG_NULL_POINTER 6
-#define BUG_ABORT 7
-#define BUG_ARITHMETIC 8
-#define BUG_BAD_MEM_ACCESS 9
-#define BUG_SIG_BUS 10
-#define GDB_MI_ASYNC_WAIT 5
-
-/**
- * Context for the Action API
- */
-struct MONKEY_ACTION_Context
-{
-  const char *binary_name;
-  char *binaryArgs;
-  const char *email_address;
-  const char *expression_database_path;
-  const char *gdb_binary_path;
-  const char *valgrind_binary_path;
-  const char *inspect_expression;
-  const char *inspect_function;
-  int debug_mode;
-  int bug_detected;
-  char *debug_report;
-  struct MONKEY_XML_Node *xml_report_node;
-
-  /* gdb debugging attributes */
-  int run_reverse;
-  int scope_depth;
-  mi_h *gdb_handle;
-  int gdb_connected;
-  const char *gdb_in_use;
-  mi_stop *gdb_stop_reason;
-  mi_frames *gdb_frames;
-  const char *gdb_null_variable;
-
-  /* Valgrind memcheck attributes */
-  char* valgrind_output_tmp_file_name;
-};
-
-
-int MONKEY_ACTION_report_file (struct MONKEY_ACTION_Context
-                                     *cntxt, const char *dumpFileName, int 
isXML);
-int MONKEY_ACTION_report_email (struct MONKEY_ACTION_Context
-                                      *cntxt, const char *dumpFileName);
-int MONKEY_ACTION_inspect_expression_database (struct
-                                                     MONKEY_ACTION_Context
-                                                     *cntxt);
-int MONKEY_ACTION_rerun_with_gdb (struct MONKEY_ACTION_Context
-                                        *cntxt);
-int MONKEY_ACTION_start_reverse_execution(struct MONKEY_ACTION_Context * 
cntxt);
-int MONKEY_ACTION_rerun_with_valgrind (struct
-                                             MONKEY_ACTION_Context
-                                             *cntxt);
-int MONKEY_ACTION_format_report (struct MONKEY_ACTION_Context
-                                       *cntxt);
-int
-MONKEY_ACTION_format_report_xml (struct MONKEY_ACTION_Context
-                                       *cntxt);
-int MONKEY_ACTION_delete_context(struct MONKEY_ACTION_Context *cntxt);
-
-int MONKEY_ACTION_check_bug_redundancy (void);
-
-
-#if 0                          /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif

Deleted: monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_edb.h
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_edb.h      
2012-07-29 11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_edb.h      
2012-07-29 17:41:22 UTC (rev 22954)
@@ -1,161 +0,0 @@
-/**
- * @file monkey/MONKEY_edb.h
- * @brief Monkey API for accessing the Expression Database (edb)
- */
-
-#ifndef MONKEY_EDB_H
-#define MONKEY_EDB_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                          /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-
-struct MONKEY_EDB_Context;
-
-/**
- * Establish a connection to the Expression Database
- *
- * @param db_file_name path the Expression Database file
- * @return context to use for Accessing the Expression Database, NULL on error
- */
-struct MONKEY_EDB_Context *MONKEY_EDB_connect (const char
-                                                            *db_file_name);
-
-
-/**
- * Disconnect from Database, and cleanup resources
- *
- * @param context context
- * @return MONKEY_OK on success, MONKEY_NO on failure
- */
-int MONKEY_EDB_disconnect (struct MONKEY_EDB_Context *cntxt);
-
-
-typedef int (*MONKEY_ExpressionIterator) (void *, int, char **,
-                                                char **);
-
-typedef int (*MONKEY_FileIterator) (void *, int, char **, char **);
-
-
-
-int
-MONKEY_EDB_get_all_outer_scopes(struct MONKEY_EDB_Context
-               *cntxt, const char *file_name,
-               int function_beginning,
-               int scope_in_question_start,
-               int scope_in_question_end,
-               MONKEY_ExpressionIterator
-               iter, void *iter_cls);
-
-int
-MONKEY_EDB_expression_function_end_scope(struct MONKEY_EDB_Context
-               *cntxt, const char *file_name,
-               int start_lineno,
-               MONKEY_ExpressionIterator
-               iter, void *iter_cls);
-int
-MONKEY_EDB_function_start_line_for_scope(struct MONKEY_EDB_Context
-               *cntxt, const char *file_name,
-               int scope_end,
-               MONKEY_ExpressionIterator
-               iter, void *iter_cls);
-/**
- * Return the line number of the end-of-scope for the expression indicated by 
start_line_no
- *
- * @param cntxt context containing the Expression Database handle
- * @param file_name path to the file in which the expression in question exists
- * @param start_line_no expression's line
- * @param iter callback function, iterator for values returned from the 
Database
- * @param iter_cls closure for the expression iterator, will contain the 
scope-end line number
- * @return MONKEY_OK on success, MONKEY_NO on failure
- */
-int
-MONKEY_EDB_get_expression_scope_end (struct MONKEY_EDB_Context
-                                           *cntxt, const char *file_name,
-                                           int start_line_no,
-                                           MONKEY_ExpressionIterator
-                                           iter, void *iter_cls);
-
-
-int
-MONKEY_EDB_get_expression_scope_end_for_expression (struct MONKEY_EDB_Context
-                                           *cntxt, const char *file_name,
-                                           const char * expr_syntax,
-                                           MONKEY_ExpressionIterator
-                                           iter, void *iter_cls);
-
-/**
- * Return all the source code file names available in the Expression Database
- *
- * @param cntxt context containing the Expression Database handle
- * @param iter callback function, iterator for values returned from the 
Database
- * @param iter_cls closure for the file names iterator, will contain the file 
names
- * @return MONKEY_OK on success, MONKEY_NO on failure
- */
-int
-MONKEY_EDB_get_file_names (struct MONKEY_EDB_Context *cntxt,
-                                 MONKEY_FileIterator iter,
-                                 void *iter_cls);
-
-
-int
-MONKEY_EDB_get_expressions_outer_scopes (struct MONKEY_EDB_Context *cntxt,
-                                  const char *file_name, int start_line_no,
-                                  int end_line_no,
-                                  MONKEY_ExpressionIterator iter,
-                                  void *iter_cls);
-
-/**
- * Run an SQLite query to retrieve those expressions that are previous to
- * given expression and are in the same scope of the given expression
- * For example, consider the following code snippet:
- *
- * {
- *   struct Something whole; // line no.1 
- *   struct SomethingElse part; // line no.2
- *   whole.part = &part; // line no.3
- *   whole.part->member = 1; // line no.4
- * }
- *
- * If the expression supplied to the function is that of line no.4 
"whole.part->member = 1;"
- * The returned list of expressions will be: whole.part (line no.4), 
whole.part->member (line no.4),
- * whole (line no.3), whole.part (line no.3), &part (line no.3), whole.part = 
&part (line no.3)
- *
- * @param cntxt context containing the Expression Database handle.
- * @param file_name path to the file in which the expression in question exists
- * @param start_line_no expression beginning line
- * @param end_line_no line number for the expression's scope end
- * @param iter callback function, iterator for expressions returned from the 
Database
- * @param iter_cls closure for the expression iterator
- * @return MONKEY_OK success, MONKEY_NO failure
- */
-int
-MONKEY_EDB_get_expressions (struct MONKEY_EDB_Context *cntxt,
-                                  const char *file_name, int start_line_no,
-                                  int end_line_no,
-                                  MONKEY_ExpressionIterator iter,
-                                  void *iter_cls);
-
-
-int
-MONKEY_EDB_get_sub_expressions (struct MONKEY_EDB_Context
-                                      *cntxt, const char *file_name,
-                                      int start_line_no, int end_line_no,
-                                      MONKEY_ExpressionIterator iter,
-                                      void *iter_cls);
-
-
-
-#if 0                          /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-#endif

Deleted: 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_xml_writer.h
===================================================================
--- 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_xml_writer.h   
    2012-07-29 11:24:08 UTC (rev 22953)
+++ 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_xml_writer.h   
    2012-07-29 17:41:22 UTC (rev 22954)
@@ -1,54 +0,0 @@
-/**
- * @file monkey/MONKEY_xml_writer.h
- * @brief Monkey API for generating XML debug report
- */
-
-
-#ifndef MONKEY_XML_WRITER_H
-#define MONKEY_XML_WRITER_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                          /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-
-struct XmlAttribute {
-       struct XmlAttribute *next;
-       struct XmlAttribute *prev;
-       const char *name;
-       const char *value;
-};
-
-
-struct MONKEY_XML_Node {
-       struct MONKEY_XML_Node *next;
-       struct MONKEY_XML_Node *prev;
-       const char *name;
-       const char *value;
-       const char *innerText;
-       struct XmlAttribute* attributeListHead;
-       struct XmlAttribute* attributeListTail;
-       struct MONKEY_XML_Node *childrenListHead;
-       struct MONKEY_XML_Node *childrenListTail;
-};
-
-struct MONKEY_XML_Node* MONKEY_XML_WRITER_new_node(const char *name, const 
char *innerText);
-int MONKEY_XML_WRITER_delete_tree(struct MONKEY_XML_Node *root);
-struct MONKEY_XML_Node* MONKEY_XML_WRITER_add_child(struct MONKEY_XML_Node 
*parent, struct MONKEY_XML_Node *child);
-int MONKEY_XML_WRITER_write_document(FILE* file, struct MONKEY_XML_Node *root);
-FILE* MONKEY_XML_WRITER_create_document(const char *filePath);
-int MONKEY_XML_WRITER_add_attribute(struct MONKEY_XML_Node* node, const char 
*attrName, const char *attrValue);
-int MONKEY_XML_WRITER_add_inner_text(struct MONKEY_XML_Node *node, const char 
*innerText);
-
-#if 0                          /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-#endif

Modified: 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist.c     
2012-07-29 11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist.c     
2012-07-29 17:41:22 UTC (rev 22954)
@@ -19,15 +19,15 @@
 */
 
 /**
- * @file monkey/gnunet-monkey.c
- * @brief Monkey: automatic debugging tool
+ * @file pathologist/pathologist.c
+ * @brief Monkey Pathologist: automated debugging tool
  */
 
 #include <stdio.h>
 #include <string.h>
 #include <sys/stat.h>
 #include "monkey_common.h"
-#include "monkey_action.h"
+#include "pathologist_action.h"
 
 #define MIN_ARG_REQUIRED 2
 
@@ -46,7 +46,7 @@
 static int ret = 0;
 
 /**
- * Main function that will launch Monkey's action api.
+ * Main function that will launch Pathologist's action api.
 */
 static void run()
 {
@@ -61,7 +61,7 @@
        {
          fprintf( stderr,
                      "Expression Database file was not provided as and 
argument, "
-                     "and there is no file named test.db in monkey's working 
directory!\n");
+                     "and there is no file named test.db in pathologist's 
working directory!\n");
          MONKEY_break (0);
          ret = 1;
          return;
@@ -72,7 +72,7 @@
   if (NULL == dumpFileName)
     {
       /* if no file name provided for the output report, use a default one in 
the current working directory */
-      dumpFileName = "monkey_output";
+      dumpFileName = "pathologist_output";
     }
 
   if (strcasecmp (mode, "email") == 0)
@@ -108,7 +108,7 @@
     {
       int retVal;
     case MONKEY_NO:
-       fprintf (stderr, "Error in using gdb. Monkey will exit now!");
+       fprintf (stderr, "Error in using gdb. Pathologist will exit now!");
        ret = 1;
       break;
     case GDB_STATE_ERROR:
@@ -122,7 +122,7 @@
       if (MONKEY_NO == retVal)
        {
          fprintf( stderr,
-                     "Error in using the expression database. Program will 
exit now!\n");
+                     "Error in using the expression database. Pathologist will 
exit now!\n");
          ret = 1;
          break;
        }
@@ -133,7 +133,7 @@
          retVal = MONKEY_ACTION_rerun_with_valgrind (cntxt);
          if (MONKEY_NO == retVal)
            {
-             fprintf( stderr, "Error using Valgrind! Monkey will continue 
debugging!\n");
+             fprintf( stderr, "Error using Valgrind! Pathologist will continue 
debugging!\n");
            }
        }
 
@@ -141,7 +141,7 @@
        if (cntxt->run_reverse) {
          retVal = MONKEY_ACTION_start_reverse_execution(cntxt);
          if (MONKEY_NO == retVal) {
-                 fprintf(stderr, "Error during Backtracking! Monkey will 
continue debugging with backtracking.\n");
+                 fprintf(stderr, "Error during Backtracking! Pathologist will 
continue debugging with backtracking.\n");
          }
        }
 
@@ -183,26 +183,26 @@
 
 /* display help */
 void showHelp() {
-   printf("Monkey: Automatically debug a service\n");
-   printf ("\t-b: binary: path to a binary file for a program to debug with 
monkey [mandatory]\n");
+   printf("Monkey Pathologist: Automatically debug a service\n");
+   printf ("\t-b: binary: path to a binary file for a program to debug with 
pathologist [mandatory]\n");
    printf ("\t-d: database: path to Expression Database file [mandatory]\n");
-   printf ("\t-m: mode: monkey's mode of operation: options are \"text\" or 
\"email\" [mandatory]\n");
-   printf ("\t-a: address: email address to which monkey will send debug 
report [optional]\n");
-   printf ("\t-f: function: function name at which monkey will set a 
breakpoint [optional]\n");
-   printf ("\t-g: gdb: path to gdb binary to use. If not passed, monkey will 
set it to /usr/bin/gdb [optional]\n");
-   printf ("\t-l: valgrind: path to valgrind binary. If not passed, monkey 
will set it to /usr/bin/valgrind [optional]\n");
-   printf ("\t-p: depth: scope depth. How many scopes should monkey lookup 
expression values outer than the scope in which the problem occurs.\n\t Default 
is 0 which means, monkey is restricted to the scope of the expression in which 
the debugged program stopped [optional]\n");
+   printf ("\t-m: mode: pathologist's mode of operation: options are \"text\" 
or \"email\" [mandatory]\n");
+   printf ("\t-a: address: email address to which pathologist will send debug 
report [optional]\n");
+   printf ("\t-f: function: function name at which pathologist will set a 
breakpoint [optional]\n");
+   printf ("\t-g: gdb: path to gdb binary to use. If not passed, pathologist 
will set it to /usr/bin/gdb [optional]\n");
+   printf ("\t-l: valgrind: path to valgrind binary. If not passed, 
pathologist will set it to /usr/bin/valgrind [optional]\n");
+   printf ("\t-p: depth: scope depth. How many scopes should pathologist 
lookup expression values outer than the scope in which the problem occurs.\n\t 
Default is 0 which means, pathologist is restricted to the scope of the 
expression in which the debugged program stopped [optional]\n");
    printf ("\t-r: reverse: enables reverse execution. By default it's not 
allowed [optional]\n");
    printf ("\t-h: help: print this help [optional]\n");
    printf ("\t-i: inspect: expression to inspect in the function specified 
after argument f [optional]\n");
-   printf ("\t-o: output: path to the debug report generated by monkey.\n\t If 
not provided monkey will save the report in a file named monkey_output in the 
current working directory [optional]\n");
-   printf ("\t-v: version: monkey's version [optional]\n");
+   printf ("\t-o: output: path to the debug report generated by 
pathologist.\n\t If not provided pathologist will save the report in a file 
named pathologist_output in the current working directory [optional]\n");
+   printf ("\t-v: version: pathologist's version [optional]\n");
    printf ("Report bugs to address@hidden");
    printf ("GNUnet home page:  http://www.gnu.org/software/gnunet/\n";);
    printf ("General help using GNU software: http://www.gnu.org/gethelp/\n";);
 }
 
-int freeMonkeyArgs()
+int freePathologistArgs()
 {
        if (NULL != mode)
                MONKEY_free(mode);
@@ -267,14 +267,14 @@
         if (argc < MIN_ARG_REQUIRED)
            {
              printf ("%s",
-                     "Monkey should take arguments: Use -h to get a list of 
options.\n");
+                     "Pathologist should take arguments: Use -h to get a list 
of options.\n");
              return 1;
            }
         /* Parsing arguments */
         for (i = 0; i < argc; i++) {
                 if (strcmp("-h", argv[i]) == 0) {
                         showHelp();
-                        freeMonkeyArgs();
+                        freePathologistArgs();
                         return 1;
                 }
                 if (strcmp("-b", argv[i]) == 0) {
@@ -320,7 +320,7 @@
                 }
         }
 
-        /* Run Monkey */
+        /* Run Pathologist */
         run();
 
   return ret;

Copied: 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_action.h 
(from rev 22908, 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_action.h)
===================================================================
--- 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_action.h  
                            (rev 0)
+++ 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_action.h  
    2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,98 @@
+/**
+ * @file monkey/MONKEY_action.h
+ * @brief Monkey API for actions taken by Monkey while debugging
+ */
+
+#ifndef MONKEY_ACTION_H
+#define MONKEY_ACTION_H
+
+#include "gdbmi.h"
+#include "pathologist_xml_writer.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                          /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+/* Debug constants */
+#define DEBUG_MODE_GDB 0
+#define GDB_STATE_STOPPED 1
+#define GDB_STATE_EXIT_NORMALLY 2
+#define GDB_STATE_ERROR 3
+#define GDB_SAFETY_COUNT 2
+#define DEBUG_MODE_VALGRIND 4
+#define DEBUG_MODE_REPORT_READY 5
+#define BUG_NULL_POINTER 6
+#define BUG_ABORT 7
+#define BUG_ARITHMETIC 8
+#define BUG_BAD_MEM_ACCESS 9
+#define BUG_SIG_BUS 10
+#define GDB_MI_ASYNC_WAIT 5
+
+/**
+ * Context for the Action API
+ */
+struct MONKEY_ACTION_Context
+{
+  const char *binary_name;
+  char *binaryArgs;
+  const char *email_address;
+  const char *expression_database_path;
+  const char *gdb_binary_path;
+  const char *valgrind_binary_path;
+  const char *inspect_expression;
+  const char *inspect_function;
+  int debug_mode;
+  int bug_detected;
+  char *debug_report;
+  struct MONKEY_XML_Node *xml_report_node;
+
+  /* gdb debugging attributes */
+  int run_reverse;
+  int scope_depth;
+  mi_h *gdb_handle;
+  int gdb_connected;
+  const char *gdb_in_use;
+  mi_stop *gdb_stop_reason;
+  mi_frames *gdb_frames;
+  const char *gdb_null_variable;
+
+  /* Valgrind memcheck attributes */
+  char* valgrind_output_tmp_file_name;
+};
+
+
+int MONKEY_ACTION_report_file (struct MONKEY_ACTION_Context
+                                     *cntxt, const char *dumpFileName, int 
isXML);
+int MONKEY_ACTION_report_email (struct MONKEY_ACTION_Context
+                                      *cntxt, const char *dumpFileName);
+int MONKEY_ACTION_inspect_expression_database (struct
+                                                     MONKEY_ACTION_Context
+                                                     *cntxt);
+int MONKEY_ACTION_rerun_with_gdb (struct MONKEY_ACTION_Context
+                                        *cntxt);
+int MONKEY_ACTION_start_reverse_execution(struct MONKEY_ACTION_Context * 
cntxt);
+int MONKEY_ACTION_rerun_with_valgrind (struct
+                                             MONKEY_ACTION_Context
+                                             *cntxt);
+int MONKEY_ACTION_format_report (struct MONKEY_ACTION_Context
+                                       *cntxt);
+int
+MONKEY_ACTION_format_report_xml (struct MONKEY_ACTION_Context
+                                       *cntxt);
+int MONKEY_ACTION_delete_context(struct MONKEY_ACTION_Context *cntxt);
+
+int MONKEY_ACTION_check_bug_redundancy (void);
+
+
+#if 0                          /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif

Copied: 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_edb.h 
(from rev 22908, 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_edb.h)
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_edb.h 
                        (rev 0)
+++ monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_edb.h 
2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,161 @@
+/**
+ * @file monkey/MONKEY_edb.h
+ * @brief Monkey API for accessing the Expression Database (edb)
+ */
+
+#ifndef MONKEY_EDB_H
+#define MONKEY_EDB_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                          /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+struct MONKEY_EDB_Context;
+
+/**
+ * Establish a connection to the Expression Database
+ *
+ * @param db_file_name path the Expression Database file
+ * @return context to use for Accessing the Expression Database, NULL on error
+ */
+struct MONKEY_EDB_Context *MONKEY_EDB_connect (const char
+                                                            *db_file_name);
+
+
+/**
+ * Disconnect from Database, and cleanup resources
+ *
+ * @param context context
+ * @return MONKEY_OK on success, MONKEY_NO on failure
+ */
+int MONKEY_EDB_disconnect (struct MONKEY_EDB_Context *cntxt);
+
+
+typedef int (*MONKEY_ExpressionIterator) (void *, int, char **,
+                                                char **);
+
+typedef int (*MONKEY_FileIterator) (void *, int, char **, char **);
+
+
+
+int
+MONKEY_EDB_get_all_outer_scopes(struct MONKEY_EDB_Context
+               *cntxt, const char *file_name,
+               int function_beginning,
+               int scope_in_question_start,
+               int scope_in_question_end,
+               MONKEY_ExpressionIterator
+               iter, void *iter_cls);
+
+int
+MONKEY_EDB_expression_function_end_scope(struct MONKEY_EDB_Context
+               *cntxt, const char *file_name,
+               int start_lineno,
+               MONKEY_ExpressionIterator
+               iter, void *iter_cls);
+int
+MONKEY_EDB_function_start_line_for_scope(struct MONKEY_EDB_Context
+               *cntxt, const char *file_name,
+               int scope_end,
+               MONKEY_ExpressionIterator
+               iter, void *iter_cls);
+/**
+ * Return the line number of the end-of-scope for the expression indicated by 
start_line_no
+ *
+ * @param cntxt context containing the Expression Database handle
+ * @param file_name path to the file in which the expression in question exists
+ * @param start_line_no expression's line
+ * @param iter callback function, iterator for values returned from the 
Database
+ * @param iter_cls closure for the expression iterator, will contain the 
scope-end line number
+ * @return MONKEY_OK on success, MONKEY_NO on failure
+ */
+int
+MONKEY_EDB_get_expression_scope_end (struct MONKEY_EDB_Context
+                                           *cntxt, const char *file_name,
+                                           int start_line_no,
+                                           MONKEY_ExpressionIterator
+                                           iter, void *iter_cls);
+
+
+int
+MONKEY_EDB_get_expression_scope_end_for_expression (struct MONKEY_EDB_Context
+                                           *cntxt, const char *file_name,
+                                           const char * expr_syntax,
+                                           MONKEY_ExpressionIterator
+                                           iter, void *iter_cls);
+
+/**
+ * Return all the source code file names available in the Expression Database
+ *
+ * @param cntxt context containing the Expression Database handle
+ * @param iter callback function, iterator for values returned from the 
Database
+ * @param iter_cls closure for the file names iterator, will contain the file 
names
+ * @return MONKEY_OK on success, MONKEY_NO on failure
+ */
+int
+MONKEY_EDB_get_file_names (struct MONKEY_EDB_Context *cntxt,
+                                 MONKEY_FileIterator iter,
+                                 void *iter_cls);
+
+
+int
+MONKEY_EDB_get_expressions_outer_scopes (struct MONKEY_EDB_Context *cntxt,
+                                  const char *file_name, int start_line_no,
+                                  int end_line_no,
+                                  MONKEY_ExpressionIterator iter,
+                                  void *iter_cls);
+
+/**
+ * Run an SQLite query to retrieve those expressions that are previous to
+ * given expression and are in the same scope of the given expression
+ * For example, consider the following code snippet:
+ *
+ * {
+ *   struct Something whole; // line no.1 
+ *   struct SomethingElse part; // line no.2
+ *   whole.part = &part; // line no.3
+ *   whole.part->member = 1; // line no.4
+ * }
+ *
+ * If the expression supplied to the function is that of line no.4 
"whole.part->member = 1;"
+ * The returned list of expressions will be: whole.part (line no.4), 
whole.part->member (line no.4),
+ * whole (line no.3), whole.part (line no.3), &part (line no.3), whole.part = 
&part (line no.3)
+ *
+ * @param cntxt context containing the Expression Database handle.
+ * @param file_name path to the file in which the expression in question exists
+ * @param start_line_no expression beginning line
+ * @param end_line_no line number for the expression's scope end
+ * @param iter callback function, iterator for expressions returned from the 
Database
+ * @param iter_cls closure for the expression iterator
+ * @return MONKEY_OK success, MONKEY_NO failure
+ */
+int
+MONKEY_EDB_get_expressions (struct MONKEY_EDB_Context *cntxt,
+                                  const char *file_name, int start_line_no,
+                                  int end_line_no,
+                                  MONKEY_ExpressionIterator iter,
+                                  void *iter_cls);
+
+
+int
+MONKEY_EDB_get_sub_expressions (struct MONKEY_EDB_Context
+                                      *cntxt, const char *file_name,
+                                      int start_line_no, int end_line_no,
+                                      MONKEY_ExpressionIterator iter,
+                                      void *iter_cls);
+
+
+
+#if 0                          /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Copied: 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_xml_writer.h
 (from rev 22908, 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/monkey_xml_writer.h)
===================================================================
--- 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_xml_writer.h
                          (rev 0)
+++ 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_xml_writer.h
  2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,54 @@
+/**
+ * @file monkey/MONKEY_xml_writer.h
+ * @brief Monkey API for generating XML debug report
+ */
+
+
+#ifndef MONKEY_XML_WRITER_H
+#define MONKEY_XML_WRITER_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                          /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+struct XmlAttribute {
+       struct XmlAttribute *next;
+       struct XmlAttribute *prev;
+       const char *name;
+       const char *value;
+};
+
+
+struct MONKEY_XML_Node {
+       struct MONKEY_XML_Node *next;
+       struct MONKEY_XML_Node *prev;
+       const char *name;
+       const char *value;
+       const char *innerText;
+       struct XmlAttribute* attributeListHead;
+       struct XmlAttribute* attributeListTail;
+       struct MONKEY_XML_Node *childrenListHead;
+       struct MONKEY_XML_Node *childrenListTail;
+};
+
+struct MONKEY_XML_Node* MONKEY_XML_WRITER_new_node(const char *name, const 
char *innerText);
+int MONKEY_XML_WRITER_delete_tree(struct MONKEY_XML_Node *root);
+struct MONKEY_XML_Node* MONKEY_XML_WRITER_add_child(struct MONKEY_XML_Node 
*parent, struct MONKEY_XML_Node *child);
+int MONKEY_XML_WRITER_write_document(FILE* file, struct MONKEY_XML_Node *root);
+FILE* MONKEY_XML_WRITER_create_document(const char *filePath);
+int MONKEY_XML_WRITER_add_attribute(struct MONKEY_XML_Node* node, const char 
*attrName, const char *attrValue);
+int MONKEY_XML_WRITER_add_inner_text(struct MONKEY_XML_Node *node, const char 
*innerText);
+
+#if 0                          /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/pathologist_xml_writer.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/test_pathologist.c
===================================================================
--- 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/test_pathologist.c    
                            (rev 0)
+++ 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/test_pathologist.c    
    2012-07-29 17:41:22 UTC (rev 22954)
@@ -0,0 +1,211 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mxml.h"
+
+int OK = 0;
+int NO = 1;
+
+int compareReports(const char *refFileName, const char *testFileName) {
+       FILE *testFilePtr;
+       FILE *refFilePtr;
+       mxml_node_t *refTree;
+       mxml_node_t *testTree;
+       mxml_node_t *refNode;
+       mxml_node_t *testNode;
+       mxml_node_t *refEpochNode;
+       mxml_node_t *testEpochNode;
+       mxml_node_t *refFunctionNode;
+       mxml_node_t *testFunctionNode;
+       mxml_node_t *refExpressionNode;
+       mxml_node_t *testExpressionNode;
+       const char *refExpressionValue;
+       const char *testExpressionValue;
+
+       refFilePtr = fopen(refFileName, "r");
+       testFilePtr = fopen(testFileName, "r");
+       if (NULL == refFilePtr) {
+               fprintf(stderr, "Test failed: cannot locate reference 
report.\n");
+               return NO;
+       }
+       if (NULL == testFilePtr) {
+               fprintf(stderr, "Test failed: cannot locate test report.\n");
+               return NO;
+       }
+
+       refTree = mxmlLoadFile(NULL, refFilePtr, MXML_TEXT_CALLBACK);
+       testTree = mxmlLoadFile(NULL, testFilePtr, MXML_TEXT_CALLBACK);
+       if (NULL == refTree) {
+               fprintf(stderr, "Test failed: cannot parse reference 
report.\n");
+               return NO;
+       }
+       if (NULL == testTree) {
+               fprintf(stderr, "Test failed: cannot parse test report.\n");
+               return NO;
+       }
+       fclose(refFilePtr);
+       fclose(testFilePtr);
+
+       refNode = refTree; testNode = testTree; // <?xml version="1.0"?>
+
+       // <crash>...
+       refNode = mxmlWalkNext(mxmlGetFirstChild(refNode), refTree, 
MXML_DESCEND);
+       testNode = mxmlWalkNext(mxmlGetFirstChild(testNode), testTree, 
MXML_DESCEND);
+       if (0 != strcmp(mxmlGetElement(refNode), "crash") ||
+                       0 != strcmp(mxmlGetElement(testNode), "crash")) {
+               fprintf(stderr, "Test failed: wrong tag. <crash> expected\n");
+               return NO;
+       }
+       if (0 != strcmp(mxmlElementGetAttr(refNode, "category"), 
mxmlElementGetAttr(testNode, "category")) ||
+                       0 != strcmp(mxmlElementGetAttr(refNode, "function"), 
mxmlElementGetAttr(testNode, "function")) ||
+                       0 != strcmp(mxmlElementGetAttr(refNode, "line"), 
mxmlElementGetAttr(testNode, "line")) ||
+                       0 != strcmp(mxmlElementGetAttr(refNode, "file"), 
mxmlElementGetAttr(testNode, "file"))) {
+               fprintf(stderr, "Test failed: crash attributes mismatch.\n");
+               return NO;
+       }
+
+        // <valgrind> or <history>...
+       refNode = mxmlWalkNext(mxmlGetFirstChild(refNode), refTree, 
MXML_DESCEND);
+       testNode = mxmlWalkNext(mxmlGetFirstChild(testNode), testTree, 
MXML_DESCEND);
+       if (0 == strcmp(mxmlGetElement(refNode), "valgrind")) {
+               if (0 != strcmp(mxmlGetElement(testNode), "valgrind")) {
+                       fprintf(stderr, "Test failed: wrong tag, <valgrind> 
expected.\n");
+                       return NO;
+               }
+               refNode = mxmlWalkNext(refNode, refTree, MXML_DESCEND); // move 
to <history>
+               testNode = mxmlWalkNext(testNode, testTree, MXML_DESCEND);
+       } else if (0 == strcmp(mxmlGetElement(refNode), "history")) {
+               if (0 != strcmp(mxmlGetElement(testNode), "history")) {
+                       fprintf(stderr, "Test failed: wrong tag, <history> 
expected.\n");
+                       return NO;
+               }
+       } else {
+               fprintf(stderr, "Test failed: unknown tag.\n");
+               return NO;
+       }
+
+       // <epoch>'s
+       refEpochNode = mxmlGetFirstChild(refNode);
+       testEpochNode = mxmlGetFirstChild(testNode);
+       while (NULL != refEpochNode && NULL != testEpochNode) {
+               if (0 != strcmp(mxmlGetElement(refEpochNode), "epoch") ||
+                               0 != strcmp(mxmlGetElement(testEpochNode), 
"epoch")) {
+                       fprintf(stderr, "Test failed: wrong tag, <epoch> 
expected.\n");
+                       return NO;
+               }
+               // Comparing the epoch steps
+               if (0 != strcmp(mxmlElementGetAttr(refEpochNode, "step"), 
mxmlElementGetAttr(testEpochNode, "step"))) {
+                       fprintf(stderr, "Test failed: epoch steps mismatch.\n");
+                       return NO;
+               }
+
+               // <trace>
+               refNode = mxmlWalkNext(mxmlGetFirstChild(refEpochNode), 
refTree, MXML_DESCEND);
+               testNode = mxmlWalkNext(mxmlGetFirstChild(testEpochNode), 
testTree, MXML_DESCEND);
+
+               // <function>'s
+               refFunctionNode = mxmlGetFirstChild(refNode);
+               testFunctionNode = mxmlGetFirstChild(testNode);
+               while (NULL != refFunctionNode && NULL != testFunctionNode) {
+                       if (0 != strcmp(mxmlGetElement(refFunctionNode), 
"function") ||
+                                       0 != 
strcmp(mxmlGetElement(testFunctionNode), "function")) {
+                               fprintf(stderr, "Test failed: wrong tag, 
<function> expected.\n");
+                               return NO;
+                       }
+                       //comparing function attributes
+                       if (0 != strcmp(mxmlElementGetAttr(refFunctionNode, 
"name"), mxmlElementGetAttr(testFunctionNode, "name")) ||
+                                       0 != 
strcmp(mxmlElementGetAttr(refFunctionNode, "line"), 
mxmlElementGetAttr(testFunctionNode, "line")) ||
+                                       0 != 
strcmp(mxmlElementGetAttr(refFunctionNode, "file"), 
mxmlElementGetAttr(testFunctionNode, "file")) ||
+                                       0 != 
strcmp(mxmlElementGetAttr(refFunctionNode, "depth"), 
mxmlElementGetAttr(testFunctionNode, "depth"))) {
+                               fprintf(stderr, "Test failed: function 
attributes mismatch.\n");
+                               return NO;
+                       }
+
+                       // <expressions>
+                       refNode = 
mxmlWalkNext(mxmlGetFirstChild(refFunctionNode), refTree, MXML_DESCEND);
+                       testNode = 
mxmlWalkNext(mxmlGetFirstChild(testFunctionNode), testTree, MXML_DESCEND);
+
+                       // <expression>'s
+                       refExpressionNode = mxmlGetFirstChild(refNode);
+                       testExpressionNode = mxmlGetFirstChild(testNode);
+                       while (NULL != refExpressionNode && NULL != 
testExpressionNode) {
+                               if (0 != 
strcmp(mxmlGetElement(refExpressionNode), "expression") ||
+                                               0 != 
strcmp(mxmlGetElement(testExpressionNode), "expression")) {
+                                       fprintf(stderr, "Test failed: wrong 
tag, <expression> expected.\n");
+                                       return NO;
+                               }
+
+                               // comparing expression syntax
+                               if (0 != 
strcmp(mxmlElementGetAttr(refExpressionNode, "name"), 
mxmlElementGetAttr(testExpressionNode, "name"))) {
+                                       fprintf(stderr, "Test failed: 
expression syntax mismatch.\n");
+                                       return NO;
+                               }
+
+                               // comparing expression values
+                               refExpressionValue = 
mxmlGetText(refExpressionNode, 0);
+                               testExpressionValue = 
mxmlGetText(testExpressionNode, 0);
+                               if (0 != strcmp(refExpressionValue, 
testExpressionValue)) {
+                                       // different pointer values are accepted
+                                       if (!(refExpressionValue[0] == '0' && 
refExpressionValue[1] == 'x'
+                                                       && 
testExpressionValue[0] == '0' && testExpressionValue[1] == 'x')) {
+                                               fprintf(stderr, "Test failed: 
expression value mismatch.\n");
+                                               return NO;
+                                       }
+                               }
+
+                               // next expression
+                               refExpressionNode = 
mxmlGetNextSibling(mxmlGetNextSibling(refExpressionNode));
+                               testExpressionNode = 
mxmlGetNextSibling(mxmlGetNextSibling(testExpressionNode));
+                       }
+                       if ((NULL == refExpressionNode && NULL != 
testExpressionNode) ||
+                                       (NULL == testExpressionNode && NULL != 
refExpressionNode)) {
+                               fprintf(stderr, "Test failed: expression 
mismatch.\n");
+                               return NO;
+                       }
+
+                       // next function
+                       refFunctionNode = 
mxmlGetNextSibling(mxmlGetNextSibling(refFunctionNode));
+                       testFunctionNode = 
mxmlGetNextSibling(mxmlGetNextSibling(testFunctionNode));
+               }
+               if ((NULL == refFunctionNode && NULL != testFunctionNode) ||
+                               (NULL == testFunctionNode && NULL != 
refFunctionNode)) {
+                       fprintf(stderr, "Test failed: function mismatch.\n");
+                       return NO;
+               }
+
+               // next epoch step
+               refEpochNode = 
mxmlGetNextSibling(mxmlGetNextSibling(refEpochNode));
+               testEpochNode = 
mxmlGetNextSibling(mxmlGetNextSibling(testEpochNode));
+       }
+       if ((NULL == refEpochNode && NULL != testEpochNode) ||
+                       (NULL == testEpochNode && NULL != refEpochNode)) {
+               fprintf(stderr, "Test failed: epoch steps mismatch.\n");
+               return NO;
+       }
+
+       mxmlDelete(refTree);
+       mxmlDelete(testTree);
+       return OK;
+}
+
+int main() {
+       int ret = OK;
+       FILE *pathologistPipe;
+       fprintf(stderr, "Testing Monkey Pathologist...\n");
+       printf("Testing Monkey Pathologist...\n");
+
+       // Bug Null Pointer Exception
+       fprintf(stderr, "Testing bug null pointer exception...\n");
+       pathologistPipe = popen("pathologist -m text -d 
refs/db/bug_null_pointer_exception.db "
+                       "-o refs/reports/test_bug_null_pointer_exception.xml -b 
refs/src/bug_null_pointer_exception", "r");
+       if (NULL == pathologistPipe) {
+               fprintf(stderr, "Fatal error: unable to run Monkey 
pathologist.\n");
+               return NO;
+       }
+       pclose(pathologistPipe);
+       if (NO == compareReports("refs/bug_null_pointer_exception_rpt.xml", 
"refs/bug_null_pointer_exception.xml")) {
+               ret = NO;
+       }
+
+       return ret;
+}


Property changes on: 
monkey/branches/MonkeyBacktracking/monkey/src/pathologist/test_pathologist.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Modified: monkey/branches/MonkeyBacktracking/monkey/src/pathologist/xml_writer.c
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/pathologist/xml_writer.c      
2012-07-29 11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/src/pathologist/xml_writer.c      
2012-07-29 17:41:22 UTC (rev 22954)
@@ -8,7 +8,7 @@
 #include <assert.h>
 #include <string.h>
 #include "monkey_common.h"
-#include "monkey_xml_writer.h"
+#include "pathologist_xml_writer.h"
 
 
 struct MONKEY_XML_Node* MONKEY_XML_WRITER_new_node(const char *name, const 
char *innerText) {

Modified: monkey/branches/MonkeyBacktracking/monkey/src/util/Makefile.am
===================================================================
--- monkey/branches/MonkeyBacktracking/monkey/src/util/Makefile.am      
2012-07-29 11:24:08 UTC (rev 22953)
+++ monkey/branches/MonkeyBacktracking/monkey/src/util/Makefile.am      
2012-07-29 17:41:22 UTC (rev 22954)
@@ -5,8 +5,8 @@
   XLIB = -lgcov
 endif
 
-lib_LTLIBRARIES = libmonkeyutil.la
+lib_LTLIBRARIES = libpathologistutil.la
 
-libmonkeyutil_la_SOURCES = \
+libpathologistutil_la_SOURCES = \
   common_allocation.c \
   str_replace_all.c
\ No newline at end of file




reply via email to

[Prev in Thread] Current Thread [Next in Thread]