Browse Source

pub.mxml. Initial Import.

woollybah 6 years ago
parent
commit
f80433d327
56 changed files with 27650 additions and 0 deletions
  1. 17 0
      mxml.mod/mxml.bmx
  2. 256 0
      mxml.mod/mxml/CHANGES.md
  3. 507 0
      mxml.mod/mxml/COPYING
  4. 201 0
      mxml.mod/mxml/LICENSE
  5. 333 0
      mxml.mod/mxml/Makefile.in
  6. 16 0
      mxml.mod/mxml/NOTICE
  7. 191 0
      mxml.mod/mxml/README.md
  8. 1568 0
      mxml.mod/mxml/config.guess
  9. 102 0
      mxml.mod/mxml/config.h
  10. 99 0
      mxml.mod/mxml/config.h.in
  11. 1793 0
      mxml.mod/mxml/config.sub
  12. 5905 0
      mxml.mod/mxml/configure
  13. 346 0
      mxml.mod/mxml/configure.ac
  14. 173 0
      mxml.mod/mxml/doc/body.man
  15. 1137 0
      mxml.mod/mxml/doc/body.md
  16. 4 0
      mxml.mod/mxml/doc/footer.man
  17. BIN
      mxml.mod/mxml/doc/mxml-cover.jpg
  18. BIN
      mxml.mod/mxml/doc/mxml-cover.opacity
  19. BIN
      mxml.mod/mxml/doc/mxml-cover.png
  20. 1353 0
      mxml.mod/mxml/doc/mxml.3
  21. BIN
      mxml.mod/mxml/doc/mxml.epub
  22. 2537 0
      mxml.mod/mxml/doc/mxml.html
  23. BIN
      mxml.mod/mxml/doc/mxml.opacity
  24. BIN
      mxml.mod/mxml/doc/mxml.png
  25. 251 0
      mxml.mod/mxml/install-sh
  26. 345 0
      mxml.mod/mxml/mxml-attr.c
  27. 438 0
      mxml.mod/mxml/mxml-entity.c
  28. 3632 0
      mxml.mod/mxml/mxml-file.c
  29. 448 0
      mxml.mod/mxml/mxml-get.c
  30. 652 0
      mxml.mod/mxml/mxml-index.c
  31. 873 0
      mxml.mod/mxml/mxml-node.c
  32. 313 0
      mxml.mod/mxml/mxml-private.c
  33. 98 0
      mxml.mod/mxml/mxml-private.h
  34. 269 0
      mxml.mod/mxml/mxml-search.c
  35. 371 0
      mxml.mod/mxml/mxml-set.c
  36. 562 0
      mxml.mod/mxml/mxml-string.c
  37. 282 0
      mxml.mod/mxml/mxml.h
  38. 10 0
      mxml.mod/mxml/mxml.pc.in
  39. 75 0
      mxml.mod/mxml/mxml.spec
  40. 29 0
      mxml.mod/mxml/test.xml
  41. 885 0
      mxml.mod/mxml/testmxml.c
  42. 132 0
      mxml.mod/mxml/vcnet/config.h
  43. 66 0
      mxml.mod/mxml/vcnet/mxml.sln
  44. 80 0
      mxml.mod/mxml/vcnet/mxml1.def
  45. 215 0
      mxml.mod/mxml/vcnet/mxml1.vcxproj
  46. 65 0
      mxml.mod/mxml/vcnet/mxml1.vcxproj.filters
  47. 4 0
      mxml.mod/mxml/vcnet/mxml1.vcxproj.user
  48. 184 0
      mxml.mod/mxml/vcnet/mxmlstat.vcxproj
  49. 57 0
      mxml.mod/mxml/vcnet/mxmlstat.vcxproj.filters
  50. 4 0
      mxml.mod/mxml/vcnet/mxmlstat.vcxproj.user
  51. 5 0
      mxml.mod/mxml/vcnet/packages.config
  52. 199 0
      mxml.mod/mxml/vcnet/testmxml.vcxproj
  53. 22 0
      mxml.mod/mxml/vcnet/testmxml.vcxproj.filters
  54. 4 0
      mxml.mod/mxml/vcnet/testmxml.vcxproj.user
  55. 528 0
      mxml.mod/mxml/xcode/mxml.xcodeproj/project.pbxproj
  56. 14 0
      mxml.mod/source.bmx

+ 17 - 0
mxml.mod/mxml.bmx

@@ -0,0 +1,17 @@
+SuperStrict
+
+Module Pub.MXML
+
+ModuleInfo "Version: 1.00"
+ModuleInfo "Author: Michael R Sweet."
+ModuleInfo "License: Apache 2.0"
+ModuleInfo "Credit: Adapted for BlitzMax by Bruce A Henderson"
+
+ModuleInfo "History: 1.00"
+ModuleInfo "History: Initial Release."
+
+Import "source.bmx"
+
+
+Const MXML_ADD_BEFORE:Int = 0
+Const MXML_ADD_AFTER:Int = 1

+ 256 - 0
mxml.mod/mxml/CHANGES.md

@@ -0,0 +1,256 @@
+# Changes in Mini-XML 3.0
+
+- Changed the license to Apache 2.0 with exceptions (Issue #239)
+- All of the internal node structures are now moved out of the public header
+  (Issue #240)
+- Fixed a potential buffer overflow when writing floating point data
+  (Issue #233)
+- Moved `mxmldoc` to a new `codedoc` project whose focus is on generating
+  code documentation (Issue #235, Issue #236, Issue #237)
+- Error messages now include the line number of the error (Issue #230)
+
+
+# Changes in Mini-XML 2.12
+
+- Added yet more documentation about using `MXML_OPAQUE_CALLBACK` when you want
+  to get full strings for inline text instead of separated words (Issue #190)
+- No longer build documentation sets on macOS since Xcode no longer supports
+  them (Issue #198)
+- Updated the `va_copy` macro for use with BCC (Issue #211)
+- The `mxmlNewCDATA` and `mxmlSetCDATA` functions incorrectly added the XML
+  trailer "]]" to the string (Issue #216)
+- Cross-compiling failed on install (Issue #218)
+- Fixed a crash bug in the `mxmlWrite` functions (Issue #228)
+- The `mxmlWrite` functions no longer write the siblings of the passed node
+  (Issue #228)
+- Updated the markdown and ZIP container libraries used for mxmldoc.
+
+
+# Changes in Mini-XML 2.11
+
+- CDATA nodes now omit the trailing "]]" for convenience (Issue #170)
+- Fixed a memory leak in mxmlDelete (Issue #183)
+- `mxmlElementSetAttrf` did not work with some versions of Visual Studio
+  (Issue #184)
+- Added `mxmlElementGetAttrByIndex` and `mxmlELementGetAttrCount` functions
+  (Issue #185)
+- The configure script now properly supports cross-compilation (Issue #188)
+- The mxmldoc utility now supports generation of EPUB files (Issue #189)
+- The mxmldoc utility now supports the `SOURCE_DATE_EPOCH` environment
+  variable for reproducible builds (Issue #193)
+- The mxmldoc utility now supports Markdown (Issue #194)
+- Fixed writing of custom data values (Issue #201)
+- Added `mxmlNewOpaquef` and `mxmlSetOpaquef` functions to add and set formatted
+  opaque string values.
+- The mxmldoc utility scanned and loaded descriptive text differently, causing
+  the detailed descriptions ("discussion") to be lost in generated
+  documentation.
+- The mxmldoc utility now supports `@exclude format@` comments to exclude
+  documentation based on the output format.  The format string can be `all` to
+  exclude documentation for all formats or a comma-delimited list such as
+  `@exclude man,html@`.
+
+
+# Changes in Mini-XML 2.10
+
+- The version number in mxml.h was wrong.
+- The mxml.spec file was out of date.
+- Mini-XML no longer allows malformed element names.
+- `mxmlLoad*` and `mxmlSAXLoad*` did not properly create text nodes when
+  MXML_TEXT_CALLBACK was specified.
+- `mxmlDelete` used a recursive algorithm which could require large amounts of
+  stack space depending on the file. (CVE-2016-4570)
+- `mxmlWrite*` used a recursive algorithm which could require large amounts of
+  stack space depending on the file. (CVE-2016-4571)
+
+
+# Changes in Mini-XML 2.9
+
+- `mxmlLoad*` did not correctly load value nodes with `MXML_NO_CALLBACK` or
+  `MXML_TEXT_CALLBACK`.
+
+
+# Changes in Mini-XML 2.8
+
+- Now call docsetutil using xcrun on macOS.
+- mxmldoc did not escape special HTML characters inside @code foo@ comments.
+- Fixed a memory leak in `mxmlElementDeleteAttr`.
+- Added `MXML_MAJOR/MINOR_VERSION` definitions to mxml.h.
+- Fixed a bug reading UTF-16 characters from a file.
+- Fixed a memory leak when loading invalid XML.
+- Fixed an XML fragment loading problem.
+
+
+# Changes in Mini-XML 2.7
+
+- Added 64-bit configurations to the VC++ project files.
+- Fixed conformance of mxmldoc's HTML and CSS output.
+- Added data accessor ("get") functions and made the `mxml_node_t` and
+  `mxml_index_t` structures private but still available in the Mini-XML header to
+  preserve source compatibility.
+- Updated the source headers to reference the Mini-XML license and its
+  exceptions to the LGPL2.
+- Fixed a memory leak when loading a badly-formed XML file.
+- Added a new mxmlFindPath function to find the value node of a named element.
+- Building a static version of the library did not work on Windows.
+- The shared library did not include a destructor for the thread-specific data
+  key on UNIX-based operating systems.
+- mxmlLoad* did not error out on XML with multiple root nodes.
+- Fixed an issue with the `_mxml_vstrdupf` function.
+- `mxmlSave*` no longer write all siblings of the passed node, just that node
+  and its children.
+
+
+# Changes in Mini-XML 2.6
+
+- Documentation fixes.
+- The mxmldoc program did not handle typedef comments properly.
+- Added support for "long long" printf formats.
+- The XML parser now ignores BOMs in UTF-8 XML files.
+- The mxmldoc program now supports generating Xcode documentation sets.
+- `mxmlSave*` did not output UTF-8 correctly on some platforms.
+- `mxmlNewXML` now adds encoding="utf-8" in the ?xml directive to avoid
+  problems with non-conformant XML parsers that assume something other
+  than UTF-8 as the default encoding.
+- Wrapping was not disabled when mxmlSetWrapMargin(0) was called, and
+  "<?xml ... ?>" was always followed by a newline.
+- The mxml.pc.in file was broken.
+- The mxmldoc program now handles "typedef enum name {} name" correctly.
+
+
+# Changes in Mini-XML 2.5
+
+- The mxmldoc program now makes greater use of CSS and supports a `--css` option
+  to embed an alternate stylesheet.
+- The mxmldoc program now supports `--header` and `--footer` options to insert
+  documentation content before and after the generated content.
+- The mxmldoc program now supports a `--framed` option to generate framed HTML
+  output.
+- The mxmldoc program now creates a table of contents including any headings in
+  the `--intro` file when generating HTML output.
+- The man pages and man page output from mxmldoc did not use "\-" for dashes.
+- The debug version of the Mini-XML DLL could not be built.
+- Processing instructions and directives did not work when not at the top level
+  of a document.
+- Spaces around the "=" in attributes were not supported.
+
+
+# Changes in Mini-XML 2.4
+
+- Fixed shared library build problems on HP-UX and Mac macOS.
+- The mxmldoc program did not output argument descriptions for functions
+  properly.
+- All global settings (custom, error, and entity callbacks and the wrap margin)
+  are now managed separately for each thread.
+- Added `mxmlElementDeleteAttr` function.
+- `mxmlElementSetAttrf` did not work.
+- `mxmlLoad*` incorrectly treated declarations as parent elements.
+- `mxmlLoad*` incorrectly allowed attributes without values.
+- Fixed Visual C++ build problems.
+- `mxmlLoad*` did not return NULL when an element contained an error.
+- Added support for the apos character entity.
+- Fixed whitespace detection with Unicode characters.
+- `mxmlWalkNext` and `mxmlWalkPrev` did not work correctly when called with a
+  node with no children as the top node.
+
+
+# Changes in Mini-XML 2.3
+
+- Added two exceptions to the LGPL to support static linking of applications
+  against Mini-XML.
+- The mxmldoc utility can now generate man pages, too.
+- Added a mxmlNewXML function.
+- Added a mxmlElementSetAttrf function.
+- Added snprintf() emulation function for test program.
+- Added the _CRT_SECURE_NO_DEPRECATE definition when building on VC++ 2005.
+- mxmlLoad* did not detect missing > characters in elements.
+- mxmlLoad* did not detect missing close tags at the end of an XML document.
+- Added user_data and ref_count members to mxml_node_t structure.
+- Added mxmlReleaseNode() and mxmlRetainNode() APIs for reference-counted nodes.
+- Added mxmlSetWrapMargin() to control the wrapping of XML output.
+- Added conditional check for EINTR error code for certain Windows compilers
+  that do not define it.
+- The mxmldoc program now generates correct HTML 4.0 output - previously it
+  generated invalid XHTML.
+- The mxmldoc program now supports "@deprecated@, "@private@", and "@since
+  version@" comments.
+- Fixed function and enumeration type bugs in mxmldoc.
+- Fixed the XML schema for mxmldoc.
+- The mxmldoc program now supports `--intro`, `--section`, and `--title`
+  options.
+- The `mxmlLoad*` functions could leak a node on an error.
+- The `mxml_vsnprintf` function could get in an infinite loop on a buffer
+  overflow.
+- Added new `mxmlNewCDATA` and `mxmlSetCDATA` functions to create and set CDATA
+  nodes, which are really just special element nodes.
+- Added new `MXML_IGNORE` type and `MXML_IGNORE_CB` callback to ignore non-
+  element nodes, e.g. whitespace.
+- `mxmlLoad*` crashed when reporting an error in some invalid XML.
+
+
+# Changes in Mini-XML 2.2.2
+
+- `mxmlLoad*` did not treat custom data as opaque, so whitespace characters
+  would be lost.
+
+
+# Changes in Mini-XML 2.2.1
+
+- `mxmlLoad*` now correctly return NULL on error.
+- `mxmlNewInteger`, `mxmlNewOpaque`, `mxmlNewReal`, `mxmlNewText`, and
+  `mxmlNewTextf` incorrectly required a parent node.
+- Fixed an XML output bug in mxmldoc.
+- The "make install" target now uses the install command to set the proper
+  permissions on UNIX/Linux/macOS.
+- Fixed a MingW/Cygwin compilation problem.
+
+
+# Changes in Mini-XML 2.2
+
+- Added shared library support.
+- `mxmlLoad*` now return an error when an XML stream contains illegal control
+  characters.
+- `mxmlLoad*` now return an error when an element contains two attributes with
+  the same name in conformance with the XML spec.
+- Added support for CDATA.
+- Updated comment and processing instruction handling - no entity support per
+  XML specification.
+- Added checking for invalid comment termination: "--->" is not allowed.
+
+
+# Changes in Mini-XML 2.1
+
+- Added support for custom data nodes.
+- Now treat UTF-8 sequences which are longer than necessary as an error.
+- Fixed entity number support.
+- Fixed mxmlLoadString() bug with UTF-8.
+- Fixed entity lookup bug.
+- Added `mxmlLoadFd` and `mxmlSaveFd` functions.
+- Fixed multi-word UTF-16 handling.
+
+
+# Changes in Mini-XML 2.0
+
+- New programmers manual.
+- Added Visual C++ project files for Microsoft Windows users.
+- Added optimizations to mxmldoc, `mxmlSaveFile`, and `mxmlIndexNew`.
+- `mxmlEntityAddCallback` now returns an integer status.
+- Added UTF-16 support (input only; all output is UTF-8).
+- Added index functions to build a searchable index of XML nodes.
+- Added character entity callback interface to support additional character
+  entities beyond those defined in the XHTML specification.
+- Added support for XHTML character entities.
+- The mxmldoc utility now produces XML output which conforms to an updated XML
+  schema, described in the file "doc/mxmldoc.xsd".
+- Changed the whitespace callback interface to return strings instead of a
+  single character, allowing for greater control over the formatting of XML
+  files written using Mini-XML. THIS CHANGE WILL REQUIRE CHANGES TO YOUR 1.x
+  CODE IF YOU USE WHITESPACE CALLBACKS.
+- The mxmldoc utility is now capable of documenting C++ classes, functions, and
+  structures, and correctly handles C++ comments.
+- Added new modular tests for mxmldoc.
+- Updated the mxmldoc output to be more compatible with embedding in manuals
+  produced with HTMLDOC.
+- The makefile incorrectly included a "/" separator between the destination path
+  and install path. This caused problems when building and installing with
+  MingW.

+ 507 - 0
mxml.mod/mxml/COPYING

@@ -0,0 +1,507 @@
+			   Mini-XML License
+			  September 18, 2010
+
+
+The Mini-XML library and included programs are provided under the
+terms of the GNU Library General Public License version 2 (LGPL2)
+with the following exceptions:
+
+  1. Static linking of applications to the Mini-XML library
+does not constitute a derivative work and does not require
+the author to provide source code for the application, use
+the shared Mini-XML libraries, or link their applications
+against a user-supplied version of Mini-XML.
+
+If you link the application to a modified version of
+Mini-XML, then the changes to Mini-XML must be provided
+under the terms of the LGPL2 in sections 1, 2, and 4.
+
+  2. You do not have to provide a copy of the Mini-XML license
+with programs that are linked to the Mini-XML library, nor
+do you have to identify the Mini-XML license in your
+program or documentation as required by section 6 of the
+LGPL2.
+
+
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+			 Version 2, June 1991
+
+	  Copyright (C) 1991 Free Software Foundation, Inc.
+       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+     Everyone is permitted to copy and distribute verbatim copies
+      of this license document, but changing it is not allowed.
+
+    [This is the first released version of the library GPL.  It is
+   numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+			       Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+     Appendix: How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!

+ 201 - 0
mxml.mod/mxml/LICENSE

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 333 - 0
mxml.mod/mxml/Makefile.in

@@ -0,0 +1,333 @@
+#
+# Makefile for Mini-XML, a small XML-like file parsing library.
+#
+# https://www.msweet.org/mxml
+#
+# Copyright © 2003-2019 by Michael R Sweet.
+#
+# Licensed under Apache License v2.0.  See the file "LICENSE" for more
+# information.
+#
+
+#
+# Compiler tools definitions...
+#
+
+AR		=	@AR@
+ARFLAGS		=	@ARFLAGS@
+ARCHFLAGS	=	@ARCHFLAGS@
+CC		=	@CC@
+CFLAGS		=	$(OPTIM) $(ARCHFLAGS) @CFLAGS@ @CPPFLAGS@ @PTHREAD_FLAGS@
+CP		=	@CP@
+DSO		=	@DSO@
+DSOFLAGS	=	@DSOFLAGS@
+LDFLAGS		=	$(OPTIM) $(ARCHFLAGS) @LDFLAGS@
+INSTALL		=	@INSTALL@
+LIBMXML		=	@LIBMXML@
+LIBS		=	@LIBS@ @PTHREAD_LIBS@
+LN		=	@LN@ -s
+MKDIR		=	@MKDIR@
+OPTIM		=	@OPTIM@
+RANLIB		=	@RANLIB@
+RM		=	@RM@ -f
+SHELL		=	/bin/sh
+
+
+#
+# Configured directories...
+#
+
+prefix		=	@prefix@
+exec_prefix	=	@exec_prefix@
+bindir		=	@bindir@
+datarootdir	=	@datarootdir@
+includedir	=	@includedir@
+libdir		=	@libdir@
+mandir		=	@mandir@
+docdir		=	@docdir@
+BUILDROOT	=	$(DSTROOT)
+
+
+#
+# Install commands...
+#
+
+INSTALL_BIN	=	$(LIBTOOL) $(INSTALL) -m 755
+INSTALL_DATA	=	$(INSTALL) -m 644
+INSTALL_DIR	=	$(INSTALL) -d
+INSTALL_LIB	=	$(LIBTOOL) $(INSTALL) -m 755
+INSTALL_MAN	=	$(INSTALL) -m 644
+INSTALL_SCRIPT	=	$(INSTALL) -m 755
+
+
+#
+# Rules...
+#
+
+.SILENT:
+.SUFFIXES:	.c .man .o
+.c.o:
+	echo Compiling $<
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+
+#
+# Targets...
+#
+
+DOCFILES	=	doc/mxml.html doc/mxmldoc.xsd README.md COPYING CHANGES.md
+PUBLIBOBJS	=	mxml-attr.o mxml-entity.o mxml-file.o mxml-get.o \
+			mxml-index.o mxml-node.o mxml-search.o mxml-set.o
+LIBOBJS		=	$(PUBLIBOBJS) mxml-private.o mxml-string.o
+OBJS		=	testmxml.o $(LIBOBJS)
+ALLTARGETS	=	$(LIBMXML) testmxml
+CROSSTARGETS	=	$(LIBMXML)
+TARGETS		=	$(@TARGETS@)
+
+
+#
+# Make everything...
+#
+
+all:		$(TARGETS)
+
+
+#
+# Clean everything...
+#
+
+clean:
+	echo Cleaning build files...
+	$(RM) $(OBJS) $(ALLTARGETS)
+	$(RM) mxml1.dll
+	$(RM) libmxml.a
+	$(RM) libmxml.so.1.6
+	$(RM) libmxml.sl.1
+	$(RM) libmxml.1.dylib
+
+
+#
+# Really clean everything...
+#
+
+distclean:	clean
+	echo Cleaning distribution files...
+	$(RM) config.cache config.log config.status
+	$(RM) Makefile config.h
+	$(RM) -r autom4te*.cache
+	$(RM) *.bck *.bak
+	$(RM) -r clang
+
+
+#
+# Run the clang.llvm.org static code analysis tool on the C sources.
+#
+
+.PHONY: clang clang-changes
+clang:
+	echo Doing static code analysis of all code using CLANG...
+	$(RM) -r clang
+	scan-build -V -k -o `pwd`/clang $(MAKE) $(MFLAGS) clean all
+clang-changes:
+	echo Doing static code analysis of changed code using CLANG...
+	scan-build -V -k -o `pwd`/clang $(MAKE) $(MFLAGS) all
+
+
+#
+# Install everything...
+#
+
+install:	$(TARGETS) install-$(LIBMXML) install-libmxml.a
+	echo Installing documentation in $(BUILDROOT)$(docdir)...
+	$(INSTALL_DIR) $(BUILDROOT)$(docdir)
+	for file in $(DOCFILES); do \
+		$(INSTALL_MAN) $$file $(BUILDROOT)$(docdir)/`basename $$file .md`; \
+	done
+	echo Installing header files in $(BUILDROOT)$(includedir)...
+	$(INSTALL_DIR) $(BUILDROOT)$(includedir)
+	$(INSTALL_DATA) mxml.h $(BUILDROOT)$(includedir)
+	echo Installing pkgconfig files in $(BUILDROOT)$(libdir)/pkgconfig...
+	$(INSTALL_DIR) $(BUILDROOT)$(libdir)/pkgconfig
+	$(INSTALL_DATA) mxml.pc $(BUILDROOT)$(libdir)/pkgconfig
+	echo Installing man pages in $(BUILDROOT)$(mandir)...
+	$(INSTALL_DIR) $(BUILDROOT)$(mandir)/man3
+	$(INSTALL_MAN) doc/mxml.3 $(BUILDROOT)$(mandir)/man3/mxml.3
+
+install-libmxml.a:	libmxml.a
+	echo Installing libmxml.a to $(BUILDROOT)$(libdir)...
+	$(INSTALL_DIR) $(BUILDROOT)$(libdir)
+	$(INSTALL_LIB) libmxml.a $(BUILDROOT)$(libdir)
+	$(RANLIB) $(BUILDROOT)$(libdir)/libmxml.a
+
+install-libmxml.so.1.6:	libmxml.so.1.6
+	echo Installing libmxml.so to $(BUILDROOT)$(libdir)...
+	$(INSTALL_DIR) $(BUILDROOT)$(libdir)
+	$(INSTALL_LIB) libmxml.so.1.6 $(BUILDROOT)$(libdir)
+	$(RM) $(BUILDROOT)$(libdir)/libmxml.so
+	$(LN) libmxml.so.1.6 $(BUILDROOT)$(libdir)/libmxml.so
+	$(RM) $(BUILDROOT)$(libdir)/libmxml.so.1
+	$(LN) libmxml.so.1.6 $(BUILDROOT)$(libdir)/libmxml.so.1
+
+install-libmxml.1.dylib: libmxml.1.dylib
+	echo Installing libmxml.dylib to $(BUILDROOT)$(libdir)...
+	$(INSTALL_DIR) $(BUILDROOT)$(libdir)
+	$(INSTALL_LIB) libmxml.1.dylib $(BUILDROOT)$(libdir)
+	$(RM) $(BUILDROOT)$(libdir)/libmxml.dylib
+	$(LN) libmxml.1.dylib $(BUILDROOT)$(libdir)/libmxml.dylib
+
+
+#
+# Uninstall everything...
+#
+
+uninstall: uninstall-$(LIBMXML) uninstall-libmxml.a
+	echo Uninstalling documentation from $(BUILDROOT)$(docdir)...
+	$(RM) -r $(BUILDROOT)$(docdir)
+	echo Uninstalling headers from $(BUILDROOT)$(includedir)...
+	$(RM) $(BUILDROOT)$(includedir)/mxml.h
+	echo Uninstalling pkgconfig files from $(BUILDROOT)$(libdir)/pkgconfig...
+	$(RM) $(BUILDROOT)$(libdir)/pkgconfig/mxml.pc
+	echo Uninstalling man pages from $(BUILDROOT)$(mandir)...
+	$(RM) $(BUILDROOT)$(mandir)/man3/mxml.3
+
+uninstall-libmxml.a:
+	echo Uninstalling libmxml.a from $(BUILDROOT)$(libdir)...
+	$(RM) $(BUILDROOT)$(libdir)/libmxml.a
+
+uninstall-libmxml.so.1.6:
+	echo Uninstalling libmxml.so from $(BUILDROOT)$(libdir)...
+	$(RM) $(BUILDROOT)$(libdir)/libmxml.so
+	$(RM) $(BUILDROOT)$(libdir)/libmxml.so.1
+	$(RM) $(BUILDROOT)$(libdir)/libmxml.so.1.4
+
+uninstall-libmxml.1.dylib:
+	echo Uninstalling libmxml.dylib from $(BUILDROOT)$(libdir)...
+	$(RM) $(BUILDROOT)$(libdir)/libmxml.dylib
+	$(RM) $(BUILDROOT)$(libdir)/libmxml.1.dylib
+
+
+#
+# Figure out lines-of-code...
+#
+
+.PHONY: sloc
+
+sloc:
+	echo "libmxml: \c"
+	sloccount $(LIBOBJS:.o=.c) mxml-private.c mxml.h 2>/dev/null | \
+		grep "Total Physical" | awk '{print $$9}'
+
+
+#
+# libmxml.a
+#
+
+libmxml.a:	$(LIBOBJS)
+	echo Creating $@...
+	$(RM) $@
+	$(AR) $(ARFLAGS) $@ $(LIBOBJS)
+	$(RANLIB) $@
+
+$(LIBOBJS):	mxml.h
+mxml-entity.o mxml-file.o mxml-private.o: mxml-private.h
+
+
+#
+# mxml1.dll
+#
+
+mxml1.dll:	$(LIBOBJS)
+	echo Creating $@...
+	$(DSO) $(DSOFLAGS) $(LDFLAGS) -o $@ $(LIBOBJS) $(LIBS)
+
+
+#
+# libmxml.so.1.6
+#
+
+libmxml.so.1.6:	$(LIBOBJS)
+	echo Creating $@...
+	$(DSO) $(DSOFLAGS) $(LDFLAGS) -o libmxml.so.1.6 $(LIBOBJS) $(LIBS)
+	$(RM) libmxml.so libmxml.so.1
+	$(LN) libmxml.so.1.6 libmxml.so
+	$(LN) libmxml.so.1.6 libmxml.so.1
+
+
+#
+# libmxml.1.dylib
+#
+
+libmxml.1.dylib:	$(LIBOBJS)
+	echo Creating $@...
+	$(DSO) $(DSOFLAGS) $(LDFLAGS) -o libmxml.1.dylib \
+		-install_name $(libdir)/libmxml.dylib \
+		-current_version 1.6.0 \
+		-compatibility_version 1.0.0 \
+		$(LIBOBJS) $(LIBS)
+	$(RM) libmxml.dylib
+	$(LN) libmxml.1.dylib libmxml.dylib
+
+
+#
+# testmxml
+#
+
+testmxml:	libmxml.a testmxml.o
+	echo Linking $@...
+	$(CC) $(LDFLAGS) -o $@ testmxml.o libmxml.a $(LIBS)
+	@echo Testing library...
+	./testmxml test.xml temp1s.xml >temp1.xml
+	./testmxml temp1.xml temp2s.xml >temp2.xml
+	@if cmp temp1.xml temp2.xml; then \
+		echo Stdio file test passed!; \
+		$(RM) temp2.xml temp2s.xml; \
+	else \
+		echo Stdio file test failed!; \
+	fi
+	@if cmp temp1.xml temp1s.xml; then \
+		echo String test passed!; \
+		$(RM) temp1.xml temp1s.xml; \
+	else \
+		echo String test failed!; \
+	fi
+	@if cmp test.xml test.xmlfd; then \
+		echo File descriptor test passed!; \
+		$(RM) test.xmlfd; \
+	else \
+		echo File descriptor test failed!; \
+	fi
+
+testmxml-vg:	$(LIBOBJS) testmxml.o
+	echo Linking $@...
+	$(CC) $(LDFLAGS) -o $@ testmxml.o $(LIBOBJS) $(LIBS)
+
+testmxml.o:	mxml.h
+
+
+#
+# Documentation (depends on separate codedoc utility)
+#
+
+.PHONY: doc
+doc:	mxml.h $(PUBLIBOBJS:.o=.c) \
+		doc/body.md doc/body.man doc/footer.man \
+		doc/mxml-cover.png
+	echo Generating API documentation...
+	$(RM) mxml.xml
+	codedoc --body doc/body.md \
+		--coverimage doc/mxml-cover.png \
+		mxml.xml mxml.h $(PUBLIBOBJS:.o=.c) >doc/mxml.html
+	codedoc --body doc/body.md \
+		--coverimage doc/mxml-cover.png \
+		--epub doc/mxml.epub mxml.xml
+	codedoc --man mxml --title "Mini-XML API" \
+		--body doc/body.man --footer doc/footer.man \
+		mxml.xml >doc/mxml.3
+	$(RM) mxml.xml
+
+
+#
+# All object files depend on the makefile and config header...
+#
+
+$(OBJS):	Makefile config.h

+ 16 - 0
mxml.mod/mxml/NOTICE

@@ -0,0 +1,16 @@
+Mini-XML
+
+Copyright © 2003-2019 by Michael R Sweet
+
+
+Exceptions to the Apache 2.0 License:
+=====================================
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 or LGPLv2 (“Combined Software”) and if
+a court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2 or LGPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of the
+License, but only in their entirety and only with respect to the Combined
+Software.

+ 191 - 0
mxml.mod/mxml/README.md

@@ -0,0 +1,191 @@
+# Mini-XML Version 3.0
+
+Mini-XML is a small XML parsing library that you can use to read XML data files
+or strings in your application without requiring large non-standard libraries.
+Mini-XML only requires a "make" program and an ANSI C compatible compiler - GCC
+works, as do most vendors' ANSI C compilers.
+
+Mini-XML provides the following functionality:
+
+- Reading of UTF-8 and UTF-16 and writing of UTF-8 encoded XML files and
+  strings.
+- Data is stored in a linked-list tree structure, preserving the XML data
+  hierarchy.
+- SAX (streamed) reading of XML files and strings to minimize memory usage.
+- Supports arbitrary element names, attributes, and attribute values with no
+  preset limits, just available memory.
+- Supports integer, real, opaque ("cdata"), and text data types in "leaf" nodes.
+- Functions for creating and managing trees of data.
+- "Find" and "walk" functions for easily locating and navigating trees of data.
+
+Mini-XML doesn't do validation or other types of processing on the data
+based upon schema files or other sources of definition information.
+
+
+## Building Mini-XML
+
+Mini-XML comes with an autoconf-based configure script; just type the
+following command to get things going:
+
+    ./configure
+
+The default install prefix is `/usr/local`, which can be overridden using the
+`--prefix` option:
+
+    ./configure --prefix=/foo
+
+Other configure options can be found using the `--help` option:
+
+    ./configure --help
+
+Once you have configured the software, type `make` to do the build and run
+the test program to verify that things are working, as follows:
+
+    make
+
+If you are using Mini-XML under Microsoft Windows with Visual C++, use the
+included project files in the `vcnet` subdirectory to build the library
+instead.  Note: The static library on Windows is NOT thread-safe.
+
+
+## Installing Mini-XML
+
+The `install` target will install Mini-XML in the lib and include
+directories:
+
+    make install
+
+Once you have installed it, use the `-lmxml` option to link your application
+against it.
+
+
+## Documentation
+
+The documentation is available in the `doc` subdirectory in the files
+`mxml.html` (HTML) and `mxml.pdf` (PDF). You can also look at the
+`testmxml.c` and `mxmldoc.c` source files for examples of using Mini-XML.
+
+Mini-XML provides a single header file which you include:
+
+    #include <mxml.h>
+
+Nodes are defined by the `mxml_node_t` structure; the `type` member defines the
+node type (`element`, `integer`, `opaque`, `real`, or `text`) which determines
+which value you want to look at in the `value` union.  New nodes can be created
+using the `mxmlNewElement()`, `mxmlNewInteger()`, `mxmlNewOpaque()`,
+`mxmlNewReal()`, and `mxmlNewText()` functions.  Only elements can have child
+nodes, and the top node must be an element, usually "?xml".
+
+You load an XML file using the `mxmlLoadFile()` function:
+
+    FILE *fp;
+    mxml_node_t *tree;
+
+    fp = fopen("filename.xml", "r");
+    tree = mxmlLoadFile(NULL, fp, MXML_OPAQUE_CALLBACK);
+    fclose(fp);
+
+Similarly, you save an XML file using the `mxmlSaveFile()` function:
+
+    FILE *fp;
+    mxml_node_t *tree;
+
+    fp = fopen("filename.xml", "w");
+    mxmlSaveFile(tree, fp, MXML_NO_CALLBACK);
+    fclose(fp);
+
+The `mxmlLoadString()`, `mxmlSaveAllocString()`, and `mxmlSaveString()`
+functions load XML node trees from and save XML node trees to strings:
+
+    char buffer[8192];
+    char *ptr;
+    mxml_node_t *tree;
+
+    ...
+    tree = mxmlLoadString(NULL, buffer, MXML_OPAQUE_CALLBACK);
+
+    ...
+    mxmlSaveString(tree, buffer, sizeof(buffer), MXML_NO_CALLBACK);
+
+    ...
+    ptr = mxmlSaveAllocString(tree, MXML_NO_CALLBACK);
+
+You can find a named element/node using the `mxmlFindElement()` function:
+
+    mxml_node_t *node = mxmlFindElement(tree, tree, "name", "attr",
+					"value", MXML_DESCEND);
+
+The `name`, `attr`, and `value` arguments can be passed as `NULL` to act as
+wildcards, e.g.:
+
+    /* Find the first "a" element */
+    node = mxmlFindElement(tree, tree, "a", NULL, NULL, MXML_DESCEND);
+
+    /* Find the first "a" element with "href" attribute */
+    node = mxmlFindElement(tree, tree, "a", "href", NULL, MXML_DESCEND);
+
+    /* Find the first "a" element with "href" to a URL */
+    node = mxmlFindElement(tree, tree, "a", "href",
+			   "http://www.minixml.org/",
+			   MXML_DESCEND);
+
+    /* Find the first element with a "src" attribute*/
+    node = mxmlFindElement(tree, tree, NULL, "src", NULL, MXML_DESCEND);
+
+    /* Find the first element with a "src" = "foo.jpg" */
+    node = mxmlFindElement(tree, tree, NULL, "src", "foo.jpg",
+			   MXML_DESCEND);
+
+You can also iterate with the same function:
+
+    mxml_node_t *node;
+
+    for (node = mxmlFindElement(tree, tree, "name", NULL, NULL,
+				MXML_DESCEND);
+	 node != NULL;
+	 node = mxmlFindElement(node, tree, "name", NULL, NULL,
+				MXML_DESCEND))
+    {
+      ... do something ...
+    }
+
+The `mxmlFindPath()` function finds the (first) value node under a specific
+element using an XPath:
+
+    mxml_node_t *value = mxmlFindPath(tree, "path/to/*/foo/bar");
+
+The `mxmlGetInteger()`, `mxmlGetOpaque()`, `mxmlGetReal()`, and
+`mxmlGetText()` functions retrieve the value from a node:
+
+    mxml_node_t *node;
+
+    int intvalue = mxmlGetInteger(node);
+
+    const char *opaquevalue = mxmlGetOpaque(node);
+
+    double realvalue = mxmlGetReal(node);
+
+    int whitespacevalue;
+    const char *textvalue = mxmlGetText(node, &whitespacevalue);
+
+Finally, once you are done with the XML data, use the `mxmlDelete()`
+function to recursively free the memory that is used for a particular node
+or the entire tree:
+
+    mxmlDelete(tree);
+
+
+## Getting Help And Reporting Problems
+
+The Mini-XML project page provides access to the Github issue tracking page:
+
+    https://www.msweet.org/mxml
+
+
+## Legal Stuff
+
+Copyright © 2003-2019 by Michael R Sweet
+
+The Mini-XML library is licensed under the Apache License Version 2.0 with an
+exception to allow linking against GPL2/LGPL2-only software.  See the files
+"LICENSE" and "NOTICE" for more information.

+ 1568 - 0
mxml.mod/mxml/config.guess

@@ -0,0 +1,1568 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright 1992-2013 Free Software Foundation, Inc.
+
+timestamp='2013-11-29'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+#
+# Please send patches with a ChangeLog entry to [email protected].
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <[email protected]>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2013 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# ([email protected] 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	LIBC=gnu
+
+	eval $set_cc_for_build
+	cat <<-EOF > $dummy.c
+	#include <features.h>
+	#if defined(__UCLIBC__)
+	LIBC=uclibc
+	#elif defined(__dietlibc__)
+	LIBC=dietlibc
+	#else
+	LIBC=gnu
+	#endif
+	EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+	;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep -q __ELF__
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+		os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+	echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm*:riscos:*:*|arm*:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# [email protected] (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    s390x:SunOS:*:*)
+	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux${UNAME_RELEASE}
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	eval $set_cc_for_build
+	SUN_ARCH="i386"
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH="x86_64"
+	    fi
+	fi
+	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[4567])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH="hppa2.0n" ;;
+			  64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+			esac ;;
+		    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^		//' << EOF >$dummy.c
+
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
+
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
+
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep -q __LP64__
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+	exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+	exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+	exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+	exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    5000:UNIX_System_V:4.*:*)
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case ${UNAME_PROCESSOR} in
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW64*:*)
+	echo ${UNAME_MACHINE}-pc-mingw64
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:MSYS*:*)
+	echo ${UNAME_MACHINE}-pc-msys
+	exit ;;
+    i*:windows32*:*)
+	# uname -m includes "-pc" on this system.
+	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:*)
+	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    authenticamd | genuineintel | EM64T)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    8664:Windows_NT:*)
+	echo x86_64-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    aarch64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    aarch64_be:Linux:*:*)
+	UNAME_MACHINE=aarch64_be
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arc:Linux:*:* | arceb:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	else
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+	    fi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    cris:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	exit ;;
+    crisv32:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	exit ;;
+    frv:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    hexagon:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:Linux:*:*)
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef ${UNAME_MACHINE}
+	#undef ${UNAME_MACHINE}el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=${UNAME_MACHINE}el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=${UNAME_MACHINE}
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+	;;
+    or1k:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    or32:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-${LIBC}
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-${LIBC}
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+	  *)    echo hppa-unknown-linux-${LIBC} ;;
+	esac
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-${LIBC}
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-${LIBC}
+	exit ;;
+    ppc64le:Linux:*:*)
+	echo powerpc64le-unknown-linux-${LIBC}
+	exit ;;
+    ppcle:Linux:*:*)
+	echo powerpcle-unknown-linux-${LIBC}
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+	exit ;;
+    sh64*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+	exit ;;
+    x86_64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    xtensa*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+	# Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configury will decide that
+	# this is a cross-build.
+	echo i586-pc-msdosdjgpp
+	exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <[email protected]>
+	echo i586-unisys-sysv4
+	exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <[email protected]>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From [email protected].
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From [email protected].
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From [email protected].
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+		echo mips-nec-sysv${UNAME_RELEASE}
+	else
+		echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+	exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
+    x86_64:Haiku:*:*)
+	echo x86_64-unknown-haiku
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	eval $set_cc_for_build
+	if test "$UNAME_PROCESSOR" = unknown ; then
+	    UNAME_PROCESSOR=powerpc
+	fi
+	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		    grep IS_64BIT_ARCH >/dev/null
+		then
+		    case $UNAME_PROCESSOR in
+			i386) UNAME_PROCESSOR=x86_64 ;;
+			powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		    esac
+		fi
+	    fi
+	elif test "$UNAME_PROCESSOR" = i386 ; then
+	    # Avoid executing cc on OS X 10.9, as it ships with a stub
+	    # that puts up a graphical alert prompting to install
+	    # developer tools.  Any system running Mac OS X 10.7 or
+	    # later (Darwin 11 and later) is required to have a 64-bit
+	    # processor. This is not true of the ARM version of Darwin
+	    # that Apple uses in portable devices.
+	    UNAME_PROCESSOR=x86_64
+	fi
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NEO-?:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSE-*:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+	echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+    i*86:AROS:*:*)
+	echo ${UNAME_MACHINE}-pc-aros
+	exit ;;
+    x86_64:VMkernel:*:*)
+	echo ${UNAME_MACHINE}-unknown-esx
+	exit ;;
+esac
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+	"4"
+#else
+	""
+#endif
+	); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    c34*)
+	echo c34-convex-bsd
+	exit ;;
+    c38*)
+	echo c38-convex-bsd
+	exit ;;
+    c4*)
+	echo c4-convex-bsd
+	exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <[email protected]> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:

+ 102 - 0
mxml.mod/mxml/config.h

@@ -0,0 +1,102 @@
+/*
+ * Configuration file for Mini-XML, a small XML file parsing library.
+ *
+ * Copyright 2003-2019 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:
+ *
+ *     https://michaelrsweet.github.io/mxml
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+
+/*
+ * Version number...
+ */
+
+#define MXML_VERSION	"3.0"
+
+
+/*
+ * Inline function support...
+ */
+
+#define inline
+
+
+/*
+ * Long long support...
+ */
+
+#define HAVE_LONG_LONG 1
+
+
+/*
+ * Do we have the *printf() functions?
+ */
+
+#undef HAVE_SNPRINTF
+#undef HAVE_VASPRINTF
+#undef HAVE_VSNPRINTF
+
+
+/*
+ * Do we have the strXXX() functions?
+ */
+
+#undef HAVE_STRDUP
+#undef HAVE_STRLCAT
+#undef HAVE_STRLCPY
+
+
+/*
+ * 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 */
+
+#  ifndef HAVE_STRLCAT
+extern size_t	_mxml_strlcat(char *, const char *, size_t);
+#    define strlcat _mxml_strlcat
+#  endif /* !HAVE_STRLCAT */
+
+#  ifndef HAVE_STRLCPY
+extern size_t	_mxml_strlcpy(char *, const char *, size_t);
+#    define strlcpy _mxml_strlcpy
+#  endif /* !HAVE_STRLCPY */
+
+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 */

+ 99 - 0
mxml.mod/mxml/config.h.in

@@ -0,0 +1,99 @@
+/*
+ * Configuration file for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * 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 *printf() functions?
+ */
+
+#undef HAVE_SNPRINTF
+#undef HAVE_VASPRINTF
+#undef HAVE_VSNPRINTF
+
+
+/*
+ * Do we have the strXXX() functions?
+ */
+
+#undef HAVE_STRDUP
+#undef HAVE_STRLCAT
+#undef HAVE_STRLCPY
+
+
+/*
+ * 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 */
+
+#  ifndef HAVE_STRLCAT
+extern size_t	_mxml_strlcat(char *, const char *, size_t);
+#    define strlcat _mxml_strlcat
+#  endif /* !HAVE_STRLCAT */
+
+#  ifndef HAVE_STRLCPY
+extern size_t	_mxml_strlcpy(char *, const char *, size_t);
+#    define strlcpy _mxml_strlcpy
+#  endif /* !HAVE_STRLCPY */
+
+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 */

+ 1793 - 0
mxml.mod/mxml/config.sub

@@ -0,0 +1,1793 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright 1992-2013 Free Software Foundation, Inc.
+
+timestamp='2013-10-01'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches with a ChangeLog entry to [email protected].
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <[email protected]>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2013 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  android-linux)
+    os=-linux-android
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray | -microblaze*)
+		os=
+		basic_machine=$1
+		;;
+	-bluegene*)
+		os=-cnk
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+	-chorusrdb)
+		os=-chorusrdb
+		basic_machine=$1
+		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*178)
+		os=-lynxos178
+		;;
+	-lynx*5)
+		os=-lynxos5
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| aarch64 | aarch64_be \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arceb \
+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+	| avr | avr32 \
+	| be32 | be64 \
+	| bfin \
+	| c4x | c8051 | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| epiphany \
+	| fido | fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| hexagon \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| k1om \
+	| le32 | le64 \
+	| lm32 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64octeon | mips64octeonel \
+	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipsr5900 | mipsr5900el \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| moxie \
+	| mt \
+	| msp430 \
+	| nds32 | nds32le | nds32be \
+	| nios | nios2 | nios2eb | nios2el \
+	| ns16k | ns32k \
+	| open8 \
+	| or1k | or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
+	| pyramid \
+	| rl78 | rx \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| we32k \
+	| x86 | xc16x | xstormy16 | xtensa \
+	| z8k | z80)
+		basic_machine=$basic_machine-unknown
+		;;
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+	xgate)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| aarch64-* | aarch64_be-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| be32-* | be64-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
+	| c8051-* | clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| hexagon-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| k1om-* \
+	| le32-* | le64-* \
+	| lm32-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+	| microblaze-* | microblazeel-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64octeon-* | mips64octeonel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipsr5900-* | mipsr5900el-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nds32-* | nds32le-* | nds32be-* \
+	| nios-* | nios2-* | nios2eb-* | nios2el-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+	| pyramid-* \
+	| rl78-* | romp-* | rs6000-* | rx-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+	| tahoe-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tile*-* \
+	| tron-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aros)
+		basic_machine=i386-pc
+		os=-aros
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	bluegene*)
+		basic_machine=powerpc-ibm
+		os=-cnk
+		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16 | cr16-*)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	microblaze*)
+		basic_machine=microblaze-xilinx
+		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
+	mingw32)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	msys)
+		basic_machine=i686-pc
+		os=-msys
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc | ppcbe)	basic_machine=powerpc-unknown
+		;;
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos | rdos64)
+		basic_machine=x86_64-pc
+		os=-rdos
+		;;
+	rdos32)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tile*)
+		basic_machine=$basic_machine-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	z80-*-coff)
+		basic_machine=z80-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+	# First match some system type aliases
+	# that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-auroraux)
+		os=-auroraux
+		;;
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* | -plan9* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* | -aros* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* | -cegcc* \
+	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-dicos*)
+		os=-dicos
+		;;
+	-nacl*)
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	score-*)
+		os=-elf
+		;;
+	spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	c8051-*)
+		os=-elf
+		;;
+	hexagon-*)
+		os=-elf
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or1k-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-cnk*|-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:

+ 5905 - 0
mxml.mod/mxml/configure

@@ -0,0 +1,5905 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for Mini-XML 3.0.
+#
+# Report bugs to <https://github.com/michaelrsweet/mxml/issues>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell [email protected] and
+$0: https://github.com/michaelrsweet/mxml/issues about your
+$0: system, including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='Mini-XML'
+PACKAGE_TARNAME='mxml'
+PACKAGE_VERSION='3.0'
+PACKAGE_STRING='Mini-XML 3.0'
+PACKAGE_BUGREPORT='https://github.com/michaelrsweet/mxml/issues'
+PACKAGE_URL='https://michaelrsweet.github.io/mxml'
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+PC_LIBS
+PC_CFLAGS
+TARGETS
+PICFLAG
+LIBMXML
+DSOFLAGS
+DSO
+PTHREAD_LIBS
+PTHREAD_FLAGS
+EGREP
+GREP
+CPP
+ARFLAGS
+RM
+MKDIR
+LN
+CP
+AR
+RANLIB
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+ac_ct_CXX
+CXXFLAGS
+CXX
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+CFLAGS
+CC
+OPTIM
+ARCHFLAGS
+LDFLAGS
+VERSION
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_ansi
+with_archflags
+with_optim
+enable_debug
+with_docdir
+with_vsnprintf
+enable_threads
+enable_shared
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures Mini-XML 3.0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/mxml]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of Mini-XML 3.0:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-debug          turn on debugging, default=no
+  --enable-threads        enable multi-threading support
+  --enable-shared         turn on shared libraries, default=no
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-ansi             set full ANSI C mode, default=no
+  --with-archflags        set additional architecture flags, default=none
+  --with-optim            set additional optimization flags, default=none
+  --with-docdir           set directory for documentation, default=${prefix}/share/doc/mxml
+  --with-vsnprintf        use vsnprintf emulation functions, default=auto
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <https://github.com/michaelrsweet/mxml/issues>.
+Mini-XML home page: <https://michaelrsweet.github.io/mxml>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+Mini-XML configure 3.0
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## ----------------------------------------------------------- ##
+## Report this to https://github.com/michaelrsweet/mxml/issues ##
+## ----------------------------------------------------------- ##"
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by Mini-XML $as_me 3.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+host_os_name=`echo $host_os | sed -e '1,$s/[0-9.]*$//g'`
+host_os_version=`echo $host_os | sed -e '1,$s/^[^0-9.]*//g'`
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+VERSION="3.0"
+
+cat >>confdefs.h <<_ACEOF
+#define MXML_VERSION "Mini-XML v$VERSION"
+_ACEOF
+
+
+CFLAGS="${CFLAGS:=}"
+CXXFLAGS="${CXXFLAGS:=}"
+LDFLAGS="${LDFLAGS:=}"
+
+
+
+# Check whether --with-ansi was given.
+if test "${with_ansi+set}" = set; then :
+  withval=$with_ansi; use_ansi="$withval"
+else
+  use_ansi="no"
+fi
+
+
+
+# Check whether --with-archflags was given.
+if test "${with_archflags+set}" = set; then :
+  withval=$with_archflags; ARCHFLAGS="$withval"
+else
+  ARCHFLAGS=""
+fi
+
+
+
+
+# Check whether --with-optim was given.
+if test "${with_optim+set}" = set; then :
+  withval=$with_optim; OPTIM="$withval"
+else
+  OPTIM=""
+fi
+
+
+
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then :
+  enableval=$enable_debug; if eval "test x$enable_debug = xyes"; then
+ 	OPTIM="$OPTIM -g"
+fi
+fi
+
+
+
+# Check whether --with-docdir was given.
+if test "${with_docdir+set}" = set; then :
+  withval=$with_docdir; docdir="$withval"
+else
+  docdir="NONE"
+fi
+
+
+
+
+
+# Check whether --with-vsnprintf was given.
+if test "${with_vsnprintf+set}" = set; then :
+  withval=$with_vsnprintf; use_vsnprintf="$withval"
+else
+  use_vsnprintf="no"
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+else
+  CXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+if test "$INSTALL" = "$ac_install_sh"; then
+	# Use full path to install-sh script...
+	INSTALL="`pwd`/install-sh -c"
+fi
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AR="${ac_tool_prefix}ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+  ac_ct_AR=$AR
+  # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_AR="ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_AR" = x; then
+    AR=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+else
+  AR="$ac_cv_prog_AR"
+fi
+
+# Extract the first word of "cp", so it can be a program name with args.
+set dummy cp; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_CP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $CP in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_CP="$CP" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_CP="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+CP=$ac_cv_path_CP
+if test -n "$CP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CP" >&5
+$as_echo "$CP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "ln", so it can be a program name with args.
+set dummy ln; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_LN+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $LN in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LN="$LN" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_LN="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+LN=$ac_cv_path_LN
+if test -n "$LN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LN" >&5
+$as_echo "$LN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "mkdir", so it can be a program name with args.
+set dummy mkdir; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MKDIR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MKDIR in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MKDIR="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MKDIR=$ac_cv_path_MKDIR
+if test -n "$MKDIR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR" >&5
+$as_echo "$MKDIR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "rm", so it can be a program name with args.
+set dummy rm; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_RM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $RM in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_RM="$RM" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+RM=$ac_cv_path_RM
+if test -n "$RM"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RM" >&5
+$as_echo "$RM" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+case "$host_os_name" in
+        darwin* | *bsd)
+                ARFLAGS="-rcv"
+                ;;
+        *)
+                ARFLAGS="crvs"
+                ;;
+esac
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if ${ac_cv_c_inline+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+
+if test "x$use_ansi" != xyes; then
+	for ac_func in strdup strlcat strlcpy
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+fi
+
+if test "x$use_vsnprintf" != xyes; then
+	for ac_func in snprintf vasprintf vsnprintf
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5
+$as_echo_n "checking for long long int... " >&6; }
+if ${ac_cv_c_long_long+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$GCC" = yes; then
+		ac_cv_c_long_long=yes
+	else
+		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+long long int i;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_long_long=yes
+else
+  ac_cv_c_long_long=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+	fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_long_long" >&5
+$as_echo "$ac_cv_c_long_long" >&6; }
+
+if test $ac_cv_c_long_long = yes; then
+	$as_echo "#define HAVE_LONG_LONG 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-threads was given.
+if test "${enable_threads+set}" = set; then :
+  enableval=$enable_threads;
+fi
+
+
+have_pthread=no
+PTHREAD_FLAGS=""
+PTHREAD_LIBS=""
+
+if test "x$enable_threads" != xno; then
+	ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes; then :
+  $as_echo "#define HAVE_PTHREAD_H 1" >>confdefs.h
+
+fi
+
+
+
+	if test x$ac_cv_header_pthread_h = xyes; then
+				for flag in -lpthreads -lpthread -pthread; do
+        		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create using $flag" >&5
+$as_echo_n "checking for pthread_create using $flag... " >&6; }
+			SAVELIBS="$LIBS"
+			LIBS="$flag $LIBS"
+        		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <pthread.h>
+int
+main ()
+{
+pthread_create(0, 0, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  have_pthread=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+        		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_pthread" >&5
+$as_echo "$have_pthread" >&6; }
+			LIBS="$SAVELIBS"
+
+			if test $have_pthread = yes; then
+				PTHREAD_FLAGS="-D_THREAD_SAFE -D_REENTRANT"
+				PTHREAD_LIBS="$flag"
+
+				# Solaris requires -D_POSIX_PTHREAD_SEMANTICS to
+				# be POSIX-compliant... :(
+				case "$host_os_name" in
+					sunos)
+					PTHREAD_FLAGS="$PTHREAD_FLAGS -D_POSIX_PTHREAD_SEMANTICS"
+					;;
+				esac
+				break
+			fi
+		done
+	fi
+fi
+
+
+
+
+DSO="${DSO:=:}"
+DSOFLAGS="${DSOFLAGS:=}"
+
+# Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+  enableval=$enable_shared;
+fi
+
+
+if test x$enable_shared != xno; then
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library support" >&5
+$as_echo_n "checking for shared library support... " >&6; }
+	PICFLAG=1
+
+	case "$host_os_name" in
+		sunos | unix_s)
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			LIBMXML="libmxml.so.1.6"
+			DSO="\$(CC)"
+			DSOFLAGS="$DSOFLAGS -Wl,-h,libmxml.so.1 -G -R\$(libdir) \$(OPTIM)"
+			LDFLAGS="$LDFLAGS -R\$(libdir)"
+                	;;
+
+		linux*)
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			LIBMXML="libmxml.so.1.6"
+			DSO="\$(CC)"
+			DSOFLAGS="$DSOFLAGS -Wl,-soname,libmxml.so.1 -shared \$(OPTIM)"
+			;;
+
+		osf | gnu)
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			LIBMXML="libmxml.so.1.6"
+			DSO="\$(CC)"
+			DSOFLAGS="$DSOFLAGS -Wl,-soname,libmxml.so.1,-rpath,\$(libdir) -shared \$(OPTIM)"
+                        LDFLAGS="$LDFLAGS -Wl,-rpath,\$(libdir)"
+			;;
+
+		*bsd)
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			LIBMXML="libmxml.so.1.6"
+			DSO="\$(CC)"
+			DSOFLAGS="$DSOFLAGS -Wl,-soname,libmxml.so.1,-R\$(libdir) -shared \$(OPTIM)"
+			LDFLAGS="$LDFLAGS -Wl,-R\$(libdir)"
+                        ;;
+
+		darwin)
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			LIBMXML="libmxml.1.dylib"
+			DSO="\$(CC)"
+			DSOFLAGS="$DSOFLAGS \$(RC_CFLAGS) -dynamiclib -lc"
+			;;
+
+                mingw)
+                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                        LIBMXML="mxml1.dll"
+                        DSO="\$(CC)"
+                        DSOFLAGS="$DSOFLAGS -shared -Wl,--out-implib,libmxml1.a,--no-undefined,--enable-runtime-pseudo-reloc"
+                        ;;
+
+		*)
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: shared libraries not supported on this platform." >&5
+$as_echo "$as_me: WARNING: shared libraries not supported on this platform." >&2;}
+			PICFLAG=0
+			LIBMXML="libmxml.a"
+			;;
+	esac
+else
+	PICFLAG=0
+	LIBMXML="libmxml.a"
+fi
+
+
+
+
+
+
+if test -n "$GCC"; then
+	CFLAGS="-Wall -D_GNU_SOURCE $CFLAGS"
+
+	if test "x$OPTIM" = x; then
+		OPTIM="-Os -g"
+	fi
+
+	if test "x$use_ansi" = xyes; then
+		CFLAGS="-ansi -pedantic $CFLAGS"
+	fi
+
+	if test $PICFLAG = 1 -a "$host_os_name" != aix; then
+    		OPTIM="-fPIC $OPTIM"
+	fi
+else
+	case "$host_os_name" in
+		hp-ux)
+			CFLAGS="-Ae $CFLAGS"
+
+			if test "x$OPTIM" = x; then
+				OPTIM="-O"
+			fi
+
+			OPTIM="+DAportable $OPTIM"
+
+			if test $PICFLAG = 1; then
+				OPTIM="+z $OPTIM"
+			fi
+			;;
+
+		unix_svr | sunos)
+			if test "x$OPTIM" = x; then
+				OPTIM="-O"
+			fi
+
+			if test $PICFLAG = 1; then
+				OPTIM="-KPIC $OPTIM"
+			fi
+			;;
+
+		*)
+			if test "x$OPTIM" = x; then
+				OPTIM="-O"
+			fi
+			;;
+	esac
+fi
+
+if test "$build" = "$host"; then
+	TARGETS="ALLTARGETS"
+else
+	TARGETS="CROSSTARGETS"
+fi
+
+
+if test "$prefix" = "NONE"; then
+	prefix="/usr/local"
+fi
+
+if test "$exec_prefix" = "NONE"; then
+	exec_prefix="$prefix"
+fi
+
+if test "$docdir" = "NONE"; then
+	docdir="$datadir/doc/mxml"
+fi
+
+if test "$mandir" = "\${prefix}/man" -a "$prefix" = "/usr"; then
+	case "$host_os_name" in
+        	*bsd | darwin | linux*)
+        		# *BSD, Darwin (macOS), and Linux
+        		mandir="/usr/share/man"
+        		;;
+        	irix)
+        		# SGI IRIX
+        		mandir="/usr/share/catman/u_man"
+        		;;
+        	*)
+        		# All others
+        		mandir="/usr/man"
+        		;;
+	esac
+fi
+
+if test "$includedir" != /usr/include; then
+	PC_CFLAGS="-I$includedir"
+else
+	PC_CFLAGS=""
+fi
+
+if test "$libdir" != /usr/lib; then
+	PC_LIBS="-L$libdir -lmxml"
+else
+	PC_LIBS="-lmxml"
+fi
+
+
+
+
+ac_config_files="$ac_config_files Makefile mxml.pc"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by Mini-XML $as_me 3.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <https://github.com/michaelrsweet/mxml/issues>.
+Mini-XML home page: <https://michaelrsweet.github.io/mxml>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+Mini-XML config.status 3.0
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "mxml.pc") CONFIG_FILES="$CONFIG_FILES mxml.pc" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+ ;;
+
+
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+

+ 346 - 0
mxml.mod/mxml/configure.ac

@@ -0,0 +1,346 @@
+dnl
+dnl Configuration script for Mini-XML, a small XML-like file parsing library.
+dnl
+dnl https://www.msweet.org/mxml
+dnl
+dnl Copyright © 2003-2019 by Michael R Sweet.
+dnl
+dnl Licensed under Apache License v2.0.  See the file "LICENSE" for more
+dnl information.
+dnl
+
+dnl Package name and version...
+AC_INIT([Mini-XML], [3.0], [https://github.com/michaelrsweet/mxml/issues], [mxml], [https://michaelrsweet.github.io/mxml])
+
+dnl This line is provided to ensure that you don't run the autoheader program
+dnl against this project.  Doing so is completely unsupported and WILL cause
+dnl problems!
+AH_TOP([#error "Somebody ran autoheader on this project which is unsupported and WILL cause problems."])
+
+dnl Get the build and host platforms and split the host_os value
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+
+[host_os_name=`echo $host_os | sed -e '1,$s/[0-9.]*$//g'`]
+[host_os_version=`echo $host_os | sed -e '1,$s/^[^0-9.]*//g'`]
+
+dnl Set the name of the config header file...
+AC_CONFIG_HEADER(config.h)
+
+dnl Version number...
+VERSION="AC_PACKAGE_VERSION"
+AC_SUBST(VERSION)
+AC_DEFINE_UNQUOTED(MXML_VERSION, "Mini-XML v$VERSION")
+
+dnl Clear default debugging options and set normal optimization by
+dnl default unless the user asks for debugging specifically.
+CFLAGS="${CFLAGS:=}"
+CXXFLAGS="${CXXFLAGS:=}"
+LDFLAGS="${LDFLAGS:=}"
+AC_SUBST(LDFLAGS)
+
+AC_ARG_WITH(ansi, [  --with-ansi             set full ANSI C mode, default=no],
+	use_ansi="$withval",
+	use_ansi="no")
+
+AC_ARG_WITH(archflags, [  --with-archflags        set additional architecture flags, default=none],
+	ARCHFLAGS="$withval",
+	ARCHFLAGS="")
+AC_SUBST(ARCHFLAGS)
+
+AC_ARG_WITH(optim,   [  --with-optim            set additional optimization flags, default=none],
+	OPTIM="$withval",
+	OPTIM="")
+AC_SUBST(OPTIM)
+
+AC_ARG_ENABLE(debug, [  --enable-debug          turn on debugging, default=no],
+if eval "test x$enable_debug = xyes"; then
+ 	OPTIM="$OPTIM -g"
+fi)
+
+AC_ARG_WITH(docdir, [  --with-docdir           set directory for documentation, default=${prefix}/share/doc/mxml],
+	docdir="$withval",
+	docdir="NONE")
+
+AC_SUBST(docdir)
+
+AC_ARG_WITH(vsnprintf, [  --with-vsnprintf        use vsnprintf emulation functions, default=auto],
+	use_vsnprintf="$withval",
+	use_vsnprintf="no")
+
+dnl Checks for programs...
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_INSTALL
+if test "$INSTALL" = "$ac_install_sh"; then
+	# Use full path to install-sh script...
+	INSTALL="`pwd`/install-sh -c"
+fi
+AC_PROG_RANLIB
+AC_CHECK_TOOL(AR,ar)
+AC_PATH_PROG(CP,cp)
+AC_PATH_PROG(LN,ln)
+AC_PATH_PROG(MKDIR,mkdir)
+AC_PATH_PROG(RM,rm)
+
+dnl Flags for "ar" command...
+case "$host_os_name" in
+        darwin* | *bsd)
+                ARFLAGS="-rcv"
+                ;;
+        *)
+                ARFLAGS="crvs"
+                ;;
+esac
+
+AC_SUBST(ARFLAGS)
+
+dnl Inline functions...
+AC_C_INLINE
+
+dnl Checks for string functions.
+if test "x$use_ansi" != xyes; then
+	AC_CHECK_FUNCS(strdup strlcat strlcpy)
+fi
+
+if test "x$use_vsnprintf" != xyes; then
+	AC_CHECK_FUNCS(snprintf vasprintf vsnprintf)
+fi
+
+dnl Check for "long long" support...
+AC_CACHE_CHECK(for long long int, ac_cv_c_long_long,
+	[if test "$GCC" = yes; then
+		ac_cv_c_long_long=yes
+	else
+		AC_TRY_COMPILE(,[long long int i;],
+			ac_cv_c_long_long=yes,
+			ac_cv_c_long_long=no)
+	fi])
+
+if test $ac_cv_c_long_long = yes; then
+	AC_DEFINE(HAVE_LONG_LONG)
+fi
+
+dnl Threading support
+AC_ARG_ENABLE(threads, [  --enable-threads        enable multi-threading support])
+
+have_pthread=no
+PTHREAD_FLAGS=""
+PTHREAD_LIBS=""
+
+if test "x$enable_threads" != xno; then
+	AC_CHECK_HEADER(pthread.h, AC_DEFINE(HAVE_PTHREAD_H))
+
+	if test x$ac_cv_header_pthread_h = xyes; then
+		dnl Check various threading options for the platforms we support
+		for flag in -lpthreads -lpthread -pthread; do
+        		AC_MSG_CHECKING([for pthread_create using $flag])
+			SAVELIBS="$LIBS"
+			LIBS="$flag $LIBS"
+        		AC_TRY_LINK([#include <pthread.h>],
+				[pthread_create(0, 0, 0, 0);],
+        			have_pthread=yes)
+        		AC_MSG_RESULT([$have_pthread])
+			LIBS="$SAVELIBS"
+
+			if test $have_pthread = yes; then
+				PTHREAD_FLAGS="-D_THREAD_SAFE -D_REENTRANT"
+				PTHREAD_LIBS="$flag"
+
+				# Solaris requires -D_POSIX_PTHREAD_SEMANTICS to
+				# be POSIX-compliant... :(
+				case "$host_os_name" in
+					sunos)
+					PTHREAD_FLAGS="$PTHREAD_FLAGS -D_POSIX_PTHREAD_SEMANTICS"
+					;;
+				esac
+				break
+			fi
+		done
+	fi
+fi
+
+AC_SUBST(PTHREAD_FLAGS)
+AC_SUBST(PTHREAD_LIBS)
+
+dnl Shared library support...
+DSO="${DSO:=:}"
+DSOFLAGS="${DSOFLAGS:=}"
+
+AC_ARG_ENABLE(shared, [  --enable-shared         turn on shared libraries, default=no])
+
+if test x$enable_shared != xno; then
+	AC_MSG_CHECKING(for shared library support)
+	PICFLAG=1
+
+	case "$host_os_name" in
+		sunos | unix_s)
+			AC_MSG_RESULT(yes)
+			LIBMXML="libmxml.so.1.6"
+			DSO="\$(CC)"
+			DSOFLAGS="$DSOFLAGS -Wl,-h,libmxml.so.1 -G -R\$(libdir) \$(OPTIM)"
+			LDFLAGS="$LDFLAGS -R\$(libdir)"
+                	;;
+
+		linux*)
+			AC_MSG_RESULT(yes)
+			LIBMXML="libmxml.so.1.6"
+			DSO="\$(CC)"
+			DSOFLAGS="$DSOFLAGS -Wl,-soname,libmxml.so.1 -shared \$(OPTIM)"
+			;;
+
+		osf | gnu)
+			AC_MSG_RESULT(yes)
+			LIBMXML="libmxml.so.1.6"
+			DSO="\$(CC)"
+			DSOFLAGS="$DSOFLAGS -Wl,-soname,libmxml.so.1,-rpath,\$(libdir) -shared \$(OPTIM)"
+                        LDFLAGS="$LDFLAGS -Wl,-rpath,\$(libdir)"
+			;;
+
+		*bsd)
+			AC_MSG_RESULT(yes)
+			LIBMXML="libmxml.so.1.6"
+			DSO="\$(CC)"
+			DSOFLAGS="$DSOFLAGS -Wl,-soname,libmxml.so.1,-R\$(libdir) -shared \$(OPTIM)"
+			LDFLAGS="$LDFLAGS -Wl,-R\$(libdir)"
+                        ;;
+
+		darwin)
+			AC_MSG_RESULT(yes)
+			LIBMXML="libmxml.1.dylib"
+			DSO="\$(CC)"
+			DSOFLAGS="$DSOFLAGS \$(RC_CFLAGS) -dynamiclib -lc"
+			;;
+
+                mingw)
+                        AC_MSG_RESULT(yes)
+                        LIBMXML="mxml1.dll"
+                        DSO="\$(CC)"
+                        DSOFLAGS="$DSOFLAGS -shared -Wl,--out-implib,libmxml1.a,--no-undefined,--enable-runtime-pseudo-reloc"
+                        ;;
+
+		*)
+			AC_MSG_RESULT(no)
+			AC_MSG_WARN(shared libraries not supported on this platform.)
+			PICFLAG=0
+			LIBMXML="libmxml.a"
+			;;
+	esac
+else
+	PICFLAG=0
+	LIBMXML="libmxml.a"
+fi
+
+AC_SUBST(DSO)
+AC_SUBST(DSOFLAGS)
+AC_SUBST(LIBMXML)
+AC_SUBST(PICFLAG)
+
+dnl Add -Wall for GCC...
+if test -n "$GCC"; then
+	CFLAGS="-Wall -D_GNU_SOURCE $CFLAGS"
+
+	if test "x$OPTIM" = x; then
+		OPTIM="-Os -g"
+	fi
+
+	if test "x$use_ansi" = xyes; then
+		CFLAGS="-ansi -pedantic $CFLAGS"
+	fi
+
+	if test $PICFLAG = 1 -a "$host_os_name" != aix; then
+    		OPTIM="-fPIC $OPTIM"
+	fi
+else
+	case "$host_os_name" in
+		hp-ux)
+			CFLAGS="-Ae $CFLAGS"
+
+			if test "x$OPTIM" = x; then
+				OPTIM="-O"
+			fi
+
+			OPTIM="+DAportable $OPTIM"
+
+			if test $PICFLAG = 1; then
+				OPTIM="+z $OPTIM"
+			fi
+			;;
+
+		unix_svr | sunos)
+			if test "x$OPTIM" = x; then
+				OPTIM="-O"
+			fi
+
+			if test $PICFLAG = 1; then
+				OPTIM="-KPIC $OPTIM"
+			fi
+			;;
+
+		*)
+			if test "x$OPTIM" = x; then
+				OPTIM="-O"
+			fi
+			;;
+	esac
+fi
+
+dnl Determine whether we are cross-compiling...
+if test "$build" = "$host"; then
+	TARGETS="ALLTARGETS"
+else
+	TARGETS="CROSSTARGETS"
+fi
+AC_SUBST(TARGETS)
+
+dnl Fix "prefix" variable if it hasn't been specified...
+if test "$prefix" = "NONE"; then
+	prefix="/usr/local"
+fi
+
+dnl Fix "exec_prefix" variable if it hasn't been specified...
+if test "$exec_prefix" = "NONE"; then
+	exec_prefix="$prefix"
+fi
+
+dnl Fix "docdir" variable if it hasn't been specified...
+if test "$docdir" = "NONE"; then
+	docdir="$datadir/doc/mxml"
+fi
+
+dnl Fix "mandir" variable if it hasn't been specified...
+if test "$mandir" = "\${prefix}/man" -a "$prefix" = "/usr"; then
+	case "$host_os_name" in
+        	*bsd | darwin | linux*)
+        		# *BSD, Darwin (macOS), and Linux
+        		mandir="/usr/share/man"
+        		;;
+        	irix)
+        		# SGI IRIX
+        		mandir="/usr/share/catman/u_man"
+        		;;
+        	*)
+        		# All others
+        		mandir="/usr/man"
+        		;;
+	esac
+fi
+
+dnl pkg-config stuff...
+if test "$includedir" != /usr/include; then
+	PC_CFLAGS="-I$includedir"
+else
+	PC_CFLAGS=""
+fi
+
+if test "$libdir" != /usr/lib; then
+	PC_LIBS="-L$libdir -lmxml"
+else
+	PC_LIBS="-lmxml"
+fi
+
+AC_SUBST(PC_CFLAGS)
+AC_SUBST(PC_LIBS)
+
+dnl Output the makefile, etc...
+AC_OUTPUT(Makefile mxml.pc)

+ 173 - 0
mxml.mod/mxml/doc/body.man

@@ -0,0 +1,173 @@
+.SH INCLUDE FILE
+#include <mxml.h>
+.SH LIBRARY
+\-lmxml
+.SH DESCRIPTION
+Mini-XML is a small XML parsing library that you can use to
+read XML and XML-like data files in your application without
+requiring large non-standard libraries.  Mini-XML only
+requires an ANSI C compatible compiler (GCC works, as do
+most vendors' ANSI C compilers) and a "make" program.
+.PP
+Mini-XML provides the following functionality:
+.IP \(bu 4
+Reading of UTF-8 and UTF-16 and writing of UTF-8 encoded XML files and strings.
+.IP \(bu 4
+Data is stored in a linked-list tree structure,
+preserving the XML data hierarchy.
+.IP \(bu 4
+Supports arbitrary element names, attributes, and attribute
+values with no preset limits, just available memory.
+.IP \(bu 4
+Supports integer, real, opaque ("CDATA"), and text data types in
+"leaf" nodes.
+.IP \(bu 4
+Functions for creating, indexing, and managing trees of data.
+.IP \(bu 4
+"Find" and "walk" functions for easily locating and navigating
+trees of data.
+.PP
+Mini-XML doesn't do validation or other types of processing
+on the data based upon schema files or other sources of
+definition information, nor does it support character
+entities other than those required by the XML
+specification.
+.SH USING MINI-XML
+Mini-XML provides a single header file which you include:
+.nf
+
+    #include <mxml.h>
+.fi
+.PP
+Nodes are defined by the "mxml_node_t" structure; the "type"
+member defines the node type (element, integer, opaque,
+real, or text) which determines which value you want to look
+at in the "value" union.  New nodes can be created using the
+"mxmlNewElement()", "mxmlNewInteger()", "mxmlNewOpaque()",
+"mxmlNewReal()", and "mxmlNewText()" functions.  Only
+elements can have child nodes, and the top node must be an
+element, usually "?xml".
+.PP
+You load an XML file using the "mxmlLoadFile()" function:
+.nf
+
+    FILE *fp;
+    mxml_node_t *tree;
+
+    fp = fopen("filename.xml", "r");
+    tree = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK);
+    fclose(fp);
+.fi
+.PP
+Similarly, you save an XML file using the "mxmlSaveFile()"
+function:
+.nf
+
+    FILE *fp;
+    mxml_node_t *tree;
+
+    fp = fopen("filename.xml", "w");
+    mxmlSaveFile(tree, fp, MXML_NO_CALLBACK);
+    fclose(fp);
+.fi
+.PP
+The "mxmlLoadString()", "mxmlSaveAllocString()", and
+"mxmlSaveString()" functions load XML node trees from and save
+XML node trees to strings:
+.nf
+
+    char buffer[8192];
+    char *ptr;
+    mxml_node_t *tree;
+
+    ...
+    tree = mxmlLoadString(NULL, buffer, MXML_NO_CALLBACK);
+
+    ...
+    mxmlSaveString(tree, buffer, sizeof(buffer),
+                   MXML_NO_CALLBACK);
+
+    ...
+    ptr = mxmlSaveAllocString(tree, MXML_NO_CALLBACK);
+.fi
+.PP
+You can find a named element/node using the "mxmlFindElement()"
+function:
+.nf
+
+    mxml_node_t *node = mxmlFindElement(tree, tree, "name",
+                                        "attr", "value",
+                                        MXML_DESCEND);
+.fi
+.PP
+The "name", "attr", and "value" arguments can be passed as
+NULL to act as wildcards, e.g.:
+.nf
+
+    /* Find the first "a" element */
+    node = mxmlFindElement(tree, tree, "a", NULL, NULL,
+                           MXML_DESCEND);
+
+    /* Find the first "a" element with "href" attribute */
+    node = mxmlFindElement(tree, tree, "a", "href", NULL,
+                           MXML_DESCEND);
+
+    /* Find the first "a" element with "href" to a URL */
+    node = mxmlFindElement(tree, tree, "a", "href",
+                           "http://www.easysw.com/~mike/mxml/",
+                           MXML_DESCEND);
+
+    /* Find the first element with a "src" attribute*/
+    node = mxmlFindElement(tree, tree, NULL, "src", NULL,
+                           MXML_DESCEND);
+
+    /* Find the first element with a "src" = "foo.jpg" */
+    node = mxmlFindElement(tree, tree, NULL, "src",
+                           "foo.jpg", MXML_DESCEND);
+.fi
+.PP
+You can also iterate with the same function:
+.nf
+
+    mxml_node_t *node;
+
+    for (node = mxmlFindElement(tree, tree, "name", NULL,
+                                NULL, MXML_DESCEND);
+         node != NULL;
+         node = mxmlFindElement(node, tree, "name", NULL,
+                                NULL, MXML_DESCEND))
+    {
+      ... do something ...
+    }
+.fi
+.PP
+To find the value of a specific node in the tree, use the "mxmlFindPath()"
+function:
+.nf
+
+    mxml_node_t *value = mxmlFindPath(tree, "path/to/*/foo/bar");
+.fi
+.PP
+The "mxmlGetInteger()", "mxmlGetOpaque()", "mxmlGetReal()", and "mxmlGetText()"
+functions retrieve the value from a node:
+.nf
+
+    mxml_node_t *node;
+
+    int intvalue = mxmlGetInteger(node);
+
+    const char *opaquevalue = mxmlGetOpaque(node);
+
+    double realvalue = mxmlGetReal(node);
+
+    int whitespacevalue;
+    const char *textvalue = mxmlGetText(node, &whitespacevalue);
+.fi
+.PP
+Finally, once you are done with the XML data, use the
+"mxmlDelete()" function to recursively free the memory that
+is used for a particular node or the entire tree:
+.nf
+
+    mxmlDelete(tree);
+.fi

+ 1137 - 0
mxml.mod/mxml/doc/body.md

@@ -0,0 +1,1137 @@
+---
+title: Mini-XML API Reference
+author: Michael R Sweet
+copyright: Copyright © 2003-2019, All Rights Reserved.
+docversion: 3.0
+...
+
+# Introduction
+
+Mini-XML is a small XML parsing library that you can use to read XML data files
+or strings in your application without requiring large non-standard libraries.
+Mini-XML provides the following functionality:
+
+- Reading of UTF-8 and UTF-16 and writing of UTF-8 encoded XML files and
+  strings.
+- Data is stored in a linked-list tree structure, preserving the XML data
+  hierarchy.
+- SAX (streamed) reading of XML files and strings to minimize memory usage.
+- Supports arbitrary element names, attributes, and attribute values with no
+  preset limits, just available memory.
+- Supports integer, real, opaque ("cdata"), and text data types in "leaf"
+  nodes.
+- Functions for creating and managing trees of data.
+- "Find" and "walk" functions for easily locating and navigating trees of
+  data.
+
+Mini-XML doesn't do validation or other types of processing on the data based
+upon schema files or other sources of definition information.
+
+
+## History
+
+Mini-XML was initially developed for the [Gutenprint](http://gutenprint.sf.net/)
+project to replace the rather large and unwieldy `libxml2` library with
+something substantially smaller and easier-to-use.  It all began one morning in
+June of 2003 when Robert posted the following sentence to the developer's list:
+
+> It's bad enough that we require libxml2, but rolling our own XML parser is a
+> bit more than we can handle.
+
+I then replied with:
+
+> Given the limited scope of what you use in XML, it should be trivial to code a
+> mini-XML API in a few hundred lines of code.
+
+I took my own challenge and coded furiously for two days to produced the initial
+public release of Mini-XML, total lines of code: 696.  Robert promptly
+integrated Mini-XML into Gutenprint and removed libxml2.
+
+Thanks to lots of feedback and support from various developers, Mini-XML has
+evolved since then to provide a more complete XML implementation and now stands
+at a whopping 4,115 lines of code, compared to 140,410 lines of code for libxml2
+version 2.9.1.
+
+
+## Resources
+
+The Mini-XML home page can be found at:
+
+    https://www.msweet.orgm/mxml
+
+From here you can download the current version of Mini-XML, the issue tracker,
+and other resources.
+
+
+## Legal Stuff
+
+The Mini-XML library is copyright © 2003-2019 by Michael R Sweet and is provided
+under the Apache License Version 2.0 with an exception to allow linking against
+GPL2/LGPL2-only software.  See the files "LICENSE" and "NOTICE" for more
+information.
+
+
+# Using Mini-XML
+
+Mini-XML provides a single header file which you include:
+
+    #include <mxml.h>
+
+The Mini-XML library is included with your program using the `-lmxml` option:
+
+    gcc -o myprogram myprogram.c -lmxml
+
+If you have the `pkg-config` software installed, you can use it to determine the
+proper compiler and linker options for your installation:
+
+    gcc `pkg-config --cflags mxml` -o myprogram myprogram.c `pkg-config --libs mxml`
+
+
+## Loading an XML File
+
+You load an XML file using the `mxmlLoadFile` function:
+
+    mxml_node_t *
+    mxmlLoadFile(mxml_node_t *top, FILE *fp,
+                 mxml_type_t (*cb)(mxml_node_t *));
+
+The `cb` argument specifies a function that assigns child (value) node types for
+each element in the document.  The callback can be a function you provide or one
+of the standard functions provided with Mini-XML.  For example, to load the XML
+file "filename.xml" containing text strings you can use the
+`MXML_OPAQUE_CALLBACK` function:
+
+    FILE *fp;
+    mxml_node_t *tree;
+
+    fp = fopen("filename.xml", "r");
+    tree = mxmlLoadFile(NULL, fp, MXML_OPAQUE_CALLBACK);
+    fclose(fp);
+
+Mini-XML also provides functions to load from a file descriptor or string:
+
+    mxml_node_t *
+    mxmlLoadFd(mxml_node_t *top, int fd,
+               mxml_type_t (*cb)(mxml_node_t *));
+
+    mxml_node_t *
+    mxmlLoadString(mxml_node_t *top, const char *s,
+                   mxml_type_t (*cb)(mxml_node_t *));
+
+
+### Load Callbacks
+
+The last argument to the `mxmlLoad` functions is a callback function which is
+used to determine the value type of each data node in an XML document.  Mini-XML
+defines several standard callbacks for simple XML data files:
+
+- `MXML_INTEGER_CALLBACK`: All data nodes contain whitespace-separated integers.
+- `MXML_OPAQUE_CALLBACK`: All data nodes contain opaque strings with whitespace preserved.
+- `MXML_REAL_CALLBACK` - All data nodes contain whitespace-separated floating-point numbers.
+- `MXML_TEXT_CALLBACK` - All data nodes contain whitespace-separated strings.
+
+You can provide your own callback functions for more complex XML documents.
+Your callback function will receive a pointer to the current element node and
+must return the value type of the immediate children for that element node:
+`MXML_CUSTOM`, `MXML_INTEGER`, `MXML_OPAQUE`, `MXML_REAL`, or `MXML_TEXT`.  The
+function is called *after* the element and its attributes have been read, so you
+can look at the element name, attributes, and attribute values to determine the
+proper value type to return.
+
+The following callback function looks for an attribute named "type" or the
+element name to determine the value type for its child nodes:
+
+    mxml_type_t
+    type_cb(mxml_node_t *node)
+    {
+      const char *type;
+
+     /*
+      * You can lookup attributes and/or use the element name,
+      * hierarchy, etc...
+      */
+
+      type = mxmlElementGetAttr(node, "type");
+      if (type == NULL)
+        type = mxmlGetElement(node);
+
+      if (!strcmp(type, "integer"))
+        return (MXML_INTEGER);
+      else if (!strcmp(type, "opaque"))
+        return (MXML_OPAQUE);
+      else if (!strcmp(type, "real"))
+        return (MXML_REAL);
+      else
+        return (MXML_TEXT);
+    }
+
+To use this callback function, simply use the name when you call any of the load
+functions:
+
+    FILE *fp;
+    mxml_node_t *tree;
+
+    fp = fopen("filename.xml", "r");
+    tree = mxmlLoadFile(NULL, fp, type_cb);
+    fclose(fp);
+
+
+## Nodes
+
+Every piece of information in an XML file is stored in memory in "nodes".  Nodes
+are defined by the `mxml_node_t` structure.  Each node has a typed value,
+optional user data, a parent node, sibling nodes (previous and next), and
+potentially child nodes.
+
+For example, if you have an XML file like the following:
+
+    <?xml version="1.0" encoding="utf-8"?>
+    <data>
+        <node>val1</node>
+        <node>val2</node>
+        <node>val3</node>
+        <group>
+            <node>val4</node>
+            <node>val5</node>
+            <node>val6</node>
+        </group>
+        <node>val7</node>
+        <node>val8</node>
+    </data>
+
+the node tree for the file would look like the following in memory:
+
+    ?xml version="1.0" encoding="utf-8"?
+      |
+    data
+      |
+    node - node - node - group - node - node
+      |      |      |      |       |      |
+    val1   val2   val3     |     val7   val8
+                           |
+                         node - node - node
+                           |      |      |
+                         val4   val5   val6
+
+where "-" is a pointer to the sibling node and "|" is a pointer to the first
+child or parent node.
+
+The `mxmlGetType` function gets the type of a node:
+
+    mxml_type_t
+    mxmlGetType(mxml_node_t *node);
+
+- `MXML_CUSTOM` : A custom value defined by your application,
+- `MXML_ELEMENT` : An XML element, CDATA, comment, or processing instruction,
+- `MXML_INTEGER` : A whitespace-delimited integer value,
+- `MXML_OPAQUE` : An opaque string value that preserves all whitespace,
+- `MXML_REAL` : A whitespace-delimited floating point value, or
+- `MXML_TEXT` : A whitespace-delimited text (fragment) value.
+
+> Note: CDATA, comment, and processing directive nodes are currently stored in
+> memory as special elements.  This will be changed in a future major release of
+> Mini-XML.
+
+The parent and sibling nodes are accessed using the `mxmlGetParent`,
+`mxmlGetNextSibling`, and `mxmlGetPreviousSibling` functions, while the children
+of an element node are accessed using the `mxmlGetFirstChild` or
+`mxmlGetLastChild` functions:
+
+    mxml_node_t *
+    mxmlGetFirstChild(mxml_node_t *node);
+
+    mxml_node_t *
+    mxmlGetLastChild(mxml_node_t *node);
+
+    mxml_node_t *
+    mxmlGetNextSibling(mxml_node_t *node);
+
+    mxml_node_t *
+    mxmlGetParent(mxml_node_t *node);
+
+    mxml_node_t *
+    mxmlGetPrevSibling(mxml_node_t *node);
+
+The `mxmlGetUserData` function gets any user (application) data associated with
+the node:
+
+    void *
+    mxmlGetUserData(mxml_node_t *node);
+
+
+## Creating XML Documents
+
+You can create and update XML documents in memory using the various `mxmlNew`
+functions. The following code will create the XML document described in the
+previous section:
+
+    mxml_node_t *xml;    /* <?xml ... ?> */
+    mxml_node_t *data;   /* <data> */
+    mxml_node_t *node;   /* <node> */
+    mxml_node_t *group;  /* <group> */
+
+    xml = mxmlNewXML("1.0");
+
+    data = mxmlNewElement(xml, "data");
+
+        node = mxmlNewElement(data, "node");
+        mxmlNewText(node, 0, "val1");
+        node = mxmlNewElement(data, "node");
+        mxmlNewText(node, 0, "val2");
+        node = mxmlNewElement(data, "node");
+        mxmlNewText(node, 0, "val3");
+
+        group = mxmlNewElement(data, "group");
+
+            node = mxmlNewElement(group, "node");
+            mxmlNewText(node, 0, "val4");
+            node = mxmlNewElement(group, "node");
+            mxmlNewText(node, 0, "val5");
+            node = mxmlNewElement(group, "node");
+            mxmlNewText(node, 0, "val6");
+
+        node = mxmlNewElement(data, "node");
+        mxmlNewText(node, 0, "val7");
+        node = mxmlNewElement(data, "node");
+        mxmlNewText(node, 0, "val8");
+
+We start by creating the declaration node common to all XML files using the
+`mxmlNewXML` function:
+
+    xml = mxmlNewXML("1.0");
+
+We then create the `<data>` node used for this document using the
+`mxmlNewElement` function.  The first argument specifies the parent node
+\(`xml`) while the second specifies the element name \(`data`):
+
+    data = mxmlNewElement(xml, "data");
+
+Each `<node>...</node>` in the file is created using the `mxmlNewElement` and
+`mxmlNewText` functions.  The first argument of `mxmlNewText` specifies the
+parent node \(`node`).  The second argument specifies whether whitespace appears
+before the text - 0 or false in this case.  The last argument specifies the
+actual text to add:
+
+    node = mxmlNewElement(data, "node");
+    mxmlNewText(node, 0, "val1");
+
+The resulting in-memory XML document can then be saved or processed just like
+one loaded from disk or a string.
+
+
+## Saving an XML File
+
+You save an XML file using the `mxmlSaveFile` function:
+
+    int
+    mxmlSaveFile(mxml_node_t *node, FILE *fp,
+                 mxml_save_cb_t cb);
+
+The `cb` argument specifies a function that returns the whitespace (if any) that
+is inserted before and after each element node.  The `MXML_NO_CALLBACK` constant
+tells Mini-XML to not include any extra whitespace.  For example, so save an XML
+file to the file "filename.xml" with no extra whitespace:
+
+    FILE *fp;
+
+    fp = fopen("filename.xml", "w");
+    mxmlSaveFile(xml, fp, MXML_NO_CALLBACK);
+    fclose(fp);
+
+Mini-XML also provides functions to save to a file descriptor or strings:
+
+    char *
+    mxmlSaveAllocString(mxml_node_t *node, mxml_save_cb_t cb);
+
+    int
+    mxmlSaveFd(mxml_node_t *node, int fd, mxml_save_cb_t cb);
+
+    int
+    mxmlSaveString(mxml_node_t *node, char *buffer, int bufsize,
+                   mxml_save_cb_t cb);
+
+
+### Controlling Line Wrapping
+
+When saving XML documents, Mini-XML normally wraps output lines at column 75 so
+that the text is readable in terminal windows.  The `mxmlSetWrapMargin` function
+overrides the default wrap margin for the current thread:
+
+    void mxmlSetWrapMargin(int column);
+
+For example, the following code sets the margin to 132 columns:
+
+    mxmlSetWrapMargin(132);
+
+while the following code disables wrapping by setting the margin to 0:
+
+    mxmlSetWrapMargin(0);
+
+
+### Save Callbacks
+
+The last argument to the `mxmlSave` functions is a callback function which is
+used to automatically insert whitespace in an XML document.  Your callback
+function will be called up to four times for each element node with a pointer to
+the node and a "where" value of `MXML_WS_BEFORE_OPEN`, `MXML_WS_AFTER_OPEN`,
+`MXML_WS_BEFORE_CLOSE`, or `MXML_WS_AFTER_CLOSE`.  The callback function should
+return `NULL` if no whitespace should be added or the string to insert (spaces,
+tabs, carriage returns, and newlines) otherwise.
+
+The following whitespace callback can be used to add whitespace to XHTML output
+to make it more readable in a standard text editor:
+
+    const char *
+    whitespace_cb(mxml_node_t *node, int where)
+    {
+      const char *element;
+
+     /*
+      * We can conditionally break to a new line before or after
+      * any element.  These are just common HTML elements...
+      */
+
+      element = mxmlGetElement(node);
+
+      if (!strcmp(element, "html") ||
+          !strcmp(element, "head") ||
+          !strcmp(element, "body") ||
+          !strcmp(element, "pre") ||
+          !strcmp(element, "p") ||
+          !strcmp(element, "h1") ||
+          !strcmp(element, "h2") ||
+          !strcmp(element, "h3") ||
+          !strcmp(element, "h4") ||
+          !strcmp(element, "h5") ||
+          !strcmp(element, "h6"))
+      {
+       /*
+        * Newlines before open and after close...
+        */
+
+        if (where == MXML_WS_BEFORE_OPEN ||
+            where == MXML_WS_AFTER_CLOSE)
+          return ("\n");
+      }
+      else if (!strcmp(element, "dl") ||
+               !strcmp(element, "ol") ||
+               !strcmp(element, "ul"))
+      {
+       /*
+        * Put a newline before and after list elements...
+        */
+
+        return ("\n");
+      }
+      else if (!strcmp(element, "dd") ||
+               !strcmp(element, "dt") ||
+               !strcmp(element, "li"))
+      {
+       /*
+        * Put a tab before <li>'s, <dd>'s, and <dt>'s, and a
+        * newline after them...
+        */
+
+        if (where == MXML_WS_BEFORE_OPEN)
+          return ("\t");
+        else if (where == MXML_WS_AFTER_CLOSE)
+          return ("\n");
+      }
+
+     /*
+      * Otherwise return NULL for no added whitespace...
+      */
+
+      return (NULL);
+    }
+
+To use this callback function, simply use the name when you call any of the save
+functions:
+
+    FILE *fp;
+    mxml_node_t *tree;
+
+    fp = fopen("filename.xml", "w");
+    mxmlSaveFile(tree, fp, whitespace_cb);
+    fclose(fp);
+
+
+## Memory Management
+
+Once you are done with the XML data, use the `mxmlDelete` function to
+recursively free the memory that is used for a particular node or the entire
+tree:
+
+    void
+    mxmlDelete(mxml_node_t *tree);
+
+You can also use reference counting to manage memory usage.  The `mxmlRetain`
+and `mxmlRelease` functions increment and decrement a node's use count,
+respectively.  When the use count goes to zero, `mxmlRelease` automatically
+calls `mxmlDelete` to actually free the memory used by the node tree.  New nodes
+start with a use count of 1.
+
+
+# More About Nodes
+
+## Element Nodes
+
+Element \(`MXML_ELEMENT`) nodes are created using the `mxmlNewElement` function.
+Element attributes are set using the `mxmlElementSetAttr` and
+`mxmlElementSetAttrf` functions and cleared using the `mxmlElementDeleteAttr`
+function:
+
+    mxml_node_t *
+    mxmlNewElement(mxml_node_t *parent, const char *name);
+
+    void
+    mxmlElementDeleteAttr(mxml_node_t *node, const char *name);
+
+    void
+    mxmlElementSetAttr(mxml_node_t *node, const char *name,
+                       const char *value);
+
+    void
+    mxmlElementSetAttrf(mxml_node_t *node, const char *name,
+                        const char *format, ...);
+
+Child nodes are added using the various `mxmlNew` functions.  The top (root)
+node must be an element, usually created by the `mxmlNewXML` function:
+
+    mxml_node_t *
+    mxmlNewXML(const char *version);
+
+The `mxmlGetElement` function retrieves the element name, the
+`mxmlElementGetAttr` function retrieves the value string for a named attribute
+associated with the element.  The `mxmlElementGetAttrByIndex` and
+`mxmlElementGetAttrCount` functions retrieve attributes by index:
+
+    const char *
+    mxmlGetElement(mxml_node_t *node);
+
+    const char *
+    mxmlElementGetAttr(mxml_node_t *node, const char *name);
+
+    const char *
+    mxmlElementGetAttrByIndex(mxml_node_t *node, int idx,
+                              const char **name);
+
+    int
+    mxmlElementGetAttrCount(mxml_node_t *node);
+
+
+## CDATA Nodes
+
+CDATA \(`MXML_ELEMENT`) nodes are created using the `mxmlNewCDATA` function:
+
+    mxml_node_t *mxmlNewCDATA(mxml_node_t *parent, const char *string);
+
+The `mxmlGetCDATA` function retrieves the CDATA string pointer for a node:
+
+    const char *mxmlGetCDATA(mxml_node_t *node);
+
+
+## Comment Nodes
+
+Because comments are currently stored as element nodes, comment
+\(`MXML_ELEMENT`) nodes are created using the `mxmlNewElement` function by
+including the surrounding "!--" and "--" characters in the element name, for
+example:
+
+    mxml_node_t *node = mxmlNewElement("!-- This is a comment --");
+
+Similarly, the `mxmlGetElement` function retrieves the comment string pointer
+for a node, which includes the surrounding "!--" and "--" characters.
+
+    const char *comment = mxmlGetElement(node);
+    /* returns "!-- This is a comment --" */
+
+
+## Processing Instruction Nodes
+
+Because processing instructions are currently stored as element nodes,
+processing instruction \(`MXML_ELEMENT`) nodes are created using the
+`mxmlNewElement` function including the surrounding "?" characters:
+
+    mxml_node_t *node = mxmlNewElement("?xml-stylesheet type=\"text/css\" href=\"style.css\"?");
+
+The `mxmlGetElement` function retrieves the processing instruction string for a
+node, including the surrounding "?" characters:
+
+    const char *instr = mxmlGetElement(node);
+    /* returned "?xml-stylesheet type=\"text/css\" href=\"style.css\"?" */
+
+
+## Integer Nodes
+
+Integer \(`MXML_INTEGER`) nodes are created using the `mxmlNewInteger` function:
+
+    mxml_node_t *
+    mxmlNewInteger(mxml_node_t *parent, int integer);
+
+The `mxmlGetInteger` function retrieves the integer value for a node:
+
+    int
+    mxmlGetInteger(mxml_node_t *node);
+
+
+## Opaque String Nodes
+
+Opaque string \(`MXML_OPAQUE`) nodes are created using the `mxmlNewOpaque`
+function:
+
+    mxml_node_t *
+    mxmlNewOpaque(mxml_node_t *parent, const char *opaque);
+
+The `mxmlGetOpaque` function retrieves the opaque string pointer for a node:
+
+    const char *
+    mxmlGetOpaque(mxml_node_t *node);
+
+
+## Text Nodes
+
+Whitespace-delimited text string \(`MXML_TEXT`) nodes are created using the
+`mxmlNewText` and `mxmlNewTextf` functions.  Each text node consists of a text
+string and (leading) whitespace flag value.
+
+    mxml_node_t *
+    mxmlNewText(mxml_node_t *parent, int whitespace,
+                const char *string);
+
+    mxml_node_t *
+    mxmlNewTextf(mxml_node_t *parent, int whitespace,
+                 const char *format, ...);
+
+The `mxmlGetText` function retrieves the text string pointer and whitespace
+flag value for a node:
+
+     const char *
+     mxmlGetText(mxml_node_t *node, int *whitespace);
+
+
+## Real Number Nodes
+
+Real number \(`MXML_REAL`) nodes are created using the `mxmlNewReal` function:
+
+    mxml_node_t *
+    mxmlNewReal(mxml_node_t *parent, double real);
+
+The `mxmlGetReal` function retrieves the real number for a node:
+
+    double
+    mxmlGetReal(mxml_node_t *node);
+
+
+# Locating Data in an XML Document
+
+Mini-XML provides many functions for enumerating, searching, and indexing XML
+documents.
+
+
+## Finding Nodes
+
+The `mxmlFindPath` function finds the (first) value node under a specific
+element using a "path":
+
+    mxml_node_t *
+    mxmlFindPath(mxml_node_t *node, const char *path);
+
+The `path` string can contain the "*" wildcard to match a single element node in
+the hierarchy.  For example, the following code will find the first "node"
+element under the "group" element, first using an explicit path and then using a
+wildcard:
+
+    mxml_node_t *value = mxmlFindPath(xml, "data/group/node");
+
+    mxml_node_t *value = mxmlFindPath(xml, "data/*/node");
+
+The `mxmlFindElement` function can be used to find a named element, optionally
+matching an attribute and value:
+
+    mxml_node_t *
+    mxmlFindElement(mxml_node_t *node, mxml_node_t *top,
+                    const char *element, const char *attr,
+                    const char *value, int descend);
+
+The "element", "attr", and "value" arguments can be passed as `NULL` to act as
+wildcards, e.g.:
+
+    /* Find the first "a" element */
+    node = mxmlFindElement(tree, tree, "a", NULL, NULL,
+                           MXML_DESCEND);
+
+    /* Find the first "a" element with "href" attribute */
+    node = mxmlFindElement(tree, tree, "a", "href", NULL,
+                           MXML_DESCEND);
+
+    /* Find the first "a" element with "href" to a URL */
+    node = mxmlFindElement(tree, tree, "a", "href",
+                           "http://michaelrsweet.github.io/",
+                           MXML_DESCEND);
+
+    /* Find the first element with a "src" attribute*/
+    node = mxmlFindElement(tree, tree, NULL, "src", NULL,
+                           MXML_DESCEND);
+
+    /* Find the first element with a "src" = "foo.jpg" */
+    node = mxmlFindElement(tree, tree, NULL, "src", "foo.jpg",
+                           MXML_DESCEND);
+
+You can also iterate with the same function:
+
+    mxml_node_t *node;
+
+    for (node = mxmlFindElement(tree, tree, "element", NULL,
+                                NULL, MXML_DESCEND);
+         node != NULL;
+         node = mxmlFindElement(node, tree, "element", NULL,
+                                NULL, MXML_DESCEND))
+    {
+      ... do something ...
+    }
+
+The `descend` argument \(`MXML_DESCEND` in the examples above) can be one of
+three constants:
+
+- `MXML_NO_DESCEND`: ignore child nodes in the element hierarchy, instead using
+  siblings (same level) or parent nodes (above) until the top (root) node is
+  reached.
+
+- `MXML_DESCEND_FIRST`: start the search with the first child of the node, and
+  then search siblings.  You'll normally use this when iterating through direct
+  children of a parent node, e.g. all of the "node" and "group" elements under
+  the "?xml" parent node in the previous example.
+
+- `MXML_DESCEND`: search child nodes first, then sibling nodes, and then parent
+  nodes.
+
+
+## Iterating Nodes
+
+While the `mxmlFindNode` and `mxmlFindPath` functions will find a particular
+element node, sometimes you need to iterate over all nodes.  The `mxmlWalkNext`
+and `mxmlWalkPrev` functions can be used to iterate through the XML node
+tree:
+
+    mxml_node_t *
+    mxmlWalkNext(mxml_node_t *node, mxml_node_t *top,
+                 int descend);
+
+    mxml_node_t *
+    mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top,
+                 int descend);
+
+Depending on the value of the `descend` argument, these functions will
+automatically traverse child, sibling, and parent nodes until the `top` node is
+reached.  For example, the following code will iterate over all of the nodes in
+the sample XML document in the previous section:
+
+    mxml_node_t *node;
+
+    for (node = xml;
+         node != NULL;
+         node = mxmlWalkNext(node, xml, MXML_DESCEND))
+    {
+      ... do something ...
+    }
+
+The nodes will be returned in the following order:
+
+    <?xml version="1.0" encoding="utf-8"?>
+    <data>
+    <node>
+    val1
+    <node>
+    val2
+    <node>
+    val3
+    <group>
+    <node>
+    val4
+    <node>
+    val5
+    <node>
+    val6
+    <node>
+    val7
+    <node>
+    val8
+
+
+## Indexing
+
+The `mxmlIndexNew` function allows you to create an index of nodes for faster
+searching and enumeration:
+
+    mxml_index_t *
+    mxmlIndexNew(mxml_node_t *node, const char *element,
+                 const char *attr);
+
+The `element` and `attr` arguments control which elements are included in the
+index.  If `element` is not `NULL` then only elements with the specified name
+are added to the index.  Similarly, if `attr` is not `NULL` then only elements
+containing the specified attribute are added to the index.  The nodes are sorted
+in the index.
+
+For example, the following code creates an index of all "id" values in an XML
+document:
+
+    mxml_index_t *ind = mxmlIndexNew(xml, NULL, "id");
+
+Once the index is created, the `mxmlIndexFind` function can be used to find a
+matching node:
+
+    mxml_node_t *
+    mxmlIndexFind(mxml_index_t *ind, const char *element,
+                  const char *value);
+
+For example, the following code will find the element whose "id" string is "42":
+
+    mxml_node_t *node = mxmlIndexFind(ind, NULL, "42");
+
+Alternately, the `mxmlIndexReset` and `mxmlIndexEnum` functions can be used to
+enumerate the nodes in the index:
+
+    mxml_node_t *
+    mxmlIndexReset(mxml_index_t *ind);
+
+    mxml_node_t *
+    mxmlIndexEnum(mxml_index_t *ind);
+
+Typically these functions will be used in a `for` loop:
+
+    mxml_node_t *node;
+
+    for (node = mxmlIndexReset(ind);
+         node != NULL;
+         node = mxmlIndexEnum(ind))
+    {
+      ... do something ...
+    }
+
+The `mxmlIndexCount` function returns the number of nodes in the index:
+
+    int
+    mxmlIndexGetCount(mxml_index_t *ind);
+
+Finally, the `mxmlIndexDelete` function frees all memory associated with the
+index:
+
+    void
+    mxmlIndexDelete(mxml_index_t *ind);
+
+
+# Custom Data Types
+
+Mini-XML supports custom data types via per-thread load and save callbacks.
+Only a single set of callbacks can be active at any time for the current thread,
+however your callbacks can store additional information in order to support
+multiple custom data types as needed.  The `MXML_CUSTOM` node type identifies
+custom data nodes.
+
+The `mxmlGetCustom` function retrieves the custom value pointer for a node.
+
+    const void *
+    mxmlGetCustom(mxml_node_t *node);
+
+Custom \(`MXML_CUSTOM`) nodes are created using the `mxmlNewCustom` function or
+using a custom per-thread load callbacks specified using the
+`mxmlSetCustomHandlers` function:
+
+    typedef void (*mxml_custom_destroy_cb_t)(void *);
+    typedef int (*mxml_custom_load_cb_t)(mxml_node_t *, const char *);
+    typedef char *(*mxml_custom_save_cb_t)(mxml_node_t *);
+
+    mxml_node_t *
+    mxmlNewCustom(mxml_node_t *parent, void *data,
+                  mxml_custom_destroy_cb_t destroy);
+
+    int
+    mxmlSetCustom(mxml_node_t *node, void *data,
+                  mxml_custom_destroy_cb_t destroy);
+
+    void
+    mxmlSetCustomHandlers(mxml_custom_load_cb_t load,
+                          mxml_custom_save_cb_t save);
+
+The load callback receives a pointer to the current data node and a string of
+opaque character data from the XML source with character entities converted to
+the corresponding UTF-8 characters.  For example, if we wanted to support a
+custom date/time type whose value is encoded as "yyyy-mm-ddThh:mm:ssZ" (ISO
+format), the load callback would look like the following:
+
+    typedef struct
+    {
+      unsigned year,    /* Year */
+               month,   /* Month */
+               day,     /* Day */
+               hour,    /* Hour */
+               minute,  /* Minute */
+               second;  /* Second */
+      time_t   unix;    /* UNIX time */
+    } iso_date_time_t;
+
+    int
+    load_custom(mxml_node_t *node, const char *data)
+    {
+      iso_date_time_t *dt;
+      struct tm tmdata;
+
+     /*
+      * Allocate data structure...
+      */
+
+      dt = calloc(1, sizeof(iso_date_time_t));
+
+     /*
+      * Try reading 6 unsigned integers from the data string...
+      */
+
+      if (sscanf(data, "%u-%u-%uT%u:%u:%uZ", &(dt->year),
+                 &(dt->month), &(dt->day), &(dt->hour),
+                 &(dt->minute), &(dt->second)) != 6)
+      {
+       /*
+        * Unable to read numbers, free the data structure and
+        * return an error...
+        */
+
+        free(dt);
+
+        return (-1);
+      }
+
+     /*
+      * Range check values...
+      */
+
+      if (dt->month < 1 || dt->month > 12 ||
+          dt->day < 1 || dt->day > 31 ||
+          dt->hour < 0 || dt->hour > 23 ||
+          dt->minute < 0 || dt->minute > 59 ||
+          dt->second < 0 || dt->second > 60)
+      {
+       /*
+        * Date information is out of range...
+        */
+
+        free(dt);
+
+        return (-1);
+      }
+
+     /*
+      * Convert ISO time to UNIX time in seconds...
+      */
+
+      tmdata.tm_year = dt->year - 1900;
+      tmdata.tm_mon  = dt->month - 1;
+      tmdata.tm_day  = dt->day;
+      tmdata.tm_hour = dt->hour;
+      tmdata.tm_min  = dt->minute;
+      tmdata.tm_sec  = dt->second;
+
+      dt->unix = gmtime(&tmdata);
+
+     /*
+      * Assign custom node data and destroy (free) function
+      * pointers...
+      */
+
+      mxmlSetCustom(node, data, free);
+
+     /*
+      * Return with no errors...
+      */
+
+      return (0);
+    }
+
+The function itself can return 0 on success or -1 if it is unable to decode the
+custom data or the data contains an error.  Custom data nodes contain a `void`
+pointer to the allocated custom data for the node and a pointer to a destructor
+function which will free the custom data when the node is deleted.  In this
+example, we use the standard `free` function since everything is contained in a
+single calloc'd block.
+
+The save callback receives the node pointer and returns an allocated string
+containing the custom data value.  The following save callback could be used for
+our ISO date/time type:
+
+    char *
+    save_custom(mxml_node_t *node)
+    {
+      char data[255];
+      iso_date_time_t *dt;
+
+
+      dt = (iso_date_time_t *)mxmlGetCustom(node);
+
+      snprintf(data, sizeof(data),
+               "%04u-%02u-%02uT%02u:%02u:%02uZ",
+               dt->year, dt->month, dt->day, dt->hour,
+               dt->minute, dt->second);
+
+      return (strdup(data));
+    }
+
+You register the callback functions using the `mxmlSetCustomHandlers` function:
+
+    mxmlSetCustomHandlers(load_custom, save_custom);
+
+
+# SAX (Stream) Loading of Documents
+
+Mini-XML supports an implementation of the Simple API for XML (SAX) which allows
+you to load and process an XML document as a stream of nodes.  Aside from
+allowing you to process XML documents of any size, the Mini-XML implementation
+also allows you to retain portions of the document in memory for later
+processing.
+
+The `mxmlSAXLoadFd`, `mxmlSAXLoadFile`, and `mxmlSAXLoadString` functions
+provide the SAX loading APIs:
+
+    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);
+
+    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);
+
+    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);
+
+Each function works like the corresponding `mxmlLoad` function but uses a
+callback to process each node as it is read.  The callback function receives the
+node, an event code, and a user data pointer you supply:
+
+    void
+    sax_cb(mxml_node_t *node, mxml_sax_event_t event,
+           void *data)
+    {
+      ... do something ...
+    }
+
+The event will be one of the following:
+
+- `MXML_SAX_CDATA`: CDATA was just read.
+- `MXML_SAX_COMMENT`: A comment was just read.
+- `MXML_SAX_DATA`: Data (custom, integer, opaque, real, or text) was just read.
+- `MXML_SAX_DIRECTIVE`: A processing directive/instruction was just read.
+- `MXML_SAX_ELEMENT_CLOSE` - A close element was just read \(`</element>`)
+- `MXML_SAX_ELEMENT_OPEN` - An open element was just read \(`<element>`)
+
+Elements are *released* after the close element is processed.  All other nodes
+are released after they are processed.  The SAX callback can *retain* the node
+using the `mxmlRetain` function.  For example, the following SAX callback will
+retain all nodes, effectively simulating a normal in-memory load:
+
+    void
+    sax_cb(mxml_node_t *node, mxml_sax_event_t event,
+           void *data)
+    {
+      if (event != MXML_SAX_ELEMENT_CLOSE)
+        mxmlRetain(node);
+    }
+
+More typically the SAX callback will only retain a small portion of the document
+that is needed for post-processing.  For example, the following SAX callback
+will retain the title and headings in an XHTML file.  It also retains the (parent) elements like `<html>`, `<head>`, and `<body>`, and processing
+directives like  `<?xml ... ?>` and  `<!DOCTYPE ... >`:
+
+    void
+    sax_cb(mxml_node_t *node, mxml_sax_event_t event,
+           void *data)
+    {
+      if (event == MXML_SAX_ELEMENT_OPEN)
+      {
+       /*
+        * Retain headings and titles...
+        */
+
+        const char *element = mxmlGetElement(node);
+
+        if (!strcmp(element, "html") ||
+            !strcmp(element, "head") ||
+            !strcmp(element, "title") ||
+            !strcmp(element, "body") ||
+            !strcmp(element, "h1") ||
+            !strcmp(element, "h2") ||
+            !strcmp(element, "h3") ||
+            !strcmp(element, "h4") ||
+            !strcmp(element, "h5") ||
+            !strcmp(element, "h6"))
+          mxmlRetain(node);
+      }
+      else if (event == MXML_SAX_DIRECTIVE)
+        mxmlRetain(node);
+      else if (event == MXML_SAX_DATA)
+      {
+        if (mxmlGetRefCount(mxmlGetParent(node)) > 1)
+        {
+         /*
+          * If the parent was retained, then retain this data
+          * node as well.
+          */
+
+          mxmlRetain(node);
+        }
+      }
+    }
+
+The resulting skeleton document tree can then be searched just like one loaded
+using the `mxmlLoad` functions.  For example, a filter that reads an XHTML
+document from stdin and then shows the title and headings in the document would
+look like:
+
+    mxml_node_t *doc, *title, *body, *heading;
+
+    doc = mxmlSAXLoadFd(NULL, 0, MXML_TEXT_CALLBACK, sax_cb,
+                        NULL);
+
+    title = mxmlFindElement(doc, doc, "title", NULL, NULL,
+                            MXML_DESCEND);
+
+    if (title)
+      print_children(title);
+
+    body = mxmlFindElement(doc, doc, "body", NULL, NULL,
+                           MXML_DESCEND);
+
+    if (body)
+    {
+      for (heading = mxmlGetFirstChild(body);
+           heading;
+           heading = mxmlGetNextSibling(heading))
+        print_children(heading);
+    }
+
+The `print_children` function is:
+
+    void
+    print_children(mxml_node_t *parent)
+    {
+      mxml_node_t *node;
+      const char *text;
+      int whitespace;
+
+      for (node = mxmlGetFirstChild(parent);
+           node != NULL;
+           node = mxmlGetNextSibling(node))
+      {
+        text = mxmlGettext(node, &whitespace);
+
+        if (whitespace)
+          putchar(' ');
+
+        fputs(text, stdout);
+      }
+
+      putchar('\n');
+    }

+ 4 - 0
mxml.mod/mxml/doc/footer.man

@@ -0,0 +1,4 @@
+.SH SEE ALSO
+Mini-XML Programmers Manual, https://www.msweet.org/mxml
+.SH COPYRIGHT
+Copyright \[co] 2003-2019 by Michael R Sweet.

BIN
mxml.mod/mxml/doc/mxml-cover.jpg


BIN
mxml.mod/mxml/doc/mxml-cover.opacity


BIN
mxml.mod/mxml/doc/mxml-cover.png


+ 1353 - 0
mxml.mod/mxml/doc/mxml.3

@@ -0,0 +1,1353 @@
+.TH mxml 3 "Mini-XML API" "01/02/19" "Mini-XML API"
+.SH NAME
+mxml \- Mini-XML API
+.SH INCLUDE FILE
+#include <mxml.h>
+.SH LIBRARY
+\-lmxml
+.SH DESCRIPTION
+Mini-XML is a small XML parsing library that you can use to
+read XML and XML-like data files in your application without
+requiring large non-standard libraries.  Mini-XML only
+requires an ANSI C compatible compiler (GCC works, as do
+most vendors' ANSI C compilers) and a "make" program.
+.PP
+Mini-XML provides the following functionality:
+.IP \(bu 4
+Reading of UTF-8 and UTF-16 and writing of UTF-8 encoded XML files and strings.
+.IP \(bu 4
+Data is stored in a linked-list tree structure,
+preserving the XML data hierarchy.
+.IP \(bu 4
+Supports arbitrary element names, attributes, and attribute
+values with no preset limits, just available memory.
+.IP \(bu 4
+Supports integer, real, opaque ("CDATA"), and text data types in
+"leaf" nodes.
+.IP \(bu 4
+Functions for creating, indexing, and managing trees of data.
+.IP \(bu 4
+"Find" and "walk" functions for easily locating and navigating
+trees of data.
+.PP
+Mini-XML doesn't do validation or other types of processing
+on the data based upon schema files or other sources of
+definition information, nor does it support character
+entities other than those required by the XML
+specification.
+.SH USING MINI-XML
+Mini-XML provides a single header file which you include:
+.nf
+
+    #include <mxml.h>
+.fi
+.PP
+Nodes are defined by the "mxml_node_t" structure; the "type"
+member defines the node type (element, integer, opaque,
+real, or text) which determines which value you want to look
+at in the "value" union.  New nodes can be created using the
+"mxmlNewElement()", "mxmlNewInteger()", "mxmlNewOpaque()",
+"mxmlNewReal()", and "mxmlNewText()" functions.  Only
+elements can have child nodes, and the top node must be an
+element, usually "?xml".
+.PP
+You load an XML file using the "mxmlLoadFile()" function:
+.nf
+
+    FILE *fp;
+    mxml_node_t *tree;
+
+    fp = fopen("filename.xml", "r");
+    tree = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK);
+    fclose(fp);
+.fi
+.PP
+Similarly, you save an XML file using the "mxmlSaveFile()"
+function:
+.nf
+
+    FILE *fp;
+    mxml_node_t *tree;
+
+    fp = fopen("filename.xml", "w");
+    mxmlSaveFile(tree, fp, MXML_NO_CALLBACK);
+    fclose(fp);
+.fi
+.PP
+The "mxmlLoadString()", "mxmlSaveAllocString()", and
+"mxmlSaveString()" functions load XML node trees from and save
+XML node trees to strings:
+.nf
+
+    char buffer[8192];
+    char *ptr;
+    mxml_node_t *tree;
+
+    ...
+    tree = mxmlLoadString(NULL, buffer, MXML_NO_CALLBACK);
+
+    ...
+    mxmlSaveString(tree, buffer, sizeof(buffer),
+                   MXML_NO_CALLBACK);
+
+    ...
+    ptr = mxmlSaveAllocString(tree, MXML_NO_CALLBACK);
+.fi
+.PP
+You can find a named element/node using the "mxmlFindElement()"
+function:
+.nf
+
+    mxml_node_t *node = mxmlFindElement(tree, tree, "name",
+                                        "attr", "value",
+                                        MXML_DESCEND);
+.fi
+.PP
+The "name", "attr", and "value" arguments can be passed as
+NULL to act as wildcards, e.g.:
+.nf
+
+    /* Find the first "a" element */
+    node = mxmlFindElement(tree, tree, "a", NULL, NULL,
+                           MXML_DESCEND);
+
+    /* Find the first "a" element with "href" attribute */
+    node = mxmlFindElement(tree, tree, "a", "href", NULL,
+                           MXML_DESCEND);
+
+    /* Find the first "a" element with "href" to a URL */
+    node = mxmlFindElement(tree, tree, "a", "href",
+                           "http://www.easysw.com/~mike/mxml/",
+                           MXML_DESCEND);
+
+    /* Find the first element with a "src" attribute*/
+    node = mxmlFindElement(tree, tree, NULL, "src", NULL,
+                           MXML_DESCEND);
+
+    /* Find the first element with a "src" = "foo.jpg" */
+    node = mxmlFindElement(tree, tree, NULL, "src",
+                           "foo.jpg", MXML_DESCEND);
+.fi
+.PP
+You can also iterate with the same function:
+.nf
+
+    mxml_node_t *node;
+
+    for (node = mxmlFindElement(tree, tree, "name", NULL,
+                                NULL, MXML_DESCEND);
+         node != NULL;
+         node = mxmlFindElement(node, tree, "name", NULL,
+                                NULL, MXML_DESCEND))
+    {
+      ... do something ...
+    }
+.fi
+.PP
+To find the value of a specific node in the tree, use the "mxmlFindPath()"
+function:
+.nf
+
+    mxml_node_t *value = mxmlFindPath(tree, "path/to/*/foo/bar");
+.fi
+.PP
+The "mxmlGetInteger()", "mxmlGetOpaque()", "mxmlGetReal()", and "mxmlGetText()"
+functions retrieve the value from a node:
+.nf
+
+    mxml_node_t *node;
+
+    int intvalue = mxmlGetInteger(node);
+
+    const char *opaquevalue = mxmlGetOpaque(node);
+
+    double realvalue = mxmlGetReal(node);
+
+    int whitespacevalue;
+    const char *textvalue = mxmlGetText(node, &whitespacevalue);
+.fi
+.PP
+Finally, once you are done with the XML data, use the
+"mxmlDelete()" function to recursively free the memory that
+is used for a particular node or the entire tree:
+.nf
+
+    mxmlDelete(tree);
+.fi
+.SH ENUMERATIONS
+.SS mxml_sax_event_e
+SAX event type.
+.TP 5
+MXML_SAX_CDATA
+.br
+CDATA node
+.TP 5
+MXML_SAX_COMMENT
+.br
+Comment node
+.TP 5
+MXML_SAX_DATA
+.br
+Data node
+.TP 5
+MXML_SAX_DIRECTIVE
+.br
+Processing directive node
+.TP 5
+MXML_SAX_ELEMENT_CLOSE
+.br
+Element closed
+.TP 5
+MXML_SAX_ELEMENT_OPEN
+.br
+Element opened
+.SS mxml_type_e
+The XML node type.
+.TP 5
+MXML_CUSTOM
+.br
+Custom data 
+.TP 5
+MXML_ELEMENT
+.br
+XML element with attributes
+.TP 5
+MXML_IGNORE
+.br
+Ignore/throw away node 
+.TP 5
+MXML_INTEGER
+.br
+Integer value
+.TP 5
+MXML_OPAQUE
+.br
+Opaque string
+.TP 5
+MXML_REAL
+.br
+Real value
+.TP 5
+MXML_TEXT
+.br
+Text fragment
+.SH FUNCTIONS
+.SS mxmlAdd
+Add a node to a tree.
+.PP
+.nf
+void mxmlAdd (
+    mxml_node_t *parent,
+    int where,
+    mxml_node_t *child,
+    mxml_node_t *node
+);
+.fi
+.PP
+Adds the specified node to the parent.  If the child argument is not
+\fBNULL\fR, puts the new node before or after the specified child depending
+on the value of the where argument.  If the child argument is \fBNULL\fR,
+puts the new node at the beginning of the child list (\fBMXML_ADD_BEFORE\fR)
+or at the end of the child list (\fBMXML_ADD_AFTER\fR).  The constant
+\fBMXML_ADD_TO_PARENT\fR can be used to specify a \fBNULL\fR child pointer.
+.SS mxmlDelete
+Delete a node and all of its children.
+.PP
+.nf
+void mxmlDelete (
+    mxml_node_t *node
+);
+.fi
+.PP
+If the specified node has a parent, this function first removes the
+node from its parent using the \fImxmlRemove\fR function.
+.SS mxmlElementDeleteAttr
+Delete an attribute.
+.PP
+.nf
+void mxmlElementDeleteAttr (
+    mxml_node_t *node,
+    const char *name
+);
+.fi
+.PP
+
+.SS mxmlElementGetAttr
+Get an attribute.
+.PP
+.nf
+const char * mxmlElementGetAttr (
+    mxml_node_t *node,
+    const char *name
+);
+.fi
+.PP
+This function returns \fBNULL\fR if the node is not an element or the
+named attribute does not exist.
+.SS mxmlElementGetAttrByIndex
+Get an element attribute by index.
+.PP
+.nf
+const char * mxmlElementGetAttrByIndex (
+    mxml_node_t *node,
+    int idx,
+    const char **name
+);
+.fi
+.PP
+The index ("idx") is 0-based.  \fBNULL\fR is returned if the specified index
+is out of range.
+
+
+.SS mxmlElementGetAttrCount
+Get the number of element attributes.
+.PP
+.nf
+int  mxmlElementGetAttrCount (
+    mxml_node_t *node
+);
+.fi
+.PP
+
+.SS mxmlElementSetAttr
+Set an attribute.
+.PP
+.nf
+void mxmlElementSetAttr (
+    mxml_node_t *node,
+    const char *name,
+    const char *value
+);
+.fi
+.PP
+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.
+.SS mxmlElementSetAttrf
+Set an attribute with a formatted value.
+.PP
+.nf
+void mxmlElementSetAttrf (
+    mxml_node_t *node,
+    const char *name,
+    const char *format,
+    ...
+);
+.fi
+.PP
+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.
+
+
+.SS mxmlEntityAddCallback
+Add a callback to convert entities to Unicode.
+.PP
+.nf
+int  mxmlEntityAddCallback (
+    mxml_entity_cb_t cb
+);
+.fi
+.SS mxmlEntityGetName
+Get the name that corresponds to the character value.
+.PP
+.nf
+const char * mxmlEntityGetName (
+    int val
+);
+.fi
+.PP
+If val does not need to be represented by a named entity, \fBNULL\fR is returned.
+.SS mxmlEntityGetValue
+Get the character corresponding to a named entity.
+.PP
+.nf
+int  mxmlEntityGetValue (
+    const char *name
+);
+.fi
+.PP
+The entity name can also be a numeric constant. -1 is returned if the
+name is not known.
+.SS mxmlEntityRemoveCallback
+Remove a callback.
+.PP
+.nf
+void mxmlEntityRemoveCallback (
+    mxml_entity_cb_t cb
+);
+.fi
+.SS mxmlFindElement
+Find the named element.
+.PP
+.nf
+mxml_node_t * mxmlFindElement (
+    mxml_node_t *node,
+    mxml_node_t *top,
+    const char *element,
+    const char *attr,
+    const char *value,
+    int descend
+);
+.fi
+.PP
+The search is constrained by the name, attribute name, and value; any
+\fBNULL\fR 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
+\fBMXML_DESCEND_FIRST\fR for the initial search and \fBMXML_NO_DESCEND\fR
+to find additional direct descendents of the node. The top node argument
+constrains the search to a particular node's children.
+.SS mxmlFindPath
+Find a node with the given path.
+.PP
+.nf
+mxml_node_t * mxmlFindPath (
+    mxml_node_t *top,
+    const char *path
+);
+.fi
+.PP
+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.
+.PP
+The first child node of the found node is returned if the given node has
+children and the first child is a value node.
+
+
+.SS mxmlGetCDATA
+Get the value for a CDATA node.
+.PP
+.nf
+const char * mxmlGetCDATA (
+    mxml_node_t *node
+);
+.fi
+.PP
+\fBNULL\fR is returned if the node is not a CDATA element.
+
+
+.SS mxmlGetCustom
+Get the value for a custom node.
+.PP
+.nf
+const void * mxmlGetCustom (
+    mxml_node_t *node
+);
+.fi
+.PP
+\fBNULL\fR is returned if the node (or its first child) is not a custom
+value node.
+
+
+.SS mxmlGetElement
+Get the name for an element node.
+.PP
+.nf
+const char * mxmlGetElement (
+    mxml_node_t *node
+);
+.fi
+.PP
+\fBNULL\fR is returned if the node is not an element node.
+
+
+.SS mxmlGetFirstChild
+Get the first child of an element node.
+.PP
+.nf
+mxml_node_t * mxmlGetFirstChild (
+    mxml_node_t *node
+);
+.fi
+.PP
+\fBNULL\fR is returned if the node is not an element node or if the node
+has no children.
+
+
+.SS mxmlGetInteger
+Get the integer value from the specified node or its
+first child.
+.PP
+.nf
+int  mxmlGetInteger (
+    mxml_node_t *node
+);
+.fi
+.PP
+0 is returned if the node (or its first child) is not an integer value node.
+
+
+.SS mxmlGetLastChild
+Get the last child of an element node.
+.PP
+.nf
+mxml_node_t * mxmlGetLastChild (
+    mxml_node_t *node
+);
+.fi
+.PP
+\fBNULL\fR is returned if the node is not an element node or if the node
+has no children.
+
+
+.SS mxmlGetNextSibling
+
+.PP
+.nf
+mxml_node_t * mxmlGetNextSibling (
+    mxml_node_t *node
+);
+.fi
+.SS mxmlGetOpaque
+Get an opaque string value for a node or its first child.
+.PP
+.nf
+const char * mxmlGetOpaque (
+    mxml_node_t *node
+);
+.fi
+.PP
+\fBNULL\fR is returned if the node (or its first child) is not an opaque
+value node.
+
+
+.SS mxmlGetParent
+Get the parent node.
+.PP
+.nf
+mxml_node_t * mxmlGetParent (
+    mxml_node_t *node
+);
+.fi
+.PP
+\fBNULL\fR is returned for a root node.
+
+
+.SS mxmlGetPrevSibling
+Get the previous node for the current parent.
+.PP
+.nf
+mxml_node_t * mxmlGetPrevSibling (
+    mxml_node_t *node
+);
+.fi
+.PP
+\fBNULL\fR is returned if this is the first child for the current parent.
+
+
+.SS mxmlGetReal
+Get the real value for a node or its first child.
+.PP
+.nf
+double  mxmlGetReal (
+    mxml_node_t *node
+);
+.fi
+.PP
+0.0 is returned if the node (or its first child) is not a real value node.
+
+
+.SS mxmlGetRefCount
+Get the current reference (use) count for a node.
+.PP
+.nf
+int  mxmlGetRefCount (
+    mxml_node_t *node
+);
+.fi
+.PP
+The initial reference count of new nodes is 1. Use the \fImxmlRetain\fR
+and \fImxmlRelease\fR functions to increment and decrement a node's
+reference count.
+
+\.
+.SS mxmlGetText
+Get the text value for a node or its first child.
+.PP
+.nf
+const char * mxmlGetText (
+    mxml_node_t *node,
+    int *whitespace
+);
+.fi
+.PP
+\fBNULL\fR is returned if the node (or its first child) is not a text node.
+The "whitespace" argument can be \fBNULL\fR.
+.PP
+Note: Text nodes consist of whitespace-delimited words. You will only get
+single words of text when reading an XML file with \fBMXML_TEXT\fR nodes.
+If you want the entire string between elements in the XML file, you MUST read
+the XML file with \fBMXML_OPAQUE\fR nodes and get the resulting strings
+using the \fImxmlGetOpaque\fR function instead.
+
+
+.SS mxmlGetType
+Get the node type.
+.PP
+.nf
+mxml_type_t  mxmlGetType (
+    mxml_node_t *node
+);
+.fi
+.PP
+\fBMXML_IGNORE\fR is returned if "node" is \fBNULL\fR.
+
+
+.SS mxmlGetUserData
+Get the user data pointer for a node.
+.PP
+.nf
+void * mxmlGetUserData (
+    mxml_node_t *node
+);
+.fi
+.PP
+
+.SS mxmlIndexDelete
+Delete an index.
+.PP
+.nf
+void mxmlIndexDelete (
+    mxml_index_t *ind
+);
+.fi
+.SS mxmlIndexEnum
+Return the next node in the index.
+.PP
+.nf
+mxml_node_t * mxmlIndexEnum (
+    mxml_index_t *ind
+);
+.fi
+.PP
+You should call \fImxmlIndexReset\fR prior to using this function to get
+the first node in the index.  Nodes are returned in the sorted order of the
+index.
+.SS mxmlIndexFind
+Find the next matching node.
+.PP
+.nf
+mxml_node_t * mxmlIndexFind (
+    mxml_index_t *ind,
+    const char *element,
+    const char *value
+);
+.fi
+.PP
+You should call \fImxmlIndexReset\fR prior to using this function for
+the first time with a particular set of "element" and "value"
+strings. Passing \fBNULL\fR for both "element" and "value" is equivalent
+to calling \fImxmlIndexEnum\fR.
+.SS mxmlIndexGetCount
+Get the number of nodes in an index.
+.PP
+.nf
+int  mxmlIndexGetCount (
+    mxml_index_t *ind
+);
+.fi
+.PP
+
+.SS mxmlIndexNew
+Create a new index.
+.PP
+.nf
+mxml_index_t * mxmlIndexNew (
+    mxml_node_t *node,
+    const char *element,
+    const char *attr
+);
+.fi
+.PP
+The index will contain all nodes that contain the named element and/or
+attribute.  If both "element" and "attr" are \fBNULL\fR, 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.
+.SS mxmlIndexReset
+Reset the enumeration/find pointer in the index and
+return the first node in the index.
+.PP
+.nf
+mxml_node_t * mxmlIndexReset (
+    mxml_index_t *ind
+);
+.fi
+.PP
+This function should be called prior to using \fImxmlIndexEnum\fR or
+\fImxmlIndexFind\fR for the first time.
+.SS mxmlLoadFd
+Load a file descriptor into an XML node tree.
+.PP
+.nf
+mxml_node_t * mxmlLoadFd (
+    mxml_node_t *top,
+    int fd,
+    mxml_load_cb_t cb
+);
+.fi
+.PP
+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.
+The constants \fBMXML_INTEGER_CALLBACK\fR, \fBMXML_OPAQUE_CALLBACK\fR,
+\fBMXML_REAL_CALLBACK\fR, and \fBMXML_TEXT_CALLBACK\fR are defined for
+loading child (data) nodes of the specified type.
+.PP
+Note: The most common programming error when using the Mini-XML library is
+to load an XML file using the \fBMXML_TEXT_CALLBACK\fR, which returns inline
+text as a series of whitespace-delimited words, instead of using the
+\fBMXML_OPAQUE_CALLBACK\fR which returns the inline text as a single string
+(including whitespace).
+.SS mxmlLoadFile
+Load a file into an XML node tree.
+.PP
+.nf
+mxml_node_t * mxmlLoadFile (
+    mxml_node_t *top,
+    FILE *fp,
+    mxml_load_cb_t cb
+);
+.fi
+.PP
+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.
+The constants \fBMXML_INTEGER_CALLBACK\fR, \fBMXML_OPAQUE_CALLBACK\fR,
+\fBMXML_REAL_CALLBACK\fR, and \fBMXML_TEXT_CALLBACK\fR are defined for
+loading child (data) nodes of the specified type.
+.PP
+Note: The most common programming error when using the Mini-XML library is
+to load an XML file using the \fBMXML_TEXT_CALLBACK\fR, which returns inline
+text as a series of whitespace-delimited words, instead of using the
+\fBMXML_OPAQUE_CALLBACK\fR which returns the inline text as a single string
+(including whitespace).
+.SS mxmlLoadString
+Load a string into an XML node tree.
+.PP
+.nf
+mxml_node_t * mxmlLoadString (
+    mxml_node_t *top,
+    const char *s,
+    mxml_load_cb_t cb
+);
+.fi
+.PP
+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.
+The constants \fBMXML_INTEGER_CALLBACK\fR, \fBMXML_OPAQUE_CALLBACK\fR,
+\fBMXML_REAL_CALLBACK\fR, and \fBMXML_TEXT_CALLBACK\fR are defined for
+loading child (data) nodes of the specified type.
+.PP
+Note: The most common programming error when using the Mini-XML library is
+to load an XML file using the \fBMXML_TEXT_CALLBACK\fR, which returns inline
+text as a series of whitespace-delimited words, instead of using the
+\fBMXML_OPAQUE_CALLBACK\fR which returns the inline text as a single string
+(including whitespace).
+.SS mxmlNewCDATA
+Create a new CDATA node.
+.PP
+.nf
+mxml_node_t * mxmlNewCDATA (
+    mxml_node_t *parent,
+    const char *data
+);
+.fi
+.PP
+The new CDATA node is added to the end of the specified parent's child
+list.  The constant \fBMXML_NO_PARENT\fR 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 currently use the
+\fBMXML_ELEMENT\fR type.
+
+
+.SS mxmlNewCustom
+Create a new custom data node.
+.PP
+.nf
+mxml_node_t * mxmlNewCustom (
+    mxml_node_t *parent,
+    void *data,
+    mxml_custom_destroy_cb_t destroy
+);
+.fi
+.PP
+The new custom node is added to the end of the specified parent's child
+list. The constant \fBMXML_NO_PARENT\fR can be used to specify that the new
+element node has no parent. \fBNULL\fR can be passed when the data in the
+node is not dynamically allocated or is separately managed.
+
+
+.SS mxmlNewElement
+Create a new element node.
+.PP
+.nf
+mxml_node_t * mxmlNewElement (
+    mxml_node_t *parent,
+    const char *name
+);
+.fi
+.PP
+The new element node is added to the end of the specified parent's child
+list. The constant \fBMXML_NO_PARENT\fR can be used to specify that the new
+element node has no parent.
+.SS mxmlNewInteger
+Create a new integer node.
+.PP
+.nf
+mxml_node_t * mxmlNewInteger (
+    mxml_node_t *parent,
+    int integer
+);
+.fi
+.PP
+The new integer node is added to the end of the specified parent's child
+list. The constant \fBMXML_NO_PARENT\fR can be used to specify that the new
+integer node has no parent.
+.SS mxmlNewOpaque
+Create a new opaque string.
+.PP
+.nf
+mxml_node_t * mxmlNewOpaque (
+    mxml_node_t *parent,
+    const char *opaque
+);
+.fi
+.PP
+The new opaque string node is added to the end of the specified parent's
+child list.  The constant \fBMXML_NO_PARENT\fR can be used to specify that
+the new opaque string node has no parent.  The opaque string must be nul-
+terminated and is copied into the new node.
+.SS mxmlNewOpaquef
+Create a new formatted opaque string node.
+.PP
+.nf
+mxml_node_t * mxmlNewOpaquef (
+    mxml_node_t *parent,
+    const char *format,
+    ...
+);
+.fi
+.PP
+The new opaque string node is added to the end of the specified parent's
+child list.  The constant \fBMXML_NO_PARENT\fR can be used to specify that
+the new opaque string node has no parent.  The format string must be
+nul-terminated and is formatted into the new node.
+.SS mxmlNewReal
+Create a new real number node.
+.PP
+.nf
+mxml_node_t * mxmlNewReal (
+    mxml_node_t *parent,
+    double real
+);
+.fi
+.PP
+The new real number node is added to the end of the specified parent's
+child list.  The constant \fBMXML_NO_PARENT\fR can be used to specify that
+the new real number node has no parent.
+.SS mxmlNewText
+Create a new text fragment node.
+.PP
+.nf
+mxml_node_t * mxmlNewText (
+    mxml_node_t *parent,
+    int whitespace,
+    const char *string
+);
+.fi
+.PP
+The new text node is added to the end of the specified parent's child
+list.  The constant \fBMXML_NO_PARENT\fR 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.
+.SS mxmlNewTextf
+Create a new formatted text fragment node.
+.PP
+.nf
+mxml_node_t * mxmlNewTextf (
+    mxml_node_t *parent,
+    int whitespace,
+    const char *format,
+    ...
+);
+.fi
+.PP
+The new text node is added to the end of the specified parent's child
+list.  The constant \fBMXML_NO_PARENT\fR 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.
+.SS mxmlNewXML
+Create a new XML document tree.
+.PP
+.nf
+mxml_node_t * mxmlNewXML (
+    const char *version
+);
+.fi
+.PP
+The "version" argument specifies the version number to put in the
+?xml element node. If \fBNULL\fR, version "1.0" is assumed.
+
+
+.SS mxmlRelease
+Release a node.
+.PP
+.nf
+int  mxmlRelease (
+    mxml_node_t *node
+);
+.fi
+.PP
+When the reference count reaches zero, the node (and any children)
+is deleted via \fImxmlDelete\fR.
+
+
+.SS mxmlRemove
+Remove a node from its parent.
+.PP
+.nf
+void mxmlRemove (
+    mxml_node_t *node
+);
+.fi
+.PP
+This function does not free memory used by the node - use \fImxmlDelete\fR
+for that.  This function does nothing if the node has no parent.
+.SS mxmlRetain
+Retain a node.
+.PP
+.nf
+int  mxmlRetain (
+    mxml_node_t *node
+);
+.fi
+.PP
+
+.SS mxmlSAXLoadFd
+Load a file descriptor into an XML node tree
+using a SAX callback.
+.PP
+.nf
+mxml_node_t * mxmlSAXLoadFd (
+    mxml_node_t *top,
+    int fd,
+    mxml_load_cb_t cb,
+    mxml_sax_cb_t sax_cb,
+    void *sax_data
+);
+.fi
+.PP
+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.
+The constants \fBMXML_INTEGER_CALLBACK\fR, \fBMXML_OPAQUE_CALLBACK\fR,
+\fBMXML_REAL_CALLBACK\fR, and \fBMXML_TEXT_CALLBACK\fR are defined for
+loading child nodes of the specified type.
+.PP
+The SAX callback must call \fImxmlRetain\fR 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.
+
+
+.SS mxmlSAXLoadFile
+Load a file into an XML node tree
+using a SAX callback.
+.PP
+.nf
+mxml_node_t * mxmlSAXLoadFile (
+    mxml_node_t *top,
+    FILE *fp,
+    mxml_load_cb_t cb,
+    mxml_sax_cb_t sax_cb,
+    void *sax_data
+);
+.fi
+.PP
+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.
+The constants \fBMXML_INTEGER_CALLBACK\fR, \fBMXML_OPAQUE_CALLBACK\fR,
+\fBMXML_REAL_CALLBACK\fR, and \fBMXML_TEXT_CALLBACK\fR are defined for
+loading child nodes of the specified type.
+.PP
+The SAX callback must call \fImxmlRetain\fR 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.
+
+
+.SS mxmlSAXLoadString
+Load a string into an XML node tree
+using a SAX callback.
+.PP
+.nf
+mxml_node_t * mxmlSAXLoadString (
+    mxml_node_t *top,
+    const char *s,
+    mxml_load_cb_t cb,
+    mxml_sax_cb_t sax_cb,
+    void *sax_data
+);
+.fi
+.PP
+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.
+The constants \fBMXML_INTEGER_CALLBACK\fR, \fBMXML_OPAQUE_CALLBACK\fR,
+\fBMXML_REAL_CALLBACK\fR, and \fBMXML_TEXT_CALLBACK\fR are defined for
+loading child nodes of the specified type.
+.PP
+The SAX callback must call \fImxmlRetain\fR 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.
+
+
+.SS mxmlSaveAllocString
+Save an XML tree to an allocated string.
+.PP
+.nf
+char * mxmlSaveAllocString (
+    mxml_node_t *node,
+    mxml_save_cb_t cb
+);
+.fi
+.PP
+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.  \fBNULL\fR is returned
+if the node would produce an empty string or if the string cannot be
+allocated.
+.PP
+The callback argument specifies a function that returns a whitespace
+string or NULL before and after each element.  If \fBMXML_NO_CALLBACK\fR
+is specified, whitespace will only be added before \fBMXML_TEXT\fR nodes
+with leading whitespace and before attribute names inside opening
+element tags.
+.SS mxmlSaveFd
+Save an XML tree to a file descriptor.
+.PP
+.nf
+int  mxmlSaveFd (
+    mxml_node_t *node,
+    int fd,
+    mxml_save_cb_t cb
+);
+.fi
+.PP
+The callback argument specifies a function that returns a whitespace
+string or NULL before and after each element. If \fBMXML_NO_CALLBACK\fR
+is specified, whitespace will only be added before \fBMXML_TEXT\fR nodes
+with leading whitespace and before attribute names inside opening
+element tags.
+.SS mxmlSaveFile
+Save an XML tree to a file.
+.PP
+.nf
+int  mxmlSaveFile (
+    mxml_node_t *node,
+    FILE *fp,
+    mxml_save_cb_t cb
+);
+.fi
+.PP
+The callback argument specifies a function that returns a whitespace
+string or NULL before and after each element. If \fBMXML_NO_CALLBACK\fR
+is specified, whitespace will only be added before \fBMXML_TEXT\fR nodes
+with leading whitespace and before attribute names inside opening
+element tags.
+.SS mxmlSaveString
+Save an XML node tree to a string.
+.PP
+.nf
+int  mxmlSaveString (
+    mxml_node_t *node,
+    char *buffer,
+    int bufsize,
+    mxml_save_cb_t cb
+);
+.fi
+.PP
+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.
+.PP
+The callback argument specifies a function that returns a whitespace
+string or NULL before and after each element. If \fBMXML_NO_CALLBACK\fR
+is specified, whitespace will only be added before \fBMXML_TEXT\fR nodes
+with leading whitespace and before attribute names inside opening
+element tags.
+.SS mxmlSetCDATA
+Set the element name of a CDATA node.
+.PP
+.nf
+int  mxmlSetCDATA (
+    mxml_node_t *node,
+    const char *data
+);
+.fi
+.PP
+The node is not changed if it (or its first child) is not a CDATA element node.
+
+
+.SS mxmlSetCustom
+Set the data and destructor of a custom data node.
+.PP
+.nf
+int  mxmlSetCustom (
+    mxml_node_t *node,
+    void *data,
+    mxml_custom_destroy_cb_t destroy
+);
+.fi
+.PP
+The node is not changed if it (or its first child) is not a custom node.
+
+
+.SS mxmlSetCustomHandlers
+Set the handling functions for custom data.
+.PP
+.nf
+void mxmlSetCustomHandlers (
+    mxml_custom_load_cb_t load,
+    mxml_custom_save_cb_t save
+);
+.fi
+.PP
+The load function accepts a node pointer and a data string and must
+return 0 on success and non-zero on error.
+.PP
+The save function accepts a node pointer and must return a malloc'd
+string on success and \fBNULL\fR on error.
+.SS mxmlSetElement
+Set the name of an element node.
+.PP
+.nf
+int  mxmlSetElement (
+    mxml_node_t *node,
+    const char *name
+);
+.fi
+.PP
+The node is not changed if it is not an element node.
+.SS mxmlSetErrorCallback
+Set the error message callback.
+.PP
+.nf
+void mxmlSetErrorCallback (
+    mxml_error_cb_t cb
+);
+.fi
+.SS mxmlSetInteger
+Set the value of an integer node.
+.PP
+.nf
+int  mxmlSetInteger (
+    mxml_node_t *node,
+    int integer
+);
+.fi
+.PP
+The node is not changed if it (or its first child) is not an integer node.
+.SS mxmlSetOpaque
+Set the value of an opaque node.
+.PP
+.nf
+int  mxmlSetOpaque (
+    mxml_node_t *node,
+    const char *opaque
+);
+.fi
+.PP
+The node is not changed if it (or its first child) is not an opaque node.
+.SS mxmlSetOpaquef
+Set the value of an opaque string node to a formatted string.
+.PP
+.nf
+int  mxmlSetOpaquef (
+    mxml_node_t *node,
+    const char *format,
+    ...
+);
+.fi
+.PP
+The node is not changed if it (or its first child) is not an opaque node.
+
+
+.SS mxmlSetReal
+Set the value of a real number node.
+.PP
+.nf
+int  mxmlSetReal (
+    mxml_node_t *node,
+    double real
+);
+.fi
+.PP
+The node is not changed if it (or its first child) is not a real number node.
+.SS mxmlSetText
+Set the value of a text node.
+.PP
+.nf
+int  mxmlSetText (
+    mxml_node_t *node,
+    int whitespace,
+    const char *string
+);
+.fi
+.PP
+The node is not changed if it (or its first child) is not a text node.
+.SS mxmlSetTextf
+Set the value of a text node to a formatted string.
+.PP
+.nf
+int  mxmlSetTextf (
+    mxml_node_t *node,
+    int whitespace,
+    const char *format,
+    ...
+);
+.fi
+.PP
+The node is not changed if it (or its first child) is not a text node.
+.SS mxmlSetUserData
+Set the user data pointer for a node.
+.PP
+.nf
+int  mxmlSetUserData (
+    mxml_node_t *node,
+    void *data
+);
+.fi
+.PP
+
+.SS mxmlSetWrapMargin
+Set the wrap margin when saving XML data.
+.PP
+.nf
+void mxmlSetWrapMargin (
+    int column
+);
+.fi
+.PP
+Wrapping is disabled when "column" is 0.
+
+
+.SS mxmlWalkNext
+Walk to the next logical node in the tree.
+.PP
+.nf
+mxml_node_t * mxmlWalkNext (
+    mxml_node_t *node,
+    mxml_node_t *top,
+    int descend
+);
+.fi
+.PP
+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.
+.SS mxmlWalkPrev
+Walk to the previous logical node in the tree.
+.PP
+.nf
+mxml_node_t * mxmlWalkPrev (
+    mxml_node_t *node,
+    mxml_node_t *top,
+    int descend
+);
+.fi
+.PP
+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.
+.SH TYPES
+.SS mxml_custom_destroy_cb_t
+Custom data destructor
+.PP
+.nf
+typedef void(*)(void *) mxml_custom_destroy_cb_t;
+.fi
+.SS mxml_custom_load_cb_t
+Custom data load callback function
+.PP
+.nf
+typedef int(*)(mxml_node_t *, const char *) mxml_custom_load_cb_t;
+.fi
+.SS mxml_custom_save_cb_t
+Custom data save callback function
+.PP
+.nf
+typedef char *(*)(mxml_node_t *) mxml_custom_save_cb_t;
+.fi
+.SS mxml_entity_cb_t
+Entity callback function
+.PP
+.nf
+typedef int(*)(const char *) mxml_entity_cb_t;
+.fi
+.SS mxml_error_cb_t
+Error callback function
+.PP
+.nf
+typedef void(*)(const char *) mxml_error_cb_t;
+.fi
+.SS mxml_index_t
+An XML node index.
+.PP
+.nf
+typedef struct mxml_index_s mxml_index_t;
+.fi
+.SS mxml_load_cb_t
+Load callback function
+.PP
+.nf
+typedef mxml_type_t(*)(mxml_node_t *) mxml_load_cb_t;
+.fi
+.SS mxml_node_t
+An XML node.
+.PP
+.nf
+typedef struct mxml_node_s mxml_node_t;
+.fi
+.SS mxml_save_cb_t
+Save callback function
+.PP
+.nf
+typedef const char *(*)(mxml_node_t *, int) mxml_save_cb_t;
+.fi
+.SS mxml_sax_cb_t
+SAX callback function
+.PP
+.nf
+typedef void(*)(mxml_node_t *, mxml_sax_event_t, void *) mxml_sax_cb_t;
+.fi
+.SS mxml_sax_event_t
+SAX event type.
+.PP
+.nf
+typedef enum mxml_sax_event_e mxml_sax_event_t;
+.fi
+.SS mxml_type_t
+The XML node type.
+.PP
+.nf
+typedef enum mxml_type_e mxml_type_t;
+.fi
+.SH SEE ALSO
+Mini-XML Programmers Manual, https://www.msweet.org/mxml
+.SH COPYRIGHT
+Copyright \[co] 2003-2019 by Michael R Sweet.

BIN
mxml.mod/mxml/doc/mxml.epub


+ 2537 - 0
mxml.mod/mxml/doc/mxml.html

@@ -0,0 +1,2537 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Mini-XML API Reference</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+    <meta name="creator" content="1.0">
+    <meta name="author" content="Michael R Sweet">
+    <meta name="copyright" content="Copyright &#xa9; 2003-2019, All Rights Reserved.">
+    <meta name="version" content="0.0">
+    <style type="text/css"><!--
+body, p, h1, h2, h3, h4 {
+  font-family: sans-serif;
+}
+div.body h1 {
+  font-size: 250%;
+  font-weight: bold;
+  margin: 0;
+}
+div.body h2 {
+  font-size: 250%;
+  margin-top: 1.5em;
+}
+div.body h3 {
+  font-size: 150%;
+  margin-bottom: 0.5em;
+  margin-top: 1.5em;
+}
+div.body h4 {
+  font-size: 110%;
+  margin-bottom: 0.5em;
+  margin-top: 1.5em;
+}
+div.body h5 {
+  font-size: 100%;
+  margin-bottom: 0.5em;
+  margin-top: 1.5em;
+}
+div.contents {
+  background: #e8e8e8;
+  border: solid thin black;
+  padding: 10px;
+}
+div.contents h1 {
+  font-size: 110%;
+}
+div.contents h2 {
+  font-size: 100%;
+}
+div.contents ul.contents {
+  font-size: 80%;
+}
+.class {
+  border-bottom: solid 2px gray;
+}
+.constants {
+}
+.description {
+  margin-top: 0.5em;
+}
+.discussion {
+}
+.enumeration {
+  border-bottom: solid 2px gray;
+}
+.function {
+  border-bottom: solid 2px gray;
+  margin-bottom: 0;
+}
+.members {
+}
+.method {
+}
+.parameters {
+}
+.returnvalue {
+}
+.struct {
+  border-bottom: solid 2px gray;
+}
+.typedef {
+  border-bottom: solid 2px gray;
+}
+.union {
+  border-bottom: solid 2px gray;
+}
+.variable {
+}
+h1, h2, h3, h4, h5, h6 {
+  page-break-inside: avoid;
+}
+blockquote {
+  border: solid thin gray;
+  box-shadow: 3px 3px 5px rgba(0,0,0,0.5);
+  padding: 0px 10px;
+  page-break-inside: avoid;
+}
+p code, li code, p.code, pre, ul.code li {
+  background: rgba(127,127,127,0.1);
+  border: thin dotted gray;
+  font-family: monospace;
+  font-size: 90%;
+  hyphens: manual;
+  -webkit-hyphens: manual;
+  page-break-inside: avoid;
+}
+p.code, pre, ul.code li {
+  padding: 10px;
+}
+p code, li code {
+  padding: 2px 5px;
+}
+a:link, a:visited {
+  text-decoration: none;
+}
+span.info {
+  background: black;
+  border: solid thin black;
+  color: white;
+  font-size: 80%;
+  font-style: italic;
+  font-weight: bold;
+  white-space: nowrap;
+}
+h3 span.info, h4 span.info {
+  border-top-left-radius: 10px;
+  border-top-right-radius: 10px;
+  float: right;
+  padding: 3px 6px;
+}
+ul.code, ul.contents, ul.subcontents {
+  list-style-type: none;
+  margin: 0;
+  padding-left: 0;
+}
+ul.code li {
+  margin: 0;
+}
+ul.contents > li {
+  margin-top: 1em;
+}
+ul.contents li ul.code, ul.contents li ul.subcontents {
+  padding-left: 2em;
+}
+table.list {
+  border-collapse: collapse;
+  width: 100%;
+}
+table.list tr:nth-child(even) {
+  background: rgba(127,127,127,0.1);]n}
+table.list th {
+  border-right: 2px solid gray;
+  font-family: monospace;
+  padding: 5px 10px 5px 2px;
+  text-align: right;
+  vertical-align: top;
+}
+table.list td {
+  padding: 5px 2px 5px 10px;
+  text-align: left;
+  vertical-align: top;
+}
+h1.title {
+}
+h2.title {
+  border-bottom: solid 2px black;
+}
+h3.title {
+  border-bottom: solid 2px black;
+}
+--></style>
+  </head>
+  <body>
+<p><img src="doc/mxml-cover.png" width="100%"></p>
+    <h1 class="title">Mini-XML API Reference</h1>
+    <p>Michael R Sweet</p>
+    <p>Copyright &#xa9; 2003-2019, All Rights Reserved.</p>
+    <div class="contents">
+      <h2 class="title">Contents</h2>
+      <ul class="contents">
+        <li><a href="#introduction">Introduction</a><ul class="subcontents">
+          <li><a href="#history">History</a></li>
+          <li><a href="#resources">Resources</a></li>
+          <li><a href="#legal-stuff">Legal Stuff</a></li>
+        </ul></li>
+        <li><a href="#using-mini-xml">Using Mini-XML</a><ul class="subcontents">
+          <li><a href="#loading-an-xml-file">Loading an XML File</a></li>
+          <li><a href="#nodes">Nodes</a></li>
+          <li><a href="#creating-xml-documents">Creating XML Documents</a></li>
+          <li><a href="#saving-an-xml-file">Saving an XML File</a></li>
+          <li><a href="#memory-management">Memory Management</a></li>
+        </ul></li>
+        <li><a href="#more-about-nodes">More About Nodes</a><ul class="subcontents">
+          <li><a href="#element-nodes">Element Nodes</a></li>
+          <li><a href="#cdata-nodes">CDATA Nodes</a></li>
+          <li><a href="#comment-nodes">Comment Nodes</a></li>
+          <li><a href="#processing-instruction-nodes">Processing Instruction Nodes</a></li>
+          <li><a href="#integer-nodes">Integer Nodes</a></li>
+          <li><a href="#opaque-string-nodes">Opaque String Nodes</a></li>
+          <li><a href="#text-nodes">Text Nodes</a></li>
+          <li><a href="#real-number-nodes">Real Number Nodes</a></li>
+        </ul></li>
+        <li><a href="#locating-data-in-an-xml-document">Locating Data in an XML Document</a><ul class="subcontents">
+          <li><a href="#finding-nodes">Finding Nodes</a></li>
+          <li><a href="#iterating-nodes">Iterating Nodes</a></li>
+          <li><a href="#indexing">Indexing</a></li>
+        </ul></li>
+        <li><a href="#custom-data-types">Custom Data Types</a></li>
+        <li><a href="#sax-stream-loading-of-documents">SAX (Stream) Loading of Documents</a></li>
+        <li><a href="#FUNCTIONS">Functions</a><ul class="subcontents">
+          <li><a href="#mxmlAdd">mxmlAdd</a></li>
+          <li><a href="#mxmlDelete">mxmlDelete</a></li>
+          <li><a href="#mxmlElementDeleteAttr">mxmlElementDeleteAttr</a></li>
+          <li><a href="#mxmlElementGetAttr">mxmlElementGetAttr</a></li>
+          <li><a href="#mxmlElementGetAttrByIndex">mxmlElementGetAttrByIndex</a></li>
+          <li><a href="#mxmlElementGetAttrCount">mxmlElementGetAttrCount</a></li>
+          <li><a href="#mxmlElementSetAttr">mxmlElementSetAttr</a></li>
+          <li><a href="#mxmlElementSetAttrf">mxmlElementSetAttrf</a></li>
+          <li><a href="#mxmlEntityAddCallback">mxmlEntityAddCallback</a></li>
+          <li><a href="#mxmlEntityGetName">mxmlEntityGetName</a></li>
+          <li><a href="#mxmlEntityGetValue">mxmlEntityGetValue</a></li>
+          <li><a href="#mxmlEntityRemoveCallback">mxmlEntityRemoveCallback</a></li>
+          <li><a href="#mxmlFindElement">mxmlFindElement</a></li>
+          <li><a href="#mxmlFindPath">mxmlFindPath</a></li>
+          <li><a href="#mxmlGetCDATA">mxmlGetCDATA</a></li>
+          <li><a href="#mxmlGetCustom">mxmlGetCustom</a></li>
+          <li><a href="#mxmlGetElement">mxmlGetElement</a></li>
+          <li><a href="#mxmlGetFirstChild">mxmlGetFirstChild</a></li>
+          <li><a href="#mxmlGetInteger">mxmlGetInteger</a></li>
+          <li><a href="#mxmlGetLastChild">mxmlGetLastChild</a></li>
+          <li><a href="#mxmlGetNextSibling">mxmlGetNextSibling</a></li>
+          <li><a href="#mxmlGetOpaque">mxmlGetOpaque</a></li>
+          <li><a href="#mxmlGetParent">mxmlGetParent</a></li>
+          <li><a href="#mxmlGetPrevSibling">mxmlGetPrevSibling</a></li>
+          <li><a href="#mxmlGetReal">mxmlGetReal</a></li>
+          <li><a href="#mxmlGetRefCount">mxmlGetRefCount</a></li>
+          <li><a href="#mxmlGetText">mxmlGetText</a></li>
+          <li><a href="#mxmlGetType">mxmlGetType</a></li>
+          <li><a href="#mxmlGetUserData">mxmlGetUserData</a></li>
+          <li><a href="#mxmlIndexDelete">mxmlIndexDelete</a></li>
+          <li><a href="#mxmlIndexEnum">mxmlIndexEnum</a></li>
+          <li><a href="#mxmlIndexFind">mxmlIndexFind</a></li>
+          <li><a href="#mxmlIndexGetCount">mxmlIndexGetCount</a></li>
+          <li><a href="#mxmlIndexNew">mxmlIndexNew</a></li>
+          <li><a href="#mxmlIndexReset">mxmlIndexReset</a></li>
+          <li><a href="#mxmlLoadFd">mxmlLoadFd</a></li>
+          <li><a href="#mxmlLoadFile">mxmlLoadFile</a></li>
+          <li><a href="#mxmlLoadString">mxmlLoadString</a></li>
+          <li><a href="#mxmlNewCDATA">mxmlNewCDATA</a></li>
+          <li><a href="#mxmlNewCustom">mxmlNewCustom</a></li>
+          <li><a href="#mxmlNewElement">mxmlNewElement</a></li>
+          <li><a href="#mxmlNewInteger">mxmlNewInteger</a></li>
+          <li><a href="#mxmlNewOpaque">mxmlNewOpaque</a></li>
+          <li><a href="#mxmlNewOpaquef">mxmlNewOpaquef</a></li>
+          <li><a href="#mxmlNewReal">mxmlNewReal</a></li>
+          <li><a href="#mxmlNewText">mxmlNewText</a></li>
+          <li><a href="#mxmlNewTextf">mxmlNewTextf</a></li>
+          <li><a href="#mxmlNewXML">mxmlNewXML</a></li>
+          <li><a href="#mxmlRelease">mxmlRelease</a></li>
+          <li><a href="#mxmlRemove">mxmlRemove</a></li>
+          <li><a href="#mxmlRetain">mxmlRetain</a></li>
+          <li><a href="#mxmlSAXLoadFd">mxmlSAXLoadFd</a></li>
+          <li><a href="#mxmlSAXLoadFile">mxmlSAXLoadFile</a></li>
+          <li><a href="#mxmlSAXLoadString">mxmlSAXLoadString</a></li>
+          <li><a href="#mxmlSaveAllocString">mxmlSaveAllocString</a></li>
+          <li><a href="#mxmlSaveFd">mxmlSaveFd</a></li>
+          <li><a href="#mxmlSaveFile">mxmlSaveFile</a></li>
+          <li><a href="#mxmlSaveString">mxmlSaveString</a></li>
+          <li><a href="#mxmlSetCDATA">mxmlSetCDATA</a></li>
+          <li><a href="#mxmlSetCustom">mxmlSetCustom</a></li>
+          <li><a href="#mxmlSetCustomHandlers">mxmlSetCustomHandlers</a></li>
+          <li><a href="#mxmlSetElement">mxmlSetElement</a></li>
+          <li><a href="#mxmlSetErrorCallback">mxmlSetErrorCallback</a></li>
+          <li><a href="#mxmlSetInteger">mxmlSetInteger</a></li>
+          <li><a href="#mxmlSetOpaque">mxmlSetOpaque</a></li>
+          <li><a href="#mxmlSetOpaquef">mxmlSetOpaquef</a></li>
+          <li><a href="#mxmlSetReal">mxmlSetReal</a></li>
+          <li><a href="#mxmlSetText">mxmlSetText</a></li>
+          <li><a href="#mxmlSetTextf">mxmlSetTextf</a></li>
+          <li><a href="#mxmlSetUserData">mxmlSetUserData</a></li>
+          <li><a href="#mxmlSetWrapMargin">mxmlSetWrapMargin</a></li>
+          <li><a href="#mxmlWalkNext">mxmlWalkNext</a></li>
+          <li><a href="#mxmlWalkPrev">mxmlWalkPrev</a></li>
+        </ul></li>
+        <li><a href="#TYPES">Data Types</a><ul class="subcontents">
+          <li><a href="#mxml_custom_destroy_cb_t">mxml_custom_destroy_cb_t</a></li>
+          <li><a href="#mxml_custom_load_cb_t">mxml_custom_load_cb_t</a></li>
+          <li><a href="#mxml_custom_save_cb_t">mxml_custom_save_cb_t</a></li>
+          <li><a href="#mxml_entity_cb_t">mxml_entity_cb_t</a></li>
+          <li><a href="#mxml_error_cb_t">mxml_error_cb_t</a></li>
+          <li><a href="#mxml_index_t">mxml_index_t</a></li>
+          <li><a href="#mxml_load_cb_t">mxml_load_cb_t</a></li>
+          <li><a href="#mxml_node_t">mxml_node_t</a></li>
+          <li><a href="#mxml_save_cb_t">mxml_save_cb_t</a></li>
+          <li><a href="#mxml_sax_cb_t">mxml_sax_cb_t</a></li>
+          <li><a href="#mxml_sax_event_t">mxml_sax_event_t</a></li>
+          <li><a href="#mxml_type_t">mxml_type_t</a></li>
+        </ul></li>
+        <li><a href="#ENUMERATIONS">Enumerations</a><ul class="subcontents">
+          <li><a href="#mxml_sax_event_e">mxml_sax_event_e</a></li>
+          <li><a href="#mxml_type_e">mxml_type_e</a></li>
+        </ul></li>
+      </ul>
+    </div>
+    <div class="body">
+    <h2><a id="introduction">Introduction</a></h2>
+    <p>Mini-XML is a small XML parsing library that you can use to read XML data files or strings in your application without requiring large non-standard libraries. Mini-XML provides the following functionality:</p>
+    <ul>
+    <li>Reading of UTF-8 and UTF-16 and writing of UTF-8 encoded XML files and strings.</li>
+    <li>Data is stored in a linked-list tree structure, preserving the XML data hierarchy.</li>
+    <li>SAX (streamed) reading of XML files and strings to minimize memory usage.</li>
+    <li>Supports arbitrary element names, attributes, and attribute values with no preset limits, just available memory.</li>
+    <li>Supports integer, real, opaque (&quot;cdata&quot;), and text data types in &quot;leaf&quot; nodes.</li>
+    <li>Functions for creating and managing trees of data.</li>
+    <li>&quot;Find&quot; and &quot;walk&quot; functions for easily locating and navigating trees of data.</li>
+</ul>
+    <p>Mini-XML doesn't do validation or other types of processing on the data based upon schema files or other sources of definition information.</p>
+    <h3><a id="history">History</a></h3>
+    <p>Mini-XML was initially developed for the <a href="http://gutenprint.sf.net/">Gutenprint</a> project to replace the rather large and unwieldy <code>libxml2</code> library with something substantially smaller and easier-to-use. It all began one morning in June of 2003 when Robert posted the following sentence to the developer's list:</p>
+    <blockquote>
+    <p>It's bad enough that we require libxml2, but rolling our own XML parser is a bit more than we can handle.</p>
+</blockquote>
+    <p>I then replied with:</p>
+    <blockquote>
+    <p>Given the limited scope of what you use in XML, it should be trivial to code a mini-XML API in a few hundred lines of code.</p>
+</blockquote>
+    <p>I took my own challenge and coded furiously for two days to produced the initial public release of Mini-XML, total lines of code: 696. Robert promptly integrated Mini-XML into Gutenprint and removed libxml2.</p>
+    <p>Thanks to lots of feedback and support from various developers, Mini-XML has evolved since then to provide a more complete XML implementation and now stands at a whopping 4,115 lines of code, compared to 140,410 lines of code for libxml2 version 2.9.1.</p>
+    <h3><a id="resources">Resources</a></h3>
+    <p>The Mini-XML home page can be found at:</p>
+    <pre><code>https://michaelrsweet.github.io/mxml
+</code></pre>
+    <p>From here you can download the current version of Mini-XML, the issue tracker, and other resources.</p>
+    <h3><a id="legal-stuff">Legal Stuff</a></h3>
+    <p>The Mini-XML library is copyright &#xa9; 2003-2017 by Michael R Sweet and is provided under version 2 of the GNU Library General Public License (LGPL2) with the following exceptions:</p>
+    <ol>
+    <li>Static linking of applications to the Mini-XML library does not constitute a derivative work and does not require the author to provide source code for the application, use the shared Mini-XML libraries, or link their applications against a user-supplied version of Mini-XML.</li>
+    <p>If you link the application to a modified version of Mini-XML, then the changes to Mini-XML must be provided under the terms of the LGPL2 in sections 1, 2, and 4.</p>
+    <li>You do not have to provide a copy of the Mini-XML license with programs that are linked to the Mini-XML library, nor do you have to identify the Mini-XML license in your program or documentation as required by section 6 of the LGPL2.</li>
+</ol>
+    <p>A copy of the complete license is available in the file <code>COPYING</code> provided with the source code.</p>
+    <h2><a id="using-mini-xml">Using Mini-XML</a></h2>
+    <p>Mini-XML provides a single header file which you include:</p>
+    <pre><code>#include &lt;mxml.h&gt;
+</code></pre>
+    <p>The Mini-XML library is included with your program using the <code>-lmxml</code> option:</p>
+    <pre><code>gcc -o myprogram myprogram.c -lmxml
+</code></pre>
+    <p>If you have the <code>pkg-config</code> software installed, you can use it to determine the proper compiler and linker options for your installation:</p>
+    <pre><code>gcc `pkg-config --cflags mxml` -o myprogram myprogram.c `pkg-config --libs mxml`
+</code></pre>
+    <h3><a id="loading-an-xml-file">Loading an XML File</a></h3>
+    <p>You load an XML file using the <code>mxmlLoadFile</code> function:</p>
+    <pre><code>mxml_node_t *
+mxmlLoadFile(mxml_node_t *top, FILE *fp,
+             mxml_type_t (*cb)(mxml_node_t *));
+</code></pre>
+    <p>The <code>cb</code> argument specifies a function that assigns child (value) node types for each element in the document. The callback can be a function you provide or one of the standard functions provided with Mini-XML. For example, to load the XML file &quot;filename.xml&quot; containing text strings you can use the <code>MXML_OPAQUE_CALLBACK</code> function:</p>
+    <pre><code>FILE *fp;
+mxml_node_t *tree;
+
+fp = fopen(&quot;filename.xml&quot;, &quot;r&quot;);
+tree = mxmlLoadFile(NULL, fp, MXML_OPAQUE_CALLBACK);
+fclose(fp);
+</code></pre>
+    <p>Mini-XML also provides functions to load from a file descriptor or string:</p>
+    <pre><code>mxml_node_t *
+mxmlLoadFd(mxml_node_t *top, int fd,
+           mxml_type_t (*cb)(mxml_node_t *));
+
+mxml_node_t *
+mxmlLoadString(mxml_node_t *top, const char *s,
+               mxml_type_t (*cb)(mxml_node_t *));
+</code></pre>
+    <h4><a id="load-callbacks">Load Callbacks</a></h4>
+    <p>The last argument to the <code>mxmlLoad</code> functions is a callback function which is used to determine the value type of each data node in an XML document. Mini-XML defines several standard callbacks for simple XML data files:</p>
+    <ul>
+    <li><code>MXML_INTEGER_CALLBACK</code>: All data nodes contain whitespace-separated integers.</li>
+    <li><code>MXML_OPAQUE_CALLBACK</code>: All data nodes contain opaque strings with whitespace preserved.</li>
+    <li><code>MXML_REAL_CALLBACK</code> - All data nodes contain whitespace-separated floating-point numbers.</li>
+    <li><code>MXML_TEXT_CALLBACK</code> - All data nodes contain whitespace-separated strings.</li>
+</ul>
+    <p>You can provide your own callback functions for more complex XML documents. Your callback function will receive a pointer to the current element node and must return the value type of the immediate children for that element node: <code>MXML_CUSTOM</code>, <code>MXML_INTEGER</code>, <code>MXML_OPAQUE</code>, <code>MXML_REAL</code>, or <code>MXML_TEXT</code>. The function is called <em>after</em> the element and its attributes have been read, so you can look at the element name, attributes, and attribute values to determine the proper value type to return.</p>
+    <p>The following callback function looks for an attribute named &quot;type&quot; or the element name to determine the value type for its child nodes:</p>
+    <pre><code>mxml_type_t
+type_cb(mxml_node_t *node)
+{
+  const char *type;
+
+ /*
+  * You can lookup attributes and/or use the element name,
+  * hierarchy, etc...
+  */
+
+  type = mxmlElementGetAttr(node, &quot;type&quot;);
+  if (type == NULL)
+    type = mxmlGetElement(node);
+
+  if (!strcmp(type, &quot;integer&quot;))
+    return (MXML_INTEGER);
+  else if (!strcmp(type, &quot;opaque&quot;))
+    return (MXML_OPAQUE);
+  else if (!strcmp(type, &quot;real&quot;))
+    return (MXML_REAL);
+  else
+    return (MXML_TEXT);
+}
+</code></pre>
+    <p>To use this callback function, simply use the name when you call any of the load functions:</p>
+    <pre><code>FILE *fp;
+mxml_node_t *tree;
+
+fp = fopen(&quot;filename.xml&quot;, &quot;r&quot;);
+tree = mxmlLoadFile(NULL, fp, type_cb);
+fclose(fp);
+</code></pre>
+    <h3><a id="nodes">Nodes</a></h3>
+    <p>Every piece of information in an XML file is stored in memory in &quot;nodes&quot;. Nodes are defined by the <code>mxml_node_t</code> structure. Each node has a typed value, optional user data, a parent node, sibling nodes (previous and next), and potentially child nodes.</p>
+    <p>For example, if you have an XML file like the following:</p>
+    <pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;data&gt;
+    &lt;node&gt;val1&lt;/node&gt;
+    &lt;node&gt;val2&lt;/node&gt;
+    &lt;node&gt;val3&lt;/node&gt;
+    &lt;group&gt;
+        &lt;node&gt;val4&lt;/node&gt;
+        &lt;node&gt;val5&lt;/node&gt;
+        &lt;node&gt;val6&lt;/node&gt;
+    &lt;/group&gt;
+    &lt;node&gt;val7&lt;/node&gt;
+    &lt;node&gt;val8&lt;/node&gt;
+&lt;/data&gt;
+</code></pre>
+    <p>the node tree for the file would look like the following in memory:</p>
+    <pre><code>?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?
+  |
+data
+  |
+node - node - node - group - node - node
+  |      |      |      |       |      |
+val1   val2   val3     |     val7   val8
+                       |
+                     node - node - node
+                       |      |      |
+                     val4   val5   val6
+</code></pre>
+where &quot;-&quot; is a pointer to the sibling node and &quot;&quot; is a pointer to the first    <p>child or parent node.</p>
+    <p>The <code>mxmlGetType</code> function gets the type of a node:</p>
+    <pre><code>mxml_type_t
+mxmlGetType(mxml_node_t *node);
+</code></pre>
+    <blockquote>
+    <p>Note: CDATA, comment, and processing directive nodes are currently stored in memory as special elements. This will be changed in a future major release of Mini-XML.</p>
+</blockquote>
+    <p>The parent and sibling nodes are accessed using the <code>mxmlGetParent</code>, <code>mxmlGetNextSibling</code>, and <code>mxmlGetPreviousSibling</code> functions, while the children of an element node are accessed using the <code>mxmlGetFirstChild</code> or <code>mxmlGetLastChild</code> functions:</p>
+    <pre><code>mxml_node_t *
+mxmlGetFirstChild(mxml_node_t *node);
+
+mxml_node_t *
+mxmlGetLastChild(mxml_node_t *node);
+
+mxml_node_t *
+mxmlGetNextSibling(mxml_node_t *node);
+
+mxml_node_t *
+mxmlGetParent(mxml_node_t *node);
+
+mxml_node_t *
+mxmlGetPrevSibling(mxml_node_t *node);
+</code></pre>
+    <p>The <code>mxmlGetUserData</code> function gets any user (application) data associated with the node:</p>
+    <pre><code>void *
+mxmlGetUserData(mxml_node_t *node);
+</code></pre>
+    <h3><a id="creating-xml-documents">Creating XML Documents</a></h3>
+    <p>You can create and update XML documents in memory using the various <code>mxmlNew</code> functions. The following code will create the XML document described in the previous section:</p>
+    <pre><code>mxml_node_t *xml;    /* &lt;?xml ... ?&gt; */
+mxml_node_t *data;   /* &lt;data&gt; */
+mxml_node_t *node;   /* &lt;node&gt; */
+mxml_node_t *group;  /* &lt;group&gt; */
+
+xml = mxmlNewXML(&quot;1.0&quot;);
+
+data = mxmlNewElement(xml, &quot;data&quot;);
+
+    node = mxmlNewElement(data, &quot;node&quot;);
+    mxmlNewText(node, 0, &quot;val1&quot;);
+    node = mxmlNewElement(data, &quot;node&quot;);
+    mxmlNewText(node, 0, &quot;val2&quot;);
+    node = mxmlNewElement(data, &quot;node&quot;);
+    mxmlNewText(node, 0, &quot;val3&quot;);
+
+    group = mxmlNewElement(data, &quot;group&quot;);
+
+        node = mxmlNewElement(group, &quot;node&quot;);
+        mxmlNewText(node, 0, &quot;val4&quot;);
+        node = mxmlNewElement(group, &quot;node&quot;);
+        mxmlNewText(node, 0, &quot;val5&quot;);
+        node = mxmlNewElement(group, &quot;node&quot;);
+        mxmlNewText(node, 0, &quot;val6&quot;);
+
+    node = mxmlNewElement(data, &quot;node&quot;);
+    mxmlNewText(node, 0, &quot;val7&quot;);
+    node = mxmlNewElement(data, &quot;node&quot;);
+    mxmlNewText(node, 0, &quot;val8&quot;);
+</code></pre>
+    <p>We start by creating the declaration node common to all XML files using the <code>mxmlNewXML</code> function:</p>
+    <pre><code>xml = mxmlNewXML(&quot;1.0&quot;);
+</code></pre>
+    <p>We then create the <code>&lt;data&gt;</code> node used for this document using the <code>mxmlNewElement</code> function. The first argument specifies the parent node (<code>xml</code>) while the second specifies the element name (<code>data</code>):</p>
+    <pre><code>data = mxmlNewElement(xml, &quot;data&quot;);
+</code></pre>
+    <p>Each <code>&lt;node&gt;...&lt;/node&gt;</code> in the file is created using the <code>mxmlNewElement</code> and <code>mxmlNewText</code> functions. The first argument of <code>mxmlNewText</code> specifies the parent node (<code>node</code>). The second argument specifies whether whitespace appears before the text - 0 or false in this case. The last argument specifies the actual text to add:</p>
+    <pre><code>node = mxmlNewElement(data, &quot;node&quot;);
+mxmlNewText(node, 0, &quot;val1&quot;);
+</code></pre>
+    <p>The resulting in-memory XML document can then be saved or processed just like one loaded from disk or a string.</p>
+    <h3><a id="saving-an-xml-file">Saving an XML File</a></h3>
+    <p>You save an XML file using the <code>mxmlSaveFile</code> function:</p>
+    <pre><code>int
+mxmlSaveFile(mxml_node_t *node, FILE *fp,
+             mxml_save_cb_t cb);
+</code></pre>
+    <p>The <code>cb</code> argument specifies a function that returns the whitespace (if any) that is inserted before and after each element node. The <code>MXML_NO_CALLBACK</code> constant tells Mini-XML to not include any extra whitespace. For example, so save an XML file to the file &quot;filename.xml&quot; with no extra whitespace:</p>
+    <pre><code>FILE *fp;
+
+fp = fopen(&quot;filename.xml&quot;, &quot;w&quot;);
+mxmlSaveFile(xml, fp, MXML_NO_CALLBACK);
+fclose(fp);
+</code></pre>
+    <p>Mini-XML also provides functions to save to a file descriptor or strings:</p>
+    <pre><code>char *
+mxmlSaveAllocString(mxml_node_t *node, mxml_save_cb_t cb);
+
+int
+mxmlSaveFd(mxml_node_t *node, int fd, mxml_save_cb_t cb);
+
+int
+mxmlSaveString(mxml_node_t *node, char *buffer, int bufsize,
+               mxml_save_cb_t cb);
+</code></pre>
+    <h4><a id="controlling-line-wrapping">Controlling Line Wrapping</a></h4>
+    <p>When saving XML documents, Mini-XML normally wraps output lines at column 75 so that the text is readable in terminal windows. The <code>mxmlSetWrapMargin</code> function overrides the default wrap margin for the current thread:</p>
+    <pre><code>void mxmlSetWrapMargin(int column);
+</code></pre>
+    <p>For example, the following code sets the margin to 132 columns:</p>
+    <pre><code>mxmlSetWrapMargin(132);
+</code></pre>
+    <p>while the following code disables wrapping by setting the margin to 0:</p>
+    <pre><code>mxmlSetWrapMargin(0);
+</code></pre>
+    <h4><a id="save-callbacks">Save Callbacks</a></h4>
+    <p>The last argument to the <code>mxmlSave</code> functions is a callback function which is used to automatically insert whitespace in an XML document. Your callback function will be called up to four times for each element node with a pointer to the node and a &quot;where&quot; value of <code>MXML_WS_BEFORE_OPEN</code>, <code>MXML_WS_AFTER_OPEN</code>, <code>MXML_WS_BEFORE_CLOSE</code>, or <code>MXML_WS_AFTER_CLOSE</code>. The callback function should return <code>NULL</code> if no whitespace should be added or the string to insert (spaces, tabs, carriage returns, and newlines) otherwise.</p>
+    <p>The following whitespace callback can be used to add whitespace to XHTML output to make it more readable in a standard text editor:</p>
+    <pre><code>const char *
+whitespace_cb(mxml_node_t *node, int where)
+{
+  const char *element;
+
+ /*
+  * We can conditionally break to a new line before or after
+  * any element.  These are just common HTML elements...
+  */
+
+  element = mxmlGetElement(node);
+
+  if (!strcmp(element, &quot;html&quot;) ||
+      !strcmp(element, &quot;head&quot;) ||
+      !strcmp(element, &quot;body&quot;) ||
+      !strcmp(element, &quot;pre&quot;) ||
+      !strcmp(element, &quot;p&quot;) ||
+      !strcmp(element, &quot;h1&quot;) ||
+      !strcmp(element, &quot;h2&quot;) ||
+      !strcmp(element, &quot;h3&quot;) ||
+      !strcmp(element, &quot;h4&quot;) ||
+      !strcmp(element, &quot;h5&quot;) ||
+      !strcmp(element, &quot;h6&quot;))
+  {
+   /*
+    * Newlines before open and after close...
+    */
+
+    if (where == MXML_WS_BEFORE_OPEN ||
+        where == MXML_WS_AFTER_CLOSE)
+      return (&quot;\n&quot;);
+  }
+  else if (!strcmp(element, &quot;dl&quot;) ||
+           !strcmp(element, &quot;ol&quot;) ||
+           !strcmp(element, &quot;ul&quot;))
+  {
+   /*
+    * Put a newline before and after list elements...
+    */
+
+    return (&quot;\n&quot;);
+  }
+  else if (!strcmp(element, &quot;dd&quot;) ||
+           !strcmp(element, &quot;dt&quot;) ||
+           !strcmp(element, &quot;li&quot;))
+  {
+   /*
+    * Put a tab before &lt;li&gt;'s, &lt;dd&gt;'s, and &lt;dt&gt;'s, and a
+    * newline after them...
+    */
+
+    if (where == MXML_WS_BEFORE_OPEN)
+      return (&quot;\t&quot;);
+    else if (where == MXML_WS_AFTER_CLOSE)
+      return (&quot;\n&quot;);
+  }
+
+ /*
+  * Otherwise return NULL for no added whitespace...
+  */
+
+  return (NULL);
+}
+</code></pre>
+    <p>To use this callback function, simply use the name when you call any of the save functions:</p>
+    <pre><code>FILE *fp;
+mxml_node_t *tree;
+
+fp = fopen(&quot;filename.xml&quot;, &quot;w&quot;);
+mxmlSaveFile(tree, fp, whitespace_cb);
+fclose(fp);
+</code></pre>
+    <h3><a id="memory-management">Memory Management</a></h3>
+    <p>Once you are done with the XML data, use the <code>mxmlDelete</code> function to recursively free the memory that is used for a particular node or the entire tree:</p>
+    <pre><code>void
+mxmlDelete(mxml_node_t *tree);
+</code></pre>
+    <p>You can also use reference counting to manage memory usage. The <code>mxmlRetain</code> and <code>mxmlRelease</code> functions increment and decrement a node's use count, respectively. When the use count goes to zero, <code>mxmlRelease</code> automatically calls <code>mxmlDelete</code> to actually free the memory used by the node tree. New nodes start with a use count of 1.</p>
+    <h2><a id="more-about-nodes">More About Nodes</a></h2>
+    <h3><a id="element-nodes">Element Nodes</a></h3>
+    <p>Element (<code>MXML_ELEMENT</code>) nodes are created using the <code>mxmlNewElement</code> function. Element attributes are set using the <code>mxmlElementSetAttr</code> and <code>mxmlElementSetAttrf</code> functions and cleared using the <code>mxmlElementDeleteAttr</code> function:</p>
+    <pre><code>mxml_node_t *
+mxmlNewElement(mxml_node_t *parent, const char *name);
+
+void
+mxmlElementDeleteAttr(mxml_node_t *node, const char *name);
+
+void
+mxmlElementSetAttr(mxml_node_t *node, const char *name,
+                   const char *value);
+
+void
+mxmlElementSetAttrf(mxml_node_t *node, const char *name,
+                    const char *format, ...);
+</code></pre>
+    <p>Child nodes are added using the various <code>mxmlNew</code> functions. The top (root) node must be an element, usually created by the <code>mxmlNewXML</code> function:</p>
+    <pre><code>mxml_node_t *
+mxmlNewXML(const char *version);
+</code></pre>
+    <p>The <code>mxmlGetElement</code> function retrieves the element name, the <code>mxmlElementGetAttr</code> function retrieves the value string for a named attribute associated with the element. The <code>mxmlElementGetAttrByIndex</code> and <code>mxmlElementGetAttrCount</code> functions retrieve attributes by index:</p>
+    <pre><code>const char *
+mxmlGetElement(mxml_node_t *node);
+
+const char *
+mxmlElementGetAttr(mxml_node_t *node, const char *name);
+
+const char *
+mxmlElementGetAttrByIndex(mxml_node_t *node, int idx,
+                          const char **name);
+
+int
+mxmlElementGetAttrCount(mxml_node_t *node);
+</code></pre>
+    <h3><a id="cdata-nodes">CDATA Nodes</a></h3>
+    <p>CDATA (<code>MXML_ELEMENT</code>) nodes are created using the <code>mxmlNewCDATA</code> function:</p>
+    <pre><code>mxml_node_t *mxmlNewCDATA(mxml_node_t *parent, const char *string);
+</code></pre>
+    <p>The <code>mxmlGetCDATA</code> function retrieves the CDATA string pointer for a node:</p>
+    <pre><code>const char *mxmlGetCDATA(mxml_node_t *node);
+</code></pre>
+    <h3><a id="comment-nodes">Comment Nodes</a></h3>
+    <p>Because comments are currently stored as element nodes, comment (<code>MXML_ELEMENT</code>) nodes are created using the <code>mxmlNewElement</code> function by including the surrounding &quot;!--&quot; and &quot;--&quot; characters in the element name, for example:</p>
+    <pre><code>mxml_node_t *node = mxmlNewElement(&quot;!-- This is a comment --&quot;);
+</code></pre>
+    <p>Similarly, the <code>mxmlGetElement</code> function retrieves the comment string pointer for a node, which includes the surrounding &quot;!--&quot; and &quot;--&quot; characters.</p>
+    <pre><code>const char *comment = mxmlGetElement(node);
+/* returns &quot;!-- This is a comment --&quot; */
+</code></pre>
+    <h3><a id="processing-instruction-nodes">Processing Instruction Nodes</a></h3>
+    <p>Because processing instructions are currently stored as element nodes, processing instruction (<code>MXML_ELEMENT</code>) nodes are created using the <code>mxmlNewElement</code> function including the surrounding &quot;?&quot; characters:</p>
+    <pre><code>mxml_node_t *node = mxmlNewElement(&quot;?xml-stylesheet type=\&quot;text/css\&quot; href=\&quot;style.css\&quot;?&quot;);
+</code></pre>
+    <p>The <code>mxmlGetElement</code> function retrieves the processing instruction string for a node, including the surrounding &quot;?&quot; characters:</p>
+    <pre><code>const char *instr = mxmlGetElement(node);
+/* returned &quot;?xml-stylesheet type=\&quot;text/css\&quot; href=\&quot;style.css\&quot;?&quot; */
+</code></pre>
+    <h3><a id="integer-nodes">Integer Nodes</a></h3>
+    <p>Integer (<code>MXML_INTEGER</code>) nodes are created using the <code>mxmlNewInteger</code> function:</p>
+    <pre><code>mxml_node_t *
+mxmlNewInteger(mxml_node_t *parent, int integer);
+</code></pre>
+    <p>The <code>mxmlGetInteger</code> function retrieves the integer value for a node:</p>
+    <pre><code>int
+mxmlGetInteger(mxml_node_t *node);
+</code></pre>
+    <h3><a id="opaque-string-nodes">Opaque String Nodes</a></h3>
+    <p>Opaque string (<code>MXML_OPAQUE</code>) nodes are created using the <code>mxmlNewOpaque</code> function:</p>
+    <pre><code>mxml_node_t *
+mxmlNewOpaque(mxml_node_t *parent, const char *opaque);
+</code></pre>
+    <p>The <code>mxmlGetOpaque</code> function retrieves the opaque string pointer for a node:</p>
+    <pre><code>const char *
+mxmlGetOpaque(mxml_node_t *node);
+</code></pre>
+    <h3><a id="text-nodes">Text Nodes</a></h3>
+    <p>Whitespace-delimited text string (<code>MXML_TEXT</code>) nodes are created using the <code>mxmlNewText</code> and <code>mxmlNewTextf</code> functions. Each text node consists of a text string and (leading) whitespace flag value.</p>
+    <pre><code>mxml_node_t *
+mxmlNewText(mxml_node_t *parent, int whitespace,
+            const char *string);
+
+mxml_node_t *
+mxmlNewTextf(mxml_node_t *parent, int whitespace,
+             const char *format, ...);
+</code></pre>
+    <p>The <code>mxmlGetText</code> function retrieves the text string pointer and whitespace flag value for a node:</p>
+    <pre><code> const char *
+ mxmlGetText(mxml_node_t *node, int *whitespace);
+</code></pre>
+    <h3><a id="real-number-nodes">Real Number Nodes</a></h3>
+    <p>Real number (<code>MXML_REAL</code>) nodes are created using the <code>mxmlNewReal</code> function:</p>
+    <pre><code>mxml_node_t *
+mxmlNewReal(mxml_node_t *parent, double real);
+</code></pre>
+    <p>The <code>mxmlGetReal</code> function retrieves the real number for a node:</p>
+    <pre><code>double
+mxmlGetReal(mxml_node_t *node);
+</code></pre>
+    <h2><a id="locating-data-in-an-xml-document">Locating Data in an XML Document</a></h2>
+    <p>Mini-XML provides many functions for enumerating, searching, and indexing XML documents.</p>
+    <h3><a id="finding-nodes">Finding Nodes</a></h3>
+    <p>The <code>mxmlFindPath</code> function finds the (first) value node under a specific element using a &quot;path&quot;:</p>
+    <pre><code>mxml_node_t *
+mxmlFindPath(mxml_node_t *node, const char *path);
+</code></pre>
+    <p>The <code>path</code> string can contain the &quot;<em>&quot;</em> <em>wildcard</em> <em>to</em> <em>match</em> <em>a</em> <em>single</em> <em>element</em> <em>node</em> <em>in</em> the hierarchy. For example, the following code will find the first &quot;node&quot; element under the &quot;group&quot; element, first using an explicit path and then using a wildcard:</p>
+    <pre><code>mxml_node_t *value = mxmlFindPath(xml, &quot;data/group/node&quot;);
+
+mxml_node_t *value = mxmlFindPath(xml, &quot;data/*/node&quot;);
+</code></pre>
+    <p>The <code>mxmlFindElement</code> function can be used to find a named element, optionally matching an attribute and value:</p>
+    <pre><code>mxml_node_t *
+mxmlFindElement(mxml_node_t *node, mxml_node_t *top,
+                const char *element, const char *attr,
+                const char *value, int descend);
+</code></pre>
+    <p>The &quot;element&quot;, &quot;attr&quot;, and &quot;value&quot; arguments can be passed as <code>NULL</code> to act as wildcards, e.g.:</p>
+    <pre><code>/* Find the first &quot;a&quot; element */
+node = mxmlFindElement(tree, tree, &quot;a&quot;, NULL, NULL,
+                       MXML_DESCEND);
+
+/* Find the first &quot;a&quot; element with &quot;href&quot; attribute */
+node = mxmlFindElement(tree, tree, &quot;a&quot;, &quot;href&quot;, NULL,
+                       MXML_DESCEND);
+
+/* Find the first &quot;a&quot; element with &quot;href&quot; to a URL */
+node = mxmlFindElement(tree, tree, &quot;a&quot;, &quot;href&quot;,
+                       &quot;http://michaelrsweet.github.io/&quot;,
+                       MXML_DESCEND);
+
+/* Find the first element with a &quot;src&quot; attribute*/
+node = mxmlFindElement(tree, tree, NULL, &quot;src&quot;, NULL,
+                       MXML_DESCEND);
+
+/* Find the first element with a &quot;src&quot; = &quot;foo.jpg&quot; */
+node = mxmlFindElement(tree, tree, NULL, &quot;src&quot;, &quot;foo.jpg&quot;,
+                       MXML_DESCEND);
+</code></pre>
+    <p>You can also iterate with the same function:</p>
+    <pre><code>mxml_node_t *node;
+
+for (node = mxmlFindElement(tree, tree, &quot;element&quot;, NULL,
+                            NULL, MXML_DESCEND);
+     node != NULL;
+     node = mxmlFindElement(node, tree, &quot;element&quot;, NULL,
+                            NULL, MXML_DESCEND))
+{
+  ... do something ...
+}
+</code></pre>
+    <p>The <code>descend</code> argument (<code>MXML_DESCEND</code> in the examples above) can be one of three constants:</p>
+    <ul>
+    <li><code>MXML_NO_DESCEND</code>: ignore child nodes in the element hierarchy, instead using siblings (same level) or parent nodes (above) until the top (root) node is reached.</li>
+    <li><code>MXML_DESCEND_FIRST</code>: start the search with the first child of the node, and then search siblings. You'll normally use this when iterating through direct children of a parent node, e.g. all of the &quot;node&quot; and &quot;group&quot; elements under the &quot;?xml&quot; parent node in the previous example.</li>
+    <li><code>MXML_DESCEND</code>: search child nodes first, then sibling nodes, and then parent nodes.</li>
+</ul>
+    <h3><a id="iterating-nodes">Iterating Nodes</a></h3>
+    <p>While the <code>mxmlFindNode</code> and <code>mxmlFindPath</code> functions will find a particular element node, sometimes you need to iterate over all nodes. The <code>mxmlWalkNext</code> and <code>mxmlWalkPrev</code> functions can be used to iterate through the XML node tree:</p>
+    <pre><code>mxml_node_t *
+mxmlWalkNext(mxml_node_t *node, mxml_node_t *top,
+             int descend);
+
+mxml_node_t *
+mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top,
+             int descend);
+</code></pre>
+    <p>Depending on the value of the <code>descend</code> argument, these functions will automatically traverse child, sibling, and parent nodes until the <code>top</code> node is reached. For example, the following code will iterate over all of the nodes in the sample XML document in the previous section:</p>
+    <pre><code>mxml_node_t *node;
+
+for (node = xml;
+     node != NULL;
+     node = mxmlWalkNext(node, xml, MXML_DESCEND))
+{
+  ... do something ...
+}
+</code></pre>
+    <p>The nodes will be returned in the following order:</p>
+    <pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;data&gt;
+&lt;node&gt;
+val1
+&lt;node&gt;
+val2
+&lt;node&gt;
+val3
+&lt;group&gt;
+&lt;node&gt;
+val4
+&lt;node&gt;
+val5
+&lt;node&gt;
+val6
+&lt;node&gt;
+val7
+&lt;node&gt;
+val8
+</code></pre>
+    <h3><a id="indexing">Indexing</a></h3>
+    <p>The <code>mxmlIndexNew</code> function allows you to create an index of nodes for faster searching and enumeration:</p>
+    <pre><code>mxml_index_t *
+mxmlIndexNew(mxml_node_t *node, const char *element,
+             const char *attr);
+</code></pre>
+    <p>The <code>element</code> and <code>attr</code> arguments control which elements are included in the index. If <code>element</code> is not <code>NULL</code> then only elements with the specified name are added to the index. Similarly, if <code>attr</code> is not <code>NULL</code> then only elements containing the specified attribute are added to the index. The nodes are sorted in the index.</p>
+    <p>For example, the following code creates an index of all &quot;id&quot; values in an XML document:</p>
+    <pre><code>mxml_index_t *ind = mxmlIndexNew(xml, NULL, &quot;id&quot;);
+</code></pre>
+    <p>Once the index is created, the <code>mxmlIndexFind</code> function can be used to find a matching node:</p>
+    <pre><code>mxml_node_t *
+mxmlIndexFind(mxml_index_t *ind, const char *element,
+              const char *value);
+</code></pre>
+    <p>For example, the following code will find the element whose &quot;id&quot; string is &quot;42&quot;:</p>
+    <pre><code>mxml_node_t *node = mxmlIndexFind(ind, NULL, &quot;42&quot;);
+</code></pre>
+    <p>Alternately, the <code>mxmlIndexReset</code> and <code>mxmlIndexEnum</code> functions can be used to enumerate the nodes in the index:</p>
+    <pre><code>mxml_node_t *
+mxmlIndexReset(mxml_index_t *ind);
+
+mxml_node_t *
+mxmlIndexEnum(mxml_index_t *ind);
+</code></pre>
+    <p>Typically these functions will be used in a <code>for</code> loop:</p>
+    <pre><code>mxml_node_t *node;
+
+for (node = mxmlIndexReset(ind);
+     node != NULL;
+     node = mxmlIndexEnum(ind))
+{
+  ... do something ...
+}
+</code></pre>
+    <p>The <code>mxmlIndexCount</code> function returns the number of nodes in the index:</p>
+    <pre><code>int
+mxmlIndexGetCount(mxml_index_t *ind);
+</code></pre>
+    <p>Finally, the <code>mxmlIndexDelete</code> function frees all memory associated with the index:</p>
+    <pre><code>void
+mxmlIndexDelete(mxml_index_t *ind);
+</code></pre>
+    <h2><a id="custom-data-types">Custom Data Types</a></h2>
+    <p>Mini-XML supports custom data types via per-thread load and save callbacks. Only a single set of callbacks can be active at any time for the current thread, however your callbacks can store additional information in order to support multiple custom data types as needed. The <code>MXML_CUSTOM</code> node type identifies custom data nodes.</p>
+    <p>The <code>mxmlGetCustom</code> function retrieves the custom value pointer for a node.</p>
+    <pre><code>const void *
+mxmlGetCustom(mxml_node_t *node);
+</code></pre>
+    <p>Custom (<code>MXML_CUSTOM</code>) nodes are created using the <code>mxmlNewCustom</code> function or using a custom per-thread load callbacks specified using the <code>mxmlSetCustomHandlers</code> function:</p>
+    <pre><code>typedef void (*mxml_custom_destroy_cb_t)(void *);
+typedef int (*mxml_custom_load_cb_t)(mxml_node_t *, const char *);
+typedef char *(*mxml_custom_save_cb_t)(mxml_node_t *);
+
+mxml_node_t *
+mxmlNewCustom(mxml_node_t *parent, void *data,
+              mxml_custom_destroy_cb_t destroy);
+
+int
+mxmlSetCustom(mxml_node_t *node, void *data,
+              mxml_custom_destroy_cb_t destroy);
+
+void
+mxmlSetCustomHandlers(mxml_custom_load_cb_t load,
+                      mxml_custom_save_cb_t save);
+</code></pre>
+    <p>The load callback receives a pointer to the current data node and a string of opaque character data from the XML source with character entities converted to the corresponding UTF-8 characters. For example, if we wanted to support a custom date/time type whose value is encoded as &quot;yyyy-mm-ddThh:mm:ssZ&quot; (ISO format), the load callback would look like the following:</p>
+    <pre><code>typedef struct
+{
+  unsigned year,    /* Year */
+           month,   /* Month */
+           day,     /* Day */
+           hour,    /* Hour */
+           minute,  /* Minute */
+           second;  /* Second */
+  time_t   unix;    /* UNIX time */
+} iso_date_time_t;
+
+int
+load_custom(mxml_node_t *node, const char *data)
+{
+  iso_date_time_t *dt;
+  struct tm tmdata;
+
+ /*
+  * Allocate data structure...
+  */
+
+  dt = calloc(1, sizeof(iso_date_time_t));
+
+ /*
+  * Try reading 6 unsigned integers from the data string...
+  */
+
+  if (sscanf(data, &quot;%u-%u-%uT%u:%u:%uZ&quot;, &amp;(dt-&gt;year),
+             &amp;(dt-&gt;month), &amp;(dt-&gt;day), &amp;(dt-&gt;hour),
+             &amp;(dt-&gt;minute), &amp;(dt-&gt;second)) != 6)
+  {
+   /*
+    * Unable to read numbers, free the data structure and
+    * return an error...
+    */
+
+    free(dt);
+
+    return (-1);
+  }
+
+ /*
+  * Range check values...
+  */
+
+  if (dt-&gt;month &lt; 1 || dt-&gt;month &gt; 12 ||
+      dt-&gt;day &lt; 1 || dt-&gt;day &gt; 31 ||
+      dt-&gt;hour &lt; 0 || dt-&gt;hour &gt; 23 ||
+      dt-&gt;minute &lt; 0 || dt-&gt;minute &gt; 59 ||
+      dt-&gt;second &lt; 0 || dt-&gt;second &gt; 60)
+  {
+   /*
+    * Date information is out of range...
+    */
+
+    free(dt);
+
+    return (-1);
+  }
+
+ /*
+  * Convert ISO time to UNIX time in seconds...
+  */
+
+  tmdata.tm_year = dt-&gt;year - 1900;
+  tmdata.tm_mon  = dt-&gt;month - 1;
+  tmdata.tm_day  = dt-&gt;day;
+  tmdata.tm_hour = dt-&gt;hour;
+  tmdata.tm_min  = dt-&gt;minute;
+  tmdata.tm_sec  = dt-&gt;second;
+
+  dt-&gt;unix = gmtime(&amp;tmdata);
+
+ /*
+  * Assign custom node data and destroy (free) function
+  * pointers...
+  */
+
+  mxmlSetCustom(node, data, free);
+
+ /*
+  * Return with no errors...
+  */
+
+  return (0);
+}
+</code></pre>
+    <p>The function itself can return 0 on success or -1 if it is unable to decode the custom data or the data contains an error. Custom data nodes contain a <code>void</code> pointer to the allocated custom data for the node and a pointer to a destructor function which will free the custom data when the node is deleted. In this example, we use the standard <code>free</code> function since everything is contained in a single calloc'd block.</p>
+    <p>The save callback receives the node pointer and returns an allocated string containing the custom data value. The following save callback could be used for our ISO date/time type:</p>
+    <pre><code>char *
+save_custom(mxml_node_t *node)
+{
+  char data[255];
+  iso_date_time_t *dt;
+
+  dt = (iso_date_time_t *)mxmlGetCustom(node);
+
+  snprintf(data, sizeof(data),
+           &quot;%04u-%02u-%02uT%02u:%02u:%02uZ&quot;,
+           dt-&gt;year, dt-&gt;month, dt-&gt;day, dt-&gt;hour,
+           dt-&gt;minute, dt-&gt;second);
+
+  return (strdup(data));
+}
+</code></pre>
+    <p>You register the callback functions using the <code>mxmlSetCustomHandlers</code> function:</p>
+    <pre><code>mxmlSetCustomHandlers(load_custom, save_custom);
+</code></pre>
+    <h2><a id="sax-stream-loading-of-documents">SAX (Stream) Loading of Documents</a></h2>
+    <p>Mini-XML supports an implementation of the Simple API for XML (SAX) which allows you to load and process an XML document as a stream of nodes. Aside from allowing you to process XML documents of any size, the Mini-XML implementation also allows you to retain portions of the document in memory for later processing.</p>
+    <p>The <code>mxmlSAXLoadFd</code>, <code>mxmlSAXLoadFile</code>, and <code>mxmlSAXLoadString</code> functions provide the SAX loading APIs:</p>
+    <pre><code>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);
+
+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);
+
+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);
+</code></pre>
+    <p>Each function works like the corresponding <code>mxmlLoad</code> function but uses a callback to process each node as it is read. The callback function receives the node, an event code, and a user data pointer you supply:</p>
+    <pre><code>void
+sax_cb(mxml_node_t *node, mxml_sax_event_t event,
+       void *data)
+{
+  ... do something ...
+}
+</code></pre>
+    <p>The event will be one of the following:</p>
+    <ul>
+    <li><code>MXML_SAX_CDATA</code>: CDATA was just read.</li>
+    <li><code>MXML_SAX_COMMENT</code>: A comment was just read.</li>
+    <li><code>MXML_SAX_DATA</code>: Data (custom, integer, opaque, real, or text) was just read.</li>
+    <li><code>MXML_SAX_DIRECTIVE</code>: A processing directive/instruction was just read.</li>
+    <li><code>MXML_SAX_ELEMENT_CLOSE</code> - A close element was just read (<code>&lt;/element&gt;</code>)</li>
+    <li><code>MXML_SAX_ELEMENT_OPEN</code> - An open element was just read (<code>&lt;element&gt;</code>)</li>
+</ul>
+    <p>Elements are <em>released</em> after the close element is processed. All other nodes are released after they are processed. The SAX callback can <em>retain</em> the node using the <code>mxmlRetain</code> function. For example, the following SAX callback will retain all nodes, effectively simulating a normal in-memory load:</p>
+    <pre><code>void
+sax_cb(mxml_node_t *node, mxml_sax_event_t event,
+       void *data)
+{
+  if (event != MXML_SAX_ELEMENT_CLOSE)
+    mxmlRetain(node);
+}
+</code></pre>
+    <p>More typically the SAX callback will only retain a small portion of the document that is needed for post-processing. For example, the following SAX callback will retain the title and headings in an XHTML file. It also retains the (parent) elements like <code>&lt;html&gt;</code>, <code>&lt;head&gt;</code>, and <code>&lt;body&gt;</code>, and processing directives like <code>&lt;?xml ... ?&gt;</code> and <code>&lt;!DOCTYPE ... &gt;</code>:</p>
+    <pre><code>void
+sax_cb(mxml_node_t *node, mxml_sax_event_t event,
+       void *data)
+{
+  if (event == MXML_SAX_ELEMENT_OPEN)
+  {
+   /*
+    * Retain headings and titles...
+    */
+
+    const char *element = mxmlGetElement(node);
+
+    if (!strcmp(element, &quot;html&quot;) ||
+        !strcmp(element, &quot;head&quot;) ||
+        !strcmp(element, &quot;title&quot;) ||
+        !strcmp(element, &quot;body&quot;) ||
+        !strcmp(element, &quot;h1&quot;) ||
+        !strcmp(element, &quot;h2&quot;) ||
+        !strcmp(element, &quot;h3&quot;) ||
+        !strcmp(element, &quot;h4&quot;) ||
+        !strcmp(element, &quot;h5&quot;) ||
+        !strcmp(element, &quot;h6&quot;))
+      mxmlRetain(node);
+  }
+  else if (event == MXML_SAX_DIRECTIVE)
+    mxmlRetain(node);
+  else if (event == MXML_SAX_DATA)
+  {
+    if (mxmlGetRefCount(mxmlGetParent(node)) &gt; 1)
+    {
+     /*
+      * If the parent was retained, then retain this data
+      * node as well.
+      */
+
+      mxmlRetain(node);
+    }
+  }
+}
+</code></pre>
+    <p>The resulting skeleton document tree can then be searched just like one loaded using the <code>mxmlLoad</code> functions. For example, a filter that reads an XHTML document from stdin and then shows the title and headings in the document would look like:</p>
+    <pre><code>mxml_node_t *doc, *title, *body, *heading;
+
+doc = mxmlSAXLoadFd(NULL, 0, MXML_TEXT_CALLBACK, sax_cb,
+                    NULL);
+
+title = mxmlFindElement(doc, doc, &quot;title&quot;, NULL, NULL,
+                        MXML_DESCEND);
+
+if (title)
+  print_children(title);
+
+body = mxmlFindElement(doc, doc, &quot;body&quot;, NULL, NULL,
+                       MXML_DESCEND);
+
+if (body)
+{
+  for (heading = mxmlGetFirstChild(body);
+       heading;
+       heading = mxmlGetNextSibling(heading))
+    print_children(heading);
+}
+</code></pre>
+    <p>The <code>print_children</code> function is:</p>
+    <pre><code>void
+print_children(mxml_node_t *parent)
+{
+  mxml_node_t *node;
+  const char *text;
+  int whitespace;
+
+  for (node = mxmlGetFirstChild(parent);
+       node != NULL;
+       node = mxmlGetNextSibling(node))
+  {
+    text = mxmlGettext(node, &amp;whitespace);
+
+    if (whitespace)
+      putchar(' ');
+
+    fputs(text, stdout);
+  }
+
+  putchar('\n');
+}
+</code></pre>
+      <h2 class="title"><a id="FUNCTIONS">Functions</a></h2>
+<h3 class="function"><a id="mxmlAdd">mxmlAdd</a></h3>
+        <p class="description">Add a node to a tree.</p>
+<p class="code">
+void mxmlAdd(<a href="#mxml_node_t">mxml_node_t</a> *parent, int where, <a href="#mxml_node_t">mxml_node_t</a> *child, <a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>parent</th>
+        <td class="description">Parent node</td></tr>
+<tr><th>where</th>
+        <td class="description">Where to add, <code>MXML_ADD_BEFORE</code> or <code>MXML_ADD_AFTER</code></td></tr>
+<tr><th>child</th>
+        <td class="description">Child node for where or <code>MXML_ADD_TO_PARENT</code></td></tr>
+<tr><th>node</th>
+        <td class="description">Node to add</td></tr>
+</tbody></table>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">Adds the specified node to the parent.  If the child argument is not
+<code>NULL</code>, puts the new node before or after the specified child depending
+on the value of the where argument.  If the child argument is <code>NULL</code>,
+puts the new node at the beginning of the child list (<code>MXML_ADD_BEFORE</code>)
+or at the end of the child list (<code>MXML_ADD_AFTER</code>).  The constant
+<code>MXML_ADD_TO_PARENT</code> can be used to specify a <code>NULL</code> child pointer.</p>
+<h3 class="function"><a id="mxmlDelete">mxmlDelete</a></h3>
+        <p class="description">Delete a node and all of its children.</p>
+<p class="code">
+void mxmlDelete(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to delete</td></tr>
+</tbody></table>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">If the specified node has a parent, this function first removes the
+node from its parent using the <a href="#mxmlRemove"><code>mxmlRemove</code></a> function.</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.4&#160;</span><a id="mxmlElementDeleteAttr">mxmlElementDeleteAttr</a></h3>
+        <p class="description">Delete an attribute.</p>
+<p class="code">
+void mxmlElementDeleteAttr(<a href="#mxml_node_t">mxml_node_t</a> *node, const char *name);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Element</td></tr>
+<tr><th>name</th>
+        <td class="description">Attribute name</td></tr>
+</tbody></table>
+<h3 class="function"><a id="mxmlElementGetAttr">mxmlElementGetAttr</a></h3>
+        <p class="description">Get an attribute.</p>
+<p class="code">
+const char *mxmlElementGetAttr(<a href="#mxml_node_t">mxml_node_t</a> *node, const char *name);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Element node</td></tr>
+<tr><th>name</th>
+        <td class="description">Name of attribute</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Attribute value or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">This function returns <code>NULL</code> if the node is not an element or the
+named attribute does not exist.</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.11&#160;</span><a id="mxmlElementGetAttrByIndex">mxmlElementGetAttrByIndex</a></h3>
+        <p class="description">Get an element attribute by index.</p>
+<p class="code">
+const char *mxmlElementGetAttrByIndex(<a href="#mxml_node_t">mxml_node_t</a> *node, int idx, const char **name);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node</td></tr>
+<tr><th>idx</th>
+        <td class="description">Attribute index, starting at 0</td></tr>
+<tr><th>name</th>
+        <td class="description">Attribute name</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Attribute value</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The index (&quot;idx&quot;) is 0-based.  <code>NULL</code> is returned if the specified index
+is out of range.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.11&#160;</span><a id="mxmlElementGetAttrCount">mxmlElementGetAttrCount</a></h3>
+        <p class="description">Get the number of element attributes.</p>
+<p class="code">
+int mxmlElementGetAttrCount(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Number of attributes</p>
+<h3 class="function"><a id="mxmlElementSetAttr">mxmlElementSetAttr</a></h3>
+        <p class="description">Set an attribute.</p>
+<p class="code">
+void mxmlElementSetAttr(<a href="#mxml_node_t">mxml_node_t</a> *node, const char *name, const char *value);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Element node</td></tr>
+<tr><th>name</th>
+        <td class="description">Name of attribute</td></tr>
+<tr><th>value</th>
+        <td class="description">Attribute value</td></tr>
+</tbody></table>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">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.</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.3&#160;</span><a id="mxmlElementSetAttrf">mxmlElementSetAttrf</a></h3>
+        <p class="description">Set an attribute with a formatted value.</p>
+<p class="code">
+void mxmlElementSetAttrf(<a href="#mxml_node_t">mxml_node_t</a> *node, const char *name, const char *format, ...);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Element node</td></tr>
+<tr><th>name</th>
+        <td class="description">Name of attribute</td></tr>
+<tr><th>format</th>
+        <td class="description">Printf-style attribute value</td></tr>
+<tr><th>...</th>
+        <td class="description">Additional arguments as needed</td></tr>
+</tbody></table>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">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.
+
+</p>
+<h3 class="function"><a id="mxmlEntityAddCallback">mxmlEntityAddCallback</a></h3>
+        <p class="description">Add a callback to convert entities to Unicode.</p>
+<p class="code">
+int mxmlEntityAddCallback(<a href="#mxml_entity_cb_t">mxml_entity_cb_t</a> cb);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>cb</th>
+        <td class="description">Callback function to add</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on failure</p>
+<h3 class="function"><a id="mxmlEntityGetName">mxmlEntityGetName</a></h3>
+        <p class="description">Get the name that corresponds to the character value.</p>
+<p class="code">
+const char *mxmlEntityGetName(int val);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>val</th>
+        <td class="description">Character value</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Entity name or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">If val does not need to be represented by a named entity, <code>NULL</code> is returned.</p>
+<h3 class="function"><a id="mxmlEntityGetValue">mxmlEntityGetValue</a></h3>
+        <p class="description">Get the character corresponding to a named entity.</p>
+<p class="code">
+int mxmlEntityGetValue(const char *name);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>name</th>
+        <td class="description">Entity name</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Character value or -1 on error</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The entity name can also be a numeric constant. -1 is returned if the
+name is not known.</p>
+<h3 class="function"><a id="mxmlEntityRemoveCallback">mxmlEntityRemoveCallback</a></h3>
+        <p class="description">Remove a callback.</p>
+<p class="code">
+void mxmlEntityRemoveCallback(<a href="#mxml_entity_cb_t">mxml_entity_cb_t</a> cb);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>cb</th>
+        <td class="description">Callback function to remove</td></tr>
+</tbody></table>
+<h3 class="function"><a id="mxmlFindElement">mxmlFindElement</a></h3>
+        <p class="description">Find the named element.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlFindElement(<a href="#mxml_node_t">mxml_node_t</a> *node, <a href="#mxml_node_t">mxml_node_t</a> *top, const char *element, const char *attr, const char *value, int descend);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Current node</td></tr>
+<tr><th>top</th>
+        <td class="description">Top node</td></tr>
+<tr><th>element</th>
+        <td class="description">Element name or <code>NULL</code> for any</td></tr>
+<tr><th>attr</th>
+        <td class="description">Attribute name, or <code>NULL</code> for none</td></tr>
+<tr><th>value</th>
+        <td class="description">Attribute value, or <code>NULL</code> for any</td></tr>
+<tr><th>descend</th>
+        <td class="description">Descend into tree - <code>MXML_DESCEND</code>, <code>MXML_NO_DESCEND</code>, or <code>MXML_DESCEND_FIRST</code></td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Element node or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The search is constrained by the name, attribute name, and value; any
+<code>NULL</code> 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
+<code>MXML_DESCEND_FIRST</code> for the initial search and <code>MXML_NO_DESCEND</code>
+to find additional direct descendents of the node. The top node argument
+constrains the search to a particular node's children.</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlFindPath">mxmlFindPath</a></h3>
+        <p class="description">Find a node with the given path.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlFindPath(<a href="#mxml_node_t">mxml_node_t</a> *top, const char *path);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>top</th>
+        <td class="description">Top node</td></tr>
+<tr><th>path</th>
+        <td class="description">Path to element</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Found node or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The &quot;path&quot; is a slash-separated list of element names. The name &quot;*&quot; is
+considered a wildcard for one or more levels of elements.  For example,
+&quot;foo/one/two&quot;, &quot;bar/two/one&quot;, &quot;*/one&quot;, and so forth.<br>
+<br>
+The first child node of the found node is returned if the given node has
+children and the first child is a value node.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetCDATA">mxmlGetCDATA</a></h3>
+        <p class="description">Get the value for a CDATA node.</p>
+<p class="code">
+const char *mxmlGetCDATA(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">CDATA value or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion"><code>NULL</code> is returned if the node is not a CDATA element.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetCustom">mxmlGetCustom</a></h3>
+        <p class="description">Get the value for a custom node.</p>
+<p class="code">
+const void *mxmlGetCustom(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Custom value or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion"><code>NULL</code> is returned if the node (or its first child) is not a custom
+value node.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetElement">mxmlGetElement</a></h3>
+        <p class="description">Get the name for an element node.</p>
+<p class="code">
+const char *mxmlGetElement(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Element name or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion"><code>NULL</code> is returned if the node is not an element node.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetFirstChild">mxmlGetFirstChild</a></h3>
+        <p class="description">Get the first child of an element node.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlGetFirstChild(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">First child or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion"><code>NULL</code> is returned if the node is not an element node or if the node
+has no children.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetInteger">mxmlGetInteger</a></h3>
+        <p class="description">Get the integer value from the specified node or its
+first child.</p>
+<p class="code">
+int mxmlGetInteger(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Integer value or 0</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">0 is returned if the node (or its first child) is not an integer value node.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetLastChild">mxmlGetLastChild</a></h3>
+        <p class="description">Get the last child of an element node.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlGetLastChild(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Last child or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion"><code>NULL</code> is returned if the node is not an element node or if the node
+has no children.
+
+</p>
+<h3 class="function"><a id="mxmlGetNextSibling">mxmlGetNextSibling</a></h3>
+        <p class="description"></p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlGetNextSibling(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Get the next node for the current parent.</p>
+        <p class="discussion"><code>NULL</code> is returned if this is the last child for the current parent.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetOpaque">mxmlGetOpaque</a></h3>
+        <p class="description">Get an opaque string value for a node or its first child.</p>
+<p class="code">
+const char *mxmlGetOpaque(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Opaque string or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion"><code>NULL</code> is returned if the node (or its first child) is not an opaque
+value node.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetParent">mxmlGetParent</a></h3>
+        <p class="description">Get the parent node.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlGetParent(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Parent node or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion"><code>NULL</code> is returned for a root node.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetPrevSibling">mxmlGetPrevSibling</a></h3>
+        <p class="description">Get the previous node for the current parent.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlGetPrevSibling(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Previous node or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion"><code>NULL</code> is returned if this is the first child for the current parent.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetReal">mxmlGetReal</a></h3>
+        <p class="description">Get the real value for a node or its first child.</p>
+<p class="code">
+double mxmlGetReal(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Real value or 0.0</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">0.0 is returned if the node (or its first child) is not a real value node.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetRefCount">mxmlGetRefCount</a></h3>
+        <p class="description">Get the current reference (use) count for a node.</p>
+<p class="code">
+int mxmlGetRefCount(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Reference count</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The initial reference count of new nodes is 1. Use the <a href="#mxmlRetain"><code>mxmlRetain</code></a>
+and <a href="#mxmlRelease"><code>mxmlRelease</code></a> functions to increment and decrement a node's
+reference count.
+
+.</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetText">mxmlGetText</a></h3>
+        <p class="description">Get the text value for a node or its first child.</p>
+<p class="code">
+const char *mxmlGetText(<a href="#mxml_node_t">mxml_node_t</a> *node, int *whitespace);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+<tr><th>whitespace</th>
+        <td class="description">1 if string is preceded by whitespace, 0 otherwise</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Text string or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion"><code>NULL</code> is returned if the node (or its first child) is not a text node.
+The &quot;whitespace&quot; argument can be <code>NULL</code>.<br>
+<br>
+Note: Text nodes consist of whitespace-delimited words. You will only get
+single words of text when reading an XML file with <code>MXML_TEXT</code> nodes.
+If you want the entire string between elements in the XML file, you MUST read
+the XML file with <code>MXML_OPAQUE</code> nodes and get the resulting strings
+using the <a href="#mxmlGetOpaque"><code>mxmlGetOpaque</code></a> function instead.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetType">mxmlGetType</a></h3>
+        <p class="description">Get the node type.</p>
+<p class="code">
+<a href="#mxml_type_t">mxml_type_t</a> mxmlGetType(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Type of node</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion"><code>MXML_IGNORE</code> is returned if &quot;node&quot; is <code>NULL</code>.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlGetUserData">mxmlGetUserData</a></h3>
+        <p class="description">Get the user data pointer for a node.</p>
+<p class="code">
+void *mxmlGetUserData(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to get</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">User data pointer</p>
+<h3 class="function"><a id="mxmlIndexDelete">mxmlIndexDelete</a></h3>
+        <p class="description">Delete an index.</p>
+<p class="code">
+void mxmlIndexDelete(<a href="#mxml_index_t">mxml_index_t</a> *ind);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>ind</th>
+        <td class="description">Index to delete</td></tr>
+</tbody></table>
+<h3 class="function"><a id="mxmlIndexEnum">mxmlIndexEnum</a></h3>
+        <p class="description">Return the next node in the index.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlIndexEnum(<a href="#mxml_index_t">mxml_index_t</a> *ind);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>ind</th>
+        <td class="description">Index to enumerate</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Next node or <code>NULL</code> if there is none</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">You should call <a href="#mxmlIndexReset"><code>mxmlIndexReset</code></a> prior to using this function to get
+the first node in the index.  Nodes are returned in the sorted order of the
+index.</p>
+<h3 class="function"><a id="mxmlIndexFind">mxmlIndexFind</a></h3>
+        <p class="description">Find the next matching node.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlIndexFind(<a href="#mxml_index_t">mxml_index_t</a> *ind, const char *element, const char *value);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>ind</th>
+        <td class="description">Index to search</td></tr>
+<tr><th>element</th>
+        <td class="description">Element name to find, if any</td></tr>
+<tr><th>value</th>
+        <td class="description">Attribute value, if any</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Node or <code>NULL</code> if none found</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">You should call <a href="#mxmlIndexReset"><code>mxmlIndexReset</code></a> prior to using this function for
+the first time with a particular set of &quot;element&quot; and &quot;value&quot;
+strings. Passing <code>NULL</code> for both &quot;element&quot; and &quot;value&quot; is equivalent
+to calling <a href="#mxmlIndexEnum"><code>mxmlIndexEnum</code></a>.</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlIndexGetCount">mxmlIndexGetCount</a></h3>
+        <p class="description">Get the number of nodes in an index.</p>
+<p class="code">
+int mxmlIndexGetCount(<a href="#mxml_index_t">mxml_index_t</a> *ind);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>ind</th>
+        <td class="description">Index of nodes</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Number of nodes in index</p>
+<h3 class="function"><a id="mxmlIndexNew">mxmlIndexNew</a></h3>
+        <p class="description">Create a new index.</p>
+<p class="code">
+<a href="#mxml_index_t">mxml_index_t</a> *mxmlIndexNew(<a href="#mxml_node_t">mxml_node_t</a> *node, const char *element, const char *attr);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">XML node tree</td></tr>
+<tr><th>element</th>
+        <td class="description">Element to index or <code>NULL</code> for all</td></tr>
+<tr><th>attr</th>
+        <td class="description">Attribute to index or <code>NULL</code> for none</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New index</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The index will contain all nodes that contain the named element and/or
+attribute.  If both &quot;element&quot; and &quot;attr&quot; are <code>NULL</code>, 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 &quot;attr&quot;
+argument is not NULL.</p>
+<h3 class="function"><a id="mxmlIndexReset">mxmlIndexReset</a></h3>
+        <p class="description">Reset the enumeration/find pointer in the index and
+return the first node in the index.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlIndexReset(<a href="#mxml_index_t">mxml_index_t</a> *ind);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>ind</th>
+        <td class="description">Index to reset</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">First node or <code>NULL</code> if there is none</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">This function should be called prior to using <a href="#mxmlIndexEnum"><code>mxmlIndexEnum</code></a> or
+<a href="#mxmlIndexFind"><code>mxmlIndexFind</code></a> for the first time.</p>
+<h3 class="function"><a id="mxmlLoadFd">mxmlLoadFd</a></h3>
+        <p class="description">Load a file descriptor into an XML node tree.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlLoadFd(<a href="#mxml_node_t">mxml_node_t</a> *top, int fd, <a href="#mxml_load_cb_t">mxml_load_cb_t</a> cb);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>top</th>
+        <td class="description">Top node</td></tr>
+<tr><th>fd</th>
+        <td class="description">File descriptor to read from</td></tr>
+<tr><th>cb</th>
+        <td class="description">Callback function or constant</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">First node or <code>NULL</code> if the file could not be read.</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">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 &lt;?xml&gt; for the entire file. The callback
+function returns the value type that should be used for child nodes.
+The constants <code>MXML_INTEGER_CALLBACK</code>, <code>MXML_OPAQUE_CALLBACK</code>,
+<code>MXML_REAL_CALLBACK</code>, and <code>MXML_TEXT_CALLBACK</code> are defined for
+loading child (data) nodes of the specified type.<br>
+<br>
+Note: The most common programming error when using the Mini-XML library is
+to load an XML file using the <code>MXML_TEXT_CALLBACK</code>, which returns inline
+text as a series of whitespace-delimited words, instead of using the
+<code>MXML_OPAQUE_CALLBACK</code> which returns the inline text as a single string
+(including whitespace).</p>
+<h3 class="function"><a id="mxmlLoadFile">mxmlLoadFile</a></h3>
+        <p class="description">Load a file into an XML node tree.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlLoadFile(<a href="#mxml_node_t">mxml_node_t</a> *top, FILE *fp, <a href="#mxml_load_cb_t">mxml_load_cb_t</a> cb);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>top</th>
+        <td class="description">Top node</td></tr>
+<tr><th>fp</th>
+        <td class="description">File to read from</td></tr>
+<tr><th>cb</th>
+        <td class="description">Callback function or constant</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">First node or <code>NULL</code> if the file could not be read.</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">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 &lt;?xml&gt; for the entire file. The callback
+function returns the value type that should be used for child nodes.
+The constants <code>MXML_INTEGER_CALLBACK</code>, <code>MXML_OPAQUE_CALLBACK</code>,
+<code>MXML_REAL_CALLBACK</code>, and <code>MXML_TEXT_CALLBACK</code> are defined for
+loading child (data) nodes of the specified type.<br>
+<br>
+Note: The most common programming error when using the Mini-XML library is
+to load an XML file using the <code>MXML_TEXT_CALLBACK</code>, which returns inline
+text as a series of whitespace-delimited words, instead of using the
+<code>MXML_OPAQUE_CALLBACK</code> which returns the inline text as a single string
+(including whitespace).</p>
+<h3 class="function"><a id="mxmlLoadString">mxmlLoadString</a></h3>
+        <p class="description">Load a string into an XML node tree.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlLoadString(<a href="#mxml_node_t">mxml_node_t</a> *top, const char *s, <a href="#mxml_load_cb_t">mxml_load_cb_t</a> cb);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>top</th>
+        <td class="description">Top node</td></tr>
+<tr><th>s</th>
+        <td class="description">String to load</td></tr>
+<tr><th>cb</th>
+        <td class="description">Callback function or constant</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">First node or <code>NULL</code> if the string has errors.</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">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 &lt;?xml&gt; for the entire string. The callback
+function returns the value type that should be used for child nodes.
+The constants <code>MXML_INTEGER_CALLBACK</code>, <code>MXML_OPAQUE_CALLBACK</code>,
+<code>MXML_REAL_CALLBACK</code>, and <code>MXML_TEXT_CALLBACK</code> are defined for
+loading child (data) nodes of the specified type.<br>
+<br>
+Note: The most common programming error when using the Mini-XML library is
+to load an XML file using the <code>MXML_TEXT_CALLBACK</code>, which returns inline
+text as a series of whitespace-delimited words, instead of using the
+<code>MXML_OPAQUE_CALLBACK</code> which returns the inline text as a single string
+(including whitespace).</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.3&#160;</span><a id="mxmlNewCDATA">mxmlNewCDATA</a></h3>
+        <p class="description">Create a new CDATA node.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlNewCDATA(<a href="#mxml_node_t">mxml_node_t</a> *parent, const char *data);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>parent</th>
+        <td class="description">Parent node or <code>MXML_NO_PARENT</code></td></tr>
+<tr><th>data</th>
+        <td class="description">Data string</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New node</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The new CDATA node is added to the end of the specified parent's child
+list.  The constant <code>MXML_NO_PARENT</code> 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 currently use the
+<code>MXML_ELEMENT</code> type.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.1&#160;</span><a id="mxmlNewCustom">mxmlNewCustom</a></h3>
+        <p class="description">Create a new custom data node.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlNewCustom(<a href="#mxml_node_t">mxml_node_t</a> *parent, void *data, <a href="#mxml_custom_destroy_cb_t">mxml_custom_destroy_cb_t</a> destroy);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>parent</th>
+        <td class="description">Parent node or <code>MXML_NO_PARENT</code></td></tr>
+<tr><th>data</th>
+        <td class="description">Pointer to data</td></tr>
+<tr><th>destroy</th>
+        <td class="description">Function to destroy data</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New node</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The new custom node is added to the end of the specified parent's child
+list. The constant <code>MXML_NO_PARENT</code> can be used to specify that the new
+element node has no parent. <code>NULL</code> can be passed when the data in the
+node is not dynamically allocated or is separately managed.
+
+</p>
+<h3 class="function"><a id="mxmlNewElement">mxmlNewElement</a></h3>
+        <p class="description">Create a new element node.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlNewElement(<a href="#mxml_node_t">mxml_node_t</a> *parent, const char *name);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>parent</th>
+        <td class="description">Parent node or <code>MXML_NO_PARENT</code></td></tr>
+<tr><th>name</th>
+        <td class="description">Name of element</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New node</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The new element node is added to the end of the specified parent's child
+list. The constant <code>MXML_NO_PARENT</code> can be used to specify that the new
+element node has no parent.</p>
+<h3 class="function"><a id="mxmlNewInteger">mxmlNewInteger</a></h3>
+        <p class="description">Create a new integer node.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlNewInteger(<a href="#mxml_node_t">mxml_node_t</a> *parent, int integer);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>parent</th>
+        <td class="description">Parent node or <code>MXML_NO_PARENT</code></td></tr>
+<tr><th>integer</th>
+        <td class="description">Integer value</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New node</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The new integer node is added to the end of the specified parent's child
+list. The constant <code>MXML_NO_PARENT</code> can be used to specify that the new
+integer node has no parent.</p>
+<h3 class="function"><a id="mxmlNewOpaque">mxmlNewOpaque</a></h3>
+        <p class="description">Create a new opaque string.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlNewOpaque(<a href="#mxml_node_t">mxml_node_t</a> *parent, const char *opaque);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>parent</th>
+        <td class="description">Parent node or <code>MXML_NO_PARENT</code></td></tr>
+<tr><th>opaque</th>
+        <td class="description">Opaque string</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New node</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The new opaque string node is added to the end of the specified parent's
+child list.  The constant <code>MXML_NO_PARENT</code> can be used to specify that
+the new opaque string node has no parent.  The opaque string must be nul-
+terminated and is copied into the new node.</p>
+<h3 class="function"><a id="mxmlNewOpaquef">mxmlNewOpaquef</a></h3>
+        <p class="description">Create a new formatted opaque string node.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlNewOpaquef(<a href="#mxml_node_t">mxml_node_t</a> *parent, const char *format, ...);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>parent</th>
+        <td class="description">Parent node or <code>MXML_NO_PARENT</code></td></tr>
+<tr><th>format</th>
+        <td class="description">Printf-style format string</td></tr>
+<tr><th>...</th>
+        <td class="description">Additional args as needed</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New node</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The new opaque string node is added to the end of the specified parent's
+child list.  The constant <code>MXML_NO_PARENT</code> can be used to specify that
+the new opaque string node has no parent.  The format string must be
+nul-terminated and is formatted into the new node.</p>
+<h3 class="function"><a id="mxmlNewReal">mxmlNewReal</a></h3>
+        <p class="description">Create a new real number node.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlNewReal(<a href="#mxml_node_t">mxml_node_t</a> *parent, double real);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>parent</th>
+        <td class="description">Parent node or <code>MXML_NO_PARENT</code></td></tr>
+<tr><th>real</th>
+        <td class="description">Real number value</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New node</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The new real number node is added to the end of the specified parent's
+child list.  The constant <code>MXML_NO_PARENT</code> can be used to specify that
+the new real number node has no parent.</p>
+<h3 class="function"><a id="mxmlNewText">mxmlNewText</a></h3>
+        <p class="description">Create a new text fragment node.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlNewText(<a href="#mxml_node_t">mxml_node_t</a> *parent, int whitespace, const char *string);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>parent</th>
+        <td class="description">Parent node or <code>MXML_NO_PARENT</code></td></tr>
+<tr><th>whitespace</th>
+        <td class="description">1 = leading whitespace, 0 = no whitespace</td></tr>
+<tr><th>string</th>
+        <td class="description">String</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New node</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The new text node is added to the end of the specified parent's child
+list.  The constant <code>MXML_NO_PARENT</code> 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.</p>
+<h3 class="function"><a id="mxmlNewTextf">mxmlNewTextf</a></h3>
+        <p class="description">Create a new formatted text fragment node.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlNewTextf(<a href="#mxml_node_t">mxml_node_t</a> *parent, int whitespace, const char *format, ...);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>parent</th>
+        <td class="description">Parent node or <code>MXML_NO_PARENT</code></td></tr>
+<tr><th>whitespace</th>
+        <td class="description">1 = leading whitespace, 0 = no whitespace</td></tr>
+<tr><th>format</th>
+        <td class="description">Printf-style format string</td></tr>
+<tr><th>...</th>
+        <td class="description">Additional args as needed</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New node</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The new text node is added to the end of the specified parent's child
+list.  The constant <code>MXML_NO_PARENT</code> 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.</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.3&#160;</span><a id="mxmlNewXML">mxmlNewXML</a></h3>
+        <p class="description">Create a new XML document tree.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlNewXML(const char *version);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>version</th>
+        <td class="description">Version number to use</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New ?xml node</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The &quot;version&quot; argument specifies the version number to put in the
+?xml element node. If <code>NULL</code>, version &quot;1.0&quot; is assumed.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.3&#160;</span><a id="mxmlRelease">mxmlRelease</a></h3>
+        <p class="description">Release a node.</p>
+<p class="code">
+int mxmlRelease(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New reference count</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">When the reference count reaches zero, the node (and any children)
+is deleted via <a href="#mxmlDelete"><code>mxmlDelete</code></a>.
+
+</p>
+<h3 class="function"><a id="mxmlRemove">mxmlRemove</a></h3>
+        <p class="description">Remove a node from its parent.</p>
+<p class="code">
+void mxmlRemove(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to remove</td></tr>
+</tbody></table>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">This function does not free memory used by the node - use <a href="#mxmlDelete"><code>mxmlDelete</code></a>
+for that.  This function does nothing if the node has no parent.</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.3&#160;</span><a id="mxmlRetain">mxmlRetain</a></h3>
+        <p class="description">Retain a node.</p>
+<p class="code">
+int mxmlRetain(<a href="#mxml_node_t">mxml_node_t</a> *node);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">New reference count</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.3&#160;</span><a id="mxmlSAXLoadFd">mxmlSAXLoadFd</a></h3>
+        <p class="description">Load a file descriptor into an XML node tree
+using a SAX callback.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlSAXLoadFd(<a href="#mxml_node_t">mxml_node_t</a> *top, int fd, <a href="#mxml_load_cb_t">mxml_load_cb_t</a> cb, <a href="#mxml_sax_cb_t">mxml_sax_cb_t</a> sax_cb, void *sax_data);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>top</th>
+        <td class="description">Top node</td></tr>
+<tr><th>fd</th>
+        <td class="description">File descriptor to read from</td></tr>
+<tr><th>cb</th>
+        <td class="description">Callback function or constant</td></tr>
+<tr><th>sax_cb</th>
+        <td class="description">SAX callback or <code>MXML_NO_CALLBACK</code></td></tr>
+<tr><th>sax_data</th>
+        <td class="description">SAX user data</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">First node or <code>NULL</code> if the file could not be read.</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">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 &lt;?xml&gt; for the entire file. The callback
+function returns the value type that should be used for child nodes.
+The constants <code>MXML_INTEGER_CALLBACK</code>, <code>MXML_OPAQUE_CALLBACK</code>,
+<code>MXML_REAL_CALLBACK</code>, and <code>MXML_TEXT_CALLBACK</code> are defined for
+loading child nodes of the specified type.<br>
+<br>
+The SAX callback must call <a href="#mxmlRetain"><code>mxmlRetain</code></a> 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.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.3&#160;</span><a id="mxmlSAXLoadFile">mxmlSAXLoadFile</a></h3>
+        <p class="description">Load a file into an XML node tree
+using a SAX callback.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlSAXLoadFile(<a href="#mxml_node_t">mxml_node_t</a> *top, FILE *fp, <a href="#mxml_load_cb_t">mxml_load_cb_t</a> cb, <a href="#mxml_sax_cb_t">mxml_sax_cb_t</a> sax_cb, void *sax_data);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>top</th>
+        <td class="description">Top node</td></tr>
+<tr><th>fp</th>
+        <td class="description">File to read from</td></tr>
+<tr><th>cb</th>
+        <td class="description">Callback function or constant</td></tr>
+<tr><th>sax_cb</th>
+        <td class="description">SAX callback or <code>MXML_NO_CALLBACK</code></td></tr>
+<tr><th>sax_data</th>
+        <td class="description">SAX user data</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">First node or <code>NULL</code> if the file could not be read.</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">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 &lt;?xml&gt; for the entire file. The callback
+function returns the value type that should be used for child nodes.
+The constants <code>MXML_INTEGER_CALLBACK</code>, <code>MXML_OPAQUE_CALLBACK</code>,
+<code>MXML_REAL_CALLBACK</code>, and <code>MXML_TEXT_CALLBACK</code> are defined for
+loading child nodes of the specified type.<br>
+<br>
+The SAX callback must call <a href="#mxmlRetain"><code>mxmlRetain</code></a> 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.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.3&#160;</span><a id="mxmlSAXLoadString">mxmlSAXLoadString</a></h3>
+        <p class="description">Load a string into an XML node tree
+using a SAX callback.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlSAXLoadString(<a href="#mxml_node_t">mxml_node_t</a> *top, const char *s, <a href="#mxml_load_cb_t">mxml_load_cb_t</a> cb, <a href="#mxml_sax_cb_t">mxml_sax_cb_t</a> sax_cb, void *sax_data);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>top</th>
+        <td class="description">Top node</td></tr>
+<tr><th>s</th>
+        <td class="description">String to load</td></tr>
+<tr><th>cb</th>
+        <td class="description">Callback function or constant</td></tr>
+<tr><th>sax_cb</th>
+        <td class="description">SAX callback or <code>MXML_NO_CALLBACK</code></td></tr>
+<tr><th>sax_data</th>
+        <td class="description">SAX user data</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">First node or <code>NULL</code> if the string has errors.</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">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 &lt;?xml&gt; for the entire string. The callback
+function returns the value type that should be used for child nodes.
+The constants <code>MXML_INTEGER_CALLBACK</code>, <code>MXML_OPAQUE_CALLBACK</code>,
+<code>MXML_REAL_CALLBACK</code>, and <code>MXML_TEXT_CALLBACK</code> are defined for
+loading child nodes of the specified type.<br>
+<br>
+The SAX callback must call <a href="#mxmlRetain"><code>mxmlRetain</code></a> 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.
+
+</p>
+<h3 class="function"><a id="mxmlSaveAllocString">mxmlSaveAllocString</a></h3>
+        <p class="description">Save an XML tree to an allocated string.</p>
+<p class="code">
+char *mxmlSaveAllocString(<a href="#mxml_node_t">mxml_node_t</a> *node, <a href="#mxml_save_cb_t">mxml_save_cb_t</a> cb);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to write</td></tr>
+<tr><th>cb</th>
+        <td class="description">Whitespace callback or <code>MXML_NO_CALLBACK</code></td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Allocated string or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">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.  <code>NULL</code> is returned
+if the node would produce an empty string or if the string cannot be
+allocated.<br>
+<br>
+The callback argument specifies a function that returns a whitespace
+string or NULL before and after each element.  If <code>MXML_NO_CALLBACK</code>
+is specified, whitespace will only be added before <code>MXML_TEXT</code> nodes
+with leading whitespace and before attribute names inside opening
+element tags.</p>
+<h3 class="function"><a id="mxmlSaveFd">mxmlSaveFd</a></h3>
+        <p class="description">Save an XML tree to a file descriptor.</p>
+<p class="code">
+int mxmlSaveFd(<a href="#mxml_node_t">mxml_node_t</a> *node, int fd, <a href="#mxml_save_cb_t">mxml_save_cb_t</a> cb);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to write</td></tr>
+<tr><th>fd</th>
+        <td class="description">File descriptor to write to</td></tr>
+<tr><th>cb</th>
+        <td class="description">Whitespace callback or <code>MXML_NO_CALLBACK</code></td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on error.</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The callback argument specifies a function that returns a whitespace
+string or NULL before and after each element. If <code>MXML_NO_CALLBACK</code>
+is specified, whitespace will only be added before <code>MXML_TEXT</code> nodes
+with leading whitespace and before attribute names inside opening
+element tags.</p>
+<h3 class="function"><a id="mxmlSaveFile">mxmlSaveFile</a></h3>
+        <p class="description">Save an XML tree to a file.</p>
+<p class="code">
+int mxmlSaveFile(<a href="#mxml_node_t">mxml_node_t</a> *node, FILE *fp, <a href="#mxml_save_cb_t">mxml_save_cb_t</a> cb);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to write</td></tr>
+<tr><th>fp</th>
+        <td class="description">File to write to</td></tr>
+<tr><th>cb</th>
+        <td class="description">Whitespace callback or <code>MXML_NO_CALLBACK</code></td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on error.</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The callback argument specifies a function that returns a whitespace
+string or NULL before and after each element. If <code>MXML_NO_CALLBACK</code>
+is specified, whitespace will only be added before <code>MXML_TEXT</code> nodes
+with leading whitespace and before attribute names inside opening
+element tags.</p>
+<h3 class="function"><a id="mxmlSaveString">mxmlSaveString</a></h3>
+        <p class="description">Save an XML node tree to a string.</p>
+<p class="code">
+int mxmlSaveString(<a href="#mxml_node_t">mxml_node_t</a> *node, char *buffer, int bufsize, <a href="#mxml_save_cb_t">mxml_save_cb_t</a> cb);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to write</td></tr>
+<tr><th>buffer</th>
+        <td class="description">String buffer</td></tr>
+<tr><th>bufsize</th>
+        <td class="description">Size of string buffer</td></tr>
+<tr><th>cb</th>
+        <td class="description">Whitespace callback or <code>MXML_NO_CALLBACK</code></td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Size of string</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">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.<br>
+<br>
+The callback argument specifies a function that returns a whitespace
+string or NULL before and after each element. If <code>MXML_NO_CALLBACK</code>
+is specified, whitespace will only be added before <code>MXML_TEXT</code> nodes
+with leading whitespace and before attribute names inside opening
+element tags.</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.3&#160;</span><a id="mxmlSetCDATA">mxmlSetCDATA</a></h3>
+        <p class="description">Set the element name of a CDATA node.</p>
+<p class="code">
+int mxmlSetCDATA(<a href="#mxml_node_t">mxml_node_t</a> *node, const char *data);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to set</td></tr>
+<tr><th>data</th>
+        <td class="description">New data string</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on failure</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The node is not changed if it (or its first child) is not a CDATA element node.
+
+</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.1&#160;</span><a id="mxmlSetCustom">mxmlSetCustom</a></h3>
+        <p class="description">Set the data and destructor of a custom data node.</p>
+<p class="code">
+int mxmlSetCustom(<a href="#mxml_node_t">mxml_node_t</a> *node, void *data, <a href="#mxml_custom_destroy_cb_t">mxml_custom_destroy_cb_t</a> destroy);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to set</td></tr>
+<tr><th>data</th>
+        <td class="description">New data pointer</td></tr>
+<tr><th>destroy</th>
+        <td class="description">New destructor function</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on failure</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The node is not changed if it (or its first child) is not a custom node.
+
+</p>
+<h3 class="function"><a id="mxmlSetCustomHandlers">mxmlSetCustomHandlers</a></h3>
+        <p class="description">Set the handling functions for custom data.</p>
+<p class="code">
+void mxmlSetCustomHandlers(<a href="#mxml_custom_load_cb_t">mxml_custom_load_cb_t</a> load, <a href="#mxml_custom_save_cb_t">mxml_custom_save_cb_t</a> save);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>load</th>
+        <td class="description">Load function</td></tr>
+<tr><th>save</th>
+        <td class="description">Save function</td></tr>
+</tbody></table>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The load function accepts a node pointer and a data string and must
+return 0 on success and non-zero on error.<br>
+<br>
+The save function accepts a node pointer and must return a malloc'd
+string on success and <code>NULL</code> on error.</p>
+<h3 class="function"><a id="mxmlSetElement">mxmlSetElement</a></h3>
+        <p class="description">Set the name of an element node.</p>
+<p class="code">
+int mxmlSetElement(<a href="#mxml_node_t">mxml_node_t</a> *node, const char *name);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to set</td></tr>
+<tr><th>name</th>
+        <td class="description">New name string</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on failure</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The node is not changed if it is not an element node.</p>
+<h3 class="function"><a id="mxmlSetErrorCallback">mxmlSetErrorCallback</a></h3>
+        <p class="description">Set the error message callback.</p>
+<p class="code">
+void mxmlSetErrorCallback(<a href="#mxml_error_cb_t">mxml_error_cb_t</a> cb);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>cb</th>
+        <td class="description">Error callback function</td></tr>
+</tbody></table>
+<h3 class="function"><a id="mxmlSetInteger">mxmlSetInteger</a></h3>
+        <p class="description">Set the value of an integer node.</p>
+<p class="code">
+int mxmlSetInteger(<a href="#mxml_node_t">mxml_node_t</a> *node, int integer);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to set</td></tr>
+<tr><th>integer</th>
+        <td class="description">Integer value</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on failure</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The node is not changed if it (or its first child) is not an integer node.</p>
+<h3 class="function"><a id="mxmlSetOpaque">mxmlSetOpaque</a></h3>
+        <p class="description">Set the value of an opaque node.</p>
+<p class="code">
+int mxmlSetOpaque(<a href="#mxml_node_t">mxml_node_t</a> *node, const char *opaque);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to set</td></tr>
+<tr><th>opaque</th>
+        <td class="description">Opaque string</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on failure</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The node is not changed if it (or its first child) is not an opaque node.</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.11&#160;</span><a id="mxmlSetOpaquef">mxmlSetOpaquef</a></h3>
+        <p class="description">Set the value of an opaque string node to a formatted string.</p>
+<p class="code">
+int mxmlSetOpaquef(<a href="#mxml_node_t">mxml_node_t</a> *node, const char *format, ...);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to set</td></tr>
+<tr><th>format</th>
+        <td class="description">Printf-style format string</td></tr>
+<tr><th>...</th>
+        <td class="description">Additional arguments as needed</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on failure</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The node is not changed if it (or its first child) is not an opaque node.
+
+</p>
+<h3 class="function"><a id="mxmlSetReal">mxmlSetReal</a></h3>
+        <p class="description">Set the value of a real number node.</p>
+<p class="code">
+int mxmlSetReal(<a href="#mxml_node_t">mxml_node_t</a> *node, double real);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to set</td></tr>
+<tr><th>real</th>
+        <td class="description">Real number value</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on failure</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The node is not changed if it (or its first child) is not a real number node.</p>
+<h3 class="function"><a id="mxmlSetText">mxmlSetText</a></h3>
+        <p class="description">Set the value of a text node.</p>
+<p class="code">
+int mxmlSetText(<a href="#mxml_node_t">mxml_node_t</a> *node, int whitespace, const char *string);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to set</td></tr>
+<tr><th>whitespace</th>
+        <td class="description">1 = leading whitespace, 0 = no whitespace</td></tr>
+<tr><th>string</th>
+        <td class="description">String</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on failure</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The node is not changed if it (or its first child) is not a text node.</p>
+<h3 class="function"><a id="mxmlSetTextf">mxmlSetTextf</a></h3>
+        <p class="description">Set the value of a text node to a formatted string.</p>
+<p class="code">
+int mxmlSetTextf(<a href="#mxml_node_t">mxml_node_t</a> *node, int whitespace, const char *format, ...);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to set</td></tr>
+<tr><th>whitespace</th>
+        <td class="description">1 = leading whitespace, 0 = no whitespace</td></tr>
+<tr><th>format</th>
+        <td class="description">Printf-style format string</td></tr>
+<tr><th>...</th>
+        <td class="description">Additional arguments as needed</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on failure</p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">The node is not changed if it (or its first child) is not a text node.</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.7&#160;</span><a id="mxmlSetUserData">mxmlSetUserData</a></h3>
+        <p class="description">Set the user data pointer for a node.</p>
+<p class="code">
+int mxmlSetUserData(<a href="#mxml_node_t">mxml_node_t</a> *node, void *data);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Node to set</td></tr>
+<tr><th>data</th>
+        <td class="description">User data pointer</td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">0 on success, -1 on failure</p>
+<h3 class="function"><span class="info">&#160;Mini-XML 2.3&#160;</span><a id="mxmlSetWrapMargin">mxmlSetWrapMargin</a></h3>
+        <p class="description">Set the wrap margin when saving XML data.</p>
+<p class="code">
+void mxmlSetWrapMargin(int column);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>column</th>
+        <td class="description">Column for wrapping, 0 to disable wrapping</td></tr>
+</tbody></table>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">Wrapping is disabled when &quot;column&quot; is 0.
+
+</p>
+<h3 class="function"><a id="mxmlWalkNext">mxmlWalkNext</a></h3>
+        <p class="description">Walk to the next logical node in the tree.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlWalkNext(<a href="#mxml_node_t">mxml_node_t</a> *node, <a href="#mxml_node_t">mxml_node_t</a> *top, int descend);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Current node</td></tr>
+<tr><th>top</th>
+        <td class="description">Top node</td></tr>
+<tr><th>descend</th>
+        <td class="description">Descend into tree - <code>MXML_DESCEND</code>, <code>MXML_NO_DESCEND</code>, or <code>MXML_DESCEND_FIRST</code></td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Next node or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">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.</p>
+<h3 class="function"><a id="mxmlWalkPrev">mxmlWalkPrev</a></h3>
+        <p class="description">Walk to the previous logical node in the tree.</p>
+<p class="code">
+<a href="#mxml_node_t">mxml_node_t</a> *mxmlWalkPrev(<a href="#mxml_node_t">mxml_node_t</a> *node, <a href="#mxml_node_t">mxml_node_t</a> *top, int descend);</p>
+<h4 class="parameters">Parameters</h4>
+<table class="list"><tbody>
+<tr><th>node</th>
+        <td class="description">Current node</td></tr>
+<tr><th>top</th>
+        <td class="description">Top node</td></tr>
+<tr><th>descend</th>
+        <td class="description">Descend into tree - <code>MXML_DESCEND</code>, <code>MXML_NO_DESCEND</code>, or <code>MXML_DESCEND_FIRST</code></td></tr>
+</tbody></table>
+<h4 class="returnvalue">Return Value</h4>
+        <p class="description">Previous node or <code>NULL</code></p>
+<h4 class="discussion">Discussion</h4>
+        <p class="discussion">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.</p>
+      <h2 class="title"><a id="TYPES">Data Types</a></h2>
+      <h3 class="typedef"><a id="mxml_custom_destroy_cb_t">mxml_custom_destroy_cb_t</a></h3>
+        <p class="description">Custom data destructor</p>
+      <p class="code">
+typedef void (*mxml_custom_destroy_cb_t)(void *);
+</p>
+      <h3 class="typedef"><a id="mxml_custom_load_cb_t">mxml_custom_load_cb_t</a></h3>
+        <p class="description">Custom data load callback function</p>
+      <p class="code">
+typedef int (*mxml_custom_load_cb_t)(<a href="#mxml_node_t">mxml_node_t</a> *, const char *);
+</p>
+      <h3 class="typedef"><a id="mxml_custom_save_cb_t">mxml_custom_save_cb_t</a></h3>
+        <p class="description">Custom data save callback function</p>
+      <p class="code">
+typedef char *(*mxml_custom_save_cb_t)(<a href="#mxml_node_t">mxml_node_t</a> *);
+</p>
+      <h3 class="typedef"><a id="mxml_entity_cb_t">mxml_entity_cb_t</a></h3>
+        <p class="description">Entity callback function</p>
+      <p class="code">
+typedef int (*mxml_entity_cb_t)(const char *);
+</p>
+      <h3 class="typedef"><a id="mxml_error_cb_t">mxml_error_cb_t</a></h3>
+        <p class="description">Error callback function</p>
+      <p class="code">
+typedef void (*mxml_error_cb_t)(const char *);
+</p>
+      <h3 class="typedef"><a id="mxml_index_t">mxml_index_t</a></h3>
+        <p class="description">An XML node index.</p>
+      <p class="code">
+typedef struct mxml_index_s mxml_index_t;
+</p>
+      <h3 class="typedef"><a id="mxml_load_cb_t">mxml_load_cb_t</a></h3>
+        <p class="description">Load callback function</p>
+      <p class="code">
+typedef <a href="#mxml_type_t">mxml_type_t</a> (*mxml_load_cb_t)(<a href="#mxml_node_t">mxml_node_t</a> *);
+</p>
+      <h3 class="typedef"><a id="mxml_node_t">mxml_node_t</a></h3>
+        <p class="description">An XML node.</p>
+      <p class="code">
+typedef struct mxml_node_s mxml_node_t;
+</p>
+      <h3 class="typedef"><a id="mxml_save_cb_t">mxml_save_cb_t</a></h3>
+        <p class="description">Save callback function</p>
+      <p class="code">
+typedef const char *(*mxml_save_cb_t)(<a href="#mxml_node_t">mxml_node_t</a> *, int);
+</p>
+      <h3 class="typedef"><a id="mxml_sax_cb_t">mxml_sax_cb_t</a></h3>
+        <p class="description">SAX callback function</p>
+      <p class="code">
+typedef void (*mxml_sax_cb_t)(<a href="#mxml_node_t">mxml_node_t</a> *, mxml_sax_event_t, void *);
+</p>
+      <h3 class="typedef"><a id="mxml_sax_event_t">mxml_sax_event_t</a></h3>
+        <p class="description">SAX event type.</p>
+      <p class="code">
+typedef enum <a href="#mxml_sax_event_e">mxml_sax_event_e</a> mxml_sax_event_t;
+</p>
+      <h3 class="typedef"><a id="mxml_type_t">mxml_type_t</a></h3>
+        <p class="description">The XML node type.</p>
+      <p class="code">
+typedef enum <a href="#mxml_type_e">mxml_type_e</a> mxml_type_t;
+</p>
+      <h2 class="title"><a id="ENUMERATIONS">Constants</a></h2>
+      <h3 class="enumeration"><a id="mxml_sax_event_e">mxml_sax_event_e</a></h3>
+        <p class="description">SAX event type.</p>
+      <h4 class="constants">Constants</h4>
+      <table class="list"><tbody>
+        <tr><th>MXML_SAX_CDATA </th>        <td class="description">CDATA node</td></tr>
+        <tr><th>MXML_SAX_COMMENT </th>        <td class="description">Comment node</td></tr>
+        <tr><th>MXML_SAX_DATA </th>        <td class="description">Data node</td></tr>
+        <tr><th>MXML_SAX_DIRECTIVE </th>        <td class="description">Processing directive node</td></tr>
+        <tr><th>MXML_SAX_ELEMENT_CLOSE </th>        <td class="description">Element closed</td></tr>
+        <tr><th>MXML_SAX_ELEMENT_OPEN </th>        <td class="description">Element opened</td></tr>
+</tbody></table>
+      <h3 class="enumeration"><a id="mxml_type_e">mxml_type_e</a></h3>
+        <p class="description">The XML node type.</p>
+      <h4 class="constants">Constants</h4>
+      <table class="list"><tbody>
+        <tr><th>MXML_CUSTOM <span class="info">&#160;Mini-XML 2.1&#160;</span></th>        <td class="description">Custom data </td></tr>
+        <tr><th>MXML_ELEMENT </th>        <td class="description">XML element with attributes</td></tr>
+        <tr><th>MXML_IGNORE <span class="info">&#160;Mini-XML 2.3&#160;</span></th>        <td class="description">Ignore/throw away node </td></tr>
+        <tr><th>MXML_INTEGER </th>        <td class="description">Integer value</td></tr>
+        <tr><th>MXML_OPAQUE </th>        <td class="description">Opaque string</td></tr>
+        <tr><th>MXML_REAL </th>        <td class="description">Real value</td></tr>
+        <tr><th>MXML_TEXT </th>        <td class="description">Text fragment</td></tr>
+</tbody></table>
+    </div>
+  </body>
+</html>

BIN
mxml.mod/mxml/doc/mxml.opacity


BIN
mxml.mod/mxml/doc/mxml.png


+ 251 - 0
mxml.mod/mxml/install-sh

@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	:
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+		chmodcmd=""
+	else
+		instcmd=$mkdirprog
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		:
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		:
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		:
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+	'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		:
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		:
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0

+ 345 - 0
mxml.mod/mxml/mxml-attr.c

@@ -0,0 +1,345 @@
+/*
+ * Attribute support code for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml-private.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 --;
+
+      if (node->value.element.num_attrs == 0)
+        free(node->value.element.attrs);
+      return;
+    }
+  }
+}
+
+
+/*
+ * 'mxmlElementGetAttr()' - Get an attribute.
+ *
+ * This function returns @code NULL@ if the node is not an element or the
+ * named attribute does not exist.
+ */
+
+const char *				/* O - Attribute value or @code 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);
+}
+
+
+/*
+ * 'mxmlElementGetAttrByIndex()' - Get an element attribute by index.
+ *
+ * The index ("idx") is 0-based.  @code NULL@ is returned if the specified index
+ * is out of range.
+ *
+ * @since Mini-XML 2.11@
+ */
+
+const char *                            /* O - Attribute value */
+mxmlElementGetAttrByIndex(
+    mxml_node_t *node,                  /* I - Node */
+    int         idx,                    /* I - Attribute index, starting at 0 */
+    const char  **name)                 /* O - Attribute name */
+{
+  if (!node || node->type != MXML_ELEMENT || idx < 0 || idx >= node->value.element.num_attrs)
+    return (NULL);
+
+  if (name)
+    *name = node->value.element.attrs[idx].name;
+
+  return (node->value.element.attrs[idx].value);
+}
+
+
+/*
+ * 'mxmlElementGetAttrCount()' - Get the number of element attributes.
+ *
+ * @since Mini-XML 2.11@
+ */
+
+int                                     /* O - Number of attributes */
+mxmlElementGetAttrCount(
+    mxml_node_t *node)                  /* I - Node */
+{
+  if (node && node->type == MXML_ELEMENT)
+    return (node->value.element.num_attrs);
+  else
+    return (0);
+}
+
+
+/*
+ * '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);
+}

+ 438 - 0
mxml.mod/mxml/mxml-entity.c

@@ -0,0 +1,438 @@
+/*
+ * Character entity support code for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * 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, @code NULL@ is returned.
+ */
+
+const char *				/* O - Entity name or @code 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);
+}

+ 3632 - 0
mxml.mod/mxml/mxml-file.c

@@ -0,0 +1,3632 @@
+/*
+ * File loading code for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * 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;
+
+typedef struct _mxml_streambuf_s		/**** File descriptor buffer ****/
+{
+  void * ctxt;			/* File descriptor */
+  mxml_read_stream_cb_t read;
+  mxml_write_stream_cb_t write;
+  unsigned char	*current,		/* Current position in buffer */
+		*end,			/* End of buffer */
+		buffer[8192];		/* Character buffer */
+} _mxml_streambuf_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_stream_getc(void *p, int *encoding);
+static int		mxml_stream_putc(int ch, void *p);
+static int		mxml_stream_read(_mxml_streambuf_t *buf);
+static int		mxml_stream_write(_mxml_streambuf_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, int *line);
+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, int *line);
+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.
+ * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@,
+ * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for
+ * loading child (data) nodes of the specified type.
+ *
+ * Note: The most common programming error when using the Mini-XML library is
+ * to load an XML file using the @code MXML_TEXT_CALLBACK@, which returns inline
+ * text as a series of whitespace-delimited words, instead of using the
+ * @code MXML_OPAQUE_CALLBACK@ which returns the inline text as a single string
+ * (including whitespace).
+ */
+
+mxml_node_t *				/* O - First node or @code 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 constant */
+{
+  _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.
+ * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@,
+ * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for
+ * loading child (data) nodes of the specified type.
+ *
+ * Note: The most common programming error when using the Mini-XML library is
+ * to load an XML file using the @code MXML_TEXT_CALLBACK@, which returns inline
+ * text as a series of whitespace-delimited words, instead of using the
+ * @code MXML_OPAQUE_CALLBACK@ which returns the inline text as a single string
+ * (including whitespace).
+ */
+
+mxml_node_t *				/* O - First node or @code 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 constant */
+{
+ /*
+  * 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.
+ * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@,
+ * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for
+ * loading child (data) nodes of the specified type.
+ *
+ * Note: The most common programming error when using the Mini-XML library is
+ * to load an XML file using the @code MXML_TEXT_CALLBACK@, which returns inline
+ * text as a series of whitespace-delimited words, instead of using the
+ * @code MXML_OPAQUE_CALLBACK@ which returns the inline text as a single string
+ * (including whitespace).
+ */
+
+mxml_node_t *				/* O - First node or @code 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 constant */
+{
+ /*
+  * Read the XML data...
+  */
+
+  return (mxml_load_data(top, (void *)&s, cb, mxml_string_getc, MXML_NO_CALLBACK,
+                         NULL));
+}
+
+/*
+ * 'mxmlLoadStream()' - Load a stream into an XML node tree.
+ *
+ * The nodes in the specified stream 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.
+ * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@,
+ * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for
+ * loading child (data) nodes of the specified type.
+ *
+ * Note: The most common programming error when using the Mini-XML library is
+ * to load an XML file using the @code MXML_TEXT_CALLBACK@, which returns inline
+ * text as a series of whitespace-delimited words, instead of using the
+ * @code MXML_OPAQUE_CALLBACK@ which returns the inline text as a single string
+ * (including whitespace).
+ */
+
+mxml_node_t *				/* O - First node or @code NULL@ if the file could not be read. */
+mxmlLoadStream(mxml_node_t    *top,	/* I - Top node */
+             mxml_read_stream_cb_t read_stream_cb, 	/* I - Stream callback */
+			 void *read_stream_context,	/* I - Stream context */
+             mxml_load_cb_t cb)		/* I - Callback function or constant */
+{
+  _mxml_streambuf_t	buf;			/* stream buffer */
+
+
+ /*
+  * Initialize the stream buffer...
+  */
+
+  buf.ctxt    = read_stream_context;
+  buf.read    = read_stream_cb;
+  buf.current = buf.buffer;
+  buf.end     = buf.buffer;
+ /*
+  * Read the XML data...
+  */
+
+  return (mxml_load_data(top, &buf, cb, mxml_stream_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.  @code 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 @code MXML_NO_CALLBACK@
+ * is specified, whitespace will only be added before @code MXML_TEXT@ nodes
+ * with leading whitespace and before attribute names inside opening
+ * element tags.
+ */
+
+char *					/* O - Allocated string or @code NULL@ */
+mxmlSaveAllocString(
+    mxml_node_t    *node,		/* I - Node to write */
+    mxml_save_cb_t cb)			/* I - Whitespace callback or @code 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 @code MXML_NO_CALLBACK@
+ * is specified, whitespace will only be added before @code 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 @code 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 @code MXML_NO_CALLBACK@
+ * is specified, whitespace will only be added before @code 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 @code 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);
+}
+
+/*
+ * 'mxmlSaveStream()' - Save an XML tree to a stream.
+ *
+ * The callback argument specifies a function that returns a whitespace
+ * string or NULL before and after each element. If @code MXML_NO_CALLBACK@
+ * is specified, whitespace will only be added before @code MXML_TEXT@ nodes
+ * with leading whitespace and before attribute names inside opening
+ * element tags.
+ */
+
+ int					/* O - 0 on success, -1 on error. */
+mxmlSaveStream(mxml_node_t    *node,	/* I - Node to write */
+             mxml_write_stream_cb_t write_stream_cb, 	/* I - Stream callback */
+			 void *write_stream_context,	/* I - Stream context */
+	   mxml_save_cb_t cb)		/* I - Whitespace callback or @code MXML_NO_CALLBACK@ */
+{
+  int		col;			/* Final column */
+  _mxml_streambuf_t	buf;			/* Stream buffer */
+  _mxml_global_t *global = _mxml_global();
+					/* Global data */
+
+
+ /*
+  * Initialize the stream buffer...
+  */
+
+  buf.ctxt    = write_stream_context;
+  buf.write   = write_stream_cb;
+  buf.current = buf.buffer;
+  buf.end     = buf.buffer + sizeof(buf.buffer);
+
+ /*
+  * Write the node...
+  */
+
+  if ((col = mxml_write_node(node, &buf, cb, 0, mxml_stream_putc, global)) < 0)
+    return (-1);
+
+  if (col > 0)
+    if (mxml_stream_putc('\n', &buf) < 0)
+      return (-1);
+
+ /*
+  * Flush and return...
+  */
+
+  return (mxml_stream_write(&buf));
+}
+
+/*
+ * '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 @code MXML_NO_CALLBACK@
+ * is specified, whitespace will only be added before @code 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 @code 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 ((int)(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.
+ * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@,
+ * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for
+ * loading child nodes of the specified type.
+ *
+ * The SAX callback must call @link 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 @code 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 constant */
+              mxml_sax_cb_t  sax_cb,	/* I - SAX callback or @code 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.
+ * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@,
+ * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for
+ * loading child nodes of the specified type.
+ *
+ * The SAX callback must call @link 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 @code 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 constant */
+    mxml_sax_cb_t  sax_cb,		/* I - SAX callback or @code 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.
+ * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@,
+ * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for
+ * loading child nodes of the specified type.
+ *
+ * The SAX callback must call @link 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 @code 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 constant */
+    mxml_sax_cb_t  sax_cb,		/* I - SAX callback or @code 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 @code 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);
+}
+
+static int				/* O  - Character or EOF */
+mxml_stream_getc(void *p,			/* I  - File descriptor buffer */
+             int  *encoding)		/* IO - Encoding */
+{
+  _mxml_streambuf_t	*buf;			/* File descriptor buffer */
+  int		ch,			/* Current character */
+		temp;			/* Temporary character */
+
+
+ /*
+  * Grab the next character in the buffer...
+  */
+
+  buf = (_mxml_streambuf_t *)p;
+
+  if (buf->current >= buf->end)
+    if (mxml_stream_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_stream_read(buf) < 0)
+	      return (EOF);
+
+	  ch = *(buf->current)++;
+
+	  if (ch != 0xff)
+	    return (EOF);
+
+	  *encoding = ENCODE_UTF16BE;
+
+	  return (mxml_stream_getc(p, encoding));
+	}
+	else if (ch == 0xff)
+	{
+	 /*
+	  * UTF-16 little-endian BOM?
+	  */
+
+	  if (buf->current >= buf->end)
+	    if (mxml_stream_read(buf) < 0)
+	      return (EOF);
+
+	  ch = *(buf->current)++;
+
+	  if (ch != 0xfe)
+	    return (EOF);
+
+	  *encoding = ENCODE_UTF16LE;
+
+	  return (mxml_stream_getc(p, encoding));
+	}
+	else if ((ch & 0xe0) == 0xc0)
+	{
+	 /*
+	  * Two-byte value...
+	  */
+
+	  if (buf->current >= buf->end)
+	    if (mxml_stream_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_stream_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_stream_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_stream_getc(p, encoding));
+	}
+	else if ((ch & 0xf8) == 0xf0)
+	{
+	 /*
+	  * Four-byte value...
+	  */
+
+	  if (buf->current >= buf->end)
+	    if (mxml_stream_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_stream_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_stream_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_stream_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_stream_read(buf) < 0)
+	      return (EOF);
+
+	  lch = *(buf->current)++;
+
+	  if (buf->current >= buf->end)
+	    if (mxml_stream_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_stream_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_stream_read(buf) < 0)
+	      return (EOF);
+
+	  lch = *(buf->current)++;
+
+	  if (buf->current >= buf->end)
+	    if (mxml_stream_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 = (int)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 = (int)write(buf->fd, ptr, buf->current - ptr)) < 0)
+      return (-1);
+
+ /*
+  * All done, reset pointers and return success...
+  */
+
+  buf->current = buf->buffer;
+
+  return (0);
+}
+
+static int				/* O - 0 on success, -1 on error */
+mxml_stream_putc(int  ch,			/* I - Character */
+             void *p)			/* I - stream buffer */
+{
+  _mxml_streambuf_t	*buf;			/* stream buffer */
+
+
+ /*
+  * Flush the write buffer as needed...
+  */
+
+  buf = (_mxml_streambuf_t *)p;
+
+  if (buf->current >= buf->end)
+    if (mxml_stream_write(buf) < 0)
+      return (-1);
+
+  *(buf->current)++ = ch;
+
+ /*
+  * Return successfully...
+  */
+
+  return (0);
+}
+
+static int				/* O - 0 on success, -1 on error */
+mxml_stream_read(_mxml_streambuf_t *buf)		/* I - File descriptor buffer */
+{
+  int	bytes;				/* Bytes read... */
+
+
+ /*
+  * Range check input...
+  */
+
+  if (!buf)
+    return (-1);
+
+ /*
+  * Read from the file descriptor...
+  */
+
+  bytes = (int)buf->read(buf->ctxt, buf->buffer, sizeof(buf->buffer));
+
+  if (bytes == 0)
+    return (-1);
+
+ /*
+  * Update the pointers and return success...
+  */
+
+  buf->current = buf->buffer;
+  buf->end     = buf->buffer + bytes;
+
+  return (0);
+}
+
+static int				/* O - 0 on success, -1 on error */
+mxml_stream_write(_mxml_streambuf_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 = (int)buf->write(buf->ctxt, 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);
+          lch = (lch << 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);
+          lch |= (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         *line)	/* IO - Current line number */
+{
+  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> on line %d.", parent ? parent->value.element.name : "null", *line);
+      break;
+    }
+  }
+
+  *entptr = '\0';
+
+  if (ch != ';')
+  {
+    mxml_error("Character entity '%s' not terminated under parent <%s> on line %d.", entity, parent ? parent->value.element.name : "null", *line);
+
+    if (ch == '\n')
+      (*line)++;
+
+    return (EOF);
+  }
+
+  if (entity[0] == '#')
+  {
+    if (entity[1] == 'x')
+      ch = (int)strtol(entity + 2, NULL, 16);
+    else
+      ch = (int)strtol(entity + 1, NULL, 10);
+  }
+  else if ((ch = mxmlEntityGetValue(entity)) < 0)
+    mxml_error("Entity name '%s;' not supported under parent <%s> on line %d.", entity, parent ? parent->value.element.name : "null", *line);
+
+  if (mxml_bad_char(ch))
+  {
+    mxml_error("Bad control character 0x%02x under parent <%s> on line %d not allowed by XML standard.", ch, parent ? parent->value.element.name : "null", *line);
+    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		line = 1,		/* Current line number */
+		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 if (parent)
+    type = MXML_TEXT;
+  else
+    type = MXML_IGNORE;
+
+  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, (int)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> on line %d.", buffer, parent ? parent->value.element.name : "null", line);
+		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> on line %d.", type == MXML_INTEGER ? "integer" : "real", buffer, parent ? parent->value.element.name : "null", line);
+	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> on line %d.", types[type], parent ? parent->value.element.name : "null", line);
+	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;
+
+    if (ch == '\n')
+      line ++;
+
+   /*
+    * 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, &line)) == EOF)
+	    goto error;
+
+	  if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
+	    goto error;
+	}
+	else if (ch < '0' && ch != '!' && ch != '-' && ch != '.' && ch != '/')
+	  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;
+
+	if (ch == '\n')
+	  line ++;
+      }
+
+      *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;
+
+	  if (ch == '\n')
+	    line ++;
+	}
+
+       /*
+        * Error out if we didn't get the whole comment...
+	*/
+
+        if (ch != '>')
+	{
+	 /*
+	  * Print error and return...
+	  */
+
+	  mxml_error("Early EOF in comment node on line %d.", line);
+	  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> on line %d.", buffer, first->value.element.name, line);
+          goto error;
+	}
+
+	if ((node = mxmlNewElement(parent, buffer)) == NULL)
+	{
+	 /*
+	  * Just print error for now...
+	  */
+
+	  mxml_error("Unable to add comment node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line);
+	  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))
+	  {
+	   /*
+	    * Drop terminator from CDATA string...
+	    */
+
+	    bufptr[-2] = '\0';
+	    break;
+	  }
+	  else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
+	    goto error;
+
+	  if (ch == '\n')
+	    line ++;
+	}
+
+       /*
+        * Error out if we didn't get the whole comment...
+	*/
+
+        if (ch != '>')
+	{
+	 /*
+	  * Print error and return...
+	  */
+
+	  mxml_error("Early EOF in CDATA node on line %d.", line);
+	  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> on line %d.", buffer, first->value.element.name, line);
+          goto error;
+	}
+
+	if ((node = mxmlNewElement(parent, buffer)) == NULL)
+	{
+	 /*
+	  * Print error and return...
+	  */
+
+	  mxml_error("Unable to add CDATA node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line);
+	  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;
+
+	  if (ch == '\n')
+	    line ++;
+	}
+
+       /*
+        * 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 on line %d.", line);
+	  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> on line %d.", buffer, first->value.element.name, line);
+          goto error;
+	}
+
+	if ((node = mxmlNewElement(parent, buffer)) == NULL)
+	{
+	 /*
+	  * Print error and return...
+	  */
+
+	  mxml_error("Unable to add processing instruction node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line);
+	  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
+	      type = MXML_TEXT;
+	  }
+	}
+      }
+      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, &line)) == EOF)
+		goto error;
+            }
+
+	    if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
+	      goto error;
+	  }
+
+	  if (ch == '\n')
+	    line ++;
+	}
+        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 on line %d.", line);
+	  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> on line %d.", buffer, first->value.element.name, line);
+          goto error;
+	}
+
+	if ((node = mxmlNewElement(parent, buffer)) == NULL)
+	{
+	 /*
+	  * Print error and return...
+	  */
+
+	  mxml_error("Unable to add declaration node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line);
+	  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
+	      type = MXML_TEXT;
+	  }
+	}
+      }
+      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> on line %d.", buffer, parent ? parent->value.element.name : "(null)", line);
+          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> on line %d.", buffer, first->value.element.name, line);
+          goto error;
+	}
+
+        if ((node = mxmlNewElement(parent, buffer)) == NULL)
+	{
+	 /*
+	  * Just print error for now...
+	  */
+
+	  mxml_error("Unable to add element node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line);
+	  goto error;
+	}
+
+        if (mxml_isspace(ch))
+        {
+	  if ((ch = mxml_parse_element(node, p, &encoding, getc_cb, &line)) == EOF)
+	    goto error;
+        }
+        else if (ch == '/')
+	{
+	  if ((ch = (*getc_cb)(p, &encoding)) != '>')
+	  {
+	    mxml_error("Expected > but got '%c' instead for element <%s/> on line %d.", ch, buffer, line);
+            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
+	    type = MXML_TEXT;
+	}
+        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, &line)) == 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 != top && parent->parent)
+      parent = parent->parent;
+
+    if (node != parent)
+    {
+      mxml_error("Missing close tag </%s> under parent <%s> on line %d.", node->value.element.name, node->parent ? node->parent->value.element.name : "(null)", line);
+
+      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             *line)		/* IO - Current line number */
+{
+  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))
+    {
+      if (ch == '\n')
+        (*line)++;
+
+      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' on line %d.", ch, node->value.element.name, quote, *line);
+        goto error;
+      }
+
+      break;
+    }
+    else if (ch == '<')
+    {
+      mxml_error("Bare < in element %s on line %d.", node->value.element.name, *line);
+      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, line)) == EOF)
+	    goto error;
+	}
+	else if (ch == '\n')
+	  (*line)++;
+
+	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 == '?')
+	{
+	  if (ch == '\n')
+	    (*line)++;
+          break;
+        }
+	else
+	{
+          if (ch == '&')
+          {
+	    if ((ch = mxml_get_entity(node, p, encoding, getc_cb, line)) == EOF)
+	      goto error;
+          }
+
+	  if (mxml_add_char(ch, &ptr, &name, &namesize))
+	    goto error;
+	}
+    }
+    }
+
+    *ptr = '\0';
+
+    if (mxmlElementGetAttr(node, name))
+    {
+      mxml_error("Duplicate attribute '%s' in element %s on line %d.", name, node->value.element.name, name, *line);
+      goto error;
+    }
+
+    while (ch != EOF && mxml_isspace(ch))
+    {
+      ch = (*getc_cb)(p, encoding);
+
+      if (ch == '\n')
+        (*line)++;
+    }
+
+    if (ch == '=')
+    {
+     /*
+      * Read the attribute value...
+      */
+
+      while ((ch = (*getc_cb)(p, encoding)) != EOF && mxml_isspace(ch))
+      {
+        if (ch == '\n')
+          (*line)++;
+      }
+
+      if (ch == EOF)
+      {
+        mxml_error("Missing value for attribute '%s' in element %s on line %d.", name, node->value.element.name, *line);
+        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, line)) == EOF)
+	        goto error;
+	    }
+	    else if (ch == '\n')
+	      (*line)++;
+
+	    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 == '>')
+	  {
+	    if (ch == '\n')
+	      (*line)++;
+
+            break;
+          }
+	  else
+	  {
+	    if (ch == '&')
+	    {
+	      if ((ch = mxml_get_entity(node, p, encoding, getc_cb, line)) == 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 on line %d.", name, node->value.element.name, *line);
+      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' on line %d.", ch, node->value.element.name, quote, *line);
+        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 */
+{
+  mxml_node_t	*current,		/* Current node */
+		*next;			/* Next node */
+  int		i,			/* Looping var */
+		width;			/* Width of attr + value */
+  _mxml_attr_t	*attr;			/* Current attribute */
+  char		s[255];			/* Temporary string */
+
+
+ /*
+  * Loop through this node and all of its children...
+  */
+
+  for (current = node; current; current = next)
+  {
+   /*
+    * Print the node value...
+    */
+
+    switch (current->type)
+    {
+      case MXML_ELEMENT :
+	  col = mxml_write_ws(current, p, cb, MXML_WS_BEFORE_OPEN, col, putc_cb);
+
+	  if ((*putc_cb)('<', p) < 0)
+	    return (-1);
+	  if (current->value.element.name[0] == '?' ||
+	      !strncmp(current->value.element.name, "!--", 3))
+	  {
+	   /*
+	    * Comments and processing instructions do not use character
+	    * entities.
+	    */
+
+	    const char	*ptr;		/* Pointer into name */
+
+	    for (ptr = current->value.element.name; *ptr; ptr ++)
+	      if ((*putc_cb)(*ptr, p) < 0)
+		return (-1);
+	  }
+	  else if (!strncmp(current->value.element.name, "![CDATA[", 8))
+	  {
+	   /*
+	    * CDATA elements do not use character entities, but also need the
+	    * "]]" terminator added at the end.
+	    */
+
+	    const char	*ptr;		/* Pointer into name */
+
+	    for (ptr = current->value.element.name; *ptr; ptr ++)
+	      if ((*putc_cb)(*ptr, p) < 0)
+		return (-1);
+
+            if ((*putc_cb)(']', p) < 0)
+              return (-1);
+            if ((*putc_cb)(']', p) < 0)
+              return (-1);
+	  }
+	  else if (mxml_write_name(current->value.element.name, p, putc_cb) < 0)
+	    return (-1);
+
+	  col += strlen(current->value.element.name) + 1;
+
+	  for (i = current->value.element.num_attrs, attr = current->value.element.attrs;
+	       i > 0;
+	       i --, attr ++)
+	  {
+	    width = (int)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 (current->child)
+	  {
+	   /*
+	    * Write children...
+	    */
+
+	    if ((*putc_cb)('>', p) < 0)
+	      return (-1);
+	    else
+	      col ++;
+
+	    col = mxml_write_ws(current, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
+	  }
+	  else if (current->value.element.name[0] == '!' ||
+		   current->value.element.name[0] == '?')
+	  {
+	   /*
+	    * The ? and ! elements are special-cases...
+	    */
+
+	    if ((*putc_cb)('>', p) < 0)
+	      return (-1);
+	    else
+	      col ++;
+
+	    col = mxml_write_ws(current, 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(current, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
+	  }
+	  break;
+
+      case MXML_INTEGER :
+	  if (current->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 ++;
+	  }
+
+	  snprintf(s, sizeof(s), "%d", current->value.integer);
+	  if (mxml_write_string(s, p, putc_cb) < 0)
+	    return (-1);
+
+	  col += strlen(s);
+	  break;
+
+      case MXML_OPAQUE :
+	  if (mxml_write_string(current->value.opaque, p, putc_cb) < 0)
+	    return (-1);
+
+	  col += strlen(current->value.opaque);
+	  break;
+
+      case MXML_REAL :
+	  if (current->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 ++;
+	  }
+
+	  snprintf(s, sizeof(s), "%f", current->value.real);
+	  if (mxml_write_string(s, p, putc_cb) < 0)
+	    return (-1);
+
+	  col += strlen(s);
+	  break;
+
+      case MXML_TEXT :
+	  if (current->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(current->value.text.string, p, putc_cb) < 0)
+	    return (-1);
+
+	  col += strlen(current->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)(current)) == 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 = (int)strlen(newline);
+
+	    free(data);
+	    break;
+	  }
+
+      default : /* Should never happen */
+	  return (-1);
+    }
+
+   /*
+    * Figure out the next node...
+    */
+
+    if ((next = current->child) == NULL)
+    {
+      if (current == node)
+      {
+       /*
+        * Don't traverse to sibling node if we are at the "root" node...
+        */
+
+        next = NULL;
+      }
+      else
+      {
+       /*
+        * Try the next sibling, and continue traversing upwards as needed...
+        */
+
+	while ((next = current->next) == NULL)
+	{
+	  if (current == node || !current->parent)
+	    break;
+
+	 /*
+	  * The ? and ! elements are special-cases and have no end tags...
+	  */
+
+	  current = current->parent;
+
+	  if (current->value.element.name[0] != '!' &&
+	      current->value.element.name[0] != '?')
+	  {
+	    col = mxml_write_ws(current, 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(current->value.element.name, p, putc_cb) < 0)
+	      return (-1);
+	    if ((*putc_cb)('>', p) < 0)
+	      return (-1);
+
+	    col += strlen(current->value.element.name) + 3;
+
+	    col = mxml_write_ws(current, p, cb, MXML_WS_AFTER_CLOSE, col, putc_cb);
+	  }
+
+	  if (current == node)
+	    break;
+	}
+      }
+    }
+  }
+
+  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);
+}

+ 448 - 0
mxml.mod/mxml/mxml-get.c

@@ -0,0 +1,448 @@
+/*
+ * Node get functions for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2014-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml-private.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 @code 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 @code 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 @code 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 @code 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 @code 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 @code 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 @code 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 @code 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 @code NULL@.
+ *
+ * Note: Text nodes consist of whitespace-delimited words. You will only get
+ * single words of text when reading an XML file with @code MXML_TEXT@ nodes.
+ * If you want the entire string between elements in the XML file, you MUST read
+ * the XML file with @code MXML_OPAQUE@ nodes and get the resulting strings
+ * using the @link mxmlGetOpaque@ function instead.
+ *
+ * @since Mini-XML 2.7@
+ */
+
+const char *				/* O - Text string or @code 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 NULL@.
+ *
+ * @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);
+}

+ 652 - 0
mxml.mod/mxml/mxml-index.c

@@ -0,0 +1,652 @@
+/*
+ * Index support code for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml-private.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.
+ *
+ * You should call @link mxmlIndexReset@ prior to using this function to get
+ * the first node in the index.  Nodes are returned in the sorted order of the
+ * index.
+ */
+
+mxml_node_t *				/* O - Next node or @code 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 @link mxmlIndexReset@ prior to using this function for
+ * the first time with a particular set of "element" and "value"
+ * strings. Passing @code NULL@ for both "element" and "value" is equivalent
+ * to calling @link mxmlIndexEnum@.
+ */
+
+mxml_node_t *				/* O - Node or @code 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...");
+    if (ind)
+      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 @code 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 @code NULL@ for all */
+             const char  *attr)		/* I - Attribute to index or @code 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 @link mxmlIndexEnum@ or
+ * @link mxmlIndexFind@ for the first time.
+ */
+
+mxml_node_t *				/* O - First node or @code 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 @code NULL@ */
+	   const char   *value,		/* I - Attribute value or @code 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));
+}

+ 873 - 0
mxml.mod/mxml/mxml-node.c

@@ -0,0 +1,873 @@
+/*
+ * Node support code for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml-private.h"
+
+
+/*
+ * Local functions...
+ */
+
+static void		mxml_free(mxml_node_t *node);
+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
+ * @code NULL@, puts the new node before or after the specified child depending
+ * on the value of the where argument.  If the child argument is @code NULL@,
+ * puts the new node at the beginning of the child list (@code MXML_ADD_BEFORE@)
+ * or at the end of the child list (@code MXML_ADD_AFTER@).  The constant
+ * @code MXML_ADD_TO_PARENT@ can be used to specify a @code NULL@ child pointer.
+ */
+
+void
+mxmlAdd(mxml_node_t *parent,		/* I - Parent node */
+        int         where,		/* I - Where to add, @code MXML_ADD_BEFORE@ or @code MXML_ADD_AFTER@ */
+        mxml_node_t *child,		/* I - Child node for where or @code 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 @link mxmlRemove@ function.
+ */
+
+void
+mxmlDelete(mxml_node_t *node)		/* I - Node to delete */
+{
+  mxml_node_t	*current,		/* Current node */
+		*next;			/* Next node */
+
+
+#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...
+  */
+
+  for (current = node->child; current; current = next)
+  {
+   /*
+    * Get the next node...
+    */
+
+    if ((next = current->child) != NULL)
+    {
+     /*
+      * Free parent nodes after child nodes have been freed...
+      */
+
+      current->child = NULL;
+      continue;
+    }
+
+    if ((next = current->next) == NULL)
+    {
+     /*
+      * Next node is the parent, which we'll free as needed...
+      */
+
+      if ((next = current->parent) == node)
+        next = NULL;
+    }
+
+   /*
+    * Free child...
+    */
+
+    mxml_free(current);
+  }
+
+ /*
+  * Then free the memory used by the parent node...
+  */
+
+  mxml_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 2.7@.
+ */
+
+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 @code 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 currently use the
+ * @code MXML_ELEMENT@ type.
+ *
+ * @since Mini-XML 2.3@
+ */
+
+mxml_node_t *				/* O - New node */
+mxmlNewCDATA(mxml_node_t *parent,	/* I - Parent node or @code 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 @code MXML_NO_PARENT@ can be used to specify that the new
+ * element node has no parent. @code 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 @code 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 @code 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 @code 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 @code 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 @code 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 string node is added to the end of the specified parent's
+ * child list.  The constant @code MXML_NO_PARENT@ can be used to specify that
+ * the new opaque string 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 @code 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);
+}
+
+
+/*
+ * 'mxmlNewOpaquef()' - Create a new formatted opaque string node.
+ *
+ * The new opaque string node is added to the end of the specified parent's
+ * child list.  The constant @code MXML_NO_PARENT@ can be used to specify that
+ * the new opaque string node has no parent.  The format string must be
+ * nul-terminated and is formatted into the new node.
+ */
+
+mxml_node_t *				/* O - New node */
+mxmlNewOpaquef(mxml_node_t *parent,	/* I - Parent node or @code MXML_NO_PARENT@ */
+               const char  *format,	/* I - Printf-style format string */
+	       ...)			/* I - Additional args as needed */
+{
+  mxml_node_t	*node;			/* New node */
+  va_list	ap;			/* Pointer to arguments */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "mxmlNewOpaquef(parent=%p, format=\"%s\", ...)\n", parent, 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_OPAQUE)) != NULL)
+  {
+    va_start(ap, format);
+
+    node->value.opaque = _mxml_vstrdupf(format, ap);
+
+    va_end(ap);
+  }
+
+  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 @code 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 @code 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 @code 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 @code 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 @code 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 @code MXML_NO_PARENT@ */
+             int         whitespace,	/* I - 1 = leading whitespace, 0 = no whitespace */
+	     const char  *format,	/* I - Printf-style format 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.
+ *
+ * This function does not free memory used by the node - use @link 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 @code 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 @link 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_free()' - Free the memory used by a node.
+ *
+ * Note: Does not free child nodes, does not remove from parent.
+ */
+
+static void
+mxml_free(mxml_node_t *node)		/* I - Node */
+{
+  int	i;				/* Looping var */
+
+
+  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);
+}
+
+
+/*
+ * '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);
+}

+ 313 - 0
mxml.mod/mxml/mxml-private.c

@@ -0,0 +1,313 @@
+/*
+ * Private functions for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * 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 */

+ 98 - 0
mxml.mod/mxml/mxml-private.h

@@ -0,0 +1,98 @@
+/*
+ * Private definitions for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml.h"
+
+
+/*
+ * Private structures...
+ */
+
+typedef struct _mxml_attr_s		/**** An XML element attribute value. ****/
+{
+  char			*name;		/* Attribute name */
+  char			*value;		/* Attribute value */
+} _mxml_attr_t;
+
+typedef struct _mxml_element_s		/**** An XML element value. ****/
+{
+  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. ****/
+{
+  int			whitespace;	/* Leading whitespace? */
+  char			*string;	/* Fragment string */
+} _mxml_text_t;
+
+typedef struct _mxml_custom_s		/**** An XML custom value. ****/
+{
+  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. ****/
+{
+  _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. ****/
+{
+  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 */
+};
+
+struct _mxml_index_s			 /**** An XML node index. ****/
+{
+  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_global_s		/**** Global, per-thread data ****/
+
+{
+  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);

+ 269 - 0
mxml.mod/mxml/mxml-search.c

@@ -0,0 +1,269 @@
+/*
+ * Search/navigation functions for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml-private.h"
+
+
+/*
+ * 'mxmlFindElement()' - Find the named element.
+ *
+ * The search is constrained by the name, attribute name, and value; any
+ * @code 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
+ * @code MXML_DESCEND_FIRST@ for the initial search and @code 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 @code NULL@ */
+mxmlFindElement(mxml_node_t *node,	/* I - Current node */
+                mxml_node_t *top,	/* I - Top node */
+                const char  *element,	/* I - Element name or @code NULL@ for any */
+		const char  *attr,	/* I - Attribute name, or @code NULL@ for none */
+		const char  *value,	/* I - Attribute value, or @code NULL@ for any */
+		int         descend)	/* I - Descend into tree - @code MXML_DESCEND@, @code MXML_NO_DESCEND@, or @code 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 &&
+	(!element || !strcmp(node->value.element.name, element)))
+    {
+     /*
+      * 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 @code 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 @code NULL@ */
+mxmlWalkNext(mxml_node_t *node,		/* I - Current node */
+             mxml_node_t *top,		/* I - Top node */
+             int         descend)	/* I - Descend into tree - @code MXML_DESCEND@, @code MXML_NO_DESCEND@, or @code 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 @code NULL@ */
+mxmlWalkPrev(mxml_node_t *node,		/* I - Current node */
+             mxml_node_t *top,		/* I - Top node */
+             int         descend)	/* I - Descend into tree - @code MXML_DESCEND@, @code MXML_NO_DESCEND@, or @code 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);
+}

+ 371 - 0
mxml.mod/mxml/mxml-set.c

@@ -0,0 +1,371 @@
+/*
+ * Node set functions for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml-private.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);
+}
+
+
+/*
+ * 'mxmlSetOpaquef()' - Set the value of an opaque string node to a formatted string.
+ *
+ * The node is not changed if it (or its first child) is not an opaque node.
+ *
+ * @since Mini-XML 2.11@
+ */
+
+int					/* O - 0 on success, -1 on failure */
+mxmlSetOpaquef(mxml_node_t *node,	/* I - Node to set */
+               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_OPAQUE)
+    node = node->child;
+
+  if (!node || node->type != MXML_OPAQUE || !format)
+    return (-1);
+
+ /*
+  * Free any old string value and set the new value...
+  */
+
+  if (node->value.opaque)
+    free(node->value.opaque);
+
+  va_start(ap, format);
+
+  node->value.opaque = _mxml_strdupf(format, ap);
+
+  va_end(ap);
+
+  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);
+}

+ 562 - 0
mxml.mod/mxml/mxml-string.c

@@ -0,0 +1,562 @@
+/*
+ * String functions for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * 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);
+#ifdef HAVE_VASPRINTF
+  if (vasprintf(&s, format, ap) < 0)
+    s = NULL;
+#else
+  s = _mxml_vstrdupf(format, ap);
+#endif /* HAVE_VASPRINTF */
+  va_end(ap);
+
+  return (s);
+}
+
+
+#ifndef HAVE_STRLCAT
+/*
+ * '_mxml_strlcat()' - Safely concatenate a string.
+ */
+
+size_t					/* O - Number of bytes copied */
+_mxml_strlcat(char       *dst,		/* I - Destination buffer */
+              const char *src,		/* I - Source string */
+              size_t     dstsize)	/* I - Size of destinatipon buffer */
+{
+  size_t	srclen;			/* Length of source string */
+  size_t	dstlen;			/* Length of destination string */
+
+
+ /*
+  * Figure out how much room is left...
+  */
+
+  dstlen = strlen(dst);
+
+  if (dstsize <= (dstlen + 1))
+    return (dstlen);		        /* No room, return immediately... */
+
+  dstsize -= dstlen + 1;
+
+ /*
+  * Figure out how much room is needed...
+  */
+
+  srclen = strlen(src);
+
+ /*
+  * Copy the appropriate amount...
+  */
+
+  if (srclen > dstsize)
+    srclen = dstsize;
+
+  memmove(dst + dstlen, src, srclen);
+  dst[dstlen + srclen] = '\0';
+
+  return (dstlen + srclen);
+}
+#endif /* !HAVE_STRLCAT */
+
+
+#ifndef HAVE_STRLCPY
+/*
+ * '_mxml_strlcpy()' - Safely copy a string.
+ */
+
+size_t					/* O - Number of bytes copied */
+_mxml_strlcpy(char       *dst,		/* I - Destination buffer */
+              const char *src,		/* I - Source string */
+              size_t     dstsize)	/* I - Size of destinatipon buffer */
+{
+  size_t        srclen;                 /* Length of source string */
+
+
+ /*
+  * Figure out how much room is needed...
+  */
+
+  dstsize --;
+
+  srclen = strlen(src);
+
+ /*
+  * Copy the appropriate amount...
+  */
+
+  if (srclen > dstsize)
+    srclen = dstsize;
+
+  memmove(dst, src, srclen);
+  dst[srclen] = '\0';
+
+  return (srclen);
+}
+#endif /* !HAVE_STRLCPY */
+
+
+#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 */
+{
+#ifdef HAVE_VASPRINTF
+  char		*s;			/* String */
+
+  if (vasprintf(&s, format, ap) < 0)
+    s = NULL;
+
+  return (s);
+
+#else
+  int		bytes;			/* Number of bytes required */
+  char		*buffer,		/* String buffer */
+		temp[256];		/* Small buffer for first vsnprintf */
+
+
+ /*
+  * First format with a tiny buffer; this will tell us how many bytes are
+  * needed...
+  */
+
+#  ifdef WIN32
+  bytes = _vscprintf(format, ap);
+
+#  else
+  va_list	apcopy;			/* Copy of argument list */
+
+  va_copy(apcopy, ap);
+  bytes = vsnprintf(temp, sizeof(temp), format, apcopy);
+#  endif /* WIN32 */
+
+  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);
+#endif /* HAVE_VASPRINTF */
+}

+ 282 - 0
mxml.mod/mxml/mxml.h

@@ -0,0 +1,282 @@
+/*
+ * Header file for Mini-XML, a small XML file parsing library.
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * 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_MAJOR_VERSION	3	/* Major version number */
+#  define MXML_MINOR_VERSION	0	/* Minor version number */
+
+#  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_node_s mxml_node_t;	/**** An XML node. ****/
+
+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 ****/
+
+typedef int (*mxml_read_stream_cb_t)(void *,void *,unsigned int);
+
+typedef int (*mxml_write_stream_cb_t)(void *,const void *,unsigned int);
+
+/*
+ * 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 const char       *mxmlElementGetAttrByIndex(mxml_node_t *node, int idx, const char **name);
+extern int              mxmlElementGetAttrCount(mxml_node_t *node);
+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 *element, 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	*mxmlLoadStream(mxml_node_t *top, mxml_read_stream_cb_t read_stream_cb,
+			            void *read_stream_context, 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	*mxmlNewOpaquef(mxml_node_t *parent, const char *format, ...)
+#    ifdef __GNUC__
+__attribute__ ((__format__ (__printf__, 2, 3)))
+#    endif /* __GNUC__ */
+;
+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 int		mxmlSaveStream(mxml_node_t *node, mxml_write_stream_cb_t write_stream_cb,
+			            void *write_stream_context, 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		mxmlSetOpaquef(mxml_node_t *node, const char *format, ...)
+#    ifdef __GNUC__
+__attribute__ ((__format__ (__printf__, 2, 3)))
+#    endif /* __GNUC__ */
+;
+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_ */

+ 10 - 0
mxml.mod/mxml/mxml.pc.in

@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Mini-XML
+Description: Lightweight XML support library
+Version: @VERSION@
+Libs: @PC_LIBS@ @PTHREAD_LIBS@
+Cflags: @PC_CFLAGS@ @PTHREAD_FLAGS@

+ 75 - 0
mxml.mod/mxml/mxml.spec

@@ -0,0 +1,75 @@
+#
+# RPM "spec" file for Mini-XML, a small XML file parsing library.
+#
+# https://www.msweet.org/mxml
+#
+# Copyright © 2003-2019 by Michael R Sweet.
+#
+# Licensed under Apache License v2.0.  See the file "LICENSE" for more
+# information.
+#
+
+Summary: Small XML file parsing library
+Name: mxml
+Version: 3.0
+Release: 1
+License: Apache 2.0
+Group: Development/Libraries
+Source: https://github.com/michaelrsweet/mxml/releases/download/release-%{version}/mxml-%{version}.tar.gz
+Url: https://www.msweet.org/mxml
+Packager: John Doe <[email protected]>
+Vendor: Michael R Sweet
+
+# Use buildroot so as not to disturb the version already installed
+BuildRoot: /var/tmp/%{name}-root
+
+%description
+Mini-XML is a small XML parsing library that you can use to read XML data files
+or strings in your application without requiring large non-standard libraries.
+Mini-XML provides the following functionality:
+
+- Reading of UTF-8 and UTF-16 and writing of UTF-8 encoded XML files and
+  strings.
+- Data is stored in a linked-list tree structure, preserving the XML data
+  hierarchy.
+- SAX (streamed) reading of XML files and strings to minimize memory usage.
+- Supports arbitrary element names, attributes, and attribute values with no
+  preset limits, just available memory.
+- Supports integer, real, opaque ("cdata"), and text data types in "leaf" nodes.
+- Functions for creating and managing trees of data.
+- "Find" and "walk" functions for easily locating and navigating trees of data.
+
+Mini-XML doesn't do validation or other types of processing on the data
+based upon schema files or other sources of definition information.
+
+%prep
+%setup
+
+%build
+CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_OPT_FLAGS" ./configure --enable-shared --prefix=/usr
+
+# If we got this far, all prerequisite libraries must be here.
+make
+
+%install
+# Make sure the RPM_BUILD_ROOT directory exists.
+rm -rf $RPM_BUILD_ROOT
+
+make BUILDROOT=$RPM_BUILD_ROOT install
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+
+%dir /usr/include
+/usr/include/mxml.h
+%dir /usr/lib
+/usr/lib/*
+%dir /usr/lib/pkgconfig
+/usr/lib/pkgconfig/mxml.pc
+%dir /usr/share/doc/mxml
+/usr/share/doc/mxml/*
+%dir /usr/share/man/man3
+/usr/share/man/man3/*

+ 29 - 0
mxml.mod/mxml/test.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<group>
+	<option>
+		<keyword type="opaque">InputSlot</keyword>
+		<default type="opaque">Auto</default>
+		<text>Media Source</text>
+		<order type="real">10.000000</order>
+		<choice>
+			<keyword type="opaque">Auto</keyword>
+			<text>Auto Tray Selection</text>
+			<code type="opaque" />
+		</choice>
+		<choice>
+			<keyword type="opaque">Upper</keyword>
+			<text>Tray 1</text>
+			<code type="opaque">&lt;&lt;/MediaPosition 0&gt;&gt;setpagedevice</code>
+		</choice>
+		<choice>
+			<keyword type="opaque">Lower</keyword>
+			<text>Tray 2</text>
+			<code type="opaque">&lt;&lt;/MediaPosition 1&gt;&gt;setpagedevice</code>
+		</choice>
+	</option>
+	<integer>123</integer>
+	<string>Now is the time for all good men to come to the aid of their
+country.</string>
+	<!-- this is a comment -->
+	<![CDATA[this is CDATA 0123456789ABCDEF]]>
+</group>

+ 885 - 0
mxml.mod/mxml/testmxml.c

@@ -0,0 +1,885 @@
+/*
+ * Test program for Mini-XML, a small XML file parsing library.
+ *
+ * Usage:
+ *
+ *   ./testmxml input.xml [string-output.xml] >stdio-output.xml
+ *   ./testmxml "<?xml ..." [string-output.xml] >stdio-output.xml
+ *
+ * https://www.msweet.org/mxml
+ *
+ * Copyright © 2003-2019 by Michael R Sweet.
+ *
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "mxml-private.h"
+#ifndef WIN32
+#  include <unistd.h>
+#endif /* !WIN32 */
+#include <fcntl.h>
+#ifndef O_BINARY
+#  define O_BINARY 0
+#endif /* !O_BINARY */
+
+
+/*
+ * Globals...
+ */
+
+int		event_counts[6];
+
+
+/*
+ * Local functions...
+ */
+
+void		sax_cb(mxml_node_t *node, mxml_sax_event_t event, void *data);
+mxml_type_t	type_cb(mxml_node_t *node);
+const char	*whitespace_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 */
+  FILE			*fp;		/* File to read */
+  int			fd;		/* File descriptor */
+  mxml_node_t		*tree,		/* XML tree */
+			*node;		/* Node which should be in test.xml */
+  mxml_index_t		*ind;		/* XML index */
+  char			buffer[16384];	/* Save string */
+  static const char	*types[] =	/* Strings for node types */
+			{
+			  "MXML_ELEMENT",
+			  "MXML_INTEGER",
+			  "MXML_OPAQUE",
+			  "MXML_REAL",
+			  "MXML_TEXT"
+			};
+
+
+ /*
+  * Check arguments...
+  */
+
+  if (argc != 2 && argc != 3)
+  {
+    fputs("Usage: testmxml filename.xml [string-output.xml]\n", stderr);
+    return (1);
+  }
+
+ /*
+  * Test the basic functionality...
+  */
+
+  tree = mxmlNewElement(MXML_NO_PARENT, "element");
+
+  if (!tree)
+  {
+    fputs("ERROR: No parent node in basic test.\n", stderr);
+    return (1);
+  }
+
+  if (tree->type != MXML_ELEMENT)
+  {
+    fprintf(stderr, "ERROR: Parent has type %s (%d), expected MXML_ELEMENT.\n",
+            tree->type < MXML_ELEMENT || tree->type > MXML_TEXT ?
+	        "UNKNOWN" : types[tree->type], tree->type);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (strcmp(tree->value.element.name, "element"))
+  {
+    fprintf(stderr, "ERROR: Parent value is \"%s\", expected \"element\".\n",
+            tree->value.element.name);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  mxmlNewInteger(tree, 123);
+  mxmlNewOpaque(tree, "opaque");
+  mxmlNewReal(tree, 123.4f);
+  mxmlNewText(tree, 1, "text");
+
+  mxmlLoadString(tree, "<group type='string'>string string string</group>",
+                 MXML_NO_CALLBACK);
+  mxmlLoadString(tree, "<group type='integer'>1 2 3</group>",
+                 MXML_INTEGER_CALLBACK);
+  mxmlLoadString(tree, "<group type='real'>1.0 2.0 3.0</group>",
+                 MXML_REAL_CALLBACK);
+  mxmlLoadString(tree, "<group>opaque opaque opaque</group>",
+                 MXML_OPAQUE_CALLBACK);
+  mxmlLoadString(tree, "<foo><bar><one><two>value<two>value2</two></two></one>"
+                       "</bar></foo>", MXML_OPAQUE_CALLBACK);
+
+  node = tree->child;
+
+  if (!node)
+  {
+    fputs("ERROR: No first child node in basic test.\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (node->type != MXML_INTEGER)
+  {
+    fprintf(stderr, "ERROR: First child has type %s (%d), expected MXML_INTEGER.\n",
+            node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
+	        "UNKNOWN" : types[node->type], node->type);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (node->value.integer != 123)
+  {
+    fprintf(stderr, "ERROR: First child value is %d, expected 123.\n",
+            node->value.integer);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  node = node->next;
+
+  if (!node)
+  {
+    fputs("ERROR: No second child node in basic test.\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (node->type != MXML_OPAQUE)
+  {
+    fprintf(stderr, "ERROR: Second child has type %s (%d), expected MXML_OPAQUE.\n",
+            node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
+	        "UNKNOWN" : types[node->type], node->type);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (!node->value.opaque || strcmp(node->value.opaque, "opaque"))
+  {
+    fprintf(stderr, "ERROR: Second child value is \"%s\", expected \"opaque\".\n",
+            node->value.opaque ? node->value.opaque : "(null)");
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  node = node->next;
+
+  if (!node)
+  {
+    fputs("ERROR: No third child node in basic test.\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (node->type != MXML_REAL)
+  {
+    fprintf(stderr, "ERROR: Third child has type %s (%d), expected MXML_REAL.\n",
+            node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
+	        "UNKNOWN" : types[node->type], node->type);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (node->value.real != 123.4f)
+  {
+    fprintf(stderr, "ERROR: Third child value is %f, expected 123.4.\n",
+            node->value.real);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  node = node->next;
+
+  if (!node)
+  {
+    fputs("ERROR: No fourth child node in basic test.\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (node->type != MXML_TEXT)
+  {
+    fprintf(stderr, "ERROR: Fourth child has type %s (%d), expected MXML_TEXT.\n",
+            node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
+	        "UNKNOWN" : types[node->type], node->type);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (!node->value.text.whitespace ||
+      !node->value.text.string || strcmp(node->value.text.string, "text"))
+  {
+    fprintf(stderr, "ERROR: Fourth child value is %d,\"%s\", expected 1,\"text\".\n",
+            node->value.text.whitespace,
+	    node->value.text.string ? node->value.text.string : "(null)");
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  for (i = 0; i < 4; i ++)
+  {
+    node = node->next;
+
+    if (!node)
+    {
+      fprintf(stderr, "ERROR: No group #%d child node in basic test.\n", i + 1);
+      mxmlDelete(tree);
+      return (1);
+    }
+
+    if (node->type != MXML_ELEMENT)
+    {
+      fprintf(stderr, "ERROR: Group child #%d has type %s (%d), expected MXML_ELEMENT.\n",
+              i + 1, node->type < MXML_ELEMENT || node->type > MXML_TEXT ?
+	                 "UNKNOWN" : types[node->type], node->type);
+      mxmlDelete(tree);
+      return (1);
+    }
+  }
+
+ /*
+  * Test mxmlFindPath...
+  */
+
+  node = mxmlFindPath(tree, "*/two");
+  if (!node)
+  {
+    fputs("ERROR: Unable to find value for \"*/two\".\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+  else if (node->type != MXML_OPAQUE || strcmp(node->value.opaque, "value"))
+  {
+    fputs("ERROR: Bad value for \"*/two\".\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  node = mxmlFindPath(tree, "foo/*/two");
+  if (!node)
+  {
+    fputs("ERROR: Unable to find value for \"foo/*/two\".\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+  else if (node->type != MXML_OPAQUE || strcmp(node->value.opaque, "value"))
+  {
+    fputs("ERROR: Bad value for \"foo/*/two\".\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  node = mxmlFindPath(tree, "foo/bar/one/two");
+  if (!node)
+  {
+    fputs("ERROR: Unable to find value for \"foo/bar/one/two\".\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+  else if (node->type != MXML_OPAQUE || strcmp(node->value.opaque, "value"))
+  {
+    fputs("ERROR: Bad value for \"foo/bar/one/two\".\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+ /*
+  * Test indices...
+  */
+
+  ind = mxmlIndexNew(tree, NULL, NULL);
+  if (!ind)
+  {
+    fputs("ERROR: Unable to create index of all nodes.\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (ind->num_nodes != 10)
+  {
+    fprintf(stderr, "ERROR: Index of all nodes contains %d "
+                    "nodes; expected 10.\n", ind->num_nodes);
+    mxmlIndexDelete(ind);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  mxmlIndexReset(ind);
+  if (!mxmlIndexFind(ind, "group", NULL))
+  {
+    fputs("ERROR: mxmlIndexFind for \"group\" failed.\n", stderr);
+    mxmlIndexDelete(ind);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  mxmlIndexDelete(ind);
+
+  ind = mxmlIndexNew(tree, "group", NULL);
+  if (!ind)
+  {
+    fputs("ERROR: Unable to create index of groups.\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (ind->num_nodes != 4)
+  {
+    fprintf(stderr, "ERROR: Index of groups contains %d "
+                    "nodes; expected 4.\n", ind->num_nodes);
+    mxmlIndexDelete(ind);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  mxmlIndexReset(ind);
+  if (!mxmlIndexEnum(ind))
+  {
+    fputs("ERROR: mxmlIndexEnum failed.\n", stderr);
+    mxmlIndexDelete(ind);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  mxmlIndexDelete(ind);
+
+  ind = mxmlIndexNew(tree, NULL, "type");
+  if (!ind)
+  {
+    fputs("ERROR: Unable to create index of type attributes.\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (ind->num_nodes != 3)
+  {
+    fprintf(stderr, "ERROR: Index of type attributes contains %d "
+                    "nodes; expected 3.\n", ind->num_nodes);
+    mxmlIndexDelete(ind);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  mxmlIndexReset(ind);
+  if (!mxmlIndexFind(ind, NULL, "string"))
+  {
+    fputs("ERROR: mxmlIndexFind for \"string\" failed.\n", stderr);
+    mxmlIndexDelete(ind);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  mxmlIndexDelete(ind);
+
+  ind = mxmlIndexNew(tree, "group", "type");
+  if (!ind)
+  {
+    fputs("ERROR: Unable to create index of elements and attributes.\n", stderr);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  if (ind->num_nodes != 3)
+  {
+    fprintf(stderr, "ERROR: Index of elements and attributes contains %d "
+                    "nodes; expected 3.\n", ind->num_nodes);
+    mxmlIndexDelete(ind);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  mxmlIndexReset(ind);
+  if (!mxmlIndexFind(ind, "group", "string"))
+  {
+    fputs("ERROR: mxmlIndexFind for \"string\" failed.\n", stderr);
+    mxmlIndexDelete(ind);
+    mxmlDelete(tree);
+    return (1);
+  }
+
+  mxmlIndexDelete(ind);
+
+ /*
+  * Check the mxmlDelete() works properly...
+  */
+
+  for (i = 0; i < 9; i ++)
+  {
+    if (tree->child)
+      mxmlDelete(tree->child);
+    else
+    {
+      fprintf(stderr, "ERROR: Child pointer prematurely NULL on child #%d\n",
+              i + 1);
+      mxmlDelete(tree);
+      return (1);
+    }
+  }
+
+  if (tree->child)
+  {
+    fputs("ERROR: Child pointer not NULL after deleting all children.\n", stderr);
+    return (1);
+  }
+
+  if (tree->last_child)
+  {
+    fputs("ERROR: Last child pointer not NULL after deleting all children.\n", stderr);
+    return (1);
+  }
+
+  mxmlDelete(tree);
+
+ /*
+  * Open the file/string using the default (MXML_NO_CALLBACK) callback...
+  */
+
+  if (argv[1][0] == '<')
+    tree = mxmlLoadString(NULL, argv[1], MXML_NO_CALLBACK);
+  else if ((fp = fopen(argv[1], "rb")) == NULL)
+  {
+    perror(argv[1]);
+    return (1);
+  }
+  else
+  {
+   /*
+    * Read the file...
+    */
+
+    tree = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK);
+
+    fclose(fp);
+  }
+
+  if (!tree)
+  {
+    fputs("Unable to read XML file with default callback.\n", stderr);
+    return (1);
+  }
+
+  if (!strcmp(argv[1], "test.xml"))
+  {
+    const char	*text;			/* Text value */
+
+   /*
+    * Verify that mxmlFindElement() and indirectly mxmlWalkNext() work
+    * properly...
+    */
+
+    if ((node = mxmlFindPath(tree, "group/option/keyword")) == NULL)
+    {
+      fputs("Unable to find group/option/keyword element in XML tree.\n", stderr);
+      mxmlDelete(tree);
+      return (1);
+    }
+
+    if (node->type != MXML_TEXT)
+    {
+      fputs("No child node of group/option/keyword.\n", stderr);
+      mxmlSaveFile(tree, stderr, MXML_NO_CALLBACK);
+      mxmlDelete(tree);
+      return (1);
+    }
+
+    if ((text = mxmlGetText(node, NULL)) == NULL || strcmp(text, "InputSlot"))
+    {
+      fprintf(stderr, "Child node of group/option/value has value \"%s\" instead of \"InputSlot\".\n", text ? text : "(null)");
+      mxmlDelete(tree);
+      return (1);
+    }
+  }
+
+  mxmlDelete(tree);
+
+ /*
+  * Open the file...
+  */
+
+  if (argv[1][0] == '<')
+    tree = mxmlLoadString(NULL, argv[1], type_cb);
+  else if ((fp = fopen(argv[1], "rb")) == NULL)
+  {
+    perror(argv[1]);
+    return (1);
+  }
+  else
+  {
+   /*
+    * Read the file...
+    */
+
+    tree = mxmlLoadFile(NULL, fp, type_cb);
+
+    fclose(fp);
+  }
+
+  if (!tree)
+  {
+    fputs("Unable to read XML file.\n", stderr);
+    return (1);
+  }
+
+  if (!strcmp(argv[1], "test.xml"))
+  {
+   /*
+    * Verify that mxmlFindElement() and indirectly mxmlWalkNext() work
+    * properly...
+    */
+
+    if ((node = mxmlFindElement(tree, tree, "choice", NULL, NULL,
+                                MXML_DESCEND)) == NULL)
+    {
+      fputs("Unable to find first <choice> element in XML tree.\n", stderr);
+      mxmlDelete(tree);
+      return (1);
+    }
+
+    if (!mxmlFindElement(node, tree, "choice", NULL, NULL, MXML_NO_DESCEND))
+    {
+      fputs("Unable to find second <choice> element in XML tree.\n", stderr);
+      mxmlDelete(tree);
+      return (1);
+    }
+  }
+
+ /*
+  * Print the XML tree...
+  */
+
+  mxmlSaveFile(tree, stdout, whitespace_cb);
+
+ /*
+  * Save the XML tree to a string and print it...
+  */
+
+  if (mxmlSaveString(tree, buffer, sizeof(buffer), whitespace_cb) > 0)
+  {
+    if (argc == 3)
+    {
+      fp = fopen(argv[2], "w");
+      fputs(buffer, fp);
+      fclose(fp);
+    }
+  }
+
+ /*
+  * Delete the tree...
+  */
+
+  mxmlDelete(tree);
+
+ /*
+  * Read from/write to file descriptors...
+  */
+
+  if (argv[1][0] != '<')
+  {
+   /*
+    * Open the file again...
+    */
+
+    if ((fd = open(argv[1], O_RDONLY | O_BINARY)) < 0)
+    {
+      perror(argv[1]);
+      return (1);
+    }
+
+   /*
+    * Read the file...
+    */
+
+    tree = mxmlLoadFd(NULL, fd, type_cb);
+
+    close(fd);
+
+   /*
+    * Create filename.xmlfd...
+    */
+
+    snprintf(buffer, sizeof(buffer), "%sfd", argv[1]);
+
+    if ((fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) < 0)
+    {
+      perror(buffer);
+      mxmlDelete(tree);
+      return (1);
+    }
+
+   /*
+    * Write the file...
+    */
+
+    mxmlSaveFd(tree, fd, whitespace_cb);
+
+    close(fd);
+
+   /*
+    * Delete the tree...
+    */
+
+    mxmlDelete(tree);
+  }
+
+ /*
+  * Test SAX methods...
+  */
+
+  memset(event_counts, 0, sizeof(event_counts));
+
+  if (argv[1][0] == '<')
+    mxmlSAXLoadString(NULL, argv[1], type_cb, sax_cb, NULL);
+  else if ((fp = fopen(argv[1], "rb")) == NULL)
+  {
+    perror(argv[1]);
+    return (1);
+  }
+  else
+  {
+   /*
+    * Read the file...
+    */
+
+    mxmlSAXLoadFile(NULL, fp, type_cb, sax_cb, NULL);
+
+    fclose(fp);
+  }
+
+  if (!strcmp(argv[1], "test.xml"))
+  {
+    if (event_counts[MXML_SAX_CDATA] != 1)
+    {
+      fprintf(stderr, "MXML_SAX_CDATA seen %d times, expected 1 times.\n",
+              event_counts[MXML_SAX_CDATA]);
+      return (1);
+    }
+
+    if (event_counts[MXML_SAX_COMMENT] != 1)
+    {
+      fprintf(stderr, "MXML_SAX_COMMENT seen %d times, expected 1 times.\n",
+              event_counts[MXML_SAX_COMMENT]);
+      return (1);
+    }
+
+    if (event_counts[MXML_SAX_DATA] != 60)
+    {
+      fprintf(stderr, "MXML_SAX_DATA seen %d times, expected 60 times.\n",
+              event_counts[MXML_SAX_DATA]);
+      return (1);
+    }
+
+    if (event_counts[MXML_SAX_DIRECTIVE] != 1)
+    {
+      fprintf(stderr, "MXML_SAX_DIRECTIVE seen %d times, expected 1 times.\n",
+              event_counts[MXML_SAX_DIRECTIVE]);
+      return (1);
+    }
+
+    if (event_counts[MXML_SAX_ELEMENT_CLOSE] != 20)
+    {
+      fprintf(stderr, "MXML_SAX_ELEMENT_CLOSE seen %d times, expected 20 times.\n",
+              event_counts[MXML_SAX_ELEMENT_CLOSE]);
+      return (1);
+    }
+
+    if (event_counts[MXML_SAX_ELEMENT_OPEN] != 20)
+    {
+      fprintf(stderr, "MXML_SAX_ELEMENT_OPEN seen %d times, expected 20 times.\n",
+              event_counts[MXML_SAX_ELEMENT_OPEN]);
+      return (1);
+    }
+  }
+
+#ifndef WIN32
+ /*
+  * Debug hooks...
+  */
+
+  if (getenv("TEST_DELAY") != NULL)
+    sleep(atoi(getenv("TEST_DELAY")));
+#  ifdef __APPLE__
+  if (getenv("TEST_LEAKS") != NULL)
+  {
+    char command[1024];
+
+    snprintf(command, sizeof(command), "leaks %d", (int)getpid());
+    if (system(command))
+      puts("Unable to check for leaks.");
+  }
+#  endif /* __APPLE__ */
+#endif /* !WIN32 */
+
+ /*
+  * Return...
+  */
+
+  return (0);
+}
+
+
+/*
+ * 'sax_cb()' - Process nodes via SAX.
+ */
+
+void
+sax_cb(mxml_node_t      *node,		/* I - Current node */
+       mxml_sax_event_t event,		/* I - SAX event */
+       void             *data)		/* I - SAX user data */
+{
+  static const char * const events[] =	/* Events */
+  {
+    "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 */
+  };
+
+
+  (void)data;
+
+ /*
+  * This SAX callback just counts the different events.
+  */
+
+  if (!node)
+    fprintf(stderr, "ERROR: SAX callback for event %s has NULL node.\n", events[event]);
+
+  event_counts[event] ++;
+}
+
+
+/*
+ * 'type_cb()' - XML data type callback for mxmlLoadFile()...
+ */
+
+mxml_type_t				/* O - Data type */
+type_cb(mxml_node_t *node)		/* I - Element node */
+{
+  const char	*type;			/* Type string */
+
+
+ /*
+  * You can lookup attributes and/or use the element name, hierarchy, etc...
+  */
+
+  if ((type = mxmlElementGetAttr(node, "type")) == NULL)
+    type = node->value.element.name;
+
+  if (!strcmp(type, "integer"))
+    return (MXML_INTEGER);
+  else if (!strcmp(type, "opaque") || !strcmp(type, "pre"))
+    return (MXML_OPAQUE);
+  else if (!strcmp(type, "real"))
+    return (MXML_REAL);
+  else
+    return (MXML_TEXT);
+}
+
+
+/*
+ * 'whitespace_cb()' - Let the mxmlSaveFile() function know when to insert
+ *                     newlines and tabs...
+ */
+
+const char *				/* O - Whitespace string or NULL */
+whitespace_cb(mxml_node_t *node,	/* I - Element node */
+              int         where)	/* I - Open or close tag? */
+{
+  mxml_node_t	*parent;		/* Parent node */
+  int		level;			/* Indentation level */
+  const char	*name;			/* Name of element */
+  static const char *tabs = "\t\t\t\t\t\t\t\t";
+					/* Tabs for indentation */
+
+
+ /*
+  * We can conditionally break to a new line before or after any element.
+  * These are just common HTML elements...
+  */
+
+  name = node->value.element.name;
+
+  if (!strcmp(name, "html") || !strcmp(name, "head") || !strcmp(name, "body") ||
+      !strcmp(name, "pre") || !strcmp(name, "p") ||
+      !strcmp(name, "h1") || !strcmp(name, "h2") || !strcmp(name, "h3") ||
+      !strcmp(name, "h4") || !strcmp(name, "h5") || !strcmp(name, "h6"))
+  {
+   /*
+    * Newlines before open and after close...
+    */
+
+    if (where == MXML_WS_BEFORE_OPEN || where == MXML_WS_AFTER_CLOSE)
+      return ("\n");
+  }
+  else if (!strcmp(name, "dl") || !strcmp(name, "ol") || !strcmp(name, "ul"))
+  {
+   /*
+    * Put a newline before and after list elements...
+    */
+
+    return ("\n");
+  }
+  else if (!strcmp(name, "dd") || !strcmp(name, "dt") || !strcmp(name, "li"))
+  {
+   /*
+    * Put a tab before <li>'s, <dd>'s, and <dt>'s, and a newline after them...
+    */
+
+    if (where == MXML_WS_BEFORE_OPEN)
+      return ("\t");
+    else if (where == MXML_WS_AFTER_CLOSE)
+      return ("\n");
+  }
+  else if (!strncmp(name, "?xml", 4))
+  {
+    if (where == MXML_WS_AFTER_OPEN)
+      return ("\n");
+    else
+      return (NULL);
+  }
+  else if (where == MXML_WS_BEFORE_OPEN ||
+           ((!strcmp(name, "choice") || !strcmp(name, "option")) &&
+	    where == MXML_WS_BEFORE_CLOSE))
+  {
+    for (level = -1, parent = node->parent;
+         parent;
+	 level ++, parent = parent->parent);
+
+    if (level > 8)
+      level = 8;
+    else if (level < 0)
+      level = 0;
+
+    return (tabs + 8 - level);
+  }
+  else if (where == MXML_WS_AFTER_CLOSE ||
+           ((!strcmp(name, "group") || !strcmp(name, "option") ||
+	     !strcmp(name, "choice")) &&
+            where == MXML_WS_AFTER_OPEN))
+    return ("\n");
+  else if (where == MXML_WS_AFTER_OPEN && !node->child)
+    return ("\n");
+
+ /*
+  * Return NULL for no added whitespace...
+  */
+
+  return (NULL);
+}

+ 132 - 0
mxml.mod/mxml/vcnet/config.h

@@ -0,0 +1,132 @@
+/*
+ * Visual Studio configuration file for Mini-XML, a small XML file parsing
+ * library.
+ *
+ * Copyright 2003-2019 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:
+ *
+ *     https://michaelrsweet.github.io/mxml
+ */
+
+/*
+ * Beginning with VC2005, Microsoft breaks ISO C and POSIX conformance
+ * by deprecating a number of functions in the name of security, even
+ * when many of the affected functions are otherwise completely secure.
+ * The _CRT_SECURE_NO_DEPRECATE definition ensures that we won't get
+ * warnings from their use...
+ *
+ * Then Microsoft decided that they should ignore this in VC2008 and use
+ * yet another define (_CRT_SECURE_NO_WARNINGS) instead...
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_WARNINGS
+
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <io.h>
+
+
+/*
+ * Microsoft also renames the POSIX functions to _name, and introduces
+ * a broken compatibility layer using the original names.  As a result,
+ * random crashes can occur when, for example, strdup() allocates memory
+ * from a different heap than used by malloc() and free().
+ *
+ * To avoid moronic problems like this, we #define the POSIX function
+ * names to the corresponding non-standard Microsoft names.
+ */
+
+#define close		_close
+#define open		_open
+#define read	        _read
+#define snprintf 	_snprintf
+#define strdup		_strdup
+#define vsnprintf 	_vsnprintf
+#define write		_write
+
+
+/*
+ * Version number...
+ */
+
+#define MXML_VERSION "Mini-XML v2.13"
+
+
+/*
+ * Inline function support...
+ */
+
+#define inline _inline
+
+
+/*
+ * Long long support...
+ */
+
+#define HAVE_LONG_LONG 1
+
+
+/*
+ * Do we have the *printf() functions?
+ */
+
+#define HAVE_SNPRINTF 1
+/* #undef HAVE_VASPRINTF */
+#define HAVE_VSNPRINTF 1
+
+
+/*
+ * Do we have the strXXX() functions?
+ */
+
+#define HAVE_STRDUP 1
+/* #undef HAVE_STRLCPY */
+
+
+/*
+ * 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 */
+
+#  ifndef HAVE_STRLCPY
+extern size_t	_mxml_strlcpy(char *, const char *, size_t);
+#    define strlcpy _mxml_strlcpy
+#  endif /* !HAVE_STRLCPY */
+
+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 */

+ 66 - 0
mxml.mod/mxml/vcnet/mxml.sln

@@ -0,0 +1,66 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28010.2036
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mxml1", "mxml1.vcxproj", "{E5AA9476-9751-4654-8109-B1A2112D5E73}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mxmldoc", "mxmldoc.vcxproj", "{D909892E-520A-4322-9A47-DAEBDA9CC7A7}"
+	ProjectSection(ProjectDependencies) = postProject
+		{E5AA9476-9751-4654-8109-B1A2112D5E73} = {E5AA9476-9751-4654-8109-B1A2112D5E73}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testmxml", "testmxml.vcxproj", "{75CAC6C4-A6BC-4935-A3C9-8F0AE0744227}"
+	ProjectSection(ProjectDependencies) = postProject
+		{CDEEBB3C-D45B-4CC5-BE9B-0BD415A27958} = {CDEEBB3C-D45B-4CC5-BE9B-0BD415A27958}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mxmlstat", "mxmlstat.vcxproj", "{CDEEBB3C-D45B-4CC5-BE9B-0BD415A27958}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{E5AA9476-9751-4654-8109-B1A2112D5E73}.Debug|Win32.ActiveCfg = Debug|Win32
+		{E5AA9476-9751-4654-8109-B1A2112D5E73}.Debug|Win32.Build.0 = Debug|Win32
+		{E5AA9476-9751-4654-8109-B1A2112D5E73}.Debug|x64.ActiveCfg = Debug|Win32
+		{E5AA9476-9751-4654-8109-B1A2112D5E73}.Debug|x64.Build.0 = Debug|Win32
+		{E5AA9476-9751-4654-8109-B1A2112D5E73}.Release|Win32.ActiveCfg = Debug|Win32
+		{E5AA9476-9751-4654-8109-B1A2112D5E73}.Release|Win32.Build.0 = Debug|Win32
+		{E5AA9476-9751-4654-8109-B1A2112D5E73}.Release|x64.ActiveCfg = Debug|Win32
+		{E5AA9476-9751-4654-8109-B1A2112D5E73}.Release|x64.Build.0 = Debug|Win32
+		{D909892E-520A-4322-9A47-DAEBDA9CC7A7}.Debug|Win32.ActiveCfg = Debug|Win32
+		{D909892E-520A-4322-9A47-DAEBDA9CC7A7}.Debug|Win32.Build.0 = Debug|Win32
+		{D909892E-520A-4322-9A47-DAEBDA9CC7A7}.Debug|x64.ActiveCfg = Debug|Win32
+		{D909892E-520A-4322-9A47-DAEBDA9CC7A7}.Debug|x64.Build.0 = Debug|Win32
+		{D909892E-520A-4322-9A47-DAEBDA9CC7A7}.Release|Win32.ActiveCfg = Debug|Win32
+		{D909892E-520A-4322-9A47-DAEBDA9CC7A7}.Release|Win32.Build.0 = Debug|Win32
+		{D909892E-520A-4322-9A47-DAEBDA9CC7A7}.Release|x64.ActiveCfg = Debug|Win32
+		{D909892E-520A-4322-9A47-DAEBDA9CC7A7}.Release|x64.Build.0 = Debug|Win32
+		{75CAC6C4-A6BC-4935-A3C9-8F0AE0744227}.Debug|Win32.ActiveCfg = Debug|Win32
+		{75CAC6C4-A6BC-4935-A3C9-8F0AE0744227}.Debug|Win32.Build.0 = Debug|Win32
+		{75CAC6C4-A6BC-4935-A3C9-8F0AE0744227}.Debug|x64.ActiveCfg = Debug|Win32
+		{75CAC6C4-A6BC-4935-A3C9-8F0AE0744227}.Debug|x64.Build.0 = Debug|Win32
+		{75CAC6C4-A6BC-4935-A3C9-8F0AE0744227}.Release|Win32.ActiveCfg = Debug|Win32
+		{75CAC6C4-A6BC-4935-A3C9-8F0AE0744227}.Release|Win32.Build.0 = Debug|Win32
+		{75CAC6C4-A6BC-4935-A3C9-8F0AE0744227}.Release|x64.ActiveCfg = Debug|Win32
+		{75CAC6C4-A6BC-4935-A3C9-8F0AE0744227}.Release|x64.Build.0 = Debug|Win32
+		{CDEEBB3C-D45B-4CC5-BE9B-0BD415A27958}.Debug|Win32.ActiveCfg = Debug|Win32
+		{CDEEBB3C-D45B-4CC5-BE9B-0BD415A27958}.Debug|Win32.Build.0 = Debug|Win32
+		{CDEEBB3C-D45B-4CC5-BE9B-0BD415A27958}.Debug|x64.ActiveCfg = Debug|Win32
+		{CDEEBB3C-D45B-4CC5-BE9B-0BD415A27958}.Debug|x64.Build.0 = Debug|Win32
+		{CDEEBB3C-D45B-4CC5-BE9B-0BD415A27958}.Release|Win32.ActiveCfg = Debug|Win32
+		{CDEEBB3C-D45B-4CC5-BE9B-0BD415A27958}.Release|Win32.Build.0 = Debug|Win32
+		{CDEEBB3C-D45B-4CC5-BE9B-0BD415A27958}.Release|x64.ActiveCfg = Debug|Win32
+		{CDEEBB3C-D45B-4CC5-BE9B-0BD415A27958}.Release|x64.Build.0 = Debug|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {0876C64C-2CF1-4A1B-974E-240A38E0EDCA}
+	EndGlobalSection
+EndGlobal

+ 80 - 0
mxml.mod/mxml/vcnet/mxml1.def

@@ -0,0 +1,80 @@
+LIBRARY "MXML1"
+EXPORTS
+ _mxml_strdupf
+ _mxml_strlcpy
+ _mxml_vstrdupf
+ mxml_ignore_cb
+ mxml_integer_cb
+ mxml_opaque_cb
+ mxml_real_cb
+ mxmlAdd
+ mxmlDelete
+ mxmlElementDeleteAttr
+ mxmlElementGetAttrByIndex
+ mxmlElementGetAttrCount
+ mxmlElementGetAttr
+ mxmlElementSetAttr
+ mxmlElementSetAttrf
+ mxmlEntityAddCallback
+ mxmlEntityGetName
+ mxmlEntityGetValue
+ mxmlEntityRemoveCallback
+ mxmlFindElement
+ mxmlFindPath
+ mxmlGetCDATA
+ mxmlGetCustom
+ mxmlGetElement
+ mxmlGetFirstChild
+ mxmlGetInteger
+ mxmlGetLastChild
+ mxmlGetNextSibling
+ mxmlGetOpaque
+ mxmlGetParent
+ mxmlGetPrevSibling
+ mxmlGetReal
+ mxmlGetRefCount
+ mxmlGetText
+ mxmlGetType
+ mxmlGetUserData
+ mxmlIndexDelete
+ mxmlIndexEnum
+ mxmlIndexFind
+ mxmlIndexGetCount
+ mxmlIndexNew
+ mxmlIndexReset
+ mxmlLoadFd
+ mxmlLoadFile
+ mxmlLoadString
+ mxmlNewCDATA
+ mxmlNewCustom
+ mxmlNewElement
+ mxmlNewInteger
+ mxmlNewOpaque
+ mxmlNewReal
+ mxmlNewText
+ mxmlNewTextf
+ mxmlNewXML
+ mxmlRelease
+ mxmlRemove
+ mxmlRetain
+ mxmlSaveAllocString
+ mxmlSaveFd
+ mxmlSaveFile
+ mxmlSaveString
+ mxmlSAXLoadFd
+ mxmlSAXLoadFile
+ mxmlSAXLoadString
+ mxmlSetCDATA
+ mxmlSetCustom
+ mxmlSetCustomHandlers
+ mxmlSetElement
+ mxmlSetErrorCallback
+ mxmlSetInteger
+ mxmlSetOpaque
+ mxmlSetReal
+ mxmlSetText
+ mxmlSetTextf
+ mxmlSetUserData
+ mxmlSetWrapMargin
+ mxmlWalkNext
+ mxmlWalkPrev

+ 215 - 0
mxml.mod/mxml/vcnet/mxml1.vcxproj

@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{E5AA9476-9751-4654-8109-B1A2112D5E73}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>15.0.27924.0</_ProjectFileVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>$(Configuration)\$(Platform)\$(ProjectName)\</OutDir>
+    <IntDir>$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>$(Configuration)\$(Platform)\$(ProjectName)\</OutDir>
+    <IntDir>$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <OutDir>$(Configuration)\$(Platform)\$(ProjectName)\</OutDir>
+    <IntDir>$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <OutDir>$(Configuration)\$(Platform)\$(ProjectName)\</OutDir>
+    <IntDir>$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MXML1_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader />
+      <WarningLevel>Level1</WarningLevel>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(Configuration)\$(Platform)\$(ProductName)\mxml1.dll</OutputFile>
+      <IgnoreSpecificDefaultLibraries>oldnames.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <ModuleDefinitionFile>.\mxml1.def</ModuleDefinitionFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>$(OutDir)mxml1.pdb</ProgramDatabaseFile>
+      <SubSystem>Windows</SubSystem>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention />
+      <ImportLibrary>$(Configuration)\$(Platform)\$(ProductName)\mxml1.lib</ImportLibrary>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MXML1_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <PrecompiledHeader />
+      <WarningLevel>Level1</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(Configuration)\$(Platform)\$(ProductName)\mxml1.dll</OutputFile>
+      <IgnoreSpecificDefaultLibraries>oldnames.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <ModuleDefinitionFile>.\mxml1.def</ModuleDefinitionFile>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention />
+      <ImportLibrary>$(Configuration)\$(Platform)\$(ProductName)\mxml1.lib</ImportLibrary>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MXML1_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader />
+      <WarningLevel>Level1</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(Configuration)\$(Platform)\$(ProductName)\mxml1.dll</OutputFile>
+      <IgnoreSpecificDefaultLibraries>oldnames.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <ModuleDefinitionFile>.\mxml1.def</ModuleDefinitionFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>$(OutDir)mxml1.pdb</ProgramDatabaseFile>
+      <SubSystem>Windows</SubSystem>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention />
+      <ImportLibrary>$(Configuration)\$(Platform)\$(ProductName)\mxml1.lib</ImportLibrary>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MXML1_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <PrecompiledHeader />
+      <WarningLevel>Level1</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(Configuration)\$(Platform)\$(ProductName)\mxml1.dll</OutputFile>
+      <IgnoreSpecificDefaultLibraries>oldnames.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <ModuleDefinitionFile>.\mxml1.def</ModuleDefinitionFile>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention />
+      <ImportLibrary>$(Configuration)\$(Platform)\$(ProductName)\mxml1.lib</ImportLibrary>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\mxml-attr.c" />
+    <ClCompile Include="..\mxml-entity.c" />
+    <ClCompile Include="..\mxml-file.c" />
+    <ClCompile Include="..\mxml-get.c" />
+    <ClCompile Include="..\mxml-index.c" />
+    <ClCompile Include="..\mxml-node.c" />
+    <ClCompile Include="..\mxml-private.c" />
+    <ClCompile Include="..\mxml-search.c" />
+    <ClCompile Include="..\mxml-set.c" />
+    <ClCompile Include="..\mxml-string.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\mxml-private.h" />
+    <ClInclude Include="..\mxml.h" />
+    <ClInclude Include="config.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="mxml1.def" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 65 - 0
mxml.mod/mxml/vcnet/mxml1.vcxproj.filters

@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\mxml-attr.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-entity.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-file.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-get.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-index.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-node.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-private.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-search.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-set.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-string.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="config.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\mxml-private.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\mxml.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="mxml1.def">
+      <Filter>Resource Files</Filter>
+    </None>
+  </ItemGroup>
+</Project>

+ 4 - 0
mxml.mod/mxml/vcnet/mxml1.vcxproj.user

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>

+ 184 - 0
mxml.mod/mxml/vcnet/mxmlstat.vcxproj

@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\mxml-private.h" />
+    <ClInclude Include="..\mxml.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\mxml-attr.c" />
+    <ClCompile Include="..\mxml-entity.c" />
+    <ClCompile Include="..\mxml-file.c" />
+    <ClCompile Include="..\mxml-get.c" />
+    <ClCompile Include="..\mxml-index.c" />
+    <ClCompile Include="..\mxml-node.c" />
+    <ClCompile Include="..\mxml-private.c" />
+    <ClCompile Include="..\mxml-search.c" />
+    <ClCompile Include="..\mxml-set.c" />
+    <ClCompile Include="..\mxml-string.c" />
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{CDEEBB3C-D45B-4CC5-BE9B-0BD415A27958}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>mxmlstat</RootNamespace>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(Configuration)\$(Platform)\$(ProjectName)\</OutDir>
+    <IntDir>$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(Configuration)\$(Platform)\$(ProjectName)\</OutDir>
+    <IntDir>$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(Configuration)\$(Platform)\$(ProjectName)\</OutDir>
+    <IntDir>$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(Configuration)\$(Platform)\$(ProjectName)\</OutDir>
+    <IntDir>$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PrecompiledHeaderFile />
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PrecompiledHeaderFile />
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PrecompiledHeaderFile />
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PrecompiledHeaderFile />
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 57 - 0
mxml.mod/mxml/vcnet/mxmlstat.vcxproj.filters

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\mxml.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\mxml-private.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\mxml-attr.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-entity.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-file.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-get.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-index.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-node.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-private.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-search.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-set.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\mxml-string.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>

+ 4 - 0
mxml.mod/mxml/vcnet/mxmlstat.vcxproj.user

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>

+ 5 - 0
mxml.mod/mxml/vcnet/packages.config

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="zlib-msvc14-x64" version="1.2.11.7795" targetFramework="native" />
+  <package id="zlib-msvc14-x86" version="1.2.11.7795" targetFramework="native" />
+</packages>

+ 199 - 0
mxml.mod/mxml/vcnet/testmxml.vcxproj

@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{75CAC6C4-A6BC-4935-A3C9-8F0AE0744227}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>15.0.27924.0</_ProjectFileVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>$(Configuration)\$(Platform)\$(ProjectName)\</OutDir>
+    <IntDir>$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>$(Configuration)\$(Platform)\$(ProjectName)\</OutDir>
+    <IntDir>$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <OutDir>$(Configuration)\$(Platform)\$(ProjectName)\</OutDir>
+    <IntDir>$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <OutDir>$(Configuration)\$(Platform)\$(ProjectName)\</OutDir>
+    <IntDir>$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>../vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader />
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(Configuration)\$(Platform)\$(ProductName)\testmxml.exe</OutputFile>
+      <IgnoreSpecificDefaultLibraries>oldnames.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>$(OutDir)testmxml.pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention />
+      <TargetMachine>MachineX86</TargetMachine>
+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>../vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <PrecompiledHeader />
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(Configuration)\$(Platform)\$(ProductName)\testmxml.exe</OutputFile>
+      <IgnoreSpecificDefaultLibraries>oldnames.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention />
+      <TargetMachine>MachineX86</TargetMachine>
+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>../vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader />
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(Configuration)\$(Platform)\$(ProductName)\testmxml.exe</OutputFile>
+      <IgnoreSpecificDefaultLibraries>oldnames.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>$(OutDir)testmxml.pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention />
+      <TargetMachine>MachineX64</TargetMachine>
+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <AdditionalIncludeDirectories>../vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <PrecompiledHeader />
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(Configuration)\$(Platform)\$(ProductName)\testmxml.exe</OutputFile>
+      <IgnoreSpecificDefaultLibraries>oldnames.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention />
+      <TargetMachine>MachineX64</TargetMachine>
+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\testmxml.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="mxmlstat.vcxproj">
+      <Project>{cdeebb3c-d45b-4cc5-be9b-0bd415a27958}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 22 - 0
mxml.mod/mxml/vcnet/testmxml.vcxproj.filters

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\testmxml.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>

+ 4 - 0
mxml.mod/mxml/vcnet/testmxml.vcxproj.user

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>

+ 528 - 0
mxml.mod/mxml/xcode/mxml.xcodeproj/project.pbxproj

@@ -0,0 +1,528 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXAggregateTarget section */
+		272C00441E8C6B5A007EBCAC /* All */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 272C00451E8C6B5A007EBCAC /* Build configuration list for PBXAggregateTarget "All" */;
+			buildPhases = (
+			);
+			dependencies = (
+				272C00491E8C6B61007EBCAC /* PBXTargetDependency */,
+				272C004D1E8C6B61007EBCAC /* PBXTargetDependency */,
+			);
+			name = All;
+			productName = All;
+		};
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+		272C00191E8C66C8007EBCAC /* mxml-attr.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C000D1E8C66C8007EBCAC /* mxml-attr.c */; };
+		272C001A1E8C66C8007EBCAC /* mxml-entity.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C000E1E8C66C8007EBCAC /* mxml-entity.c */; };
+		272C001B1E8C66C8007EBCAC /* mxml-file.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C000F1E8C66C8007EBCAC /* mxml-file.c */; };
+		272C001C1E8C66C8007EBCAC /* mxml-get.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00101E8C66C8007EBCAC /* mxml-get.c */; };
+		272C001D1E8C66C8007EBCAC /* mxml-index.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00111E8C66C8007EBCAC /* mxml-index.c */; };
+		272C001E1E8C66C8007EBCAC /* mxml-node.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00121E8C66C8007EBCAC /* mxml-node.c */; };
+		272C001F1E8C66C8007EBCAC /* mxml-private.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00131E8C66C8007EBCAC /* mxml-private.c */; };
+		272C00201E8C66C8007EBCAC /* mxml-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 272C00141E8C66C8007EBCAC /* mxml-private.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		272C00211E8C66C8007EBCAC /* mxml-search.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00151E8C66C8007EBCAC /* mxml-search.c */; };
+		272C00221E8C66C8007EBCAC /* mxml-set.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00161E8C66C8007EBCAC /* mxml-set.c */; };
+		272C00231E8C66C8007EBCAC /* mxml-string.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00171E8C66C8007EBCAC /* mxml-string.c */; };
+		272C00241E8C66C8007EBCAC /* mxml.h in Headers */ = {isa = PBXBuildFile; fileRef = 272C00181E8C66C8007EBCAC /* mxml.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		272C00261E8C66CF007EBCAC /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 272C00251E8C66CF007EBCAC /* config.h */; };
+		272C00421E8C6B30007EBCAC /* testmxml.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00401E8C6B1B007EBCAC /* testmxml.c */; };
+		272C00501E8C6B89007EBCAC /* libmxml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 272C00051E8C6664007EBCAC /* libmxml.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		272C00481E8C6B61007EBCAC /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 272CFFFD1E8C6664007EBCAC /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 272C00041E8C6664007EBCAC;
+			remoteInfo = libmxml;
+		};
+		272C004C1E8C6B61007EBCAC /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 272CFFFD1E8C6664007EBCAC /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 272C00381E8C6AEB007EBCAC;
+			remoteInfo = testmxml;
+		};
+		272C004E1E8C6B83007EBCAC /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 272CFFFD1E8C6664007EBCAC /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 272C00041E8C6664007EBCAC;
+			remoteInfo = libmxml;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		272C00371E8C6AEB007EBCAC /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		272C00051E8C6664007EBCAC /* libmxml.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libmxml.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		272C000D1E8C66C8007EBCAC /* mxml-attr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-attr.c"; path = "../mxml-attr.c"; sourceTree = "<group>"; };
+		272C000E1E8C66C8007EBCAC /* mxml-entity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-entity.c"; path = "../mxml-entity.c"; sourceTree = "<group>"; };
+		272C000F1E8C66C8007EBCAC /* mxml-file.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-file.c"; path = "../mxml-file.c"; sourceTree = "<group>"; };
+		272C00101E8C66C8007EBCAC /* mxml-get.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-get.c"; path = "../mxml-get.c"; sourceTree = "<group>"; };
+		272C00111E8C66C8007EBCAC /* mxml-index.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-index.c"; path = "../mxml-index.c"; sourceTree = "<group>"; };
+		272C00121E8C66C8007EBCAC /* mxml-node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-node.c"; path = "../mxml-node.c"; sourceTree = "<group>"; };
+		272C00131E8C66C8007EBCAC /* mxml-private.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-private.c"; path = "../mxml-private.c"; sourceTree = "<group>"; };
+		272C00141E8C66C8007EBCAC /* mxml-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "mxml-private.h"; path = "../mxml-private.h"; sourceTree = "<group>"; };
+		272C00151E8C66C8007EBCAC /* mxml-search.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-search.c"; path = "../mxml-search.c"; sourceTree = "<group>"; };
+		272C00161E8C66C8007EBCAC /* mxml-set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-set.c"; path = "../mxml-set.c"; sourceTree = "<group>"; };
+		272C00171E8C66C8007EBCAC /* mxml-string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-string.c"; path = "../mxml-string.c"; sourceTree = "<group>"; };
+		272C00181E8C66C8007EBCAC /* mxml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mxml.h; path = ../mxml.h; sourceTree = "<group>"; };
+		272C00251E8C66CF007EBCAC /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
+		272C00391E8C6AEB007EBCAC /* testmxml */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testmxml; sourceTree = BUILT_PRODUCTS_DIR; };
+		272C00401E8C6B1B007EBCAC /* testmxml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = testmxml.c; path = ../testmxml.c; sourceTree = "<group>"; };
+		272C00551E8EF972007EBCAC /* libarchive.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libarchive.tbd; path = usr/lib/libarchive.tbd; sourceTree = SDKROOT; };
+		272C005A1E943423007EBCAC /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		272C00021E8C6664007EBCAC /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		272C00361E8C6AEB007EBCAC /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				272C00501E8C6B89007EBCAC /* libmxml.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		272C00061E8C6664007EBCAC /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				272C00051E8C6664007EBCAC /* libmxml.a */,
+				272C00391E8C6AEB007EBCAC /* testmxml */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		272C000C1E8C66A2007EBCAC /* libmxml */ = {
+			isa = PBXGroup;
+			children = (
+				272C000D1E8C66C8007EBCAC /* mxml-attr.c */,
+				272C000E1E8C66C8007EBCAC /* mxml-entity.c */,
+				272C000F1E8C66C8007EBCAC /* mxml-file.c */,
+				272C00101E8C66C8007EBCAC /* mxml-get.c */,
+				272C00111E8C66C8007EBCAC /* mxml-index.c */,
+				272C00121E8C66C8007EBCAC /* mxml-node.c */,
+				272C00131E8C66C8007EBCAC /* mxml-private.c */,
+				272C00141E8C66C8007EBCAC /* mxml-private.h */,
+				272C00151E8C66C8007EBCAC /* mxml-search.c */,
+				272C00161E8C66C8007EBCAC /* mxml-set.c */,
+				272C00171E8C66C8007EBCAC /* mxml-string.c */,
+				272C00181E8C66C8007EBCAC /* mxml.h */,
+			);
+			name = libmxml;
+			sourceTree = "<group>";
+		};
+		272C00321E8C6ABB007EBCAC /* tools */ = {
+			isa = PBXGroup;
+			children = (
+				272C00401E8C6B1B007EBCAC /* testmxml.c */,
+			);
+			name = tools;
+			sourceTree = "<group>";
+		};
+		272C00541E8EF971007EBCAC /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				272C005A1E943423007EBCAC /* libz.tbd */,
+				272C00551E8EF972007EBCAC /* libarchive.tbd */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		272CFFFC1E8C6664007EBCAC = {
+			isa = PBXGroup;
+			children = (
+				272C00251E8C66CF007EBCAC /* config.h */,
+				272C000C1E8C66A2007EBCAC /* libmxml */,
+				272C00321E8C6ABB007EBCAC /* tools */,
+				272C00061E8C6664007EBCAC /* Products */,
+				272C00541E8EF971007EBCAC /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		272C00031E8C6664007EBCAC /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				272C00241E8C66C8007EBCAC /* mxml.h in Headers */,
+				272C00201E8C66C8007EBCAC /* mxml-private.h in Headers */,
+				272C00261E8C66CF007EBCAC /* config.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		272C00041E8C6664007EBCAC /* libmxml */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 272C00091E8C6664007EBCAC /* Build configuration list for PBXNativeTarget "libmxml" */;
+			buildPhases = (
+				272C00011E8C6664007EBCAC /* Sources */,
+				272C00021E8C6664007EBCAC /* Frameworks */,
+				272C00031E8C6664007EBCAC /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = libmxml;
+			productName = mxml;
+			productReference = 272C00051E8C6664007EBCAC /* libmxml.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		272C00381E8C6AEB007EBCAC /* testmxml */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 272C003D1E8C6AEB007EBCAC /* Build configuration list for PBXNativeTarget "testmxml" */;
+			buildPhases = (
+				272C00351E8C6AEB007EBCAC /* Sources */,
+				272C00361E8C6AEB007EBCAC /* Frameworks */,
+				272C00371E8C6AEB007EBCAC /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				272C004F1E8C6B83007EBCAC /* PBXTargetDependency */,
+			);
+			name = testmxml;
+			productName = testmxml;
+			productReference = 272C00391E8C6AEB007EBCAC /* testmxml */;
+			productType = "com.apple.product-type.tool";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		272CFFFD1E8C6664007EBCAC /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 1010;
+				ORGANIZATIONNAME = "Michael R Sweet";
+				TargetAttributes = {
+					272C00041E8C6664007EBCAC = {
+						CreatedOnToolsVersion = 8.3;
+						DevelopmentTeam = RU58A2256H;
+						ProvisioningStyle = Automatic;
+					};
+					272C00381E8C6AEB007EBCAC = {
+						CreatedOnToolsVersion = 8.3;
+						DevelopmentTeam = RU58A2256H;
+						ProvisioningStyle = Automatic;
+					};
+					272C00441E8C6B5A007EBCAC = {
+						CreatedOnToolsVersion = 8.3;
+						DevelopmentTeam = RU58A2256H;
+						ProvisioningStyle = Automatic;
+					};
+				};
+			};
+			buildConfigurationList = 272C00001E8C6664007EBCAC /* Build configuration list for PBXProject "mxml" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = 272CFFFC1E8C6664007EBCAC;
+			productRefGroup = 272C00061E8C6664007EBCAC /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				272C00441E8C6B5A007EBCAC /* All */,
+				272C00041E8C6664007EBCAC /* libmxml */,
+				272C00381E8C6AEB007EBCAC /* testmxml */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		272C00011E8C6664007EBCAC /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				272C001A1E8C66C8007EBCAC /* mxml-entity.c in Sources */,
+				272C001E1E8C66C8007EBCAC /* mxml-node.c in Sources */,
+				272C001B1E8C66C8007EBCAC /* mxml-file.c in Sources */,
+				272C001C1E8C66C8007EBCAC /* mxml-get.c in Sources */,
+				272C00221E8C66C8007EBCAC /* mxml-set.c in Sources */,
+				272C00191E8C66C8007EBCAC /* mxml-attr.c in Sources */,
+				272C001D1E8C66C8007EBCAC /* mxml-index.c in Sources */,
+				272C001F1E8C66C8007EBCAC /* mxml-private.c in Sources */,
+				272C00231E8C66C8007EBCAC /* mxml-string.c in Sources */,
+				272C00211E8C66C8007EBCAC /* mxml-search.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		272C00351E8C6AEB007EBCAC /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				272C00421E8C6B30007EBCAC /* testmxml.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		272C00491E8C6B61007EBCAC /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 272C00041E8C6664007EBCAC /* libmxml */;
+			targetProxy = 272C00481E8C6B61007EBCAC /* PBXContainerItemProxy */;
+		};
+		272C004D1E8C6B61007EBCAC /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 272C00381E8C6AEB007EBCAC /* testmxml */;
+			targetProxy = 272C004C1E8C6B61007EBCAC /* PBXContainerItemProxy */;
+		};
+		272C004F1E8C6B83007EBCAC /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 272C00041E8C6664007EBCAC /* libmxml */;
+			targetProxy = 272C004E1E8C6B83007EBCAC /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		272C00071E8C6664007EBCAC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
+				CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
+				CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_LABEL = YES;
+				GCC_WARN_UNUSED_PARAMETER = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				RUN_CLANG_STATIC_ANALYZER = YES;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		272C00081E8C6664007EBCAC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
+				CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
+				CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_LABEL = YES;
+				GCC_WARN_UNUSED_PARAMETER = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				RUN_CLANG_STATIC_ANALYZER = YES;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		272C000A1E8C6664007EBCAC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEVELOPMENT_TEAM = RU58A2256H;
+				EXECUTABLE_PREFIX = "";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		272C000B1E8C6664007EBCAC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEVELOPMENT_TEAM = RU58A2256H;
+				EXECUTABLE_PREFIX = "";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+		272C003E1E8C6AEB007EBCAC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEVELOPMENT_TEAM = RU58A2256H;
+				MACOSX_DEPLOYMENT_TARGET = 10.12;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		272C003F1E8C6AEB007EBCAC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEVELOPMENT_TEAM = RU58A2256H;
+				MACOSX_DEPLOYMENT_TARGET = 10.12;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+		272C00461E8C6B5A007EBCAC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEVELOPMENT_TEAM = RU58A2256H;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		272C00471E8C6B5A007EBCAC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEVELOPMENT_TEAM = RU58A2256H;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		272C00001E8C6664007EBCAC /* Build configuration list for PBXProject "mxml" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				272C00071E8C6664007EBCAC /* Debug */,
+				272C00081E8C6664007EBCAC /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		272C00091E8C6664007EBCAC /* Build configuration list for PBXNativeTarget "libmxml" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				272C000A1E8C6664007EBCAC /* Debug */,
+				272C000B1E8C6664007EBCAC /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		272C003D1E8C6AEB007EBCAC /* Build configuration list for PBXNativeTarget "testmxml" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				272C003E1E8C6AEB007EBCAC /* Debug */,
+				272C003F1E8C6AEB007EBCAC /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		272C00451E8C6B5A007EBCAC /* Build configuration list for PBXAggregateTarget "All" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				272C00461E8C6B5A007EBCAC /* Debug */,
+				272C00471E8C6B5A007EBCAC /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 272CFFFD1E8C6664007EBCAC /* Project object */;
+}

+ 14 - 0
mxml.mod/source.bmx

@@ -0,0 +1,14 @@
+SuperStrict
+
+Import "mxml/*.h"
+
+Import "mxml/mxml-attr.c"
+Import "mxml/mxml-entity.c"
+Import "mxml/mxml-file.c"
+Import "mxml/mxml-get.c"
+Import "mxml/mxml-index.c"
+Import "mxml/mxml-node.c"
+Import "mxml/mxml-search.c"
+Import "mxml/mxml-set.c"
+Import "mxml/mxml-private.c"
+Import "mxml/mxml-string.c"