home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / modules / xml / expat / xmlparse / xmlparse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  42.7 KB  |  1,612 lines

  1. /*
  2. The contents of this file are subject to the Mozilla Public License
  3. Version 1.0 (the "License"); you may not use this file except in
  4. compliance with the License. You may obtain a copy of the License at
  5. http://www.mozilla.org/MPL/
  6.  
  7. Software distributed under the License is distributed on an "AS IS"
  8. basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  9. License for the specific language governing rights and limitations
  10. under the License.
  11.  
  12. The Original Code is expat.
  13.  
  14. The Initial Developer of the Original Code is James Clark.
  15. Portions created by James Clark are Copyright (C) 1998
  16. James Clark. All Rights Reserved.
  17.  
  18. Contributor(s):
  19. */
  20.  
  21. #include "xmldef.h"
  22. #include "xmlparse.h"
  23. #include "xmltok.h"
  24. #include "xmlrole.h"
  25. #include "hashtable.h"
  26.  
  27. #include <stdlib.h>
  28. #include <string.h>
  29.  
  30. #define INIT_TAG_BUF_SIZE 32
  31. #define INIT_DATA_BUF_SIZE 1024
  32. #define INIT_ATTS_SIZE 16
  33. #define INIT_BLOCK_SIZE 1024
  34. #define INIT_BUFFER_SIZE 1024
  35.  
  36. typedef struct tag {
  37.   struct tag *parent;
  38.   const char *rawName;
  39.   int rawNameLength;
  40.   const char *name;
  41.   char *buf;
  42.   char *bufEnd;
  43. } TAG;
  44.  
  45. typedef struct {
  46.   const char *name;
  47.   const char *textPtr;
  48.   int textLen;
  49.   const char *systemId;
  50.   const char *publicId;
  51.   const char *notation;
  52.   char open;
  53.   char magic;
  54. } ENTITY;
  55.  
  56. typedef struct block {
  57.   struct block *next;
  58.   int size;
  59.   char s[1];
  60. } BLOCK;
  61.  
  62. typedef struct {
  63.   BLOCK *blocks;
  64.   BLOCK *freeBlocks;
  65.   const char *end;
  66.   char *ptr;
  67.   char *start;
  68. } STRING_POOL;
  69.  
  70. /* The byte before the name is a scratch byte used to determine whether
  71. an attribute has been specified. */
  72. typedef struct {
  73.   char *name;
  74.   char maybeTokenized;
  75. } ATTRIBUTE_ID;
  76.  
  77. typedef struct {
  78.   const ATTRIBUTE_ID *id;
  79.   char isCdata;
  80.   const char *value;
  81. } DEFAULT_ATTRIBUTE;
  82.  
  83. typedef struct {
  84.   const char *name;
  85.   int nDefaultAtts;
  86.   int allocDefaultAtts;
  87.   DEFAULT_ATTRIBUTE *defaultAtts;
  88. } ELEMENT_TYPE;
  89.  
  90. typedef struct {
  91.   HASH_TABLE generalEntities;
  92.   HASH_TABLE elementTypes;
  93.   HASH_TABLE attributeIds;
  94.   STRING_POOL pool;
  95.   int complete;
  96.   int standalone;
  97. } DTD;
  98.  
  99. typedef enum XML_Error Processor(XML_Parser parser,
  100.                  const char *start,
  101.                  const char *end,
  102.                  const char **endPtr);
  103.  
  104. static Processor prologProcessor;
  105. static Processor contentProcessor;
  106. static Processor epilogProcessor;
  107. static Processor errorProcessor;
  108.  
  109. static enum XML_Error
  110. doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
  111.       const char *start, const char *end, const char **endPtr);
  112. static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *tagName, const char *s);
  113. static int
  114. defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, const char *dfltValue);
  115. static enum XML_Error
  116. storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
  117.             STRING_POOL *);
  118. static enum XML_Error
  119. appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
  120.             STRING_POOL *);
  121. static ATTRIBUTE_ID *
  122. getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
  123. static enum XML_Error
  124. storeEntityValue(XML_Parser parser, const char *start, const char *end);
  125. static int
  126. reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
  127.  
  128. static int dtdInit(DTD *);
  129. static void dtdDestroy(DTD *);
  130. static void poolInit(STRING_POOL *);
  131. static void poolClear(STRING_POOL *);
  132. static void poolDestroy(STRING_POOL *);
  133. static char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
  134.             const char *ptr, const char *end);
  135. static char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
  136.                  const char *ptr, const char *end);
  137. static int poolGrow(STRING_POOL *pool);
  138.  
  139. #define poolStart(pool) ((pool)->start)
  140. #define poolEnd(pool) ((pool)->ptr)
  141. #define poolLength(pool) ((pool)->ptr - (pool)->start)
  142. #define poolChop(pool) ((void)--(pool->ptr))
  143. #define poolLastByte(pool) (((pool)->ptr)[-1])
  144. #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
  145. #define poolFinish(pool) ((pool)->start = (pool)->ptr)
  146. #define poolAppendByte(pool, c) \
  147.   (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
  148.    ? 0 \
  149.    : ((*((pool)->ptr)++ = c), 1))
  150.  
  151. typedef struct {
  152.   char *buffer;
  153.   /* first character to be parsed */
  154.   const char *bufferPtr;
  155.   /* past last character to be parsed */
  156.   char *bufferEnd;
  157.   /* allocated end of buffer */
  158.   const char *bufferLim;
  159.   long bufferEndByteIndex;
  160.   char *dataBuf;
  161.   char *dataBufEnd;
  162.   void *userData;
  163.   XML_StartElementHandler startElementHandler;
  164.   XML_EndElementHandler endElementHandler;
  165.   XML_CharacterDataHandler characterDataHandler;
  166.   XML_ProcessingInstructionHandler processingInstructionHandler;
  167.   const ENCODING *encoding;
  168.   INIT_ENCODING initEncoding;
  169.   PROLOG_STATE prologState;
  170.   Processor *processor;
  171.   enum XML_Error errorCode;
  172.   const char *errorPtr;
  173.   int tagLevel;
  174.   ENTITY *declEntity;
  175.   ELEMENT_TYPE *declElementType;
  176.   ATTRIBUTE_ID *declAttributeId;
  177.   char declAttributeIsCdata;
  178.   DTD dtd;
  179.   TAG *tagStack;
  180.   TAG *freeTagList;
  181.   int attsSize;
  182.   ATTRIBUTE *atts;
  183.   POSITION position;
  184.   long errorByteIndex;
  185.   STRING_POOL tempPool;
  186.   STRING_POOL temp2Pool;
  187.   char *groupConnector;
  188.   unsigned groupSize;
  189.   int hadExternalDoctype;
  190. } Parser;
  191.  
  192. #define userData (((Parser *)parser)->userData)
  193. #define startElementHandler (((Parser *)parser)->startElementHandler)
  194. #define endElementHandler (((Parser *)parser)->endElementHandler)
  195. #define characterDataHandler (((Parser *)parser)->characterDataHandler)
  196. #define processingInstructionHandler (((Parser *)parser)->processingInstructionHandler)
  197. #define encoding (((Parser *)parser)->encoding)
  198. #define initEncoding (((Parser *)parser)->initEncoding)
  199. #define prologState (((Parser *)parser)->prologState)
  200. #define processor (((Parser *)parser)->processor)
  201. #define errorCode (((Parser *)parser)->errorCode)
  202. #define errorPtr (((Parser *)parser)->errorPtr)
  203. #define errorByteIndex (((Parser *)parser)->errorByteIndex)
  204. #define position (((Parser *)parser)->position)
  205. #define tagLevel (((Parser *)parser)->tagLevel)
  206. #define buffer (((Parser *)parser)->buffer)
  207. #define bufferPtr (((Parser *)parser)->bufferPtr)
  208. #define bufferEnd (((Parser *)parser)->bufferEnd)
  209. #define bufferEndByteIndex (((Parser *)parser)->bufferEndByteIndex)
  210. #define bufferLim (((Parser *)parser)->bufferLim)
  211. #define dataBuf (((Parser *)parser)->dataBuf)
  212. #define dataBufEnd (((Parser *)parser)->dataBufEnd)
  213. #define dtd (((Parser *)parser)->dtd)
  214. #define declEntity (((Parser *)parser)->declEntity)
  215. #define declElementType (((Parser *)parser)->declElementType)
  216. #define declAttributeId (((Parser *)parser)->declAttributeId)
  217. #define declAttributeIsCdata (((Parser *)parser)->declAttributeIsCdata)
  218. #define freeTagList (((Parser *)parser)->freeTagList)
  219. #define tagStack (((Parser *)parser)->tagStack)
  220. #define atts (((Parser *)parser)->atts)
  221. #define attsSize (((Parser *)parser)->attsSize)
  222. #define tempPool (((Parser *)parser)->tempPool)
  223. #define temp2Pool (((Parser *)parser)->temp2Pool)
  224. #define groupConnector (((Parser *)parser)->groupConnector)
  225. #define groupSize (((Parser *)parser)->groupSize)
  226. #define hadExternalDoctype (((Parser *)parser)->hadExternalDoctype)
  227.  
  228. XML_Parser XML_ParserCreate(const char *encodingName)
  229. {
  230.   XML_Parser parser = malloc(sizeof(Parser));
  231.   if (!parser)
  232.     return parser;
  233.   processor = prologProcessor;
  234.   XmlPrologStateInit(&prologState);
  235.   userData = 0;
  236.   startElementHandler = 0;
  237.   endElementHandler = 0;
  238.   characterDataHandler = 0;
  239.   processingInstructionHandler = 0;
  240.   buffer = 0;
  241.   bufferPtr = 0;
  242.   bufferEnd = 0;
  243.   bufferEndByteIndex = 0;
  244.   bufferLim = 0;
  245.   declElementType = 0;
  246.   declAttributeId = 0;
  247.   declEntity = 0;
  248.   memset(&position, 0, sizeof(POSITION));
  249.   errorCode = XML_ERROR_NONE;
  250.   errorByteIndex = 0;
  251.   errorPtr = 0;
  252.   tagLevel = 0;
  253.   tagStack = 0;
  254.   freeTagList = 0;
  255.   attsSize = INIT_ATTS_SIZE;
  256.   atts = malloc(attsSize * sizeof(ATTRIBUTE));
  257.   dataBuf = malloc(INIT_DATA_BUF_SIZE);
  258.   groupSize = 0;
  259.   groupConnector = 0;
  260.   hadExternalDoctype = 0;
  261.   poolInit(&tempPool);
  262.   poolInit(&temp2Pool);
  263.   if (!dtdInit(&dtd) || !atts || !dataBuf) {
  264.     XML_ParserFree(parser);
  265.     return 0;
  266.   }
  267.   dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
  268.   if (!XmlInitEncoding(&initEncoding, &encoding, encodingName)) {
  269.     errorCode = XML_ERROR_UNKNOWN_ENCODING;
  270.     processor = errorProcessor;
  271.   }
  272.   return parser;
  273. }
  274.  
  275. void XML_ParserFree(XML_Parser parser)
  276. {
  277.   for (;;) {
  278.     TAG *p;
  279.     if (tagStack == 0) {
  280.       if (freeTagList == 0)
  281.     break;
  282.       tagStack = freeTagList;
  283.       freeTagList = 0;
  284.     }
  285.     p = tagStack;
  286.     tagStack = tagStack->parent;
  287.     free(p->buf);
  288.     free(p);
  289.   }
  290.   poolDestroy(&tempPool);
  291.   poolDestroy(&temp2Pool);
  292.   dtdDestroy(&dtd);
  293.   free((void *)atts);
  294.   free(groupConnector);
  295.   free(buffer);
  296.   free(dataBuf);
  297.   free(parser);
  298. }
  299.  
  300. void XML_SetUserData(XML_Parser parser, void *p)
  301. {
  302.   userData = p;
  303. }
  304.  
  305. void XML_SetElementHandler(XML_Parser parser,
  306.                XML_StartElementHandler start,
  307.                XML_EndElementHandler end)
  308. {
  309.   startElementHandler = start;
  310.   endElementHandler = end;
  311. }
  312.  
  313. void XML_SetCharacterDataHandler(XML_Parser parser,
  314.                  XML_CharacterDataHandler handler)
  315. {
  316.   characterDataHandler = handler;
  317. }
  318.  
  319. void XML_SetProcessingInstructionHandler(XML_Parser parser,
  320.                      XML_ProcessingInstructionHandler handler)
  321. {
  322.   processingInstructionHandler = handler;
  323. }
  324.  
  325. int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
  326. {
  327.   bufferEndByteIndex += len;
  328.   if (len == 0) {
  329.     if (!isFinal)
  330.       return 1;
  331.     errorCode = processor(parser, bufferPtr, bufferEnd, 0);
  332.     return errorCode == XML_ERROR_NONE;
  333.   }
  334.   else if (bufferPtr == bufferEnd) {
  335.     const char *end;
  336.     int nLeftOver;
  337.     if (isFinal) {
  338.       errorCode = processor(parser, s, s + len, 0);
  339.       if (errorCode == XML_ERROR_NONE)
  340.     return 1;
  341.       if (errorPtr) {
  342.     errorByteIndex = bufferEndByteIndex - (s + len - errorPtr);
  343.     XmlUpdatePosition(encoding, s, errorPtr, &position);
  344.       }
  345.       return 0;
  346.     }
  347.     errorCode = processor(parser, s, s + len, &end);
  348.     if (errorCode != XML_ERROR_NONE) {
  349.       if (errorPtr) {
  350.     errorByteIndex = bufferEndByteIndex - (s + len - errorPtr);
  351.     XmlUpdatePosition(encoding, s, errorPtr, &position);
  352.       }
  353.       return 0;
  354.     }
  355.     XmlUpdatePosition(encoding, s, end, &position);
  356.     nLeftOver = s + len - end;
  357.     if (nLeftOver) {
  358.       if (buffer == 0 || nLeftOver > bufferLim - buffer) {
  359.     /* FIXME avoid integer overflow */
  360.     buffer = realloc(buffer, len * 2);
  361.     if (!buffer) {
  362.       errorCode = XML_ERROR_NO_MEMORY;
  363.       return 0;
  364.     }
  365.     bufferLim = buffer + len * 2;
  366.       }
  367.       memcpy(buffer, end, nLeftOver);
  368.       bufferPtr = buffer;
  369.       bufferEnd = buffer + nLeftOver;
  370.     }
  371.     return 1;
  372.   }
  373.   else {
  374.     memcpy(XML_GetBuffer(parser, len), s, len);
  375.     return XML_ParseBuffer(parser, len, isFinal);
  376.   }
  377. }
  378.  
  379. int XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
  380. {
  381.   const char *start = bufferPtr;
  382.   bufferEnd += len;
  383.   errorCode = processor(parser, bufferPtr, bufferEnd,
  384.             isFinal ? (const char **)0 : &bufferPtr);
  385.   if (errorCode == XML_ERROR_NONE) {
  386.     if (!isFinal)
  387.       XmlUpdatePosition(encoding, start, bufferPtr, &position);
  388.     return 1;
  389.   }
  390.   else {
  391.     if (errorPtr) {
  392.       errorByteIndex = bufferEndByteIndex - (bufferEnd - errorPtr);
  393.       XmlUpdatePosition(encoding, start, errorPtr, &position);
  394.     }
  395.     return 0;
  396.   }
  397. }
  398.  
  399. void *XML_GetBuffer(XML_Parser parser, int len)
  400. {
  401.   if (len > bufferLim - bufferEnd) {
  402.     /* FIXME avoid integer overflow */
  403.     int neededSize = len + (bufferEnd - bufferPtr);
  404.     if (neededSize  <= bufferLim - buffer) {
  405.       memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
  406.       bufferEnd = buffer + (bufferEnd - bufferPtr);
  407.       bufferPtr = buffer;
  408.     }
  409.     else {
  410.       char *newBuf;
  411.       int bufferSize = bufferLim - bufferPtr;
  412.       if (bufferSize == 0)
  413.     bufferSize = INIT_BUFFER_SIZE;
  414.       do {
  415.     bufferSize *= 2;
  416.       } while (bufferSize < neededSize);
  417.       newBuf = malloc(bufferSize);
  418.       if (newBuf == 0) {
  419.     errorCode = XML_ERROR_NO_MEMORY;
  420.     return 0;
  421.       }
  422.       bufferLim = newBuf + bufferSize;
  423.       if (bufferPtr) {
  424.     memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
  425.     free(buffer);
  426.       }
  427.       bufferEnd = newBuf + (bufferEnd - bufferPtr);
  428.       bufferPtr = buffer = newBuf;
  429.     }
  430.   }
  431.   return bufferEnd;
  432. }
  433.  
  434. int XML_GetErrorCode(XML_Parser parser)
  435. {
  436.   return errorCode;
  437. }
  438.  
  439. int XML_GetErrorLineNumber(XML_Parser parser)
  440. {
  441.   return position.lineNumber + 1;
  442. }
  443.  
  444. int XML_GetErrorColumnNumber(XML_Parser parser)
  445. {
  446.   return position.columnNumber;
  447. }
  448.  
  449. long XML_GetErrorByteIndex(XML_Parser parser)
  450. {
  451.   return errorByteIndex;
  452. }
  453.  
  454. const char *XML_ErrorString(int code)
  455. {
  456.   static const char *message[] = {
  457.     0,
  458.     "out of memory",
  459.     "syntax error",
  460.     "no element found",
  461.     "not well-formed",
  462.     "unclosed token",
  463.     "unclosed token",
  464.     "mismatched tag",
  465.     "duplicate attribute",
  466.     "junk after document element",
  467.     "parameter entity reference not allowed within declaration in internal subset",
  468.     "undefined entity",
  469.     "recursive entity reference",
  470.     "asynchronous entity",
  471.     "reference to invalid character number",
  472.     "reference to binary entity",
  473.     "reference to external entity in attribute",
  474.     "xml processing instruction not at start of external entity",
  475.     "unknown encoding",
  476.     "encoding specified in XML declaration is incorrect"
  477.   };
  478.   if (code > 0 && code < sizeof(message)/sizeof(message[0]))
  479.     return message[code];
  480.   return 0;
  481. }
  482.  
  483. static
  484. enum XML_Error contentProcessor(XML_Parser parser,
  485.                 const char *start,
  486.                 const char *end,
  487.                 const char **endPtr)
  488. {
  489.   return doContent(parser, 0, encoding, start, end, endPtr);
  490. }
  491.  
  492. static enum XML_Error
  493. doContent(XML_Parser parser,
  494.       int startTagLevel,
  495.       const ENCODING *enc,
  496.       const char *s,
  497.       const char *end,
  498.       const char **nextPtr)
  499. {
  500.   const ENCODING *utf8 = XmlGetInternalEncoding(XML_UTF8_ENCODING);
  501.   for (;;) {
  502.     const char *next;
  503.     int tok = XmlContentTok(enc, s, end, &next);
  504.     switch (tok) {
  505.     case XML_TOK_TRAILING_CR:
  506.     case XML_TOK_NONE:
  507.       if (nextPtr) {
  508.     *nextPtr = s;
  509.     return XML_ERROR_NONE;
  510.       }
  511.       if (startTagLevel > 0) {
  512.     if (tagLevel != startTagLevel) {
  513.       errorPtr = s;
  514.       return XML_ERROR_ASYNC_ENTITY;
  515.         }
  516.     return XML_ERROR_NONE;
  517.       }
  518.       errorPtr = s;
  519.       return XML_ERROR_NO_ELEMENTS;
  520.     case XML_TOK_INVALID:
  521.       errorPtr = next;
  522.       return XML_ERROR_INVALID_TOKEN;
  523.     case XML_TOK_PARTIAL:
  524.       if (nextPtr) {
  525.     *nextPtr = s;
  526.     return XML_ERROR_NONE;
  527.       }
  528.       errorPtr = s;
  529.       return XML_ERROR_UNCLOSED_TOKEN;
  530.     case XML_TOK_PARTIAL_CHAR:
  531.       if (nextPtr) {
  532.     *nextPtr = s;
  533.     return XML_ERROR_NONE;
  534.       }
  535.       errorPtr = s;
  536.       return XML_ERROR_PARTIAL_CHAR;
  537.     case XML_TOK_ENTITY_REF:
  538.       {
  539.     const char *name = poolStoreString(&dtd.pool, enc,
  540.                        s + enc->minBytesPerChar,
  541.                        next - enc->minBytesPerChar);
  542.     ENTITY *entity;
  543.     if (!name)
  544.       return XML_ERROR_NO_MEMORY;
  545.     entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
  546.     poolDiscard(&dtd.pool);
  547.     if (!entity) {
  548.       if (dtd.complete || dtd.standalone) {
  549.         errorPtr = s;
  550.         return XML_ERROR_UNDEFINED_ENTITY;
  551.       }
  552.       break;
  553.     }
  554.     if (entity->magic) {
  555.       if (characterDataHandler)
  556.         characterDataHandler(userData, entity->textPtr, entity->textLen);
  557.       break;
  558.     }
  559.     if (entity->open) {
  560.       errorPtr = s;
  561.       return XML_ERROR_RECURSIVE_ENTITY_REF;
  562.     }
  563.     if (entity->notation) {
  564.       errorPtr = s;
  565.       return XML_ERROR_BINARY_ENTITY_REF;
  566.     }
  567.     if (entity) {
  568.       if (entity->textPtr) {
  569.         enum XML_Error result;
  570.         entity->open = 1;
  571.         result = doContent(parser,
  572.                    tagLevel,
  573.                    utf8,
  574.                    entity->textPtr,
  575.                    entity->textPtr + entity->textLen,
  576.                    0);
  577.         entity->open = 0;
  578.         if (result) {
  579.           errorPtr = s;
  580.           return result;
  581.         }
  582.       }
  583.     }
  584.     break;
  585.       }
  586.     case XML_TOK_START_TAG_WITH_ATTS:
  587.       if (!startElementHandler) {
  588.     enum XML_Error result = storeAtts(parser, enc, 0, s);
  589.     if (result)
  590.       return result;
  591.       }
  592.       /* fall through */
  593.     case XML_TOK_START_TAG_NO_ATTS:
  594.       {
  595.     TAG *tag;
  596.     if (freeTagList) {
  597.       tag = freeTagList;
  598.       freeTagList = freeTagList->parent;
  599.     }
  600.     else {
  601.       tag = malloc(sizeof(TAG));
  602.       if (!tag)
  603.         return XML_ERROR_NO_MEMORY;
  604.       tag->buf = malloc(INIT_TAG_BUF_SIZE);
  605.       if (!tag->buf)
  606.         return XML_ERROR_NO_MEMORY;
  607.       tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
  608.     }
  609.     tag->parent = tagStack;
  610.     tagStack = tag;
  611.     tag->rawName = s + enc->minBytesPerChar;
  612.     tag->rawNameLength = XmlNameLength(enc, tag->rawName);
  613.     if (nextPtr) {
  614.       if (tag->rawNameLength > tag->bufEnd - tag->buf) {
  615.         int bufSize = tag->rawNameLength * 4;
  616.         tag->buf = realloc(tag->buf, bufSize);
  617.         if (!tag->buf)
  618.           return XML_ERROR_NO_MEMORY;
  619.         tag->bufEnd = tag->buf + bufSize;
  620.       }
  621.       memcpy(tag->buf, tag->rawName, tag->rawNameLength);
  622.       tag->rawName = tag->buf;
  623.     }
  624.     ++tagLevel;
  625.     if (startElementHandler) {
  626.       enum XML_Error result;
  627.       char *toPtr;
  628.       const char *rawNameEnd = tag->rawName + tag->rawNameLength;
  629.       for (;;) {
  630.         const char *fromPtr = tag->rawName;
  631.         int bufSize;
  632.         toPtr = tag->buf;
  633.         if (nextPtr)
  634.           toPtr += tag->rawNameLength;
  635.         tag->name = toPtr;
  636.         XmlConvert(enc, XML_UTF8_ENCODING,
  637.                &fromPtr, rawNameEnd,
  638.                    &toPtr, tag->bufEnd - 1);
  639.         if (fromPtr == rawNameEnd)
  640.           break;
  641.         bufSize = (tag->bufEnd - tag->buf) << 1;
  642.         tag->buf = realloc(tag->buf, bufSize);
  643.         if (!tag->buf)
  644.           return XML_ERROR_NO_MEMORY;
  645.         tag->bufEnd = tag->buf + bufSize;
  646.       }
  647.       *toPtr = 0;
  648.       result = storeAtts(parser, enc, tag->name, s);
  649.       if (result)
  650.         return result;
  651.       startElementHandler(userData, tag->name, (const char **)atts);
  652.       poolClear(&tempPool);
  653.     }
  654.     else
  655.       tag->name = 0;
  656.     break;
  657.       }
  658.     case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
  659.       if (!startElementHandler) {
  660.     enum XML_Error result = storeAtts(parser, enc, 0, s);
  661.     if (result)
  662.       return result;
  663.       }
  664.       /* fall through */
  665.     case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
  666.       if (startElementHandler || endElementHandler) {
  667.     const char *rawName = s + enc->minBytesPerChar;
  668.     const char *name = poolStoreString(&tempPool, enc, rawName,
  669.                        rawName
  670.                        + XmlNameLength(enc, rawName));
  671.     if (!name)
  672.       return XML_ERROR_NO_MEMORY;
  673.     poolFinish(&tempPool);
  674.     if (startElementHandler) {
  675.       enum XML_Error result = storeAtts(parser, enc, name, s);
  676.       if (result)
  677.         return result;
  678.       startElementHandler(userData, name, (const char **)atts);
  679.     }
  680.     if (endElementHandler)
  681.       endElementHandler(userData, name);
  682.     poolClear(&tempPool);
  683.       }
  684.       if (tagLevel == 0)
  685.     return epilogProcessor(parser, next, end, nextPtr);
  686.       break;
  687.     case XML_TOK_END_TAG:
  688.       if (tagLevel == startTagLevel) {
  689.         errorPtr = s;
  690.         return XML_ERROR_ASYNC_ENTITY;
  691.       }
  692.       else {
  693.     int len;
  694.     const char *rawName;
  695.     TAG *tag = tagStack;
  696.     tagStack = tag->parent;
  697.     tag->parent = freeTagList;
  698.     freeTagList = tag;
  699.     rawName = s + enc->minBytesPerChar*2;
  700.     len = XmlNameLength(enc, rawName);
  701.     if (len != tag->rawNameLength
  702.         || memcmp(tag->rawName, rawName, len) != 0) {
  703.       errorPtr = rawName;
  704.       return XML_ERROR_TAG_MISMATCH;
  705.     }
  706.     --tagLevel;
  707.     if (endElementHandler) {
  708.       if (tag->name)
  709.         endElementHandler(userData, tag->name);
  710.       else {
  711.         const char *name = poolStoreString(&tempPool, enc, rawName,
  712.                                            rawName + len);
  713.         if (!name)
  714.         return XML_ERROR_NO_MEMORY;
  715.         endElementHandler(userData, name);
  716.         poolClear(&tempPool);
  717.       }
  718.     }
  719.     if (tagLevel == 0)
  720.       return epilogProcessor(parser, next, end, nextPtr);
  721.       }
  722.       break;
  723.     case XML_TOK_CHAR_REF:
  724.       {
  725.     int n = XmlCharRefNumber(enc, s);
  726.     if (n < 0) {
  727.       errorPtr = s;
  728.       return XML_ERROR_BAD_CHAR_REF;
  729.     }
  730.     if (characterDataHandler) {
  731.       char buf[XML_MAX_BYTES_PER_CHAR];
  732.       characterDataHandler(userData, buf, XmlEncode(utf8, n, buf));
  733.     }
  734.       }
  735.       break;
  736.     case XML_TOK_XML_DECL:
  737.       errorPtr = s;
  738.       return XML_ERROR_MISPLACED_XML_PI;
  739.     case XML_TOK_DATA_NEWLINE:
  740.       if (characterDataHandler) {
  741.     char c = '\n';
  742.     characterDataHandler(userData, &c, 1);
  743.       }
  744.       break;
  745.     case XML_TOK_CDATA_SECTION:
  746.       if (characterDataHandler) {
  747.     const char *lim = next - enc->minBytesPerChar * 3;
  748.     s += enc->minBytesPerChar * 9;
  749.     do {
  750.       char *dataPtr = dataBuf;
  751.       XmlConvert(enc, XML_UTF8_ENCODING, &s, lim, &dataPtr, dataBufEnd);
  752.       characterDataHandler(userData, dataBuf, dataPtr - dataBuf);
  753.     } while (s != lim);
  754.       }
  755.       break;
  756.     case XML_TOK_DATA_CHARS:
  757.       if (characterDataHandler) {
  758.     do {
  759.       char *dataPtr = dataBuf;
  760.       XmlConvert(enc, XML_UTF8_ENCODING, &s, next, &dataPtr, dataBufEnd);
  761.       characterDataHandler(userData, dataBuf, dataPtr - dataBuf);
  762.     } while (s != next);
  763.       }
  764.       break;
  765.     case XML_TOK_PI:
  766.       if (!reportProcessingInstruction(parser, enc, s, next))
  767.     return XML_ERROR_NO_MEMORY;
  768.       break;
  769.     }
  770.     s = next;
  771.   }
  772.   /* not reached */
  773. }
  774.  
  775. /* If tagName is non-null, build a real list of attributes,
  776. otherwise just check the attributes for well-formedness. */
  777.  
  778. static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
  779.                 const char *tagName, const char *s)
  780. {
  781.   ELEMENT_TYPE *elementType = 0;
  782.   int nDefaultAtts = 0;
  783.   const char **appAtts = (const char **)atts;
  784.   int i;
  785.   int n;
  786.  
  787.   if (tagName) {
  788.     elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagName, 0);
  789.     if (elementType)
  790.       nDefaultAtts = elementType->nDefaultAtts;
  791.   }
  792.   
  793.   n = XmlGetAttributes(enc, s, attsSize, atts);
  794.   if (n + nDefaultAtts > attsSize) {
  795.     attsSize = 2*n;
  796.     atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE));
  797.     if (!atts)
  798.       return XML_ERROR_NO_MEMORY;
  799.     if (n > attsSize)
  800.       XmlGetAttributes(enc, s, n, atts);
  801.   }
  802.   for (i = 0; i < n; i++) {
  803.     ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
  804.                       atts[i].name
  805.                       + XmlNameLength(enc, atts[i].name));
  806.     if (!attId)
  807.       return XML_ERROR_NO_MEMORY;
  808.     if ((attId->name)[-1]) {
  809.       errorPtr = atts[i].name;
  810.       return XML_ERROR_DUPLICATE_ATTRIBUTE;
  811.     }
  812.     (attId->name)[-1] = 1;
  813.     appAtts[i << 1] = attId->name;
  814.     if (!atts[i].normalized) {
  815.       enum XML_Error result;
  816.       int isCdata = 1;
  817.  
  818.       if (attId->maybeTokenized) {
  819.     int j;
  820.     for (j = 0; j < nDefaultAtts; j++) {
  821.       if (attId == elementType->defaultAtts[j].id) {
  822.         isCdata = elementType->defaultAtts[j].isCdata;
  823.         break;
  824.       }
  825.     }
  826.       }
  827.  
  828.       result = storeAttributeValue(parser, enc, isCdata,
  829.                    atts[i].valuePtr, atts[i].valueEnd,
  830.                        &tempPool);
  831.       if (result)
  832.     return result;
  833.       if (tagName) {
  834.     appAtts[(i << 1) + 1] = poolStart(&tempPool);
  835.     poolFinish(&tempPool);
  836.       }
  837.       else
  838.     poolDiscard(&tempPool);
  839.     }
  840.     else if (tagName) {
  841.       appAtts[(i << 1) + 1] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
  842.       if (appAtts[(i << 1) + 1] == 0)
  843.     return XML_ERROR_NO_MEMORY;
  844.       poolFinish(&tempPool);
  845.     }
  846.   }
  847.   if (tagName) {
  848.     int j;
  849.     for (j = 0; j < nDefaultAtts; j++) {
  850.       const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j;
  851.       if (!(da->id->name)[-1] && da->value) {
  852.     (da->id->name)[-1] = 1;
  853.     appAtts[i << 1] = da->id->name;
  854.     appAtts[(i << 1) + 1] = da->value;
  855.     i++;
  856.       }
  857.     }
  858.     appAtts[i << 1] = 0;
  859.   }
  860.   while (i-- > 0)
  861.     ((char *)appAtts[i << 1])[-1] = 0;
  862.   return XML_ERROR_NONE;
  863. }
  864.  
  865. static enum XML_Error
  866. prologProcessor(XML_Parser parser,
  867.         const char *s,
  868.         const char *end,
  869.         const char **nextPtr)
  870. {
  871.   for (;;) {
  872.     const char *next;
  873.     int tok = XmlPrologTok(encoding, s, end, &next);
  874.     if (tok <= 0) {
  875.       if (nextPtr != 0 && tok != XML_TOK_INVALID) {
  876.     *nextPtr = s;
  877.     return XML_ERROR_NONE;
  878.       }
  879.       switch (tok) {
  880.       case XML_TOK_INVALID:
  881.     errorPtr = next;
  882.     return XML_ERROR_INVALID_TOKEN;
  883.       case XML_TOK_NONE:
  884.     return XML_ERROR_NO_ELEMENTS;
  885.       case XML_TOK_PARTIAL:
  886.     return XML_ERROR_UNCLOSED_TOKEN;
  887.       case XML_TOK_PARTIAL_CHAR:
  888.     return XML_ERROR_PARTIAL_CHAR;
  889.       case XML_TOK_TRAILING_CR:
  890.     errorPtr = s + encoding->minBytesPerChar;
  891.     return XML_ERROR_NO_ELEMENTS;
  892.       default:
  893.     abort();
  894.       }
  895.     }
  896.     switch (XmlTokenRole(&prologState, tok, s, next, encoding)) {
  897.     case XML_ROLE_XML_DECL:
  898.       {
  899.     const char *encodingName = 0;
  900.     const ENCODING *newEncoding = 0;
  901.     const char *version;
  902.     int standalone = -1;
  903.     if (!XmlParseXmlDecl(0,
  904.                  encoding,
  905.                  s,
  906.                  next,
  907.                  &errorPtr,
  908.                  &version,
  909.                  &encodingName,
  910.                  &newEncoding,
  911.                  &standalone))
  912.       return XML_ERROR_SYNTAX;
  913.     if (newEncoding) {
  914.       if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
  915.         errorPtr = encodingName;
  916.         return XML_ERROR_INCORRECT_ENCODING;
  917.       }
  918.       encoding = newEncoding;
  919.     }
  920.     else if (encodingName) {
  921.       errorPtr = encodingName;
  922.       return XML_ERROR_UNKNOWN_ENCODING;
  923.     }
  924.     if (standalone == 1)
  925.       dtd.standalone = 1;
  926.     break;
  927.       }
  928.     case XML_ROLE_DOCTYPE_SYSTEM_ID:
  929.       hadExternalDoctype = 1;
  930.       break;
  931.     case XML_ROLE_DOCTYPE_PUBLIC_ID:
  932.     case XML_ROLE_ENTITY_PUBLIC_ID:
  933.     case XML_ROLE_NOTATION_PUBLIC_ID:
  934.       if (!XmlIsPublicId(encoding, s, next, &errorPtr))
  935.     return XML_ERROR_SYNTAX;
  936.       break;
  937.     case XML_ROLE_INSTANCE_START:
  938.       processor = contentProcessor;
  939.       if (hadExternalDoctype)
  940.     dtd.complete = 0;
  941.       return contentProcessor(parser, s, end, nextPtr);
  942.     case XML_ROLE_ATTLIST_ELEMENT_NAME:
  943.       {
  944.     const char *name = poolStoreString(&dtd.pool, encoding, s, next);
  945.     if (!name)
  946.       return XML_ERROR_NO_MEMORY;
  947.     declElementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
  948.     if (!declElementType)
  949.       return XML_ERROR_NO_MEMORY;
  950.     if (declElementType->name != name)
  951.       poolDiscard(&dtd.pool);
  952.     else
  953.       poolFinish(&dtd.pool);
  954.     break;
  955.       }
  956.     case XML_ROLE_ATTRIBUTE_NAME:
  957.       declAttributeId = getAttributeId(parser, encoding, s, next);
  958.       if (!declAttributeId)
  959.     return XML_ERROR_NO_MEMORY;
  960.       declAttributeIsCdata = 0;
  961.       break;
  962.     case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
  963.       declAttributeIsCdata = 1;
  964.       break;
  965.     case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
  966.     case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
  967.       if (dtd.complete
  968.       && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0))
  969.     return XML_ERROR_NO_MEMORY;
  970.       break;
  971.     case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
  972.     case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
  973.       {
  974.     const char *attVal;
  975.     enum XML_Error result
  976.       = storeAttributeValue(parser, encoding, declAttributeIsCdata,
  977.                 s + encoding->minBytesPerChar,
  978.                     next - encoding->minBytesPerChar,
  979.                     &dtd.pool);
  980.     if (result)
  981.       return result;
  982.     attVal = poolStart(&dtd.pool);
  983.     poolFinish(&dtd.pool);
  984.     if (dtd.complete
  985.         && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, attVal))
  986.       return XML_ERROR_NO_MEMORY;
  987.     break;
  988.       }
  989.     case XML_ROLE_ENTITY_VALUE:
  990.       {
  991.     enum XML_Error result = storeEntityValue(parser, s, next);
  992.     if (result != XML_ERROR_NONE)
  993.       return result;
  994.       }
  995.       break;
  996.     case XML_ROLE_ENTITY_SYSTEM_ID:
  997.       if (declEntity) {
  998.     declEntity->systemId = poolStoreString(&dtd.pool, encoding,
  999.                                            s + encoding->minBytesPerChar,
  1000.                              next - encoding->minBytesPerChar);
  1001.     if (!declEntity->systemId)
  1002.       return XML_ERROR_NO_MEMORY;
  1003.     poolFinish(&dtd.pool);
  1004.       }
  1005.       break;
  1006.     case XML_ROLE_ENTITY_NOTATION_NAME:
  1007.       if (declEntity) {
  1008.     declEntity->notation = poolStoreString(&dtd.pool, encoding, s, next);
  1009.     if (!declEntity->notation)
  1010.       return XML_ERROR_NO_MEMORY;
  1011.     poolFinish(&dtd.pool);
  1012.       }
  1013.       break;
  1014.     case XML_ROLE_GENERAL_ENTITY_NAME:
  1015.       {
  1016.     const char *name = poolStoreString(&dtd.pool, encoding, s, next);
  1017.     if (!name)
  1018.       return XML_ERROR_NO_MEMORY;
  1019.     if (dtd.complete) {
  1020.       declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY));
  1021.       if (!declEntity)
  1022.         return XML_ERROR_NO_MEMORY;
  1023.       if (declEntity->name != name) {
  1024.         poolDiscard(&dtd.pool);
  1025.         declEntity = 0;
  1026.       }
  1027.       else
  1028.         poolFinish(&dtd.pool);
  1029.     }
  1030.     else {
  1031.       poolDiscard(&dtd.pool);
  1032.       declEntity = 0;
  1033.     }
  1034.       }
  1035.       break;
  1036.     case XML_ROLE_PARAM_ENTITY_NAME:
  1037.       declEntity = 0;
  1038.       break;
  1039.     case XML_ROLE_ERROR:
  1040.       errorPtr = s;
  1041.       switch (tok) {
  1042.       case XML_TOK_PARAM_ENTITY_REF:
  1043.     return XML_ERROR_PARAM_ENTITY_REF;
  1044.       case XML_TOK_XML_DECL:
  1045.     return XML_ERROR_MISPLACED_XML_PI;
  1046.       default:
  1047.     return XML_ERROR_SYNTAX;
  1048.       }
  1049.     case XML_ROLE_GROUP_OPEN:
  1050.       if (prologState.level >= groupSize) {
  1051.     if (groupSize)
  1052.       groupConnector = realloc(groupConnector, groupSize *= 2);
  1053.     else
  1054.       groupConnector = malloc(groupSize = 32);
  1055.     if (!groupConnector)
  1056.       return XML_ERROR_NO_MEMORY;
  1057.       }
  1058.       groupConnector[prologState.level] = 0;
  1059.       break;
  1060.     case XML_ROLE_GROUP_SEQUENCE:
  1061.       if (groupConnector[prologState.level] == '|') {
  1062.     errorPtr = s;
  1063.     return XML_ERROR_SYNTAX;
  1064.       }
  1065.       groupConnector[prologState.level] = ',';
  1066.       break;
  1067.     case XML_ROLE_GROUP_CHOICE:
  1068.       if (groupConnector[prologState.level] == ',') {
  1069.     errorPtr = s;
  1070.     return XML_ERROR_SYNTAX;
  1071.       }
  1072.       groupConnector[prologState.level] = '|';
  1073.       break;
  1074.     case XML_ROLE_PARAM_ENTITY_REF:
  1075.       dtd.complete = 0;
  1076.       break;
  1077.     case XML_ROLE_NONE:
  1078.       switch (tok) {
  1079.       case XML_TOK_PI:
  1080.     if (!reportProcessingInstruction(parser, encoding, s, next))
  1081.       return XML_ERROR_NO_MEMORY;
  1082.     break;
  1083.       }
  1084.       break;
  1085.     }
  1086.     s = next;
  1087.   }
  1088.   /* not reached */
  1089. }
  1090.  
  1091. static
  1092. enum XML_Error epilogProcessor(XML_Parser parser,
  1093.                    const char *s,
  1094.                    const char *end,
  1095.                    const char **nextPtr)
  1096. {
  1097.   processor = epilogProcessor;
  1098.   for (;;) {
  1099.     const char *next;
  1100.     int tok = XmlPrologTok(encoding, s, end, &next);
  1101.     switch (tok) {
  1102.     case XML_TOK_TRAILING_CR:
  1103.     case XML_TOK_NONE:
  1104.       if (nextPtr)
  1105.     *nextPtr = end;
  1106.       return XML_ERROR_NONE;
  1107.     case XML_TOK_PROLOG_S:
  1108.     case XML_TOK_COMMENT:
  1109.       break;
  1110.     case XML_TOK_PI:
  1111.       if (!reportProcessingInstruction(parser, encoding, s, next))
  1112.     return XML_ERROR_NO_MEMORY;
  1113.       break;
  1114.     case XML_TOK_INVALID:
  1115.       errorPtr = next;
  1116.       return XML_ERROR_INVALID_TOKEN;
  1117.     case XML_TOK_PARTIAL:
  1118.       if (nextPtr) {
  1119.     *nextPtr = s;
  1120.     return XML_ERROR_NONE;
  1121.       }
  1122.       errorPtr = s;
  1123.       return XML_ERROR_UNCLOSED_TOKEN;
  1124.     case XML_TOK_PARTIAL_CHAR:
  1125.       if (nextPtr) {
  1126.     *nextPtr = s;
  1127.     return XML_ERROR_NONE;
  1128.       }
  1129.       errorPtr = s;
  1130.       return XML_ERROR_PARTIAL_CHAR;
  1131.     default:
  1132.       errorPtr = s;
  1133.       return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
  1134.     }
  1135.     s = next;
  1136.   }
  1137. }
  1138.  
  1139. static
  1140. enum XML_Error errorProcessor(XML_Parser parser,
  1141.                   const char *s,
  1142.                   const char *end,
  1143.                   const char **nextPtr)
  1144. {
  1145.   return errorCode;
  1146. }
  1147.  
  1148. static enum XML_Error
  1149. storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
  1150.             const char *ptr, const char *end,
  1151.             STRING_POOL *pool)
  1152. {
  1153.   enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
  1154.   if (result)
  1155.     return result;
  1156.   if (!isCdata && poolLength(pool) && poolLastByte(pool) == ' ')
  1157.     poolChop(pool);
  1158.   if (!poolAppendByte(pool, 0))
  1159.     return XML_ERROR_NO_MEMORY;
  1160.   return XML_ERROR_NONE;
  1161. }
  1162.  
  1163. static enum XML_Error
  1164. appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
  1165.              const char *ptr, const char *end,
  1166.              STRING_POOL *pool)
  1167. {
  1168.   const ENCODING *utf8 = XmlGetInternalEncoding(XML_UTF8_ENCODING);
  1169.   for (;;) {
  1170.     const char *next;
  1171.     int tok = XmlAttributeValueTok(enc, ptr, end, &next);
  1172.     switch (tok) {
  1173.     case XML_TOK_NONE:
  1174.       return XML_ERROR_NONE;
  1175.     case XML_TOK_INVALID:
  1176.       errorPtr = next;
  1177.       return XML_ERROR_INVALID_TOKEN;
  1178.     case XML_TOK_PARTIAL:
  1179.       errorPtr = ptr;
  1180.       return XML_ERROR_INVALID_TOKEN;
  1181.     case XML_TOK_CHAR_REF:
  1182.       {
  1183.     char buf[XML_MAX_BYTES_PER_CHAR];
  1184.     int i;
  1185.     int n = XmlCharRefNumber(enc, ptr);
  1186.     if (n < 0) {
  1187.       errorPtr = ptr;
  1188.             return XML_ERROR_BAD_CHAR_REF;
  1189.     }
  1190.     if (!isCdata
  1191.         && n == ' '
  1192.         && (poolLength(pool) == 0 || poolLastByte(pool) == ' '))
  1193.       break;
  1194.     n = XmlEncode(utf8, n, buf);
  1195.     if (!n) {
  1196.       errorPtr = ptr;
  1197.       return XML_ERROR_BAD_CHAR_REF;
  1198.     }
  1199.     for (i = 0; i < n; i++) {
  1200.       if (!poolAppendByte(pool, buf[i]))
  1201.         return XML_ERROR_NO_MEMORY;
  1202.     }
  1203.       }
  1204.       break;
  1205.     case XML_TOK_DATA_CHARS:
  1206.       if (!poolAppend(pool, enc, ptr, next))
  1207.     return XML_ERROR_NO_MEMORY;
  1208.       break;
  1209.       break;
  1210.     case XML_TOK_TRAILING_CR:
  1211.       next = ptr + enc->minBytesPerChar;
  1212.       /* fall through */
  1213.     case XML_TOK_ATTRIBUTE_VALUE_S:
  1214.     case XML_TOK_DATA_NEWLINE:
  1215.       if (!isCdata && (poolLength(pool) == 0 || poolLastByte(pool) == ' '))
  1216.     break;
  1217.       if (!poolAppendByte(pool, ' '))
  1218.     return XML_ERROR_NO_MEMORY;
  1219.       break;
  1220.     case XML_TOK_ENTITY_REF:
  1221.       {
  1222.     const char *name = poolStoreString(&temp2Pool, enc,
  1223.                        ptr + enc->minBytesPerChar,
  1224.                        next - enc->minBytesPerChar);
  1225.     ENTITY *entity;
  1226.     if (!name)
  1227.       return XML_ERROR_NO_MEMORY;
  1228.     entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
  1229.     poolDiscard(&temp2Pool);
  1230.     if (!entity) {
  1231.       if (dtd.complete) {
  1232.         errorPtr = ptr;
  1233.         return XML_ERROR_UNDEFINED_ENTITY;
  1234.       }
  1235.     }
  1236.     else if (entity->open) {
  1237.       errorPtr = ptr;
  1238.       return XML_ERROR_RECURSIVE_ENTITY_REF;
  1239.     }
  1240.     else if (entity->notation) {
  1241.       errorPtr = ptr;
  1242.       return XML_ERROR_BINARY_ENTITY_REF;
  1243.     }
  1244.     else if (entity->magic) {
  1245.       int i;
  1246.       for (i = 0; i < entity->textLen; i++)
  1247.         if (!poolAppendByte(pool, entity->textPtr[i]))
  1248.           return XML_ERROR_NO_MEMORY;
  1249.     }
  1250.     else if (!entity->textPtr) {
  1251.       errorPtr = ptr;
  1252.         return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
  1253.     }
  1254.     else {
  1255.       enum XML_Error result;
  1256.       const char *textEnd = entity->textPtr + entity->textLen;
  1257.       entity->open = 1;
  1258.       result = appendAttributeValue(parser, utf8, isCdata, entity->textPtr, textEnd, pool);
  1259.       entity->open = 0;
  1260.       if (result) {
  1261.         errorPtr = ptr;
  1262.         return result;
  1263.       }
  1264.     }
  1265.       }
  1266.       break;
  1267.     default:
  1268.       abort();
  1269.     }
  1270.     ptr = next;
  1271.   }
  1272.   /* not reached */
  1273. }
  1274.  
  1275. static
  1276. enum XML_Error storeEntityValue(XML_Parser parser,
  1277.                 const char *entityTextPtr,
  1278.                 const char *entityTextEnd)
  1279. {
  1280.   const ENCODING *utf8 = XmlGetInternalEncoding(XML_UTF8_ENCODING);
  1281.   STRING_POOL *pool = &(dtd.pool);
  1282.   entityTextPtr += encoding->minBytesPerChar;
  1283.   entityTextEnd -= encoding->minBytesPerChar;
  1284.   for (;;) {
  1285.     const char *next;
  1286.     int tok = XmlEntityValueTok(encoding, entityTextPtr, entityTextEnd, &next);
  1287.     switch (tok) {
  1288.     case XML_TOK_PARAM_ENTITY_REF:
  1289.       errorPtr = entityTextPtr;
  1290.       return XML_ERROR_SYNTAX;
  1291.     case XML_TOK_NONE:
  1292.       if (declEntity) {
  1293.     declEntity->textPtr = pool->start;
  1294.     declEntity->textLen = pool->ptr - pool->start;
  1295.     poolFinish(pool);
  1296.       }
  1297.       else
  1298.     poolDiscard(pool);
  1299.       return XML_ERROR_NONE;
  1300.     case XML_TOK_ENTITY_REF:
  1301.     case XML_TOK_DATA_CHARS:
  1302.       if (!poolAppend(pool, encoding, entityTextPtr, next))
  1303.     return XML_ERROR_NO_MEMORY;
  1304.       break;
  1305.     case XML_TOK_TRAILING_CR:
  1306.       next = entityTextPtr + encoding->minBytesPerChar;
  1307.       /* fall through */
  1308.     case XML_TOK_DATA_NEWLINE:
  1309.       if (pool->end == pool->ptr && !poolGrow(pool))
  1310.     return XML_ERROR_NO_MEMORY;
  1311.       *(pool->ptr)++ = '\n';
  1312.       break;
  1313.     case XML_TOK_CHAR_REF:
  1314.       {
  1315.     char buf[XML_MAX_BYTES_PER_CHAR];
  1316.     int i;
  1317.     int n = XmlCharRefNumber(encoding, entityTextPtr);
  1318.     if (n < 0) {
  1319.       errorPtr = entityTextPtr;
  1320.       return XML_ERROR_BAD_CHAR_REF;
  1321.     }
  1322.     n = XmlEncode(utf8, n, buf);
  1323.     if (!n) {
  1324.       errorPtr = entityTextPtr;
  1325.       return XML_ERROR_BAD_CHAR_REF;
  1326.     }
  1327.     for (i = 0; i < n; i++) {
  1328.       if (pool->end == pool->ptr && !poolGrow(pool))
  1329.         return XML_ERROR_NO_MEMORY;
  1330.       *(pool->ptr)++ = buf[i];
  1331.     }
  1332.       }
  1333.       break;
  1334.     case XML_TOK_PARTIAL:
  1335.       errorPtr = entityTextPtr;
  1336.       return XML_ERROR_INVALID_TOKEN;
  1337.     case XML_TOK_INVALID:
  1338.       errorPtr = next;
  1339.       return XML_ERROR_INVALID_TOKEN;
  1340.     default:
  1341.       abort();
  1342.     }
  1343.     entityTextPtr = next;
  1344.   }
  1345.   /* not reached */
  1346. }
  1347.  
  1348. static void
  1349. normalizeLines(char *s)
  1350. {
  1351.   char *p;
  1352.   s = strchr(s, '\r');
  1353.   if (!s)
  1354.     return;
  1355.   p = s;
  1356.   while (*s) {
  1357.     if (*s == '\r') {
  1358.       *p++ = '\n';
  1359.       if (*++s == '\n')
  1360.         s++;
  1361.     }
  1362.     else
  1363.       *p++ = *s++;
  1364.   }
  1365.   *p = '\0';
  1366. }
  1367.  
  1368. static int
  1369. reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
  1370. {
  1371.   const char *target;
  1372.   char *data;
  1373.   const char *tem;
  1374.   if (!processingInstructionHandler)
  1375.     return 1;
  1376.   target = start + enc->minBytesPerChar * 2;
  1377.   tem = target + XmlNameLength(enc, target);
  1378.   target = poolStoreString(&tempPool, enc, target, tem);
  1379.   if (!target)
  1380.     return 0;
  1381.   poolFinish(&tempPool);
  1382.   data = poolStoreString(&tempPool, enc,
  1383.             XmlSkipS(enc, tem),
  1384.             end - enc->minBytesPerChar*2);
  1385.   if (!data)
  1386.     return 0;
  1387.   normalizeLines(data);
  1388.   processingInstructionHandler(userData, target, data);
  1389.   poolClear(&tempPool);
  1390.   return 1;
  1391. }
  1392.  
  1393. static int
  1394. defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata, const char *value)
  1395. {
  1396.   DEFAULT_ATTRIBUTE *att;
  1397.   if (type->nDefaultAtts == type->allocDefaultAtts) {
  1398.     if (type->allocDefaultAtts == 0)
  1399.       type->allocDefaultAtts = 8;
  1400.     else
  1401.       type->allocDefaultAtts *= 2;
  1402.     type->defaultAtts = realloc(type->defaultAtts,
  1403.                 type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
  1404.     if (!type->defaultAtts)
  1405.       return 0;
  1406.   }
  1407.   att = type->defaultAtts + type->nDefaultAtts;
  1408.   att->id = attId;
  1409.   att->value = value;
  1410.   att->isCdata = isCdata;
  1411.   if (!isCdata)
  1412.     attId->maybeTokenized = 1;
  1413.   type->nDefaultAtts += 1;
  1414.   return 1;
  1415. }
  1416.  
  1417. static ATTRIBUTE_ID *
  1418. getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
  1419. {
  1420.   ATTRIBUTE_ID *id;
  1421.   const char *name;
  1422.   if (!poolAppendByte(&dtd.pool, 0))
  1423.     return 0;
  1424.   name = poolStoreString(&dtd.pool, enc, start, end);
  1425.   if (!name)
  1426.     return 0;
  1427.   ++name;
  1428.   id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID));
  1429.   if (!id)
  1430.     return 0;
  1431.   if (id->name != name)
  1432.     poolDiscard(&dtd.pool);
  1433.   else
  1434.     poolFinish(&dtd.pool);
  1435.   return id;
  1436. }
  1437.  
  1438. static int dtdInit(DTD *p)
  1439. {
  1440.   static const char *names[] = { "lt", "amp", "gt", "quot", "apos" };
  1441.   static const char chars[] = { '<', '&', '>', '"', '\'' };
  1442.   int i;
  1443.  
  1444.   poolInit(&(p->pool));
  1445.   hashTableInit(&(p->generalEntities));
  1446.   for (i = 0; i < 5; i++) {
  1447.     ENTITY *entity = (ENTITY *)lookup(&(p->generalEntities), names[i], sizeof(ENTITY));
  1448.     if (!entity)
  1449.       return 0;
  1450.     entity->textPtr = chars + i;
  1451.     entity->textLen = 1;
  1452.     entity->magic = 1;
  1453.   }
  1454.   hashTableInit(&(p->elementTypes));
  1455.   hashTableInit(&(p->attributeIds));
  1456.   p->complete = 1;
  1457.   return 1;
  1458. }
  1459.  
  1460. static void dtdDestroy(DTD *p)
  1461. {
  1462.   HASH_TABLE_ITER iter;
  1463.   hashTableIterInit(&iter, &(p->elementTypes));
  1464.   for (;;) {
  1465.     ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
  1466.     if (!e)
  1467.       break;
  1468.     free(e->defaultAtts);
  1469.   }
  1470.   hashTableDestroy(&(p->generalEntities));
  1471.   hashTableDestroy(&(p->elementTypes));
  1472.   hashTableDestroy(&(p->attributeIds));
  1473.   poolDestroy(&(p->pool));
  1474. }
  1475.  
  1476. static
  1477. void poolInit(STRING_POOL *pool)
  1478. {
  1479.   pool->blocks = 0;
  1480.   pool->freeBlocks = 0;
  1481.   pool->start = 0;
  1482.   pool->ptr = 0;
  1483.   pool->end = 0;
  1484. }
  1485.  
  1486. static
  1487. void poolClear(STRING_POOL *pool)
  1488. {
  1489.   if (!pool->freeBlocks)
  1490.     pool->freeBlocks = pool->blocks;
  1491.   else {
  1492.     BLOCK *p = pool->blocks;
  1493.     while (p) {
  1494.       BLOCK *tem = p->next;
  1495.       p->next = pool->freeBlocks;
  1496.       pool->freeBlocks = p;
  1497.       p = tem;
  1498.     }
  1499.   }
  1500.   pool->blocks = 0;
  1501.   pool->start = 0;
  1502.   pool->ptr = 0;
  1503.   pool->end = 0;
  1504. }
  1505.  
  1506. static
  1507. void poolDestroy(STRING_POOL *pool)
  1508. {
  1509.   BLOCK *p = pool->blocks;
  1510.   while (p) {
  1511.     BLOCK *tem = p->next;
  1512.     free(p);
  1513.     p = tem;
  1514.   }
  1515.   pool->blocks = 0;
  1516.   p = pool->freeBlocks;
  1517.   while (p) {
  1518.     BLOCK *tem = p->next;
  1519.     free(p);
  1520.     p = tem;
  1521.   }
  1522.   pool->freeBlocks = 0;
  1523.   pool->ptr = 0;
  1524.   pool->start = 0;
  1525.   pool->end = 0;
  1526. }
  1527.  
  1528. static
  1529. char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
  1530.          const char *ptr, const char *end)
  1531. {
  1532.   if (!pool->ptr && !poolGrow(pool))
  1533.     return 0;
  1534.   for (;;) {
  1535.     XmlConvert(enc, XML_UTF8_ENCODING, &ptr, end, &(pool->ptr), pool->end);
  1536.     if (ptr == end)
  1537.       break;
  1538.     if (!poolGrow(pool))
  1539.       return 0;
  1540.   }
  1541.   return pool->start;
  1542. }
  1543.  
  1544.  
  1545. static
  1546. char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
  1547.               const char *ptr, const char *end)
  1548. {
  1549.   if (!poolAppend(pool, enc, ptr, end))
  1550.     return 0;
  1551.   if (pool->ptr == pool->end && !poolGrow(pool))
  1552.     return 0;
  1553.   *(pool->ptr)++ = 0;
  1554.   return pool->start;
  1555. }
  1556.  
  1557. static
  1558. int poolGrow(STRING_POOL *pool)
  1559. {
  1560.   if (pool->freeBlocks) {
  1561.     if (pool->start == 0) {
  1562.       pool->blocks = pool->freeBlocks;
  1563.       pool->freeBlocks = pool->freeBlocks->next;
  1564.       pool->blocks->next = 0;
  1565.       pool->start = pool->blocks->s;
  1566.       pool->end = pool->start + pool->blocks->size;
  1567.       pool->ptr = pool->start;
  1568.       return 1;
  1569.     }
  1570.     if (pool->end - pool->start < pool->freeBlocks->size) {
  1571.       BLOCK *tem = pool->freeBlocks->next;
  1572.       pool->freeBlocks->next = pool->blocks;
  1573.       pool->blocks = pool->freeBlocks;
  1574.       pool->freeBlocks = tem;
  1575.       memcpy(pool->blocks->s, pool->start, pool->end - pool->start);
  1576.       pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
  1577.       pool->start = pool->blocks->s;
  1578.       pool->end = pool->start + pool->blocks->size;
  1579.       return 1;
  1580.     }
  1581.   }
  1582.   if (pool->blocks && pool->start == pool->blocks->s) {
  1583.     int blockSize = (pool->end - pool->start)*2;
  1584.     pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize);
  1585.     if (!pool->blocks)
  1586.       return 0;
  1587.     pool->blocks->size = blockSize;
  1588.     pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
  1589.     pool->start = pool->blocks->s;
  1590.     pool->end = pool->start + blockSize;
  1591.   }
  1592.   else {
  1593.     BLOCK *tem;
  1594.     int blockSize = pool->end - pool->start;
  1595.     if (blockSize < INIT_BLOCK_SIZE)
  1596.       blockSize = INIT_BLOCK_SIZE;
  1597.     else
  1598.       blockSize *= 2;
  1599.     tem = malloc(offsetof(BLOCK, s) + blockSize);
  1600.     if (!tem)
  1601.       return 0;
  1602.     tem->size = blockSize;
  1603.     tem->next = pool->blocks;
  1604.     pool->blocks = tem;
  1605.     memcpy(tem->s, pool->start, pool->ptr - pool->start);
  1606.     pool->ptr = tem->s + (pool->ptr - pool->start);
  1607.     pool->start = tem->s;
  1608.     pool->end = tem->s + blockSize;
  1609.   }
  1610.   return 1;
  1611. }
  1612.