]> granicus.if.org Git - libexpat/commitdiff
Initial Revision
authorJames Clark <jjc@jclark.com>
Mon, 2 Feb 1998 12:40:34 +0000 (12:40 +0000)
committerJames Clark <jjc@jclark.com>
Mon, 2 Feb 1998 12:40:34 +0000 (12:40 +0000)
expat/xmlparse/xmlparse.c [new file with mode: 0755]
expat/xmlparse/xmlparse.h [new file with mode: 0755]

diff --git a/expat/xmlparse/xmlparse.c b/expat/xmlparse/xmlparse.c
new file mode 100755 (executable)
index 0000000..d70c361
--- /dev/null
@@ -0,0 +1,1372 @@
+
+/* FIXME
+
+Normalize tokenized attribute values.
+
+Do attribute defaulting.
+
+*/
+
+
+#include "xmlparse.h"
+#include "xmltok.h"
+#include "xmlrole.h"
+#include "hashtable.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct {
+  const char *name;
+  const char *textPtr;
+  size_t textLen;
+  const char *systemId;
+  const char *publicId;
+  const char *notation;
+  char open;
+  char magic;
+} ENTITY;
+
+#define INIT_BLOCK_SIZE 1024
+
+typedef struct block {
+  struct block *next;
+  int size;
+  char s[1];
+} BLOCK;
+
+typedef struct {
+  BLOCK *blocks;
+  BLOCK *freeBlocks;
+  const char *end;
+  char *ptr;
+  char *start;
+} STRING_POOL;
+
+typedef struct {
+  HASH_TABLE generalEntities;
+  HASH_TABLE paramEntities;
+  STRING_POOL pool;
+  int containsRef;
+  int standalone;
+  char *groupConnector;
+  size_t groupSize;
+} DTD;
+
+typedef enum XML_Error Processor(XML_Parser parser,
+                                const char *start,
+                                const char *end,
+                                const char **endPtr);
+
+static Processor prologProcessor;
+static Processor contentProcessor;
+static Processor epilogProcessor;
+
+static
+int doContent(XML_Parser parser,
+             int startTagLevel,
+             const ENCODING *enc,
+             const char *start,
+             const char *end,
+             const char **endPtr);
+
+static enum XML_Error
+checkGeneralTextEntity(XML_Parser parser,
+                      const char *s, const char *end,
+                      const char **nextPtr,
+                      const ENCODING **enc);
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s);
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *, const char *, const char *,
+                   STRING_POOL *);
+static enum XML_Error
+checkAttributeUniqueness(XML_Parser parser, const ENCODING *enc, int nAtts);
+static enum XML_Error
+storeEntityValue(XML_Parser parser, const char *start, const char *end);
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+
+static
+const char *pushTag(XML_Parser parser, const ENCODING *enc, const char *rawName);
+
+
+static int dtdInit(DTD *);
+static void dtdDestroy(DTD *);
+static void poolInit(STRING_POOL *);
+static void poolClear(STRING_POOL *);
+static void poolDestroy(STRING_POOL *);
+static const char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+                             const char *ptr, const char *end);
+static const char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+                           const char *ptr, const char *end);
+static int poolGrow(STRING_POOL *pool);
+
+#define poolStart(pool) ((pool)->start)
+#define poolEnd(pool) ((pool)->ptr)
+#define poolLength(pool) ((pool)->ptr - (pool)->start)
+#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
+#define poolFinish(pool) ((pool)->start = (pool)->ptr)
+#define poolAppendByte(pool, c) \
+  (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
+   ? 0 \
+   : ((*((pool)->ptr)++ = c), 1))
+
+typedef struct {
+  char *buffer;
+  /* first character to be parsed */
+  const char *bufferPtr;
+  /* past last character to be parsed */
+  char *bufferEnd;
+  /* allocated end of buffer */
+  const char *bufferLim;
+  long bufferEndByteIndex;
+  void *userData;
+  XML_StartElementHandler startElementHandler;
+  XML_EndElementHandler endElementHandler;
+  XML_CharacterDataHandler characterDataHandler;
+  XML_ProcessingInstructionHandler processingInstructionHandler;
+  const ENCODING *encoding;
+  INIT_ENCODING initEncoding;
+  PROLOG_STATE prologState;
+  Processor *processor;
+  enum XML_Error errorCode;
+  const char *errorPtr;
+  int tagLevel;
+  ENTITY *declEntity;
+  DTD dtd;
+  char *tagStack;
+  char *tagStackPtr;
+  const char *tagStackEnd;
+  int attsSize;
+  ATTRIBUTE *atts;
+  POSITION position;
+  long errorByteIndex;
+  STRING_POOL tempPool;
+} Parser;
+
+#define userData (((Parser *)parser)->userData)
+#define startElementHandler (((Parser *)parser)->startElementHandler)
+#define endElementHandler (((Parser *)parser)->endElementHandler)
+#define characterDataHandler (((Parser *)parser)->characterDataHandler)
+#define processingInstructionHandler (((Parser *)parser)->processingInstructionHandler)
+#define encoding (((Parser *)parser)->encoding)
+#define initEncoding (((Parser *)parser)->initEncoding)
+#define prologState (((Parser *)parser)->prologState)
+#define processor (((Parser *)parser)->processor)
+#define errorCode (((Parser *)parser)->errorCode)
+#define errorPtr (((Parser *)parser)->errorPtr)
+#define errorByteIndex (((Parser *)parser)->errorByteIndex)
+#define position (((Parser *)parser)->position)
+#define tagLevel (((Parser *)parser)->tagLevel)
+#define buffer (((Parser *)parser)->buffer)
+#define bufferPtr (((Parser *)parser)->bufferPtr)
+#define bufferEnd (((Parser *)parser)->bufferEnd)
+#define bufferEndByteIndex (((Parser *)parser)->bufferEndByteIndex)
+#define bufferLim (((Parser *)parser)->bufferLim)
+#define dtd (((Parser *)parser)->dtd)
+#define declEntity (((Parser *)parser)->declEntity)
+#define tagStackEnd (((Parser *)parser)->tagStackEnd)
+#define tagStackPtr (((Parser *)parser)->tagStackPtr)
+#define tagStack (((Parser *)parser)->tagStack)
+#define atts (((Parser *)parser)->atts)
+#define attsSize (((Parser *)parser)->attsSize)
+#define tempPool (((Parser *)parser)->tempPool)
+
+XML_Parser XML_ParserCreate(const char *encodingName)
+{
+  XML_Parser parser = malloc(sizeof(Parser));
+  if (!parser)
+    return parser;
+  processor = prologProcessor;
+  XmlInitEncoding(&initEncoding, &encoding);
+  XmlPrologStateInit(&prologState);
+  userData = 0;
+  startElementHandler = 0;
+  endElementHandler = 0;
+  characterDataHandler = 0;
+  processingInstructionHandler = 0;
+  buffer = 0;
+  bufferPtr = 0;
+  bufferEnd = 0;
+  bufferEndByteIndex = 0;
+  bufferLim = 0;
+  memset(&position, 0, sizeof(POSITION));
+  errorCode = XML_ERROR_NONE;
+  errorByteIndex = 0;
+  errorPtr = 0;
+  tagLevel = 0;
+  tagStack = malloc(1024);
+  tagStackPtr = tagStack;
+  attsSize = 1024;
+  atts = malloc(attsSize * sizeof(ATTRIBUTE));
+  poolInit(&tempPool);
+  if (!dtdInit(&dtd) || !atts || !tagStack) {
+    XML_ParserFree(parser);
+    return 0;
+  }
+  tagStackEnd = tagStack + 1024;
+  *tagStackPtr++ = '\0';
+  return parser;
+}
+
+void XML_ParserFree(XML_Parser parser)
+{
+  poolDestroy(&tempPool);
+  dtdDestroy(&dtd);
+  free((void *)tagStack);
+  free((void *)atts);
+  free(buffer);
+  free(parser);
+}
+
+void XML_SetUserData(XML_Parser parser, void *p)
+{
+  userData = p;
+}
+
+void XML_SetElementHandler(XML_Parser parser,
+                          XML_StartElementHandler start,
+                          XML_EndElementHandler end)
+{
+  startElementHandler = start;
+  endElementHandler = end;
+}
+
+void XML_SetCharacterDataHandler(XML_Parser parser,
+                                XML_CharacterDataHandler handler)
+{
+  characterDataHandler = handler;
+}
+
+void XML_SetProcessingInstructionHandler(XML_Parser parser,
+                                        XML_ProcessingInstructionHandler handler)
+{
+  processingInstructionHandler = handler;
+}
+
+int XML_Parse(XML_Parser parser, const char *s, size_t len, int isFinal)
+{
+  bufferEndByteIndex += len;
+  if (len == 0) {
+    if (!isFinal)
+      return 1;
+    errorCode = processor(parser, bufferPtr, bufferEnd, 0);
+    return errorCode == XML_ERROR_NONE;
+  }
+  else if (bufferPtr == bufferEnd) {
+    const char *end;
+    int nLeftOver;
+    if (isFinal) {
+      errorCode = processor(parser, s, s + len, 0);
+      if (errorCode == XML_ERROR_NONE)
+       return 1;
+      if (errorPtr) {
+       errorByteIndex = bufferEndByteIndex - (s + len - errorPtr);
+       XmlUpdatePosition(encoding, s, errorPtr, &position);
+      }
+      return 0;
+    }
+    errorCode = processor(parser, s, s + len, &end);
+    if (errorCode != XML_ERROR_NONE) {
+      if (errorPtr) {
+       errorByteIndex = bufferEndByteIndex - (s + len - errorPtr);
+       XmlUpdatePosition(encoding, s, errorPtr, &position);
+      }
+      return 0;
+    }
+    XmlUpdatePosition(encoding, s, end, &position);
+    nLeftOver = s + len - end;
+    if (nLeftOver) {
+      if (buffer == 0 || nLeftOver > bufferLim - buffer) {
+       /* FIXME avoid integer overflow */
+       buffer = realloc(buffer, len * 2);
+       if (!buffer) {
+         errorCode = XML_ERROR_NO_MEMORY;
+         return 0;
+       }
+       bufferLim = buffer + len * 2;
+      }
+      memcpy(buffer, end, nLeftOver);
+      bufferPtr = buffer;
+      bufferEnd = buffer + nLeftOver;
+    }
+    return 1;
+  }
+  else {
+    memcpy(XML_GetBuffer(parser, len), s, len);
+    return XML_ParseBuffer(parser, len, isFinal);
+  }
+}
+
+int XML_ParseBuffer(XML_Parser parser, size_t len, int isFinal)
+{
+  const char *start = bufferPtr;
+  bufferEnd += len;
+  errorCode = processor(parser, bufferPtr, bufferEnd,
+                       isFinal ? (const char **)0 : &bufferPtr);
+  if (errorCode == XML_ERROR_NONE) {
+    if (!isFinal)
+      XmlUpdatePosition(encoding, start, bufferPtr, &position);
+    return 1;
+  }
+  else {
+    if (errorPtr) {
+      errorByteIndex = bufferEndByteIndex - (bufferEnd - errorPtr);
+      XmlUpdatePosition(encoding, start, errorPtr, &position);
+    }
+    return 0;
+  }
+}
+
+void *XML_GetBuffer(XML_Parser parser, size_t len)
+{
+  if (len > bufferLim - bufferEnd) {
+    /* FIXME avoid integer overflow */
+    int neededSize = len + (bufferEnd - bufferPtr);
+    if (neededSize  <= bufferLim - buffer) {
+      memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
+      bufferEnd = buffer + (bufferEnd - bufferPtr);
+      bufferPtr = buffer;
+    }
+    else {
+      char *newBuf;
+      size_t bufferSize = bufferLim  - bufferPtr;
+      do {
+       bufferSize *= 2;
+      } while (bufferSize < neededSize);
+      newBuf = malloc(bufferSize);
+      if (newBuf == 0) {
+       errorCode = XML_ERROR_NO_MEMORY;
+       return 0;
+      }
+      bufferLim = newBuf + bufferSize;
+      memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
+      bufferEnd = newBuf + (bufferEnd - bufferPtr);
+      bufferPtr = buffer = newBuf;
+    }
+  }
+  return bufferEnd;
+}
+
+int XML_GetErrorCode(XML_Parser parser)
+{
+  return errorCode;
+}
+
+int XML_GetErrorLineNumber(XML_Parser parser)
+{
+  return position.lineNumber;
+}
+
+int XML_GetErrorColumnNumber(XML_Parser parser)
+{
+  return position.columnNumber;
+}
+
+long XML_GetErrorByteIndex(XML_Parser parser)
+{
+  return errorByteIndex;
+}
+
+const char *XML_ErrorString(int code)
+{
+  static const char *message[] = {
+    0,
+    "out of memory",
+    "syntax error",
+    "no element found",
+    "not well-formed",
+    "unclosed token",
+    "unclosed token",
+    "mismatched tag",
+    "duplicate attribute",
+    "junk after document element",
+    "parameter entity reference not allowed within declaration in internal subset",
+    "undefined entity",
+    "recursive entity reference",
+    "asynchronous entity",
+    "reference to invalid character number",
+    "reference to binary entity",
+    "reference to external entity in attribute",
+    "xml processing instruction not at start of external entity",
+    "unknown encoding",
+    "encoding specified in XML declaration is incorrect"
+  };
+  if (code > 0 && code < sizeof(message)/sizeof(message[0]))
+    return message[code];
+  return 0;
+}
+
+static
+enum XML_ERROR contentProcessor(XML_Parser parser,
+                               const char *start,
+                               const char *end,
+                               const char **endPtr)
+{
+  return doContent(parser, 0, encoding, start, end, endPtr);
+}
+
+static enum XML_Error
+doContent(XML_Parser parser,
+         int startTagLevel,
+         const ENCODING *enc,
+         const char *s,
+         const char *end,
+         const char **nextPtr)
+{
+  static const char *nullPtr = 0;
+  const ENCODING *utf8 = XmlGetInternalEncoding(XML_UTF8_ENCODING);
+  for (;;) {
+    const char **appAtts;
+    const char *next;
+    int tok = XmlContentTok(enc, s, end, &next);
+    switch (tok) {
+    case XML_TOK_TRAILING_CR:
+    case XML_TOK_NONE:
+      if (nextPtr) {
+       *nextPtr = s;
+       return XML_ERROR_NONE;
+      }
+      if (startTagLevel > 0) {
+       if (tagLevel != startTagLevel) {
+         errorPtr = s;
+         return XML_ERROR_ASYNC_ENTITY;
+        }
+       return XML_ERROR_NONE;
+      }
+      errorPtr = s;
+      return XML_ERROR_NO_ELEMENTS;
+    case XML_TOK_INVALID:
+      errorPtr = next;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_PARTIAL:
+      if (nextPtr) {
+       *nextPtr = s;
+       return XML_ERROR_NONE;
+      }
+      errorPtr = s;
+      return XML_ERROR_UNCLOSED_TOKEN;
+    case XML_TOK_PARTIAL_CHAR:
+      if (nextPtr) {
+       *nextPtr = s;
+       return XML_ERROR_NONE;
+      }
+      errorPtr = s;
+      return XML_ERROR_PARTIAL_CHAR;
+    case XML_TOK_ENTITY_REF:
+      {
+       const char *name = poolStoreString(&dtd.pool, enc,
+                                          s + enc->minBytesPerChar,
+                                          next - enc->minBytesPerChar);
+       ENTITY *entity;
+       if (!name)
+         return XML_ERROR_NO_MEMORY;
+       entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
+       poolDiscard(&dtd.pool);
+       if (!entity) {
+         if (!dtd.containsRef || dtd.standalone) {
+           errorPtr = s;
+           return XML_ERROR_UNDEFINED_ENTITY;
+         }
+         break;
+       }
+       if (entity->magic) {
+         if (characterDataHandler)
+           characterDataHandler(userData, entity->textPtr, entity->textLen);
+         break;
+       }
+       if (entity->open) {
+         errorPtr = s;
+         return XML_ERROR_RECURSIVE_ENTITY_REF;
+       }
+       if (entity->notation) {
+         errorPtr = s;
+         return XML_ERROR_BINARY_ENTITY_REF;
+       }
+       if (entity) {
+         if (entity->textPtr) {
+           enum XML_Error result;
+           entity->open = 1;
+           result = doContent(parser,
+                              tagLevel,
+                              utf8,
+                              entity->textPtr,
+                              entity->textPtr + entity->textLen,
+                              0);
+           entity->open = 0;
+           if (result) {
+             errorPtr = s;
+             return result;
+           }
+         }
+       }
+       break;
+      }
+    case XML_TOK_START_TAG_WITH_ATTS:
+      {
+       const char *name;
+       enum XML_Error result = storeAtts(parser, enc, s);
+       if (result)
+         return result;
+       name = pushTag(parser, enc, s + enc->minBytesPerChar);
+       if (!name)
+         return XML_ERROR_NO_MEMORY;
+       ++tagLevel;
+       if (startElementHandler) {
+         startElementHandler(userData, name, (const char **)atts);
+         poolClear(&tempPool);
+       }
+       break;
+      }
+    case XML_TOK_START_TAG_NO_ATTS:
+      {
+       const char *name = pushTag(parser, enc, s + enc->minBytesPerChar);
+       ++tagLevel;
+       if (!name)
+         return XML_ERROR_NO_MEMORY;
+       if (startElementHandler)
+         startElementHandler(userData, name, &nullPtr);
+       break;
+      }
+    case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
+      {
+       enum XML_Error result = storeAtts(parser, enc, s);
+       if (result)
+         return result;
+       appAtts = (const char **)atts;
+       goto emptyElement;
+      }
+    case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
+      appAtts = &nullPtr;
+    emptyElement:
+      if (startElementHandler || endElementHandler) {
+       const char *nameStart = s + enc->minBytesPerChar;
+       const char *name = poolStoreString(&tempPool, enc, nameStart,
+                                          nameStart
+                                          + XmlNameLength(enc, nameStart));
+       if (!name)
+         return XML_ERROR_NO_MEMORY;
+       if (startElementHandler)
+         startElementHandler(userData, name, appAtts);
+       if (endElementHandler)
+         endElementHandler(userData, name);
+       poolClear(&tempPool);
+      }
+      if (tagLevel == 0)
+       return epilogProcessor(parser, next, end, nextPtr);
+      break;
+    case XML_TOK_END_TAG:
+      if (tagLevel == startTagLevel) {
+        errorPtr = s;
+        return XML_ERROR_ASYNC_ENTITY;
+      }
+      else {
+       const char *rawNameStart = s + enc->minBytesPerChar * 2;
+       const char *nameEnd;
+       const char *name = poolStoreString(&tempPool, enc, rawNameStart,
+                                          rawNameStart
+                                          + XmlNameLength(enc, rawNameStart));
+       if (!name)
+         return XML_ERROR_NO_MEMORY;
+       nameEnd = poolEnd(&tempPool);
+       for (;;) {
+         --nameEnd;
+         --tagStackPtr;
+         if (nameEnd == name) {
+           if (tagStackPtr[-1] == '\0')
+             break;
+           return XML_ERROR_TAG_MISMATCH;
+         }
+         if (*nameEnd != *tagStackPtr)
+           return XML_ERROR_TAG_MISMATCH;
+       }
+       --tagLevel;
+       if (endElementHandler)
+         endElementHandler(userData, name);
+       poolDiscard(&tempPool);
+       if (tagLevel == 0)
+         return epilogProcessor(parser, next, end, nextPtr);
+      }
+      break;
+    case XML_TOK_CHAR_REF:
+      {
+       int n = XmlCharRefNumber(enc, s);
+       if (n < 0) {
+         errorPtr = s;
+         return XML_ERROR_BAD_CHAR_REF;
+       }
+       if (characterDataHandler) {
+         char buf[XML_MAX_BYTES_PER_CHAR];
+         characterDataHandler(userData, buf, XmlEncode(utf8, n, buf));
+       }
+      }
+      break;
+    case XML_TOK_XML_DECL:
+      errorPtr = s;
+      return XML_ERROR_MISPLACED_XML_PI;
+    case XML_TOK_DATA_NEWLINE:
+      if (characterDataHandler) {
+       char c = '\n';
+       characterDataHandler(userData, &c, 1);
+      }
+      break;
+    case XML_TOK_CDATA_SECTION:
+      if (characterDataHandler) {
+       if (!poolAppend(&tempPool,
+                       enc,
+                       s + enc->minBytesPerChar * 9,
+                       next - enc->minBytesPerChar * 3))
+         return XML_ERROR_NO_MEMORY;
+       characterDataHandler(userData, poolStart(&tempPool), poolLength(&tempPool));
+       poolDiscard(&tempPool);
+      }
+      break;
+    case XML_TOK_DATA_CHARS:
+      if (characterDataHandler) {
+       /* FIXME Do this efficiently */
+       if (!poolAppend(&tempPool, enc, s, next))
+         return XML_ERROR_NO_MEMORY;
+       characterDataHandler(userData, poolStart(&tempPool), poolLength(&tempPool));
+       poolDiscard(&tempPool);
+      }
+      break;
+    case XML_TOK_PI:
+      if (!reportProcessingInstruction(parser, enc, s, next))
+       return XML_ERROR_NO_MEMORY;
+      break;
+    }
+    s = next;
+  }
+  /* not reached */
+}
+
+static
+const char *pushTag(XML_Parser parser, const ENCODING *enc, const char *rawName)
+{
+  const char *name = tagStackPtr;
+  const char *rawNameEnd = rawName + XmlNameLength(enc, rawName);
+  for (;;) {
+    char *newStack;
+    size_t newSize;
+    XmlConvert(enc, XML_UTF8_ENCODING,
+       &rawName, rawNameEnd,
+               &tagStackPtr, tagStackEnd - 1);
+     if (rawName == rawNameEnd)
+       break;
+     newSize = (tagStackEnd - tagStack) >> 1;
+     newStack = realloc(tagStack, newSize);
+    if (!newStack)
+      return 0;
+    tagStackEnd = newStack + newSize;
+    tagStackPtr = newStack + (tagStackPtr - tagStack);
+    name = newStack + (name - tagStack);
+    tagStack = newStack;
+   }
+  *tagStackPtr++ = '\0';
+  return name;
+}
+
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,        const char *s)
+{
+  const char **appAtts = 0;
+  int i;
+  int n = XmlGetAttributes(enc, s, attsSize, atts);
+  if (n > attsSize) {
+    attsSize = 2*n;
+    atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE));
+    if (!atts)
+      return XML_ERROR_NO_MEMORY;
+    XmlGetAttributes(enc, s, n, atts);
+  }
+  if (n > 1) {
+    enum XML_Error result = checkAttributeUniqueness(parser, enc, n);
+    if (result)
+      return result;
+  }
+  if (startElementHandler)
+    appAtts = (const char **)atts;
+  for (i = 0; i < n; i++) {
+    if (appAtts) {
+      appAtts[i << 1] = poolStoreString(&tempPool, enc,
+                                       atts[i].name,
+                                       atts[i].name
+                                       + XmlNameLength(enc, atts[i].name));
+      if (appAtts[i << 1] == 0)
+       return XML_ERROR_NO_MEMORY;
+      poolFinish(&tempPool);
+    }
+    if (!atts[i].normalized) {
+      enum XML_Error result
+       = storeAttributeValue(parser, enc,
+                             atts[i].valuePtr,
+                             atts[i].valueEnd,
+                             &tempPool);
+      if (result)
+       return result;
+      if (!poolAppendByte(&tempPool, '\0'))
+       return XML_ERROR_NO_MEMORY;
+      if (appAtts) {
+       appAtts[(i << 1) + 1] = poolStart(&tempPool);
+       poolFinish(&tempPool);
+      }
+      else
+       poolDiscard(&tempPool);
+    }
+    else if (appAtts) {
+      appAtts[(i << 1) + 1] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
+      if (appAtts[(i << 1) + 1] == 0)
+       return XML_ERROR_NO_MEMORY;
+      poolFinish(&tempPool);
+    }
+  }
+  if (appAtts)
+    appAtts[n << 1] = 0;
+  return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+prologProcessor(XML_Parser parser,
+               const char *s,
+               const char *end,
+               const char **nextPtr)
+{
+  for (;;) {
+    const char *next;
+    int tok = XmlPrologTok(encoding, s, end, &next);
+    if (tok <= 0) {
+      if (nextPtr != 0 && tok != XML_TOK_INVALID) {
+       *nextPtr = s;
+       return XML_ERROR_NONE;
+      }
+      switch (tok) {
+      case XML_TOK_INVALID:
+       errorPtr = next;
+       return XML_ERROR_INVALID_TOKEN;
+      case XML_TOK_NONE:
+       return XML_ERROR_NO_ELEMENTS;
+      case XML_TOK_PARTIAL:
+       return XML_ERROR_UNCLOSED_TOKEN;
+      case XML_TOK_PARTIAL_CHAR:
+       return XML_ERROR_PARTIAL_CHAR;
+      case XML_TOK_TRAILING_CR:
+       errorPtr = s + encoding->minBytesPerChar;
+       return XML_ERROR_NO_ELEMENTS;
+      default:
+       abort();
+      }
+    }
+    switch (XmlTokenRole(&prologState, tok, s, next, encoding)) {
+    case XML_ROLE_XML_DECL:
+      {
+       const char *encodingName = 0;
+       const ENCODING *newEncoding = 0;
+       const char *version;
+       int standalone = -1;
+       if (!XmlParseXmlDecl(0,
+                            encoding,
+                            s,
+                            next,
+                            &errorPtr,
+                            &version,
+                            &encodingName,
+                            &newEncoding,
+                            &standalone))
+         return XML_ERROR_SYNTAX;
+       if (newEncoding) {
+         if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
+           errorPtr = encodingName;
+           return XML_ERROR_INCORRECT_ENCODING;
+         }
+         encoding = newEncoding;
+       }
+       else if (encodingName) {
+         errorPtr = encodingName;
+         return XML_ERROR_UNKNOWN_ENCODING;
+       }
+       if (standalone == 1)
+         dtd.standalone = 1;
+       break;
+      }
+    case XML_ROLE_DOCTYPE_SYSTEM_ID:
+      dtd.containsRef = 1;
+      break;
+    case XML_ROLE_DOCTYPE_PUBLIC_ID:
+    case XML_ROLE_ENTITY_PUBLIC_ID:
+    case XML_ROLE_NOTATION_PUBLIC_ID:
+      if (!XmlIsPublicId(encoding, s, next, &errorPtr))
+       return XML_ERROR_SYNTAX;
+      break;
+    case XML_ROLE_INSTANCE_START:
+      processor = contentProcessor;
+      return contentProcessor(parser, s, end, nextPtr);
+    case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
+    case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
+      {
+       enum XML_Error result
+         = storeAttributeValue(parser, encoding, s + encoding->minBytesPerChar,
+                               next - encoding->minBytesPerChar,
+                               &dtd.pool);
+       if (result)
+         return result;
+       poolFinish(&dtd.pool);
+       break;
+      }
+    case XML_ROLE_ENTITY_VALUE:
+      {
+       enum XML_Error result = storeEntityValue(parser, s, next);
+       if (result != XML_ERROR_NONE)
+         return result;
+      }
+      break;
+    case XML_ROLE_ENTITY_SYSTEM_ID:
+      if (declEntity) {
+       declEntity->systemId = poolStoreString(&dtd.pool, encoding,
+                                              s + encoding->minBytesPerChar,
+                                              next - encoding->minBytesPerChar);
+       if (!declEntity->systemId)
+         return XML_ERROR_NO_MEMORY;
+       poolFinish(&dtd.pool);
+      }
+      break;
+    case XML_ROLE_PARAM_ENTITY_REF:
+      {
+       const char *name = poolStoreString(&dtd.pool, encoding,
+                                          s + encoding->minBytesPerChar,
+                                          next - encoding->minBytesPerChar);
+       ENTITY *entity;
+       if (!name)
+         return XML_ERROR_NO_MEMORY;
+       entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
+       poolDiscard(&dtd.pool);
+       if (!entity) {
+         if (!dtd.containsRef || dtd.standalone) {
+           errorPtr = s;
+           return XML_ERROR_UNDEFINED_ENTITY;
+         }
+       }
+      }
+      break;
+    case XML_ROLE_ENTITY_NOTATION_NAME:
+      if (declEntity) {
+       declEntity->notation = poolStoreString(&dtd.pool, encoding, s, next);
+       if (!declEntity->notation)
+         return XML_ERROR_NO_MEMORY;
+       poolFinish(&dtd.pool);
+      }
+      break;
+    case XML_ROLE_GENERAL_ENTITY_NAME:
+      {
+       const char *name = poolStoreString(&dtd.pool, encoding, s, next);
+       if (!name)
+         return XML_ERROR_NO_MEMORY;
+       declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY));
+       if (declEntity->name != name) {
+         poolDiscard(&dtd.pool);
+         declEntity = 0;
+       }
+       else
+         poolFinish(&dtd.pool);
+      }
+      break;
+    case XML_ROLE_PARAM_ENTITY_NAME:
+      {
+       const char *name = poolStoreString(&dtd.pool, encoding, s, next);
+       if (!name)
+         return XML_ERROR_NO_MEMORY;
+       declEntity = (ENTITY *)lookup(&dtd.paramEntities, name, sizeof(ENTITY));
+       if (declEntity->name != name) {
+         poolDiscard(&dtd.pool);
+         declEntity = 0;
+       }
+       else
+         poolFinish(&dtd.pool);
+      }
+      break;
+    case XML_ROLE_ERROR:
+      errorPtr = s;
+      switch (tok) {
+      case XML_TOK_PARAM_ENTITY_REF:
+       return XML_ERROR_PARAM_ENTITY_REF;
+      case XML_TOK_XML_DECL:
+       return XML_ERROR_MISPLACED_XML_PI;
+      default:
+       return XML_ERROR_SYNTAX;
+      }
+    case XML_ROLE_GROUP_OPEN:
+      if (prologState.level >= dtd.groupSize) {
+       if (dtd.groupSize)
+         dtd.groupConnector = realloc(dtd.groupConnector, dtd.groupSize *= 2);
+       else
+         dtd.groupConnector = malloc(dtd.groupSize = 32);
+       if (!dtd.groupConnector)
+         return XML_ERROR_NO_MEMORY;
+      }
+      dtd.groupConnector[prologState.level] = 0;
+      break;
+    case XML_ROLE_GROUP_SEQUENCE:
+      if (dtd.groupConnector[prologState.level] == '|') {
+       *nextPtr = s;
+       return XML_ERROR_SYNTAX;
+      }
+      dtd.groupConnector[prologState.level] = ',';
+      break;
+    case XML_ROLE_GROUP_CHOICE:
+      if (dtd.groupConnector[prologState.level] == ',') {
+       *nextPtr = s;
+       return XML_ERROR_SYNTAX;
+      }
+      dtd.groupConnector[prologState.level] = '|';
+      break;
+    case XML_ROLE_NONE:
+      switch (tok) {
+      case XML_TOK_PARAM_ENTITY_REF:
+       dtd.containsRef = 1;
+       break;
+      case XML_TOK_PI:
+       if (!reportProcessingInstruction(parser, encoding, s, next))
+         return XML_ERROR_NO_MEMORY;
+       break;
+      }
+      break;
+    }
+    s = next;
+  }
+  /* not reached */
+}
+
+static
+enum XML_Error epilogProcessor(XML_Parser parser,
+                              const char *s,
+                              const char *end,
+                              const char **nextPtr)
+{
+  processor = epilogProcessor;
+  for (;;) {
+    const char *next;
+    int tok = XmlPrologTok(encoding, s, end, &next);
+    switch (tok) {
+    case XML_TOK_TRAILING_CR:
+    case XML_TOK_NONE:
+      if (nextPtr)
+       *nextPtr = end;
+      return XML_ERROR_NONE;
+    case XML_TOK_PROLOG_S:
+    case XML_TOK_COMMENT:
+      break;
+    case XML_TOK_PI:
+      if (!reportProcessingInstruction(parser, encoding, s, next))
+       return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_INVALID:
+      errorPtr = next;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_PARTIAL:
+      if (nextPtr) {
+       *nextPtr = s;
+       return XML_ERROR_NONE;
+      }
+      errorPtr = s;
+      return XML_ERROR_UNCLOSED_TOKEN;
+    case XML_TOK_PARTIAL_CHAR:
+      if (nextPtr) {
+       *nextPtr = s;
+       return XML_ERROR_NONE;
+      }
+      errorPtr = s;
+      return XML_ERROR_PARTIAL_CHAR;
+    default:
+      errorPtr = s;
+      return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
+    }
+    s = next;
+  }
+}
+
+static enum XML_Error
+checkAttributeUniqueness(XML_Parser parser, const ENCODING *enc, int nAtts)
+{
+  int i;
+  for (i = 1; i < nAtts; i++) {
+    int j;
+    for (j = 0; j < i; j++) {
+      if (XmlSameName(enc, atts[i].name, atts[j].name)) {
+       errorPtr = atts[i].name;
+       return XML_ERROR_DUPLICATE_ATTRIBUTE;
+      }
+    }
+  }
+  return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *enc,
+                   const char *ptr, const char *end,
+                   STRING_POOL *pool)
+{
+  const ENCODING *utf8 = XmlGetInternalEncoding(XML_UTF8_ENCODING);
+  for (;;) {
+    const char *next;
+    int tok = XmlAttributeValueTok(enc, ptr, end, &next);
+    switch (tok) {
+    case XML_TOK_NONE:
+      return XML_ERROR_NONE;
+    case XML_TOK_INVALID:
+      errorPtr = next;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_PARTIAL:
+      errorPtr = ptr;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_CHAR_REF:
+      if (XmlCharRefNumber(enc, ptr) < 0) {
+       errorPtr = ptr;
+       return XML_ERROR_BAD_CHAR_REF;
+      }
+      else {
+       char buf[XML_MAX_BYTES_PER_CHAR];
+       int i;
+       int n = XmlCharRefNumber(enc, ptr);
+       if (n < 0) {
+         errorPtr = ptr;
+         return XML_ERROR_BAD_CHAR_REF;
+       }
+       n = XmlEncode(utf8, n, buf);
+       if (!n) {
+         errorPtr = ptr;
+         return XML_ERROR_BAD_CHAR_REF;
+       }
+       for (i = 0; i < n; i++) {
+         if (!poolAppendByte(pool, buf[i]))
+           return XML_ERROR_NO_MEMORY;
+       }
+      }
+      break;
+    case XML_TOK_DATA_CHARS:
+      if (!poolAppend(pool, enc, ptr, next))
+       return XML_ERROR_NO_MEMORY;
+      break;
+      break;
+    case XML_TOK_TRAILING_CR:
+      next = ptr + enc->minBytesPerChar;
+      /* fall through */
+    case XML_TOK_DATA_NEWLINE:
+      if (!poolAppendByte(pool, ' '))
+       return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_ENTITY_REF:
+      {
+       const char *name = poolStoreString(&dtd.pool, enc,
+                                          ptr + enc->minBytesPerChar,
+                                          next - enc->minBytesPerChar);
+       ENTITY *entity;
+       if (!name)
+         return XML_ERROR_NO_MEMORY;
+       entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
+       poolDiscard(&dtd.pool);
+       if (!entity) {
+         if (!dtd.containsRef) {
+           errorPtr = ptr;
+           return XML_ERROR_UNDEFINED_ENTITY;
+         }
+       }
+       else if (entity->open) {
+         errorPtr = ptr;
+         return XML_ERROR_RECURSIVE_ENTITY_REF;
+       }
+       else if (entity->notation) {
+         errorPtr = ptr;
+         return XML_ERROR_BINARY_ENTITY_REF;
+       }
+       else if (entity->magic) {
+         int i;
+         for (i = 0; i < entity->textLen; i++)
+           if (!poolAppendByte(pool, entity->textPtr[i]))
+             return XML_ERROR_NO_MEMORY;
+       }
+       else if (!entity->textPtr) {
+         errorPtr = ptr;
+         return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
+       }
+       else {
+         enum XML_Error result;
+         const char *textEnd = entity->textPtr + entity->textLen;
+         entity->open = 1;
+         result = storeAttributeValue(parser, utf8, entity->textPtr, textEnd, pool);
+         entity->open = 0;
+         if (result) {
+           errorPtr = ptr;
+           return result;
+         }
+       }
+      }
+      break;
+    default:
+      abort();
+    }
+    ptr = next;
+  }
+  /* not reached */
+}
+
+static
+enum XML_Error storeEntityValue(XML_Parser parser,
+                               const char *entityTextPtr,
+                               const char *entityTextEnd)
+{
+  const ENCODING *utf8 = XmlGetInternalEncoding(XML_UTF8_ENCODING);
+  STRING_POOL *pool = &(dtd.pool);
+  entityTextPtr += encoding->minBytesPerChar;
+  entityTextEnd -= encoding->minBytesPerChar;
+  for (;;) {
+    const char *next;
+    int tok = XmlEntityValueTok(encoding, entityTextPtr, entityTextEnd, &next);
+    switch (tok) {
+    case XML_TOK_PARAM_ENTITY_REF:
+      errorPtr = entityTextPtr;
+      return XML_ERROR_SYNTAX;
+    case XML_TOK_NONE:
+      if (declEntity) {
+       declEntity->textPtr = pool->start;
+       declEntity->textLen = pool->ptr - pool->start;
+       poolFinish(pool);
+      }
+      else
+       poolDiscard(pool);
+      return XML_ERROR_NONE;
+    case XML_TOK_ENTITY_REF:
+    case XML_TOK_DATA_CHARS:
+      if (!poolAppend(pool, encoding, entityTextPtr, next))
+       return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_TRAILING_CR:
+      next = entityTextPtr + encoding->minBytesPerChar;
+      /* fall through */
+    case XML_TOK_DATA_NEWLINE:
+      if (pool->end == pool->ptr && !poolGrow(pool))
+       return XML_ERROR_NO_MEMORY;
+      *(pool->ptr)++ = '\n';
+      break;
+    case XML_TOK_CHAR_REF:
+      {
+       char buf[XML_MAX_BYTES_PER_CHAR];
+       int i;
+       int n = XmlCharRefNumber(encoding, entityTextPtr);
+       if (n < 0) {
+         errorPtr = entityTextPtr;
+         return XML_ERROR_BAD_CHAR_REF;
+       }
+       n = XmlEncode(utf8, n, buf);
+       if (!n) {
+         errorPtr = entityTextPtr;
+         return XML_ERROR_BAD_CHAR_REF;
+       }
+       for (i = 0; i < n; i++) {
+         if (pool->end == pool->ptr && !poolGrow(pool))
+           return XML_ERROR_NO_MEMORY;
+         *(pool->ptr)++ = buf[i];
+       }
+      }
+      break;
+    case XML_TOK_PARTIAL:
+      errorPtr = entityTextPtr;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_INVALID:
+      errorPtr = next;
+      return XML_ERROR_INVALID_TOKEN;
+    default:
+      abort();
+    }
+    entityTextPtr = next;
+  }
+  /* not reached */
+}
+
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+  const char *target;
+  int targetLen;
+  const char *data;
+  if (!processingInstructionHandler)
+    return 1;
+  target = start + enc->minBytesPerChar * 2;
+  targetLen = XmlNameLength(enc, target);
+  target = poolStoreString(&tempPool, enc, target, target + targetLen);
+  if (!target)
+    return 0;
+  poolFinish(&tempPool);
+  data = XmlSkipS(enc, start + enc->minBytesPerChar*2 + targetLen);
+  data = poolStoreString(&tempPool, enc,
+                        data,
+                        end - enc->minBytesPerChar*2);
+  if (!data)
+    return 0;
+  processingInstructionHandler(userData, target, data);
+  poolClear(&tempPool);
+  return 1;
+}
+
+static int dtdInit(DTD *p)
+{
+  static const char *names[] = { "lt", "amp", "gt", "quot", "apos" };
+  static const char chars[] = { '<', '&', '>', '"', '\'' };
+  int i;
+
+  poolInit(&(p->pool));
+  hashTableInit(&(p->generalEntities));
+  for (i = 0; i < 5; i++) {
+    ENTITY *entity = (ENTITY *)lookup(&(p->generalEntities), names[i], sizeof(ENTITY));
+    if (!entity)
+      return 0;
+    entity->textPtr = chars + i;
+    entity->textLen = 1;
+    entity->magic = 1;
+  }
+  hashTableInit(&(p->paramEntities));
+  p->containsRef = 0;
+  p->groupSize = 0;
+  p->groupConnector = 0;
+  return 1;
+}
+
+static void dtdDestroy(DTD *p)
+{
+  poolDestroy(&(p->pool));
+  hashTableDestroy(&(p->generalEntities));
+  hashTableDestroy(&(p->paramEntities));
+  free(p->groupConnector);
+}
+
+static
+void poolInit(STRING_POOL *pool)
+{
+  pool->blocks = 0;
+  pool->freeBlocks = 0;
+  pool->start = 0;
+  pool->ptr = 0;
+  pool->end = 0;
+}
+
+static
+void poolClear(STRING_POOL *pool)
+{
+  if (!pool->freeBlocks)
+    pool->freeBlocks = pool->blocks;
+  else {
+    BLOCK *p = pool->blocks;
+    while (p) {
+      BLOCK *tem = p->next;
+      p->next = pool->freeBlocks;
+      pool->freeBlocks = p;
+      p = tem;
+    }
+  }
+  pool->blocks = 0;
+  pool->start = 0;
+  pool->ptr = 0;
+  pool->end = 0;
+}
+
+static
+void poolDestroy(STRING_POOL *pool)
+{
+  BLOCK *p = pool->blocks;
+  while (p) {
+    BLOCK *tem = p->next;
+    free(p);
+    p = tem;
+  }
+  pool->blocks = 0;
+  p = pool->freeBlocks;
+  while (p) {
+    BLOCK *tem = p->next;
+    free(p);
+    p = tem;
+  }
+  pool->freeBlocks = 0;
+  pool->ptr = 0;
+  pool->start = 0;
+  pool->end = 0;
+}
+
+static
+const char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+                      const char *ptr, const char *end)
+{
+  for (;;) {
+    XmlConvert(enc, XML_UTF8_ENCODING, &ptr, end, &(pool->ptr), pool->end);
+    if (ptr == end)
+      break;
+    if (!poolGrow(pool))
+      return 0;
+  }
+  return pool->start;
+}
+
+
+static
+const char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+                           const char *ptr, const char *end)
+{
+  if (!poolAppend(pool, enc, ptr, end))
+    return 0;
+  if (pool->ptr == pool->end && !poolGrow(pool))
+    return 0;
+  *(pool->ptr)++ = 0;
+  return pool->start;
+}
+
+static
+int poolGrow(STRING_POOL *pool)
+{
+  if (pool->freeBlocks) {
+    if (pool->start == 0) {
+      pool->blocks = pool->freeBlocks;
+      pool->freeBlocks = pool->freeBlocks->next;
+      pool->blocks->next = 0;
+      pool->start = pool->blocks->s;
+      pool->end = pool->start + pool->blocks->size;
+      pool->ptr = pool->start;
+      return 1;
+    }
+    if (pool->end - pool->start < pool->freeBlocks->size) {
+      BLOCK *tem = pool->freeBlocks->next;
+      pool->freeBlocks->next = pool->blocks;
+      pool->blocks = pool->freeBlocks;
+      pool->freeBlocks = tem;
+      memcpy(pool->blocks->s, pool->start, pool->end - pool->start);
+      pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+      pool->start = pool->blocks->s;
+      pool->end = pool->start + pool->blocks->size;
+      return 1;
+    }
+  }
+  if (pool->blocks && pool->start == pool->blocks->s) {
+    size_t blockSize = (pool->end - pool->start)*2;
+    pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize);
+    if (!pool->blocks)
+      return 0;
+    pool->blocks->size = blockSize;
+    pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+    pool->start = pool->blocks->s;
+    pool->end = pool->start + blockSize;
+  }
+  else {
+    BLOCK *tem;
+    size_t blockSize = pool->end - pool->start;
+    if (blockSize < INIT_BLOCK_SIZE)
+      blockSize = INIT_BLOCK_SIZE;
+    else
+      blockSize *= 2;
+    tem = malloc(offsetof(BLOCK, s) + blockSize);
+    if (!tem)
+      return 0;
+    tem->size = blockSize;
+    tem->next = pool->blocks;
+    pool->blocks = tem;
+    memcpy(tem->s, pool->start, pool->ptr - pool->start);
+    pool->ptr = tem->s + (pool->ptr - pool->start);
+    pool->start = tem->s;
+    pool->end = tem->s + blockSize;
+  }
+  return 1;
+}
diff --git a/expat/xmlparse/xmlparse.h b/expat/xmlparse/xmlparse.h
new file mode 100755 (executable)
index 0000000..21cac7d
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef XmlParse_INCLUDED
+#define XmlParse_INCLUDED 1
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef XMLPARSEAPI
+#define XMLPARSEAPI /* as nothing */
+#endif
+
+typedef void *XML_Parser;
+
+/* Constructs a new parser; encoding should be the name of the charset from
+the Content-Type header if the Content-Type is text/xml, or null otherwise. */
+
+XML_Parser XMLPARSEAPI
+XML_ParserCreate(const char *encoding);
+
+/* Information is UTF-8 encoded. */
+
+/* atts is array of name/value pairs, terminated by NULL;
+   names and values are '\0' terminated. */
+
+typedef void (*XML_StartElementHandler)(void *userData,
+                                       const char *name,
+                                       const char **atts);
+
+typedef void (*XML_EndElementHandler)(void *userData,
+                                     const char *name);
+
+typedef void (*XML_CharacterDataHandler)(void *userData,
+                                        const char *s,
+                                        size_t len);
+
+/* target and data are '\0' terminated */
+typedef void (*XML_ProcessingInstructionHandler)(void *userData,
+                                                const char *target,
+                                                const char *data);
+
+void XMLPARSEAPI
+XML_SetElementHandler(XML_Parser parser,
+                     XML_StartElementHandler start,
+                     XML_EndElementHandler end);
+
+void XMLPARSEAPI
+XML_SetCharacterDataHandler(XML_Parser parser,
+                           XML_CharacterDataHandler handler);
+
+void XMLPARSEAPI
+XML_SetProcessingInstructionHandler(XML_Parser parser,
+                                   XML_ProcessingInstructionHandler handler);
+
+/* This value is passed as the userData argument to callbacks. */
+void XMLPARSEAPI
+XML_SetUserData(XML_Parser parser, void *userData);
+
+/* Parses some input. Returns 0 if a fatal error is detected.
+The last call to XML_Parse must have isFinal true;
+len may be zero for this call (or any other). */
+int XMLPARSEAPI
+XML_Parse(XML_Parser parser, const char *s, size_t len, int isFinal);
+
+void XMLPARSEAPI *
+XML_GetBuffer(XML_Parser parser, size_t len);
+
+int XMLPARSEAPI
+XML_ParseBuffer(XML_Parser parser, size_t len, int isFinal);
+
+/* If XML_Parser or XML_ParseEnd have returned 0, then XML_GetError*
+returns information about the error. */
+
+enum XML_Error {
+  XML_ERROR_NONE,
+  XML_ERROR_NO_MEMORY,
+  XML_ERROR_SYNTAX,
+  XML_ERROR_NO_ELEMENTS,
+  XML_ERROR_INVALID_TOKEN,
+  XML_ERROR_UNCLOSED_TOKEN,
+  XML_ERROR_PARTIAL_CHAR,
+  XML_ERROR_TAG_MISMATCH,
+  XML_ERROR_DUPLICATE_ATTRIBUTE,
+  XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
+  XML_ERROR_PARAM_ENTITY_REF,
+  XML_ERROR_UNDEFINED_ENTITY,
+  XML_ERROR_RECURSIVE_ENTITY_REF,
+  XML_ERROR_ASYNC_ENTITY,
+  XML_ERROR_BAD_CHAR_REF,
+  XML_ERROR_BINARY_ENTITY_REF,
+  XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
+  XML_ERROR_MISPLACED_XML_PI,
+  XML_ERROR_UNKNOWN_ENCODING,
+  XML_ERROR_INCORRECT_ENCODING
+};
+
+int XMLPARSEAPI XML_GetErrorCode(XML_Parser parser);
+int XMLPARSEAPI XML_GetErrorLineNumber(XML_Parser parser);
+int XMLPARSEAPI XML_GetErrorColumnNumber(XML_Parser parser);
+long XMLPARSEAPI XML_GetErrorByteIndex(XML_Parser parser);
+
+void XMLPARSEAPI
+XML_ParserFree(XML_Parser parser);
+
+const char XMLPARSEAPI *
+XML_ErrorString(int code);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlParse_INCLUDED */