Home | History | Annotate | Download | only in expat
      1 /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
      2    See the file COPYING for copying permission.
      3 */
      4 
      5 #define XML_BUILDING_EXPAT 1
      6 
      7 #ifdef COMPILED_FROM_DSP
      8 #include "winconfig.h"
      9 #elif defined(MACOS_CLASSIC)
     10 #include "macconfig.h"
     11 #elif defined(__amigaos4__)
     12 #include "amigaconfig.h"
     13 #elif defined(HAVE_EXPAT_CONFIG_H)
     14 #include <expat_config.h>
     15 #endif /* ndef COMPILED_FROM_DSP */
     16 
     17 #include <stddef.h>
     18 #include <string.h>                     /* memset(), memcpy() */
     19 #include <assert.h>
     20 
     21 #if defined(UEFI_C_SOURCE)
     22   #include <expat/expat.h>
     23 #else
     24   #include "expat.h"
     25 #endif
     26 
     27 #ifdef XML_UNICODE
     28 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
     29 #define XmlConvert XmlUtf16Convert
     30 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
     31 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
     32 #define XmlEncode XmlUtf16Encode
     33 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
     34 typedef unsigned short ICHAR;
     35 #else
     36 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
     37 #define XmlConvert XmlUtf8Convert
     38 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
     39 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
     40 #define XmlEncode XmlUtf8Encode
     41 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
     42 typedef char ICHAR;
     43 #endif
     44 
     45 
     46 #ifndef XML_NS
     47 
     48 #define XmlInitEncodingNS XmlInitEncoding
     49 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
     50 #undef XmlGetInternalEncodingNS
     51 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
     52 #define XmlParseXmlDeclNS XmlParseXmlDecl
     53 
     54 #endif
     55 
     56 #ifdef XML_UNICODE
     57 
     58 #ifdef XML_UNICODE_WCHAR_T
     59 #define XML_T(x) (const wchar_t)x
     60 #define XML_L(x) L ## x
     61 #else
     62 #define XML_T(x) (const unsigned short)x
     63 #define XML_L(x) x
     64 #endif
     65 
     66 #else
     67 
     68 #define XML_T(x) x
     69 #define XML_L(x) x
     70 
     71 #endif
     72 
     73 /* Round up n to be a multiple of sz, where sz is a power of 2. */
     74 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
     75 
     76 /* Handle the case where memmove() doesn't exist. */
     77 #ifndef HAVE_MEMMOVE
     78 #ifdef HAVE_BCOPY
     79 #define memmove(d,s,l) bcopy((s),(d),(l))
     80 #else
     81 #error memmove does not exist on this platform, nor is a substitute available
     82 #endif /* HAVE_BCOPY */
     83 #endif /* HAVE_MEMMOVE */
     84 
     85 #include "internal.h"
     86 #include "xmltok.h"
     87 #include "xmlrole.h"
     88 
     89 typedef const XML_Char *KEY;
     90 
     91 typedef struct {
     92   KEY name;
     93 } NAMED;
     94 
     95 typedef struct {
     96   NAMED **v;
     97   unsigned char power;
     98   size_t size;
     99   size_t used;
    100   const XML_Memory_Handling_Suite *mem;
    101 } HASH_TABLE;
    102 
    103 /* Basic character hash algorithm, taken from Python's string hash:
    104    h = h * 1000003 ^ character, the constant being a prime number.
    105 
    106 */
    107 #ifdef XML_UNICODE
    108 #define CHAR_HASH(h, c) \
    109   (((h) * 0xF4243) ^ (unsigned short)(c))
    110 #else
    111 #define CHAR_HASH(h, c) \
    112   (((h) * 0xF4243) ^ (unsigned char)(c))
    113 #endif
    114 
    115 /* For probing (after a collision) we need a step size relative prime
    116    to the hash table size, which is a power of 2. We use double-hashing,
    117    since we can calculate a second hash value cheaply by taking those bits
    118    of the first hash value that were discarded (masked out) when the table
    119    index was calculated: index = hash & mask, where mask = table->size - 1.
    120    We limit the maximum step size to table->size / 4 (mask >> 2) and make
    121    it odd, since odd numbers are always relative prime to a power of 2.
    122 */
    123 #define SECOND_HASH(hash, mask, power) \
    124   ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
    125 #define PROBE_STEP(hash, mask, power) \
    126   ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
    127 
    128 typedef struct {
    129   NAMED **p;
    130   NAMED **end;
    131 } HASH_TABLE_ITER;
    132 
    133 #define INIT_TAG_BUF_SIZE 32  /* must be a multiple of sizeof(XML_Char) */
    134 #define INIT_DATA_BUF_SIZE 1024
    135 #define INIT_ATTS_SIZE 16
    136 #define INIT_ATTS_VERSION 0xFFFFFFFF
    137 #define INIT_BLOCK_SIZE 1024
    138 #define INIT_BUFFER_SIZE 1024
    139 
    140 #define EXPAND_SPARE 24
    141 
    142 typedef struct binding {
    143   struct prefix *prefix;
    144   struct binding *nextTagBinding;
    145   struct binding *prevPrefixBinding;
    146   const struct attribute_id *attId;
    147   XML_Char *uri;
    148   int uriLen;
    149   int uriAlloc;
    150 } BINDING;
    151 
    152 typedef struct prefix {
    153   const XML_Char *name;
    154   BINDING *binding;
    155 } PREFIX;
    156 
    157 typedef struct {
    158   const XML_Char *str;
    159   const XML_Char *localPart;
    160   const XML_Char *prefix;
    161   int strLen;
    162   int uriLen;
    163   int prefixLen;
    164 } TAG_NAME;
    165 
    166 /* TAG represents an open element.
    167    The name of the element is stored in both the document and API
    168    encodings.  The memory buffer 'buf' is a separately-allocated
    169    memory area which stores the name.  During the XML_Parse()/
    170    XMLParseBuffer() when the element is open, the memory for the 'raw'
    171    version of the name (in the document encoding) is shared with the
    172    document buffer.  If the element is open across calls to
    173    XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
    174    contain the 'raw' name as well.
    175 
    176    A parser re-uses these structures, maintaining a list of allocated
    177    TAG objects in a free list.
    178 */
    179 typedef struct tag {
    180   struct tag *parent;           /* parent of this element */
    181   const char *rawName;          /* tagName in the original encoding */
    182   int rawNameLength;
    183   TAG_NAME name;                /* tagName in the API encoding */
    184   char *buf;                    /* buffer for name components */
    185   char *bufEnd;                 /* end of the buffer */
    186   BINDING *bindings;
    187 } TAG;
    188 
    189 typedef struct {
    190   const XML_Char *name;
    191   const XML_Char *textPtr;
    192   int textLen;                  /* length in XML_Chars */
    193   int processed;                /* # of processed bytes - when suspended */
    194   const XML_Char *systemId;
    195   const XML_Char *base;
    196   const XML_Char *publicId;
    197   const XML_Char *notation;
    198   XML_Bool open;
    199   XML_Bool is_param;
    200   XML_Bool is_internal; /* true if declared in internal subset outside PE */
    201 } ENTITY;
    202 
    203 typedef struct {
    204   enum XML_Content_Type         type;
    205   enum XML_Content_Quant        quant;
    206   const XML_Char *              name;
    207   int                           firstchild;
    208   int                           lastchild;
    209   int                           childcnt;
    210   int                           nextsib;
    211 } CONTENT_SCAFFOLD;
    212 
    213 #define INIT_SCAFFOLD_ELEMENTS 32
    214 
    215 typedef struct block {
    216   struct block *next;
    217   int size;
    218   XML_Char s[1];
    219 } BLOCK;
    220 
    221 typedef struct {
    222   BLOCK *blocks;
    223   BLOCK *freeBlocks;
    224   const XML_Char *end;
    225   XML_Char *ptr;
    226   XML_Char *start;
    227   const XML_Memory_Handling_Suite *mem;
    228 } STRING_POOL;
    229 
    230 /* The XML_Char before the name is used to determine whether
    231    an attribute has been specified. */
    232 typedef struct attribute_id {
    233   XML_Char *name;
    234   PREFIX *prefix;
    235   XML_Bool maybeTokenized;
    236   XML_Bool xmlns;
    237 } ATTRIBUTE_ID;
    238 
    239 typedef struct {
    240   const ATTRIBUTE_ID *id;
    241   XML_Bool isCdata;
    242   const XML_Char *value;
    243 } DEFAULT_ATTRIBUTE;
    244 
    245 typedef struct {
    246   unsigned long version;
    247   unsigned long hash;
    248   const XML_Char *uriName;
    249 } NS_ATT;
    250 
    251 typedef struct {
    252   const XML_Char *name;
    253   PREFIX *prefix;
    254   const ATTRIBUTE_ID *idAtt;
    255   int nDefaultAtts;
    256   int allocDefaultAtts;
    257   DEFAULT_ATTRIBUTE *defaultAtts;
    258 } ELEMENT_TYPE;
    259 
    260 typedef struct {
    261   HASH_TABLE generalEntities;
    262   HASH_TABLE elementTypes;
    263   HASH_TABLE attributeIds;
    264   HASH_TABLE prefixes;
    265   STRING_POOL pool;
    266   STRING_POOL entityValuePool;
    267   /* false once a parameter entity reference has been skipped */
    268   XML_Bool keepProcessing;
    269   /* true once an internal or external PE reference has been encountered;
    270      this includes the reference to an external subset */
    271   XML_Bool hasParamEntityRefs;
    272   XML_Bool standalone;
    273 #ifdef XML_DTD
    274   /* indicates if external PE has been read */
    275   XML_Bool paramEntityRead;
    276   HASH_TABLE paramEntities;
    277 #endif /* XML_DTD */
    278   PREFIX defaultPrefix;
    279   /* === scaffolding for building content model === */
    280   XML_Bool in_eldecl;
    281   CONTENT_SCAFFOLD *scaffold;
    282   unsigned contentStringLen;
    283   unsigned scaffSize;
    284   unsigned scaffCount;
    285   int scaffLevel;
    286   int *scaffIndex;
    287 } DTD;
    288 
    289 typedef struct open_internal_entity {
    290   const char *internalEventPtr;
    291   const char *internalEventEndPtr;
    292   struct open_internal_entity *next;
    293   ENTITY *entity;
    294   int startTagLevel;
    295   XML_Bool betweenDecl; /* WFC: PE Between Declarations */
    296 } OPEN_INTERNAL_ENTITY;
    297 
    298 typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
    299                                          const char *start,
    300                                          const char *end,
    301                                          const char **endPtr);
    302 
    303 static Processor prologProcessor;
    304 static Processor prologInitProcessor;
    305 static Processor contentProcessor;
    306 static Processor cdataSectionProcessor;
    307 #ifdef XML_DTD
    308 static Processor ignoreSectionProcessor;
    309 static Processor externalParEntProcessor;
    310 static Processor externalParEntInitProcessor;
    311 static Processor entityValueProcessor;
    312 static Processor entityValueInitProcessor;
    313 #endif /* XML_DTD */
    314 static Processor epilogProcessor;
    315 static Processor errorProcessor;
    316 static Processor externalEntityInitProcessor;
    317 static Processor externalEntityInitProcessor2;
    318 static Processor externalEntityInitProcessor3;
    319 static Processor externalEntityContentProcessor;
    320 static Processor internalEntityProcessor;
    321 
    322 static enum XML_Error
    323 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
    324 static enum XML_Error
    325 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
    326                const char *s, const char *next);
    327 static enum XML_Error
    328 initializeEncoding(XML_Parser parser);
    329 static enum XML_Error
    330 doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
    331          const char *end, int tok, const char *next, const char **nextPtr,
    332          XML_Bool haveMore);
    333 static enum XML_Error
    334 processInternalEntity(XML_Parser parser, ENTITY *entity,
    335                       XML_Bool betweenDecl);
    336 static enum XML_Error
    337 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
    338           const char *start, const char *end, const char **endPtr,
    339           XML_Bool haveMore);
    340 static enum XML_Error
    341 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
    342                const char *end, const char **nextPtr, XML_Bool haveMore);
    343 #ifdef XML_DTD
    344 static enum XML_Error
    345 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
    346                 const char *end, const char **nextPtr, XML_Bool haveMore);
    347 #endif /* XML_DTD */
    348 
    349 static enum XML_Error
    350 storeAtts(XML_Parser parser, const ENCODING *, const char *s,
    351           TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
    352 static enum XML_Error
    353 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
    354            const XML_Char *uri, BINDING **bindingsPtr);
    355 static int
    356 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
    357                 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
    358 static enum XML_Error
    359 storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
    360                     const char *, const char *, STRING_POOL *);
    361 static enum XML_Error
    362 appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
    363                      const char *, const char *, STRING_POOL *);
    364 static ATTRIBUTE_ID *
    365 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
    366                const char *end);
    367 static int
    368 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
    369 static enum XML_Error
    370 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
    371                  const char *end);
    372 static int
    373 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
    374                             const char *start, const char *end);
    375 static int
    376 reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
    377               const char *end);
    378 static void
    379 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
    380               const char *end);
    381 
    382 static const XML_Char * getContext(XML_Parser parser);
    383 static XML_Bool
    384 setContext(XML_Parser parser, const XML_Char *context);
    385 
    386 static void FASTCALL normalizePublicId(XML_Char *s);
    387 
    388 static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
    389 /* do not call if parentParser != NULL */
    390 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
    391 static void
    392 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
    393 static int
    394 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
    395 static int
    396 copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
    397 
    398 static NAMED *
    399 lookup(HASH_TABLE *table, KEY name, size_t createSize);
    400 static void FASTCALL
    401 hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
    402 static void FASTCALL hashTableClear(HASH_TABLE *);
    403 static void FASTCALL hashTableDestroy(HASH_TABLE *);
    404 static void FASTCALL
    405 hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
    406 static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
    407 
    408 static void FASTCALL
    409 poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
    410 static void FASTCALL poolClear(STRING_POOL *);
    411 static void FASTCALL poolDestroy(STRING_POOL *);
    412 static XML_Char *
    413 poolAppend(STRING_POOL *pool, const ENCODING *enc,
    414            const char *ptr, const char *end);
    415 static XML_Char *
    416 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
    417                 const char *ptr, const char *end);
    418 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
    419 static const XML_Char * FASTCALL
    420 poolCopyString(STRING_POOL *pool, const XML_Char *s);
    421 static const XML_Char *
    422 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
    423 static const XML_Char * FASTCALL
    424 poolAppendString(STRING_POOL *pool, const XML_Char *s);
    425 
    426 static int FASTCALL nextScaffoldPart(XML_Parser parser);
    427 static XML_Content * build_model(XML_Parser parser);
    428 static ELEMENT_TYPE *
    429 getElementType(XML_Parser parser, const ENCODING *enc,
    430                const char *ptr, const char *end);
    431 
    432 static XML_Parser
    433 parserCreate(const XML_Char *encodingName,
    434              const XML_Memory_Handling_Suite *memsuite,
    435              const XML_Char *nameSep,
    436              DTD *dtd);
    437 static void
    438 parserInit(XML_Parser parser, const XML_Char *encodingName);
    439 
    440 #define poolStart(pool) ((pool)->start)
    441 #define poolEnd(pool) ((pool)->ptr)
    442 #define poolLength(pool) ((pool)->ptr - (pool)->start)
    443 #define poolChop(pool) ((void)--(pool->ptr))
    444 #define poolLastChar(pool) (((pool)->ptr)[-1])
    445 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
    446 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
    447 #define poolAppendChar(pool, c) \
    448   (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
    449    ? 0 \
    450    : ((*((pool)->ptr)++ = c), 1))
    451 
    452 struct XML_ParserStruct {
    453   /* The first member must be userData so that the XML_GetUserData
    454      macro works. */
    455   void *m_userData;
    456   void *m_handlerArg;
    457   char *m_buffer;
    458   const XML_Memory_Handling_Suite m_mem;
    459   /* first character to be parsed */
    460   const char *m_bufferPtr;
    461   /* past last character to be parsed */
    462   char *m_bufferEnd;
    463   /* allocated end of buffer */
    464   const char *m_bufferLim;
    465   XML_Index m_parseEndByteIndex;
    466   const char *m_parseEndPtr;
    467   XML_Char *m_dataBuf;
    468   XML_Char *m_dataBufEnd;
    469   XML_StartElementHandler m_startElementHandler;
    470   XML_EndElementHandler m_endElementHandler;
    471   XML_CharacterDataHandler m_characterDataHandler;
    472   XML_ProcessingInstructionHandler m_processingInstructionHandler;
    473   XML_CommentHandler m_commentHandler;
    474   XML_StartCdataSectionHandler m_startCdataSectionHandler;
    475   XML_EndCdataSectionHandler m_endCdataSectionHandler;
    476   XML_DefaultHandler m_defaultHandler;
    477   XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
    478   XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
    479   XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
    480   XML_NotationDeclHandler m_notationDeclHandler;
    481   XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
    482   XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
    483   XML_NotStandaloneHandler m_notStandaloneHandler;
    484   XML_ExternalEntityRefHandler m_externalEntityRefHandler;
    485   XML_Parser m_externalEntityRefHandlerArg;
    486   XML_SkippedEntityHandler m_skippedEntityHandler;
    487   XML_UnknownEncodingHandler m_unknownEncodingHandler;
    488   XML_ElementDeclHandler m_elementDeclHandler;
    489   XML_AttlistDeclHandler m_attlistDeclHandler;
    490   XML_EntityDeclHandler m_entityDeclHandler;
    491   XML_XmlDeclHandler m_xmlDeclHandler;
    492   const ENCODING *m_encoding;
    493   INIT_ENCODING m_initEncoding;
    494   const ENCODING *m_internalEncoding;
    495   const XML_Char *m_protocolEncodingName;
    496   XML_Bool m_ns;
    497   XML_Bool m_ns_triplets;
    498   void *m_unknownEncodingMem;
    499   void *m_unknownEncodingData;
    500   void *m_unknownEncodingHandlerData;
    501   void (XMLCALL *m_unknownEncodingRelease)(void *);
    502   PROLOG_STATE m_prologState;
    503   Processor *m_processor;
    504   enum XML_Error m_errorCode;
    505   const char *m_eventPtr;
    506   const char *m_eventEndPtr;
    507   const char *m_positionPtr;
    508   OPEN_INTERNAL_ENTITY *m_openInternalEntities;
    509   OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
    510   XML_Bool m_defaultExpandInternalEntities;
    511   int m_tagLevel;
    512   ENTITY *m_declEntity;
    513   const XML_Char *m_doctypeName;
    514   const XML_Char *m_doctypeSysid;
    515   const XML_Char *m_doctypePubid;
    516   const XML_Char *m_declAttributeType;
    517   const XML_Char *m_declNotationName;
    518   const XML_Char *m_declNotationPublicId;
    519   ELEMENT_TYPE *m_declElementType;
    520   ATTRIBUTE_ID *m_declAttributeId;
    521   XML_Bool m_declAttributeIsCdata;
    522   XML_Bool m_declAttributeIsId;
    523   DTD *m_dtd;
    524   const XML_Char *m_curBase;
    525   TAG *m_tagStack;
    526   TAG *m_freeTagList;
    527   BINDING *m_inheritedBindings;
    528   BINDING *m_freeBindingList;
    529   int m_attsSize;
    530   int m_nSpecifiedAtts;
    531   int m_idAttIndex;
    532   ATTRIBUTE *m_atts;
    533   NS_ATT *m_nsAtts;
    534   unsigned long m_nsAttsVersion;
    535   unsigned char m_nsAttsPower;
    536   POSITION m_position;
    537   STRING_POOL m_tempPool;
    538   STRING_POOL m_temp2Pool;
    539   char *m_groupConnector;
    540   unsigned int m_groupSize;
    541   XML_Char m_namespaceSeparator;
    542   XML_Parser m_parentParser;
    543   XML_ParsingStatus m_parsingStatus;
    544 #ifdef XML_DTD
    545   XML_Bool m_isParamEntity;
    546   XML_Bool m_useForeignDTD;
    547   enum XML_ParamEntityParsing m_paramEntityParsing;
    548 #endif
    549 };
    550 
    551 #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
    552 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
    553 #define FREE(p) (parser->m_mem.free_fcn((p)))
    554 
    555 #define userData (parser->m_userData)
    556 #define handlerArg (parser->m_handlerArg)
    557 #define startElementHandler (parser->m_startElementHandler)
    558 #define endElementHandler (parser->m_endElementHandler)
    559 #define characterDataHandler (parser->m_characterDataHandler)
    560 #define processingInstructionHandler \
    561         (parser->m_processingInstructionHandler)
    562 #define commentHandler (parser->m_commentHandler)
    563 #define startCdataSectionHandler \
    564         (parser->m_startCdataSectionHandler)
    565 #define endCdataSectionHandler (parser->m_endCdataSectionHandler)
    566 #define defaultHandler (parser->m_defaultHandler)
    567 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
    568 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
    569 #define unparsedEntityDeclHandler \
    570         (parser->m_unparsedEntityDeclHandler)
    571 #define notationDeclHandler (parser->m_notationDeclHandler)
    572 #define startNamespaceDeclHandler \
    573         (parser->m_startNamespaceDeclHandler)
    574 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
    575 #define notStandaloneHandler (parser->m_notStandaloneHandler)
    576 #define externalEntityRefHandler \
    577         (parser->m_externalEntityRefHandler)
    578 #define externalEntityRefHandlerArg \
    579         (parser->m_externalEntityRefHandlerArg)
    580 #define internalEntityRefHandler \
    581         (parser->m_internalEntityRefHandler)
    582 #define skippedEntityHandler (parser->m_skippedEntityHandler)
    583 #define unknownEncodingHandler (parser->m_unknownEncodingHandler)
    584 #define elementDeclHandler (parser->m_elementDeclHandler)
    585 #define attlistDeclHandler (parser->m_attlistDeclHandler)
    586 #define entityDeclHandler (parser->m_entityDeclHandler)
    587 #define xmlDeclHandler (parser->m_xmlDeclHandler)
    588 #define encoding (parser->m_encoding)
    589 #define initEncoding (parser->m_initEncoding)
    590 #define internalEncoding (parser->m_internalEncoding)
    591 #define unknownEncodingMem (parser->m_unknownEncodingMem)
    592 #define unknownEncodingData (parser->m_unknownEncodingData)
    593 #define unknownEncodingHandlerData \
    594   (parser->m_unknownEncodingHandlerData)
    595 #define unknownEncodingRelease (parser->m_unknownEncodingRelease)
    596 #define protocolEncodingName (parser->m_protocolEncodingName)
    597 #define ns (parser->m_ns)
    598 #define ns_triplets (parser->m_ns_triplets)
    599 #define prologState (parser->m_prologState)
    600 #define processor (parser->m_processor)
    601 #define errorCode (parser->m_errorCode)
    602 #define eventPtr (parser->m_eventPtr)
    603 #define eventEndPtr (parser->m_eventEndPtr)
    604 #define positionPtr (parser->m_positionPtr)
    605 #define position (parser->m_position)
    606 #define openInternalEntities (parser->m_openInternalEntities)
    607 #define freeInternalEntities (parser->m_freeInternalEntities)
    608 #define defaultExpandInternalEntities \
    609         (parser->m_defaultExpandInternalEntities)
    610 #define tagLevel (parser->m_tagLevel)
    611 #define buffer (parser->m_buffer)
    612 #define bufferPtr (parser->m_bufferPtr)
    613 #define bufferEnd (parser->m_bufferEnd)
    614 #define parseEndByteIndex (parser->m_parseEndByteIndex)
    615 #define parseEndPtr (parser->m_parseEndPtr)
    616 #define bufferLim (parser->m_bufferLim)
    617 #define dataBuf (parser->m_dataBuf)
    618 #define dataBufEnd (parser->m_dataBufEnd)
    619 #define _dtd (parser->m_dtd)
    620 #define curBase (parser->m_curBase)
    621 #define declEntity (parser->m_declEntity)
    622 #define doctypeName (parser->m_doctypeName)
    623 #define doctypeSysid (parser->m_doctypeSysid)
    624 #define doctypePubid (parser->m_doctypePubid)
    625 #define declAttributeType (parser->m_declAttributeType)
    626 #define declNotationName (parser->m_declNotationName)
    627 #define declNotationPublicId (parser->m_declNotationPublicId)
    628 #define declElementType (parser->m_declElementType)
    629 #define declAttributeId (parser->m_declAttributeId)
    630 #define declAttributeIsCdata (parser->m_declAttributeIsCdata)
    631 #define declAttributeIsId (parser->m_declAttributeIsId)
    632 #define freeTagList (parser->m_freeTagList)
    633 #define freeBindingList (parser->m_freeBindingList)
    634 #define inheritedBindings (parser->m_inheritedBindings)
    635 #define tagStack (parser->m_tagStack)
    636 #define atts (parser->m_atts)
    637 #define attsSize (parser->m_attsSize)
    638 #define nSpecifiedAtts (parser->m_nSpecifiedAtts)
    639 #define idAttIndex (parser->m_idAttIndex)
    640 #define nsAtts (parser->m_nsAtts)
    641 #define nsAttsVersion (parser->m_nsAttsVersion)
    642 #define nsAttsPower (parser->m_nsAttsPower)
    643 #define tempPool (parser->m_tempPool)
    644 #define temp2Pool (parser->m_temp2Pool)
    645 #define groupConnector (parser->m_groupConnector)
    646 #define groupSize (parser->m_groupSize)
    647 #define namespaceSeparator (parser->m_namespaceSeparator)
    648 #define parentParser (parser->m_parentParser)
    649 #define ps_parsing (parser->m_parsingStatus.parsing)
    650 #define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
    651 #ifdef XML_DTD
    652 #define isParamEntity (parser->m_isParamEntity)
    653 #define useForeignDTD (parser->m_useForeignDTD)
    654 #define paramEntityParsing (parser->m_paramEntityParsing)
    655 #endif /* XML_DTD */
    656 
    657 XML_Parser XMLCALL
    658 XML_ParserCreate(const XML_Char *encodingName)
    659 {
    660   return XML_ParserCreate_MM(encodingName, NULL, NULL);
    661 }
    662 
    663 XML_Parser XMLCALL
    664 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
    665 {
    666   XML_Char tmp[2];
    667   *tmp = nsSep;
    668   return XML_ParserCreate_MM(encodingName, NULL, tmp);
    669 }
    670 
    671 static const XML_Char implicitContext[] = {
    672   'x', 'm', 'l', '=', 'h', 't', 't', 'p', ':', '/', '/',
    673   'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
    674   'X', 'M', 'L', '/', '1', '9', '9', '8', '/',
    675   'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0'
    676 };
    677 
    678 XML_Parser XMLCALL
    679 XML_ParserCreate_MM(const XML_Char *encodingName,
    680                     const XML_Memory_Handling_Suite *memsuite,
    681                     const XML_Char *nameSep)
    682 {
    683   XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL);
    684   if (parser != NULL && ns) {
    685     /* implicit context only set for root parser, since child
    686        parsers (i.e. external entity parsers) will inherit it
    687     */
    688     if (!setContext(parser, implicitContext)) {
    689       XML_ParserFree(parser);
    690       return NULL;
    691     }
    692   }
    693   return parser;
    694 }
    695 
    696 static XML_Parser
    697 parserCreate(const XML_Char *encodingName,
    698              const XML_Memory_Handling_Suite *memsuite,
    699              const XML_Char *nameSep,
    700              DTD *dtd)
    701 {
    702   XML_Parser parser;
    703 
    704   if (memsuite) {
    705     XML_Memory_Handling_Suite *mtemp;
    706     parser = (XML_Parser)
    707       memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
    708     if (parser != NULL) {
    709       mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
    710       mtemp->malloc_fcn = memsuite->malloc_fcn;
    711       mtemp->realloc_fcn = memsuite->realloc_fcn;
    712       mtemp->free_fcn = memsuite->free_fcn;
    713     }
    714   }
    715   else {
    716     XML_Memory_Handling_Suite *mtemp;
    717     parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
    718     if (parser != NULL) {
    719       mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
    720       mtemp->malloc_fcn = malloc;
    721       mtemp->realloc_fcn = realloc;
    722       mtemp->free_fcn = free;
    723     }
    724   }
    725 
    726   if (!parser)
    727     return parser;
    728 
    729   buffer = NULL;
    730   bufferLim = NULL;
    731 
    732   attsSize = INIT_ATTS_SIZE;
    733   atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
    734   if (atts == NULL) {
    735     FREE(parser);
    736     return NULL;
    737   }
    738   dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
    739   if (dataBuf == NULL) {
    740     FREE(atts);
    741     FREE(parser);
    742     return NULL;
    743   }
    744   dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
    745 
    746   if (dtd)
    747     _dtd = dtd;
    748   else {
    749     _dtd = dtdCreate(&parser->m_mem);
    750     if (_dtd == NULL) {
    751       FREE(dataBuf);
    752       FREE(atts);
    753       FREE(parser);
    754       return NULL;
    755     }
    756   }
    757 
    758   freeBindingList = NULL;
    759   freeTagList = NULL;
    760   freeInternalEntities = NULL;
    761 
    762   groupSize = 0;
    763   groupConnector = NULL;
    764 
    765   unknownEncodingHandler = NULL;
    766   unknownEncodingHandlerData = NULL;
    767 
    768   namespaceSeparator = '!';
    769   ns = XML_FALSE;
    770   ns_triplets = XML_FALSE;
    771 
    772   nsAtts = NULL;
    773   nsAttsVersion = 0;
    774   nsAttsPower = 0;
    775 
    776   poolInit(&tempPool, &(parser->m_mem));
    777   poolInit(&temp2Pool, &(parser->m_mem));
    778   parserInit(parser, encodingName);
    779 
    780   if (encodingName && !protocolEncodingName) {
    781     XML_ParserFree(parser);
    782     return NULL;
    783   }
    784 
    785   if (nameSep) {
    786     ns = XML_TRUE;
    787     internalEncoding = XmlGetInternalEncodingNS();
    788     namespaceSeparator = *nameSep;
    789   }
    790   else {
    791     internalEncoding = XmlGetInternalEncoding();
    792   }
    793 
    794   return parser;
    795 }
    796 
    797 static void
    798 parserInit(XML_Parser parser, const XML_Char *encodingName)
    799 {
    800   processor = prologInitProcessor;
    801   XmlPrologStateInit(&prologState);
    802   protocolEncodingName = (encodingName != NULL
    803                           ? poolCopyString(&tempPool, encodingName)
    804                           : NULL);
    805   curBase = NULL;
    806   XmlInitEncoding(&initEncoding, &encoding, 0);
    807   userData = NULL;
    808   handlerArg = NULL;
    809   startElementHandler = NULL;
    810   endElementHandler = NULL;
    811   characterDataHandler = NULL;
    812   processingInstructionHandler = NULL;
    813   commentHandler = NULL;
    814   startCdataSectionHandler = NULL;
    815   endCdataSectionHandler = NULL;
    816   defaultHandler = NULL;
    817   startDoctypeDeclHandler = NULL;
    818   endDoctypeDeclHandler = NULL;
    819   unparsedEntityDeclHandler = NULL;
    820   notationDeclHandler = NULL;
    821   startNamespaceDeclHandler = NULL;
    822   endNamespaceDeclHandler = NULL;
    823   notStandaloneHandler = NULL;
    824   externalEntityRefHandler = NULL;
    825   externalEntityRefHandlerArg = parser;
    826   skippedEntityHandler = NULL;
    827   elementDeclHandler = NULL;
    828   attlistDeclHandler = NULL;
    829   entityDeclHandler = NULL;
    830   xmlDeclHandler = NULL;
    831   bufferPtr = buffer;
    832   bufferEnd = buffer;
    833   parseEndByteIndex = 0;
    834   parseEndPtr = NULL;
    835   declElementType = NULL;
    836   declAttributeId = NULL;
    837   declEntity = NULL;
    838   doctypeName = NULL;
    839   doctypeSysid = NULL;
    840   doctypePubid = NULL;
    841   declAttributeType = NULL;
    842   declNotationName = NULL;
    843   declNotationPublicId = NULL;
    844   declAttributeIsCdata = XML_FALSE;
    845   declAttributeIsId = XML_FALSE;
    846   memset(&position, 0, sizeof(POSITION));
    847   errorCode = XML_ERROR_NONE;
    848   eventPtr = NULL;
    849   eventEndPtr = NULL;
    850   positionPtr = NULL;
    851   openInternalEntities = NULL;
    852   defaultExpandInternalEntities = XML_TRUE;
    853   tagLevel = 0;
    854   tagStack = NULL;
    855   inheritedBindings = NULL;
    856   nSpecifiedAtts = 0;
    857   unknownEncodingMem = NULL;
    858   unknownEncodingRelease = NULL;
    859   unknownEncodingData = NULL;
    860   parentParser = NULL;
    861   ps_parsing = XML_INITIALIZED;
    862 #ifdef XML_DTD
    863   isParamEntity = XML_FALSE;
    864   useForeignDTD = XML_FALSE;
    865   paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
    866 #endif
    867 }
    868 
    869 /* moves list of bindings to freeBindingList */
    870 static void FASTCALL
    871 moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
    872 {
    873   while (bindings) {
    874     BINDING *b = bindings;
    875     bindings = bindings->nextTagBinding;
    876     b->nextTagBinding = freeBindingList;
    877     freeBindingList = b;
    878   }
    879 }
    880 
    881 XML_Bool XMLCALL
    882 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
    883 {
    884   TAG *tStk;
    885   OPEN_INTERNAL_ENTITY *openEntityList;
    886   if (parentParser)
    887     return XML_FALSE;
    888   /* move tagStack to freeTagList */
    889   tStk = tagStack;
    890   while (tStk) {
    891     TAG *tag = tStk;
    892     tStk = tStk->parent;
    893     tag->parent = freeTagList;
    894     moveToFreeBindingList(parser, tag->bindings);
    895     tag->bindings = NULL;
    896     freeTagList = tag;
    897   }
    898   /* move openInternalEntities to freeInternalEntities */
    899   openEntityList = openInternalEntities;
    900   while (openEntityList) {
    901     OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
    902     openEntityList = openEntity->next;
    903     openEntity->next = freeInternalEntities;
    904     freeInternalEntities = openEntity;
    905   }
    906   moveToFreeBindingList(parser, inheritedBindings);
    907   FREE(unknownEncodingMem);
    908   if (unknownEncodingRelease)
    909     unknownEncodingRelease(unknownEncodingData);
    910   poolClear(&tempPool);
    911   poolClear(&temp2Pool);
    912   parserInit(parser, encodingName);
    913   dtdReset(_dtd, &parser->m_mem);
    914   return setContext(parser, implicitContext);
    915 }
    916 
    917 enum XML_Status XMLCALL
    918 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
    919 {
    920   /* Block after XML_Parse()/XML_ParseBuffer() has been called.
    921      XXX There's no way for the caller to determine which of the
    922      XXX possible error cases caused the XML_STATUS_ERROR return.
    923   */
    924   if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
    925     return XML_STATUS_ERROR;
    926   if (encodingName == NULL)
    927     protocolEncodingName = NULL;
    928   else {
    929     protocolEncodingName = poolCopyString(&tempPool, encodingName);
    930     if (!protocolEncodingName)
    931       return XML_STATUS_ERROR;
    932   }
    933   return XML_STATUS_OK;
    934 }
    935 
    936 XML_Parser XMLCALL
    937 XML_ExternalEntityParserCreate(XML_Parser oldParser,
    938                                const XML_Char *context,
    939                                const XML_Char *encodingName)
    940 {
    941   XML_Parser parser = oldParser;
    942   DTD *newDtd = NULL;
    943   DTD *oldDtd = _dtd;
    944   XML_StartElementHandler oldStartElementHandler = startElementHandler;
    945   XML_EndElementHandler oldEndElementHandler = endElementHandler;
    946   XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
    947   XML_ProcessingInstructionHandler oldProcessingInstructionHandler
    948       = processingInstructionHandler;
    949   XML_CommentHandler oldCommentHandler = commentHandler;
    950   XML_StartCdataSectionHandler oldStartCdataSectionHandler
    951       = startCdataSectionHandler;
    952   XML_EndCdataSectionHandler oldEndCdataSectionHandler
    953       = endCdataSectionHandler;
    954   XML_DefaultHandler oldDefaultHandler = defaultHandler;
    955   XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
    956       = unparsedEntityDeclHandler;
    957   XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
    958   XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
    959       = startNamespaceDeclHandler;
    960   XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
    961       = endNamespaceDeclHandler;
    962   XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
    963   XML_ExternalEntityRefHandler oldExternalEntityRefHandler
    964       = externalEntityRefHandler;
    965   XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
    966   XML_UnknownEncodingHandler oldUnknownEncodingHandler
    967       = unknownEncodingHandler;
    968   XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
    969   XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
    970   XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
    971   XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
    972   ELEMENT_TYPE * oldDeclElementType = declElementType;
    973 
    974   void *oldUserData = userData;
    975   void *oldHandlerArg = handlerArg;
    976   XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
    977   XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
    978 #ifdef XML_DTD
    979   enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
    980   int oldInEntityValue = prologState.inEntityValue;
    981 #endif
    982   XML_Bool oldns_triplets = ns_triplets;
    983 
    984 #ifdef XML_DTD
    985   if (!context)
    986     newDtd = oldDtd;
    987 #endif /* XML_DTD */
    988 
    989   /* Note that the magical uses of the pre-processor to make field
    990      access look more like C++ require that `parser' be overwritten
    991      here.  This makes this function more painful to follow than it
    992      would be otherwise.
    993   */
    994   if (ns) {
    995     XML_Char tmp[2];
    996     *tmp = namespaceSeparator;
    997     parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
    998   }
    999   else {
   1000     parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
   1001   }
   1002 
   1003   if (!parser)
   1004     return NULL;
   1005 
   1006   startElementHandler = oldStartElementHandler;
   1007   endElementHandler = oldEndElementHandler;
   1008   characterDataHandler = oldCharacterDataHandler;
   1009   processingInstructionHandler = oldProcessingInstructionHandler;
   1010   commentHandler = oldCommentHandler;
   1011   startCdataSectionHandler = oldStartCdataSectionHandler;
   1012   endCdataSectionHandler = oldEndCdataSectionHandler;
   1013   defaultHandler = oldDefaultHandler;
   1014   unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
   1015   notationDeclHandler = oldNotationDeclHandler;
   1016   startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
   1017   endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
   1018   notStandaloneHandler = oldNotStandaloneHandler;
   1019   externalEntityRefHandler = oldExternalEntityRefHandler;
   1020   skippedEntityHandler = oldSkippedEntityHandler;
   1021   unknownEncodingHandler = oldUnknownEncodingHandler;
   1022   elementDeclHandler = oldElementDeclHandler;
   1023   attlistDeclHandler = oldAttlistDeclHandler;
   1024   entityDeclHandler = oldEntityDeclHandler;
   1025   xmlDeclHandler = oldXmlDeclHandler;
   1026   declElementType = oldDeclElementType;
   1027   userData = oldUserData;
   1028   if (oldUserData == oldHandlerArg)
   1029     handlerArg = userData;
   1030   else
   1031     handlerArg = parser;
   1032   if (oldExternalEntityRefHandlerArg != oldParser)
   1033     externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
   1034   defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
   1035   ns_triplets = oldns_triplets;
   1036   parentParser = oldParser;
   1037 #ifdef XML_DTD
   1038   paramEntityParsing = oldParamEntityParsing;
   1039   prologState.inEntityValue = oldInEntityValue;
   1040   if (context) {
   1041 #endif /* XML_DTD */
   1042     if (!dtdCopy(_dtd, oldDtd, &parser->m_mem)
   1043       || !setContext(parser, context)) {
   1044       XML_ParserFree(parser);
   1045       return NULL;
   1046     }
   1047     processor = externalEntityInitProcessor;
   1048 #ifdef XML_DTD
   1049   }
   1050   else {
   1051     /* The DTD instance referenced by _dtd is shared between the document's
   1052        root parser and external PE parsers, therefore one does not need to
   1053        call setContext. In addition, one also *must* not call setContext,
   1054        because this would overwrite existing prefix->binding pointers in
   1055        _dtd with ones that get destroyed with the external PE parser.
   1056        This would leave those prefixes with dangling pointers.
   1057     */
   1058     isParamEntity = XML_TRUE;
   1059     XmlPrologStateInitExternalEntity(&prologState);
   1060     processor = externalParEntInitProcessor;
   1061   }
   1062 #endif /* XML_DTD */
   1063   return parser;
   1064 }
   1065 
   1066 static void FASTCALL
   1067 destroyBindings(BINDING *bindings, XML_Parser parser)
   1068 {
   1069   for (;;) {
   1070     BINDING *b = bindings;
   1071     if (!b)
   1072       break;
   1073     bindings = b->nextTagBinding;
   1074     FREE(b->uri);
   1075     FREE(b);
   1076   }
   1077 }
   1078 
   1079 void XMLCALL
   1080 XML_ParserFree(XML_Parser parser)
   1081 {
   1082   TAG *tagList;
   1083   OPEN_INTERNAL_ENTITY *entityList;
   1084   if (parser == NULL)
   1085     return;
   1086   /* free tagStack and freeTagList */
   1087   tagList = tagStack;
   1088   for (;;) {
   1089     TAG *p;
   1090     if (tagList == NULL) {
   1091       if (freeTagList == NULL)
   1092         break;
   1093       tagList = freeTagList;
   1094       freeTagList = NULL;
   1095     }
   1096     p = tagList;
   1097     tagList = tagList->parent;
   1098     FREE(p->buf);
   1099     destroyBindings(p->bindings, parser);
   1100     FREE(p);
   1101   }
   1102   /* free openInternalEntities and freeInternalEntities */
   1103   entityList = openInternalEntities;
   1104   for (;;) {
   1105     OPEN_INTERNAL_ENTITY *openEntity;
   1106     if (entityList == NULL) {
   1107       if (freeInternalEntities == NULL)
   1108         break;
   1109       entityList = freeInternalEntities;
   1110       freeInternalEntities = NULL;
   1111     }
   1112     openEntity = entityList;
   1113     entityList = entityList->next;
   1114     FREE(openEntity);
   1115   }
   1116 
   1117   destroyBindings(freeBindingList, parser);
   1118   destroyBindings(inheritedBindings, parser);
   1119   poolDestroy(&tempPool);
   1120   poolDestroy(&temp2Pool);
   1121 #ifdef XML_DTD
   1122   /* external parameter entity parsers share the DTD structure
   1123      parser->m_dtd with the root parser, so we must not destroy it
   1124   */
   1125   if (!isParamEntity && _dtd)
   1126 #else
   1127   if (_dtd)
   1128 #endif /* XML_DTD */
   1129     dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
   1130   FREE((void *)atts);
   1131   FREE(groupConnector);
   1132   FREE(buffer);
   1133   FREE(dataBuf);
   1134   FREE(nsAtts);
   1135   FREE(unknownEncodingMem);
   1136   if (unknownEncodingRelease)
   1137     unknownEncodingRelease(unknownEncodingData);
   1138   FREE(parser);
   1139 }
   1140 
   1141 void XMLCALL
   1142 XML_UseParserAsHandlerArg(XML_Parser parser)
   1143 {
   1144   handlerArg = parser;
   1145 }
   1146 
   1147 enum XML_Error XMLCALL
   1148 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
   1149 {
   1150 #ifdef XML_DTD
   1151   /* block after XML_Parse()/XML_ParseBuffer() has been called */
   1152   if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
   1153     return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
   1154   useForeignDTD = useDTD;
   1155   return XML_ERROR_NONE;
   1156 #else
   1157   return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
   1158 #endif
   1159 }
   1160 
   1161 void XMLCALL
   1162 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
   1163 {
   1164   /* block after XML_Parse()/XML_ParseBuffer() has been called */
   1165   if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
   1166     return;
   1167   ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
   1168 }
   1169 
   1170 void XMLCALL
   1171 XML_SetUserData(XML_Parser parser, void *p)
   1172 {
   1173   if (handlerArg == userData)
   1174     handlerArg = userData = p;
   1175   else
   1176     userData = p;
   1177 }
   1178 
   1179 enum XML_Status XMLCALL
   1180 XML_SetBase(XML_Parser parser, const XML_Char *p)
   1181 {
   1182   if (p) {
   1183     p = poolCopyString(&_dtd->pool, p);
   1184     if (!p)
   1185       return XML_STATUS_ERROR;
   1186     curBase = p;
   1187   }
   1188   else
   1189     curBase = NULL;
   1190   return XML_STATUS_OK;
   1191 }
   1192 
   1193 const XML_Char * XMLCALL
   1194 XML_GetBase(XML_Parser parser)
   1195 {
   1196   return curBase;
   1197 }
   1198 
   1199 int XMLCALL
   1200 XML_GetSpecifiedAttributeCount(XML_Parser parser)
   1201 {
   1202   return nSpecifiedAtts;
   1203 }
   1204 
   1205 int XMLCALL
   1206 XML_GetIdAttributeIndex(XML_Parser parser)
   1207 {
   1208   return idAttIndex;
   1209 }
   1210 
   1211 void XMLCALL
   1212 XML_SetElementHandler(XML_Parser parser,
   1213                       XML_StartElementHandler start,
   1214                       XML_EndElementHandler end)
   1215 {
   1216   startElementHandler = start;
   1217   endElementHandler = end;
   1218 }
   1219 
   1220 void XMLCALL
   1221 XML_SetStartElementHandler(XML_Parser parser,
   1222                            XML_StartElementHandler start) {
   1223   startElementHandler = start;
   1224 }
   1225 
   1226 void XMLCALL
   1227 XML_SetEndElementHandler(XML_Parser parser,
   1228                          XML_EndElementHandler end) {
   1229   endElementHandler = end;
   1230 }
   1231 
   1232 void XMLCALL
   1233 XML_SetCharacterDataHandler(XML_Parser parser,
   1234                             XML_CharacterDataHandler handler)
   1235 {
   1236   characterDataHandler = handler;
   1237 }
   1238 
   1239 void XMLCALL
   1240 XML_SetProcessingInstructionHandler(XML_Parser parser,
   1241                                     XML_ProcessingInstructionHandler handler)
   1242 {
   1243   processingInstructionHandler = handler;
   1244 }
   1245 
   1246 void XMLCALL
   1247 XML_SetCommentHandler(XML_Parser parser,
   1248                       XML_CommentHandler handler)
   1249 {
   1250   commentHandler = handler;
   1251 }
   1252 
   1253 void XMLCALL
   1254 XML_SetCdataSectionHandler(XML_Parser parser,
   1255                            XML_StartCdataSectionHandler start,
   1256                            XML_EndCdataSectionHandler end)
   1257 {
   1258   startCdataSectionHandler = start;
   1259   endCdataSectionHandler = end;
   1260 }
   1261 
   1262 void XMLCALL
   1263 XML_SetStartCdataSectionHandler(XML_Parser parser,
   1264                                 XML_StartCdataSectionHandler start) {
   1265   startCdataSectionHandler = start;
   1266 }
   1267 
   1268 void XMLCALL
   1269 XML_SetEndCdataSectionHandler(XML_Parser parser,
   1270                               XML_EndCdataSectionHandler end) {
   1271   endCdataSectionHandler = end;
   1272 }
   1273 
   1274 void XMLCALL
   1275 XML_SetDefaultHandler(XML_Parser parser,
   1276                       XML_DefaultHandler handler)
   1277 {
   1278   defaultHandler = handler;
   1279   defaultExpandInternalEntities = XML_FALSE;
   1280 }
   1281 
   1282 void XMLCALL
   1283 XML_SetDefaultHandlerExpand(XML_Parser parser,
   1284                             XML_DefaultHandler handler)
   1285 {
   1286   defaultHandler = handler;
   1287   defaultExpandInternalEntities = XML_TRUE;
   1288 }
   1289 
   1290 void XMLCALL
   1291 XML_SetDoctypeDeclHandler(XML_Parser parser,
   1292                           XML_StartDoctypeDeclHandler start,
   1293                           XML_EndDoctypeDeclHandler end)
   1294 {
   1295   startDoctypeDeclHandler = start;
   1296   endDoctypeDeclHandler = end;
   1297 }
   1298 
   1299 void XMLCALL
   1300 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
   1301                                XML_StartDoctypeDeclHandler start) {
   1302   startDoctypeDeclHandler = start;
   1303 }
   1304 
   1305 void XMLCALL
   1306 XML_SetEndDoctypeDeclHandler(XML_Parser parser,
   1307                              XML_EndDoctypeDeclHandler end) {
   1308   endDoctypeDeclHandler = end;
   1309 }
   1310 
   1311 void XMLCALL
   1312 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
   1313                                  XML_UnparsedEntityDeclHandler handler)
   1314 {
   1315   unparsedEntityDeclHandler = handler;
   1316 }
   1317 
   1318 void XMLCALL
   1319 XML_SetNotationDeclHandler(XML_Parser parser,
   1320                            XML_NotationDeclHandler handler)
   1321 {
   1322   notationDeclHandler = handler;
   1323 }
   1324 
   1325 void XMLCALL
   1326 XML_SetNamespaceDeclHandler(XML_Parser parser,
   1327                             XML_StartNamespaceDeclHandler start,
   1328                             XML_EndNamespaceDeclHandler end)
   1329 {
   1330   startNamespaceDeclHandler = start;
   1331   endNamespaceDeclHandler = end;
   1332 }
   1333 
   1334 void XMLCALL
   1335 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
   1336                                  XML_StartNamespaceDeclHandler start) {
   1337   startNamespaceDeclHandler = start;
   1338 }
   1339 
   1340 void XMLCALL
   1341 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
   1342                                XML_EndNamespaceDeclHandler end) {
   1343   endNamespaceDeclHandler = end;
   1344 }
   1345 
   1346 void XMLCALL
   1347 XML_SetNotStandaloneHandler(XML_Parser parser,
   1348                             XML_NotStandaloneHandler handler)
   1349 {
   1350   notStandaloneHandler = handler;
   1351 }
   1352 
   1353 void XMLCALL
   1354 XML_SetExternalEntityRefHandler(XML_Parser parser,
   1355                                 XML_ExternalEntityRefHandler handler)
   1356 {
   1357   externalEntityRefHandler = handler;
   1358 }
   1359 
   1360 void XMLCALL
   1361 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
   1362 {
   1363   if (arg)
   1364     externalEntityRefHandlerArg = (XML_Parser)arg;
   1365   else
   1366     externalEntityRefHandlerArg = parser;
   1367 }
   1368 
   1369 void XMLCALL
   1370 XML_SetSkippedEntityHandler(XML_Parser parser,
   1371                             XML_SkippedEntityHandler handler)
   1372 {
   1373   skippedEntityHandler = handler;
   1374 }
   1375 
   1376 void XMLCALL
   1377 XML_SetUnknownEncodingHandler(XML_Parser parser,
   1378                               XML_UnknownEncodingHandler handler,
   1379                               void *data)
   1380 {
   1381   unknownEncodingHandler = handler;
   1382   unknownEncodingHandlerData = data;
   1383 }
   1384 
   1385 void XMLCALL
   1386 XML_SetElementDeclHandler(XML_Parser parser,
   1387                           XML_ElementDeclHandler eldecl)
   1388 {
   1389   elementDeclHandler = eldecl;
   1390 }
   1391 
   1392 void XMLCALL
   1393 XML_SetAttlistDeclHandler(XML_Parser parser,
   1394                           XML_AttlistDeclHandler attdecl)
   1395 {
   1396   attlistDeclHandler = attdecl;
   1397 }
   1398 
   1399 void XMLCALL
   1400 XML_SetEntityDeclHandler(XML_Parser parser,
   1401                          XML_EntityDeclHandler handler)
   1402 {
   1403   entityDeclHandler = handler;
   1404 }
   1405 
   1406 void XMLCALL
   1407 XML_SetXmlDeclHandler(XML_Parser parser,
   1408                       XML_XmlDeclHandler handler) {
   1409   xmlDeclHandler = handler;
   1410 }
   1411 
   1412 int XMLCALL
   1413 XML_SetParamEntityParsing(XML_Parser parser,
   1414                           enum XML_ParamEntityParsing peParsing)
   1415 {
   1416   /* block after XML_Parse()/XML_ParseBuffer() has been called */
   1417   if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
   1418     return 0;
   1419 #ifdef XML_DTD
   1420   paramEntityParsing = peParsing;
   1421   return 1;
   1422 #else
   1423   return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
   1424 #endif
   1425 }
   1426 
   1427 enum XML_Status XMLCALL
   1428 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
   1429 {
   1430   switch (ps_parsing) {
   1431   case XML_SUSPENDED:
   1432     errorCode = XML_ERROR_SUSPENDED;
   1433     return XML_STATUS_ERROR;
   1434   case XML_FINISHED:
   1435     errorCode = XML_ERROR_FINISHED;
   1436     return XML_STATUS_ERROR;
   1437   default:
   1438     ps_parsing = XML_PARSING;
   1439   }
   1440 
   1441   if (len == 0) {
   1442     ps_finalBuffer = (XML_Bool)isFinal;
   1443     if (!isFinal)
   1444       return XML_STATUS_OK;
   1445     positionPtr = bufferPtr;
   1446     parseEndPtr = bufferEnd;
   1447 
   1448     /* If data are left over from last buffer, and we now know that these
   1449        data are the final chunk of input, then we have to check them again
   1450        to detect errors based on that fact.
   1451     */
   1452     errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
   1453 
   1454     if (errorCode == XML_ERROR_NONE) {
   1455       switch (ps_parsing) {
   1456       case XML_SUSPENDED:
   1457         XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
   1458         positionPtr = bufferPtr;
   1459         return XML_STATUS_SUSPENDED;
   1460       case XML_INITIALIZED:
   1461       case XML_PARSING:
   1462         ps_parsing = XML_FINISHED;
   1463         /* fall through */
   1464       default:
   1465         return XML_STATUS_OK;
   1466       }
   1467     }
   1468     eventEndPtr = eventPtr;
   1469     processor = errorProcessor;
   1470     return XML_STATUS_ERROR;
   1471   }
   1472 #ifndef XML_CONTEXT_BYTES
   1473   else if (bufferPtr == bufferEnd) {
   1474     const char *end;
   1475     int nLeftOver;
   1476     enum XML_Error result;
   1477     parseEndByteIndex += len;
   1478     positionPtr = s;
   1479     ps_finalBuffer = (XML_Bool)isFinal;
   1480 
   1481     errorCode = processor(parser, s, parseEndPtr = s + len, &end);
   1482 
   1483     if (errorCode != XML_ERROR_NONE) {
   1484       eventEndPtr = eventPtr;
   1485       processor = errorProcessor;
   1486       return XML_STATUS_ERROR;
   1487     }
   1488     else {
   1489       switch (ps_parsing) {
   1490       case XML_SUSPENDED:
   1491         result = XML_STATUS_SUSPENDED;
   1492         break;
   1493       case XML_INITIALIZED:
   1494       case XML_PARSING:
   1495         result = XML_STATUS_OK;
   1496         if (isFinal) {
   1497           ps_parsing = XML_FINISHED;
   1498           return result;
   1499         }
   1500         break;
   1501       default:
   1502         /* XML_FINISHED case required by compiler - but not tested - djv */
   1503         return XML_STATUS_OK;
   1504       }
   1505     }
   1506 
   1507     XmlUpdatePosition(encoding, positionPtr, end, &position);
   1508     nLeftOver = s + len - end;
   1509     if (nLeftOver) {
   1510       if (buffer == NULL || nLeftOver > bufferLim - buffer) {
   1511         /* FIXME avoid integer overflow */
   1512         char *temp;
   1513         temp = (buffer == NULL
   1514                 ? (char *)MALLOC(len * 2)
   1515                 : (char *)REALLOC(buffer, len * 2));
   1516         if (temp == NULL) {
   1517           errorCode = XML_ERROR_NO_MEMORY;
   1518           return XML_STATUS_ERROR;
   1519         }
   1520         buffer = temp;
   1521         if (!buffer) {
   1522           errorCode = XML_ERROR_NO_MEMORY;
   1523           eventPtr = eventEndPtr = NULL;
   1524           processor = errorProcessor;
   1525           return XML_STATUS_ERROR;
   1526         }
   1527         bufferLim = buffer + len * 2;
   1528       }
   1529       memcpy(buffer, end, nLeftOver);
   1530     }
   1531     bufferPtr = buffer;
   1532     bufferEnd = buffer + nLeftOver;
   1533     positionPtr = bufferPtr;
   1534     parseEndPtr = bufferEnd;
   1535     eventPtr = bufferPtr;
   1536     eventEndPtr = bufferPtr;
   1537     return result;
   1538   }
   1539 #endif  /* not defined XML_CONTEXT_BYTES */
   1540   else {
   1541     void *buff = XML_GetBuffer(parser, len);
   1542     if (buff == NULL)
   1543       return XML_STATUS_ERROR;
   1544     else {
   1545       memcpy(buff, s, len);
   1546       return XML_ParseBuffer(parser, len, isFinal);
   1547     }
   1548   }
   1549 }
   1550 
   1551 enum XML_Status XMLCALL
   1552 XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
   1553 {
   1554   const char *start;
   1555   enum XML_Status result = XML_STATUS_OK;
   1556 
   1557   switch (ps_parsing) {
   1558   case XML_SUSPENDED:
   1559     errorCode = XML_ERROR_SUSPENDED;
   1560     return XML_STATUS_ERROR;
   1561   case XML_FINISHED:
   1562     errorCode = XML_ERROR_FINISHED;
   1563     return XML_STATUS_ERROR;
   1564   default:
   1565     ps_parsing = XML_PARSING;
   1566   }
   1567 
   1568   start = bufferPtr;
   1569   positionPtr = start;
   1570   bufferEnd += len;
   1571   parseEndPtr = bufferEnd;
   1572   parseEndByteIndex += len;
   1573   ps_finalBuffer = (XML_Bool)isFinal;
   1574 
   1575   errorCode = processor(parser, start, parseEndPtr, &bufferPtr);
   1576 
   1577   if (errorCode != XML_ERROR_NONE) {
   1578     eventEndPtr = eventPtr;
   1579     processor = errorProcessor;
   1580     return XML_STATUS_ERROR;
   1581   }
   1582   else {
   1583     switch (ps_parsing) {
   1584     case XML_SUSPENDED:
   1585       result = XML_STATUS_SUSPENDED;
   1586       break;
   1587     case XML_INITIALIZED:
   1588     case XML_PARSING:
   1589       if (isFinal) {
   1590         ps_parsing = XML_FINISHED;
   1591         return result;
   1592       }
   1593     default: ;  /* should not happen */
   1594     }
   1595   }
   1596 
   1597   XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
   1598   positionPtr = bufferPtr;
   1599   return result;
   1600 }
   1601 
   1602 void * XMLCALL
   1603 XML_GetBuffer(XML_Parser parser, int len)
   1604 {
   1605   switch (ps_parsing) {
   1606   case XML_SUSPENDED:
   1607     errorCode = XML_ERROR_SUSPENDED;
   1608     return NULL;
   1609   case XML_FINISHED:
   1610     errorCode = XML_ERROR_FINISHED;
   1611     return NULL;
   1612   default: ;
   1613   }
   1614 
   1615   if (len > bufferLim - bufferEnd) {
   1616     /* FIXME avoid integer overflow */
   1617     int neededSize = len + (int)(bufferEnd - bufferPtr);
   1618 #ifdef XML_CONTEXT_BYTES
   1619     int keep = (int)(bufferPtr - buffer);
   1620 
   1621     if (keep > XML_CONTEXT_BYTES)
   1622       keep = XML_CONTEXT_BYTES;
   1623     neededSize += keep;
   1624 #endif  /* defined XML_CONTEXT_BYTES */
   1625     if (neededSize  <= bufferLim - buffer) {
   1626 #ifdef XML_CONTEXT_BYTES
   1627       if (keep < bufferPtr - buffer) {
   1628         int offset = (int)(bufferPtr - buffer) - keep;
   1629         memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
   1630         bufferEnd -= offset;
   1631         bufferPtr -= offset;
   1632       }
   1633 #else
   1634       memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
   1635       bufferEnd = buffer + (bufferEnd - bufferPtr);
   1636       bufferPtr = buffer;
   1637 #endif  /* not defined XML_CONTEXT_BYTES */
   1638     }
   1639     else {
   1640       char *newBuf;
   1641       int bufferSize = (int)(bufferLim - bufferPtr);
   1642       if (bufferSize == 0)
   1643         bufferSize = INIT_BUFFER_SIZE;
   1644       do {
   1645         bufferSize *= 2;
   1646       } while (bufferSize < neededSize);
   1647       newBuf = (char *)MALLOC(bufferSize);
   1648       if (newBuf == 0) {
   1649         errorCode = XML_ERROR_NO_MEMORY;
   1650         return NULL;
   1651       }
   1652       bufferLim = newBuf + bufferSize;
   1653 #ifdef XML_CONTEXT_BYTES
   1654       if (bufferPtr) {
   1655         int keep = (int)(bufferPtr - buffer);
   1656         if (keep > XML_CONTEXT_BYTES)
   1657           keep = XML_CONTEXT_BYTES;
   1658         memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
   1659         FREE(buffer);
   1660         buffer = newBuf;
   1661         bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
   1662         bufferPtr = buffer + keep;
   1663       }
   1664       else {
   1665         bufferEnd = newBuf + (bufferEnd - bufferPtr);
   1666         bufferPtr = buffer = newBuf;
   1667       }
   1668 #else
   1669       if (bufferPtr) {
   1670         memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
   1671         FREE(buffer);
   1672       }
   1673       bufferEnd = newBuf + (bufferEnd - bufferPtr);
   1674       bufferPtr = buffer = newBuf;
   1675 #endif  /* not defined XML_CONTEXT_BYTES */
   1676     }
   1677   }
   1678   return bufferEnd;
   1679 }
   1680 
   1681 enum XML_Status XMLCALL
   1682 XML_StopParser(XML_Parser parser, XML_Bool resumable)
   1683 {
   1684   switch (ps_parsing) {
   1685   case XML_SUSPENDED:
   1686     if (resumable) {
   1687       errorCode = XML_ERROR_SUSPENDED;
   1688       return XML_STATUS_ERROR;
   1689     }
   1690     ps_parsing = XML_FINISHED;
   1691     break;
   1692   case XML_FINISHED:
   1693     errorCode = XML_ERROR_FINISHED;
   1694     return XML_STATUS_ERROR;
   1695   default:
   1696     if (resumable) {
   1697 #ifdef XML_DTD
   1698       if (isParamEntity) {
   1699         errorCode = XML_ERROR_SUSPEND_PE;
   1700         return XML_STATUS_ERROR;
   1701       }
   1702 #endif
   1703       ps_parsing = XML_SUSPENDED;
   1704     }
   1705     else
   1706       ps_parsing = XML_FINISHED;
   1707   }
   1708   return XML_STATUS_OK;
   1709 }
   1710 
   1711 enum XML_Status XMLCALL
   1712 XML_ResumeParser(XML_Parser parser)
   1713 {
   1714   enum XML_Status result = XML_STATUS_OK;
   1715 
   1716   if (ps_parsing != XML_SUSPENDED) {
   1717     errorCode = XML_ERROR_NOT_SUSPENDED;
   1718     return XML_STATUS_ERROR;
   1719   }
   1720   ps_parsing = XML_PARSING;
   1721 
   1722   errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
   1723 
   1724   if (errorCode != XML_ERROR_NONE) {
   1725     eventEndPtr = eventPtr;
   1726     processor = errorProcessor;
   1727     return XML_STATUS_ERROR;
   1728   }
   1729   else {
   1730     switch (ps_parsing) {
   1731     case XML_SUSPENDED:
   1732       result = XML_STATUS_SUSPENDED;
   1733       break;
   1734     case XML_INITIALIZED:
   1735     case XML_PARSING:
   1736       if (ps_finalBuffer) {
   1737         ps_parsing = XML_FINISHED;
   1738         return result;
   1739       }
   1740     default: ;
   1741     }
   1742   }
   1743 
   1744   XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
   1745   positionPtr = bufferPtr;
   1746   return result;
   1747 }
   1748 
   1749 void XMLCALL
   1750 XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
   1751 {
   1752   assert(status != NULL);
   1753   *status = parser->m_parsingStatus;
   1754 }
   1755 
   1756 enum XML_Error XMLCALL
   1757 XML_GetErrorCode(XML_Parser parser)
   1758 {
   1759   return errorCode;
   1760 }
   1761 
   1762 XML_Index XMLCALL
   1763 XML_GetCurrentByteIndex(XML_Parser parser)
   1764 {
   1765   if (eventPtr)
   1766     return parseEndByteIndex - (parseEndPtr - eventPtr);
   1767   return -1;
   1768 }
   1769 
   1770 int XMLCALL
   1771 XML_GetCurrentByteCount(XML_Parser parser)
   1772 {
   1773   if (eventEndPtr && eventPtr)
   1774     return (int)(eventEndPtr - eventPtr);
   1775   return 0;
   1776 }
   1777 
   1778 const char * XMLCALL
   1779 XML_GetInputContext(XML_Parser parser, int *offset, int *size)
   1780 {
   1781 #ifdef XML_CONTEXT_BYTES
   1782   if (eventPtr && buffer) {
   1783     *offset = (int)(eventPtr - buffer);
   1784     *size   = (int)(bufferEnd - buffer);
   1785     return buffer;
   1786   }
   1787 #endif /* defined XML_CONTEXT_BYTES */
   1788   return (char *) 0;
   1789 }
   1790 
   1791 XML_Size XMLCALL
   1792 XML_GetCurrentLineNumber(XML_Parser parser)
   1793 {
   1794   if (eventPtr && eventPtr >= positionPtr) {
   1795     XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
   1796     positionPtr = eventPtr;
   1797   }
   1798   return position.lineNumber + 1;
   1799 }
   1800 
   1801 XML_Size XMLCALL
   1802 XML_GetCurrentColumnNumber(XML_Parser parser)
   1803 {
   1804   if (eventPtr && eventPtr >= positionPtr) {
   1805     XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
   1806     positionPtr = eventPtr;
   1807   }
   1808   return position.columnNumber;
   1809 }
   1810 
   1811 void XMLCALL
   1812 XML_FreeContentModel(XML_Parser parser, XML_Content *model)
   1813 {
   1814   FREE(model);
   1815 }
   1816 
   1817 void * XMLCALL
   1818 XML_MemMalloc(XML_Parser parser, size_t size)
   1819 {
   1820   return MALLOC(size);
   1821 }
   1822 
   1823 void * XMLCALL
   1824 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
   1825 {
   1826   return REALLOC(ptr, size);
   1827 }
   1828 
   1829 void XMLCALL
   1830 XML_MemFree(XML_Parser parser, void *ptr)
   1831 {
   1832   FREE(ptr);
   1833 }
   1834 
   1835 void XMLCALL
   1836 XML_DefaultCurrent(XML_Parser parser)
   1837 {
   1838   if (defaultHandler) {
   1839     if (openInternalEntities)
   1840       reportDefault(parser,
   1841                     internalEncoding,
   1842                     openInternalEntities->internalEventPtr,
   1843                     openInternalEntities->internalEventEndPtr);
   1844     else
   1845       reportDefault(parser, encoding, eventPtr, eventEndPtr);
   1846   }
   1847 }
   1848 
   1849 const XML_LChar * XMLCALL
   1850 XML_ErrorString(enum XML_Error code)
   1851 {
   1852   static const XML_LChar* const message[] = {
   1853     0,
   1854     XML_L("out of memory"),
   1855     XML_L("syntax error"),
   1856     XML_L("no element found"),
   1857     XML_L("not well-formed (invalid token)"),
   1858     XML_L("unclosed token"),
   1859     XML_L("partial character"),
   1860     XML_L("mismatched tag"),
   1861     XML_L("duplicate attribute"),
   1862     XML_L("junk after document element"),
   1863     XML_L("illegal parameter entity reference"),
   1864     XML_L("undefined entity"),
   1865     XML_L("recursive entity reference"),
   1866     XML_L("asynchronous entity"),
   1867     XML_L("reference to invalid character number"),
   1868     XML_L("reference to binary entity"),
   1869     XML_L("reference to external entity in attribute"),
   1870     XML_L("XML or text declaration not at start of entity"),
   1871     XML_L("unknown encoding"),
   1872     XML_L("encoding specified in XML declaration is incorrect"),
   1873     XML_L("unclosed CDATA section"),
   1874     XML_L("error in processing external entity reference"),
   1875     XML_L("document is not standalone"),
   1876     XML_L("unexpected parser state - please send a bug report"),
   1877     XML_L("entity declared in parameter entity"),
   1878     XML_L("requested feature requires XML_DTD support in Expat"),
   1879     XML_L("cannot change setting once parsing has begun"),
   1880     XML_L("unbound prefix"),
   1881     XML_L("must not undeclare prefix"),
   1882     XML_L("incomplete markup in parameter entity"),
   1883     XML_L("XML declaration not well-formed"),
   1884     XML_L("text declaration not well-formed"),
   1885     XML_L("illegal character(s) in public id"),
   1886     XML_L("parser suspended"),
   1887     XML_L("parser not suspended"),
   1888     XML_L("parsing aborted"),
   1889     XML_L("parsing finished"),
   1890     XML_L("cannot suspend in external parameter entity"),
   1891     XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
   1892     XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
   1893     XML_L("prefix must not be bound to one of the reserved namespace names")
   1894   };
   1895   if (code > 0 && code < sizeof(message)/sizeof(message[0]))
   1896     return message[code];
   1897   return NULL;
   1898 }
   1899 
   1900 const XML_LChar * XMLCALL
   1901 XML_ExpatVersion(void) {
   1902 
   1903   /* V1 is used to string-ize the version number. However, it would
   1904      string-ize the actual version macro *names* unless we get them
   1905      substituted before being passed to V1. CPP is defined to expand
   1906      a macro, then rescan for more expansions. Thus, we use V2 to expand
   1907      the version macros, then CPP will expand the resulting V1() macro
   1908      with the correct numerals. */
   1909   /* ### I'm assuming cpp is portable in this respect... */
   1910 
   1911 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
   1912 #define V2(a,b,c) XML_L("expat_")V1(a,b,c)
   1913 
   1914   return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
   1915 
   1916 #undef V1
   1917 #undef V2
   1918 }
   1919 
   1920 XML_Expat_Version XMLCALL
   1921 XML_ExpatVersionInfo(void)
   1922 {
   1923   XML_Expat_Version version;
   1924 
   1925   version.major = XML_MAJOR_VERSION;
   1926   version.minor = XML_MINOR_VERSION;
   1927   version.micro = XML_MICRO_VERSION;
   1928 
   1929   return version;
   1930 }
   1931 
   1932 const XML_Feature * XMLCALL
   1933 XML_GetFeatureList(void)
   1934 {
   1935   static const XML_Feature features[] = {
   1936     {XML_FEATURE_SIZEOF_XML_CHAR,  XML_L("sizeof(XML_Char)"),
   1937      sizeof(XML_Char)},
   1938     {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
   1939      sizeof(XML_LChar)},
   1940 #ifdef XML_UNICODE
   1941     {XML_FEATURE_UNICODE,          XML_L("XML_UNICODE"), 0},
   1942 #endif
   1943 #ifdef XML_UNICODE_WCHAR_T
   1944     {XML_FEATURE_UNICODE_WCHAR_T,  XML_L("XML_UNICODE_WCHAR_T"), 0},
   1945 #endif
   1946 #ifdef XML_DTD
   1947     {XML_FEATURE_DTD,              XML_L("XML_DTD"), 0},
   1948 #endif
   1949 #ifdef XML_CONTEXT_BYTES
   1950     {XML_FEATURE_CONTEXT_BYTES,    XML_L("XML_CONTEXT_BYTES"),
   1951      XML_CONTEXT_BYTES},
   1952 #endif
   1953 #ifdef XML_MIN_SIZE
   1954     {XML_FEATURE_MIN_SIZE,         XML_L("XML_MIN_SIZE"), 0},
   1955 #endif
   1956 #ifdef XML_NS
   1957     {XML_FEATURE_NS,               XML_L("XML_NS"), 0},
   1958 #endif
   1959     {XML_FEATURE_END,              NULL, 0}
   1960   };
   1961 
   1962   return features;
   1963 }
   1964 
   1965 /* Initially tag->rawName always points into the parse buffer;
   1966    for those TAG instances opened while the current parse buffer was
   1967    processed, and not yet closed, we need to store tag->rawName in a more
   1968    permanent location, since the parse buffer is about to be discarded.
   1969 */
   1970 static XML_Bool
   1971 storeRawNames(XML_Parser parser)
   1972 {
   1973   TAG *tag = tagStack;
   1974   while (tag) {
   1975     int bufSize;
   1976     int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
   1977     char *rawNameBuf = tag->buf + nameLen;
   1978     /* Stop if already stored.  Since tagStack is a stack, we can stop
   1979        at the first entry that has already been copied; everything
   1980        below it in the stack is already been accounted for in a
   1981        previous call to this function.
   1982     */
   1983     if (tag->rawName == rawNameBuf)
   1984       break;
   1985     /* For re-use purposes we need to ensure that the
   1986        size of tag->buf is a multiple of sizeof(XML_Char).
   1987     */
   1988     bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
   1989     if (bufSize > tag->bufEnd - tag->buf) {
   1990       char *temp = (char *)REALLOC(tag->buf, bufSize);
   1991       if (temp == NULL)
   1992         return XML_FALSE;
   1993       /* if tag->name.str points to tag->buf (only when namespace
   1994          processing is off) then we have to update it
   1995       */
   1996       if (tag->name.str == (XML_Char *)tag->buf)
   1997         tag->name.str = (XML_Char *)temp;
   1998       /* if tag->name.localPart is set (when namespace processing is on)
   1999          then update it as well, since it will always point into tag->buf
   2000       */
   2001       if (tag->name.localPart)
   2002         tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
   2003                                                   (XML_Char *)tag->buf);
   2004       tag->buf = temp;
   2005       tag->bufEnd = temp + bufSize;
   2006       rawNameBuf = temp + nameLen;
   2007     }
   2008     memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
   2009     tag->rawName = rawNameBuf;
   2010     tag = tag->parent;
   2011   }
   2012   return XML_TRUE;
   2013 }
   2014 
   2015 static enum XML_Error PTRCALL
   2016 contentProcessor(XML_Parser parser,
   2017                  const char *start,
   2018                  const char *end,
   2019                  const char **endPtr)
   2020 {
   2021   enum XML_Error result = doContent(parser, 0, encoding, start, end,
   2022                                     endPtr, (XML_Bool)!ps_finalBuffer);
   2023   if (result == XML_ERROR_NONE) {
   2024     if (!storeRawNames(parser))
   2025       return XML_ERROR_NO_MEMORY;
   2026   }
   2027   return result;
   2028 }
   2029 
   2030 static enum XML_Error PTRCALL
   2031 externalEntityInitProcessor(XML_Parser parser,
   2032                             const char *start,
   2033                             const char *end,
   2034                             const char **endPtr)
   2035 {
   2036   enum XML_Error result = initializeEncoding(parser);
   2037   if (result != XML_ERROR_NONE)
   2038     return result;
   2039   processor = externalEntityInitProcessor2;
   2040   return externalEntityInitProcessor2(parser, start, end, endPtr);
   2041 }
   2042 
   2043 static enum XML_Error PTRCALL
   2044 externalEntityInitProcessor2(XML_Parser parser,
   2045                              const char *start,
   2046                              const char *end,
   2047                              const char **endPtr)
   2048 {
   2049   const char *next = start; /* XmlContentTok doesn't always set the last arg */
   2050   int tok = XmlContentTok(encoding, start, end, &next);
   2051   switch (tok) {
   2052   case XML_TOK_BOM:
   2053     /* If we are at the end of the buffer, this would cause the next stage,
   2054        i.e. externalEntityInitProcessor3, to pass control directly to
   2055        doContent (by detecting XML_TOK_NONE) without processing any xml text
   2056        declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
   2057     */
   2058     if (next == end && !ps_finalBuffer) {
   2059       *endPtr = next;
   2060       return XML_ERROR_NONE;
   2061     }
   2062     start = next;
   2063     break;
   2064   case XML_TOK_PARTIAL:
   2065     if (!ps_finalBuffer) {
   2066       *endPtr = start;
   2067       return XML_ERROR_NONE;
   2068     }
   2069     eventPtr = start;
   2070     return XML_ERROR_UNCLOSED_TOKEN;
   2071   case XML_TOK_PARTIAL_CHAR:
   2072     if (!ps_finalBuffer) {
   2073       *endPtr = start;
   2074       return XML_ERROR_NONE;
   2075     }
   2076     eventPtr = start;
   2077     return XML_ERROR_PARTIAL_CHAR;
   2078   }
   2079   processor = externalEntityInitProcessor3;
   2080   return externalEntityInitProcessor3(parser, start, end, endPtr);
   2081 }
   2082 
   2083 static enum XML_Error PTRCALL
   2084 externalEntityInitProcessor3(XML_Parser parser,
   2085                              const char *start,
   2086                              const char *end,
   2087                              const char **endPtr)
   2088 {
   2089   int tok;
   2090   const char *next = start; /* XmlContentTok doesn't always set the last arg */
   2091   eventPtr = start;
   2092   tok = XmlContentTok(encoding, start, end, &next);
   2093   eventEndPtr = next;
   2094 
   2095   switch (tok) {
   2096   case XML_TOK_XML_DECL:
   2097     {
   2098       enum XML_Error result;
   2099       result = processXmlDecl(parser, 1, start, next);
   2100       if (result != XML_ERROR_NONE)
   2101         return result;
   2102       switch (ps_parsing) {
   2103       case XML_SUSPENDED:
   2104         *endPtr = next;
   2105         return XML_ERROR_NONE;
   2106       case XML_FINISHED:
   2107         return XML_ERROR_ABORTED;
   2108       default:
   2109         start = next;
   2110       }
   2111     }
   2112     break;
   2113   case XML_TOK_PARTIAL:
   2114     if (!ps_finalBuffer) {
   2115       *endPtr = start;
   2116       return XML_ERROR_NONE;
   2117     }
   2118     return XML_ERROR_UNCLOSED_TOKEN;
   2119   case XML_TOK_PARTIAL_CHAR:
   2120     if (!ps_finalBuffer) {
   2121       *endPtr = start;
   2122       return XML_ERROR_NONE;
   2123     }
   2124     return XML_ERROR_PARTIAL_CHAR;
   2125   }
   2126   processor = externalEntityContentProcessor;
   2127   tagLevel = 1;
   2128   return externalEntityContentProcessor(parser, start, end, endPtr);
   2129 }
   2130 
   2131 static enum XML_Error PTRCALL
   2132 externalEntityContentProcessor(XML_Parser parser,
   2133                                const char *start,
   2134                                const char *end,
   2135                                const char **endPtr)
   2136 {
   2137   enum XML_Error result = doContent(parser, 1, encoding, start, end,
   2138                                     endPtr, (XML_Bool)!ps_finalBuffer);
   2139   if (result == XML_ERROR_NONE) {
   2140     if (!storeRawNames(parser))
   2141       return XML_ERROR_NO_MEMORY;
   2142   }
   2143   return result;
   2144 }
   2145 
   2146 static enum XML_Error
   2147 doContent(XML_Parser parser,
   2148           int startTagLevel,
   2149           const ENCODING *enc,
   2150           const char *s,
   2151           const char *end,
   2152           const char **nextPtr,
   2153           XML_Bool haveMore)
   2154 {
   2155   /* save one level of indirection */
   2156   DTD * const dtd = _dtd;
   2157 
   2158   const char **eventPP;
   2159   const char **eventEndPP;
   2160   if (enc == encoding) {
   2161     eventPP = &eventPtr;
   2162     eventEndPP = &eventEndPtr;
   2163   }
   2164   else {
   2165     eventPP = &(openInternalEntities->internalEventPtr);
   2166     eventEndPP = &(openInternalEntities->internalEventEndPtr);
   2167   }
   2168   *eventPP = s;
   2169 
   2170   for (;;) {
   2171     const char *next = s; /* XmlContentTok doesn't always set the last arg */
   2172     int tok = XmlContentTok(enc, s, end, &next);
   2173     *eventEndPP = next;
   2174     switch (tok) {
   2175     case XML_TOK_TRAILING_CR:
   2176       if (haveMore) {
   2177         *nextPtr = s;
   2178         return XML_ERROR_NONE;
   2179       }
   2180       *eventEndPP = end;
   2181       if (characterDataHandler) {
   2182         XML_Char c = 0xA;
   2183         characterDataHandler(handlerArg, &c, 1);
   2184       }
   2185       else if (defaultHandler)
   2186         reportDefault(parser, enc, s, end);
   2187       /* We are at the end of the final buffer, should we check for
   2188          XML_SUSPENDED, XML_FINISHED?
   2189       */
   2190       if (startTagLevel == 0)
   2191         return XML_ERROR_NO_ELEMENTS;
   2192       if (tagLevel != startTagLevel)
   2193         return XML_ERROR_ASYNC_ENTITY;
   2194       *nextPtr = end;
   2195       return XML_ERROR_NONE;
   2196     case XML_TOK_NONE:
   2197       if (haveMore) {
   2198         *nextPtr = s;
   2199         return XML_ERROR_NONE;
   2200       }
   2201       if (startTagLevel > 0) {
   2202         if (tagLevel != startTagLevel)
   2203           return XML_ERROR_ASYNC_ENTITY;
   2204         *nextPtr = s;
   2205         return XML_ERROR_NONE;
   2206       }
   2207       return XML_ERROR_NO_ELEMENTS;
   2208     case XML_TOK_INVALID:
   2209       *eventPP = next;
   2210       return XML_ERROR_INVALID_TOKEN;
   2211     case XML_TOK_PARTIAL:
   2212       if (haveMore) {
   2213         *nextPtr = s;
   2214         return XML_ERROR_NONE;
   2215       }
   2216       return XML_ERROR_UNCLOSED_TOKEN;
   2217     case XML_TOK_PARTIAL_CHAR:
   2218       if (haveMore) {
   2219         *nextPtr = s;
   2220         return XML_ERROR_NONE;
   2221       }
   2222       return XML_ERROR_PARTIAL_CHAR;
   2223     case XML_TOK_ENTITY_REF:
   2224       {
   2225         const XML_Char *name;
   2226         ENTITY *entity;
   2227         XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
   2228                                               s + enc->minBytesPerChar,
   2229                                               next - enc->minBytesPerChar);
   2230         if (ch) {
   2231           if (characterDataHandler)
   2232             characterDataHandler(handlerArg, &ch, 1);
   2233           else if (defaultHandler)
   2234             reportDefault(parser, enc, s, next);
   2235           break;
   2236         }
   2237         name = poolStoreString(&dtd->pool, enc,
   2238                                 s + enc->minBytesPerChar,
   2239                                 next - enc->minBytesPerChar);
   2240         if (!name)
   2241           return XML_ERROR_NO_MEMORY;
   2242         entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
   2243         poolDiscard(&dtd->pool);
   2244         /* First, determine if a check for an existing declaration is needed;
   2245            if yes, check that the entity exists, and that it is internal,
   2246            otherwise call the skipped entity or default handler.
   2247         */
   2248         if (!dtd->hasParamEntityRefs || dtd->standalone) {
   2249           if (!entity)
   2250             return XML_ERROR_UNDEFINED_ENTITY;
   2251           else if (!entity->is_internal)
   2252             return XML_ERROR_ENTITY_DECLARED_IN_PE;
   2253         }
   2254         else if (!entity) {
   2255           if (skippedEntityHandler)
   2256             skippedEntityHandler(handlerArg, name, 0);
   2257           else if (defaultHandler)
   2258             reportDefault(parser, enc, s, next);
   2259           break;
   2260         }
   2261         if (entity->open)
   2262           return XML_ERROR_RECURSIVE_ENTITY_REF;
   2263         if (entity->notation)
   2264           return XML_ERROR_BINARY_ENTITY_REF;
   2265         if (entity->textPtr) {
   2266           enum XML_Error result;
   2267           if (!defaultExpandInternalEntities) {
   2268             if (skippedEntityHandler)
   2269               skippedEntityHandler(handlerArg, entity->name, 0);
   2270             else if (defaultHandler)
   2271               reportDefault(parser, enc, s, next);
   2272             break;
   2273           }
   2274           result = processInternalEntity(parser, entity, XML_FALSE);
   2275           if (result != XML_ERROR_NONE)
   2276             return result;
   2277         }
   2278         else if (externalEntityRefHandler) {
   2279           const XML_Char *context;
   2280           entity->open = XML_TRUE;
   2281           context = getContext(parser);
   2282           entity->open = XML_FALSE;
   2283           if (!context)
   2284             return XML_ERROR_NO_MEMORY;
   2285           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
   2286                                         context,
   2287                                         entity->base,
   2288                                         entity->systemId,
   2289                                         entity->publicId))
   2290             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
   2291           poolDiscard(&tempPool);
   2292         }
   2293         else if (defaultHandler)
   2294           reportDefault(parser, enc, s, next);
   2295         break;
   2296       }
   2297     case XML_TOK_START_TAG_NO_ATTS:
   2298       /* fall through */
   2299     case XML_TOK_START_TAG_WITH_ATTS:
   2300       {
   2301         TAG *tag;
   2302         enum XML_Error result;
   2303         XML_Char *toPtr;
   2304         if (freeTagList) {
   2305           tag = freeTagList;
   2306           freeTagList = freeTagList->parent;
   2307         }
   2308         else {
   2309           tag = (TAG *)MALLOC(sizeof(TAG));
   2310           if (!tag)
   2311             return XML_ERROR_NO_MEMORY;
   2312           tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
   2313           if (!tag->buf) {
   2314             FREE(tag);
   2315             return XML_ERROR_NO_MEMORY;
   2316           }
   2317           tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
   2318         }
   2319         tag->bindings = NULL;
   2320         tag->parent = tagStack;
   2321         tagStack = tag;
   2322         tag->name.localPart = NULL;
   2323         tag->name.prefix = NULL;
   2324         tag->rawName = s + enc->minBytesPerChar;
   2325         tag->rawNameLength = XmlNameLength(enc, tag->rawName);
   2326         ++tagLevel;
   2327         {
   2328           const char *rawNameEnd = tag->rawName + tag->rawNameLength;
   2329           const char *fromPtr = tag->rawName;
   2330           toPtr = (XML_Char *)tag->buf;
   2331           for (;;) {
   2332             int bufSize;
   2333             int convLen;
   2334             XmlConvert(enc,
   2335                        &fromPtr, rawNameEnd,
   2336                        (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
   2337             convLen = (int)(toPtr - (XML_Char *)tag->buf);
   2338             if (fromPtr == rawNameEnd) {
   2339               tag->name.strLen = convLen;
   2340               break;
   2341             }
   2342             bufSize = (int)(tag->bufEnd - tag->buf) << 1;
   2343             {
   2344               char *temp = (char *)REALLOC(tag->buf, bufSize);
   2345               if (temp == NULL)
   2346                 return XML_ERROR_NO_MEMORY;
   2347               tag->buf = temp;
   2348               tag->bufEnd = temp + bufSize;
   2349               toPtr = (XML_Char *)temp + convLen;
   2350             }
   2351           }
   2352         }
   2353         tag->name.str = (XML_Char *)tag->buf;
   2354         *toPtr = XML_T('\0');
   2355         result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
   2356         if (result)
   2357           return result;
   2358         if (startElementHandler)
   2359           startElementHandler(handlerArg, tag->name.str,
   2360                               (const XML_Char **)atts);
   2361         else if (defaultHandler)
   2362           reportDefault(parser, enc, s, next);
   2363         poolClear(&tempPool);
   2364         break;
   2365       }
   2366     case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
   2367       /* fall through */
   2368     case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
   2369       {
   2370         const char *rawName = s + enc->minBytesPerChar;
   2371         enum XML_Error result;
   2372         BINDING *bindings = NULL;
   2373         XML_Bool noElmHandlers = XML_TRUE;
   2374         TAG_NAME name;
   2375         name.str = poolStoreString(&tempPool, enc, rawName,
   2376                                    rawName + XmlNameLength(enc, rawName));
   2377         if (!name.str)
   2378           return XML_ERROR_NO_MEMORY;
   2379         poolFinish(&tempPool);
   2380         result = storeAtts(parser, enc, s, &name, &bindings);
   2381         if (result)
   2382           return result;
   2383         poolFinish(&tempPool);
   2384         if (startElementHandler) {
   2385           startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
   2386           noElmHandlers = XML_FALSE;
   2387         }
   2388         if (endElementHandler) {
   2389           if (startElementHandler)
   2390             *eventPP = *eventEndPP;
   2391           endElementHandler(handlerArg, name.str);
   2392           noElmHandlers = XML_FALSE;
   2393         }
   2394         if (noElmHandlers && defaultHandler)
   2395           reportDefault(parser, enc, s, next);
   2396         poolClear(&tempPool);
   2397         while (bindings) {
   2398           BINDING *b = bindings;
   2399           if (endNamespaceDeclHandler)
   2400             endNamespaceDeclHandler(handlerArg, b->prefix->name);
   2401           bindings = bindings->nextTagBinding;
   2402           b->nextTagBinding = freeBindingList;
   2403           freeBindingList = b;
   2404           b->prefix->binding = b->prevPrefixBinding;
   2405         }
   2406       }
   2407       if (tagLevel == 0)
   2408         return epilogProcessor(parser, next, end, nextPtr);
   2409       break;
   2410     case XML_TOK_END_TAG:
   2411       if (tagLevel == startTagLevel)
   2412         return XML_ERROR_ASYNC_ENTITY;
   2413       else {
   2414         int len;
   2415         const char *rawName;
   2416         TAG *tag = tagStack;
   2417         tagStack = tag->parent;
   2418         tag->parent = freeTagList;
   2419         freeTagList = tag;
   2420         rawName = s + enc->minBytesPerChar*2;
   2421         len = XmlNameLength(enc, rawName);
   2422         if (len != tag->rawNameLength
   2423             || memcmp(tag->rawName, rawName, len) != 0) {
   2424           *eventPP = rawName;
   2425           return XML_ERROR_TAG_MISMATCH;
   2426         }
   2427         --tagLevel;
   2428         if (endElementHandler) {
   2429           const XML_Char *localPart;
   2430           const XML_Char *prefix;
   2431           XML_Char *uri;
   2432           localPart = tag->name.localPart;
   2433           if (ns && localPart) {
   2434             /* localPart and prefix may have been overwritten in
   2435                tag->name.str, since this points to the binding->uri
   2436                buffer which gets re-used; so we have to add them again
   2437             */
   2438             uri = (XML_Char *)tag->name.str + tag->name.uriLen;
   2439             /* don't need to check for space - already done in storeAtts() */
   2440             while (*localPart) *uri++ = *localPart++;
   2441             prefix = (XML_Char *)tag->name.prefix;
   2442             if (ns_triplets && prefix) {
   2443               *uri++ = namespaceSeparator;
   2444               while (*prefix) *uri++ = *prefix++;
   2445              }
   2446             *uri = XML_T('\0');
   2447           }
   2448           endElementHandler(handlerArg, tag->name.str);
   2449         }
   2450         else if (defaultHandler)
   2451           reportDefault(parser, enc, s, next);
   2452         while (tag->bindings) {
   2453           BINDING *b = tag->bindings;
   2454           if (endNamespaceDeclHandler)
   2455             endNamespaceDeclHandler(handlerArg, b->prefix->name);
   2456           tag->bindings = tag->bindings->nextTagBinding;
   2457           b->nextTagBinding = freeBindingList;
   2458           freeBindingList = b;
   2459           b->prefix->binding = b->prevPrefixBinding;
   2460         }
   2461         if (tagLevel == 0)
   2462           return epilogProcessor(parser, next, end, nextPtr);
   2463       }
   2464       break;
   2465     case XML_TOK_CHAR_REF:
   2466       {
   2467         int n = XmlCharRefNumber(enc, s);
   2468         if (n < 0)
   2469           return XML_ERROR_BAD_CHAR_REF;
   2470         if (characterDataHandler) {
   2471           XML_Char buf[XML_ENCODE_MAX];
   2472           characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
   2473         }
   2474         else if (defaultHandler)
   2475           reportDefault(parser, enc, s, next);
   2476       }
   2477       break;
   2478     case XML_TOK_XML_DECL:
   2479       return XML_ERROR_MISPLACED_XML_PI;
   2480     case XML_TOK_DATA_NEWLINE:
   2481       if (characterDataHandler) {
   2482         XML_Char c = 0xA;
   2483         characterDataHandler(handlerArg, &c, 1);
   2484       }
   2485       else if (defaultHandler)
   2486         reportDefault(parser, enc, s, next);
   2487       break;
   2488     case XML_TOK_CDATA_SECT_OPEN:
   2489       {
   2490         enum XML_Error result;
   2491         if (startCdataSectionHandler)
   2492           startCdataSectionHandler(handlerArg);
   2493 #if 0
   2494         /* Suppose you doing a transformation on a document that involves
   2495            changing only the character data.  You set up a defaultHandler
   2496            and a characterDataHandler.  The defaultHandler simply copies
   2497            characters through.  The characterDataHandler does the
   2498            transformation and writes the characters out escaping them as
   2499            necessary.  This case will fail to work if we leave out the
   2500            following two lines (because & and < inside CDATA sections will
   2501            be incorrectly escaped).
   2502 
   2503            However, now we have a start/endCdataSectionHandler, so it seems
   2504            easier to let the user deal with this.
   2505         */
   2506         else if (characterDataHandler)
   2507           characterDataHandler(handlerArg, dataBuf, 0);
   2508 #endif
   2509         else if (defaultHandler)
   2510           reportDefault(parser, enc, s, next);
   2511         result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
   2512         if (result != XML_ERROR_NONE)
   2513           return result;
   2514         else if (!next) {
   2515           processor = cdataSectionProcessor;
   2516           return result;
   2517         }
   2518       }
   2519       break;
   2520     case XML_TOK_TRAILING_RSQB:
   2521       if (haveMore) {
   2522         *nextPtr = s;
   2523         return XML_ERROR_NONE;
   2524       }
   2525       if (characterDataHandler) {
   2526         if (MUST_CONVERT(enc, s)) {
   2527           ICHAR *dataPtr = (ICHAR *)dataBuf;
   2528           XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
   2529           characterDataHandler(handlerArg, dataBuf,
   2530                                (int)(dataPtr - (ICHAR *)dataBuf));
   2531         }
   2532         else
   2533           characterDataHandler(handlerArg,
   2534                                (XML_Char *)s,
   2535                                (int)((XML_Char *)end - (XML_Char *)s));
   2536       }
   2537       else if (defaultHandler)
   2538         reportDefault(parser, enc, s, end);
   2539       /* We are at the end of the final buffer, should we check for
   2540          XML_SUSPENDED, XML_FINISHED?
   2541       */
   2542       if (startTagLevel == 0) {
   2543         *eventPP = end;
   2544         return XML_ERROR_NO_ELEMENTS;
   2545       }
   2546       if (tagLevel != startTagLevel) {
   2547         *eventPP = end;
   2548         return XML_ERROR_ASYNC_ENTITY;
   2549       }
   2550       *nextPtr = end;
   2551       return XML_ERROR_NONE;
   2552     case XML_TOK_DATA_CHARS:
   2553       if (characterDataHandler) {
   2554         if (MUST_CONVERT(enc, s)) {
   2555           for (;;) {
   2556             ICHAR *dataPtr = (ICHAR *)dataBuf;
   2557             XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
   2558             *eventEndPP = s;
   2559             characterDataHandler(handlerArg, dataBuf,
   2560                                  (int)(dataPtr - (ICHAR *)dataBuf));
   2561             if (s == next)
   2562               break;
   2563             *eventPP = s;
   2564           }
   2565         }
   2566         else
   2567           characterDataHandler(handlerArg,
   2568                                (XML_Char *)s,
   2569                                (int)((XML_Char *)next - (XML_Char *)s));
   2570       }
   2571       else if (defaultHandler)
   2572         reportDefault(parser, enc, s, next);
   2573       break;
   2574     case XML_TOK_PI:
   2575       if (!reportProcessingInstruction(parser, enc, s, next))
   2576         return XML_ERROR_NO_MEMORY;
   2577       break;
   2578     case XML_TOK_COMMENT:
   2579       if (!reportComment(parser, enc, s, next))
   2580         return XML_ERROR_NO_MEMORY;
   2581       break;
   2582     default:
   2583       if (defaultHandler)
   2584         reportDefault(parser, enc, s, next);
   2585       break;
   2586     }
   2587     *eventPP = s = next;
   2588     switch (ps_parsing) {
   2589     case XML_SUSPENDED:
   2590       *nextPtr = next;
   2591       return XML_ERROR_NONE;
   2592     case XML_FINISHED:
   2593       return XML_ERROR_ABORTED;
   2594     default: ;
   2595     }
   2596   }
   2597   /* not reached */
   2598 }
   2599 
   2600 /* Precondition: all arguments must be non-NULL;
   2601    Purpose:
   2602    - normalize attributes
   2603    - check attributes for well-formedness
   2604    - generate namespace aware attribute names (URI, prefix)
   2605    - build list of attributes for startElementHandler
   2606    - default attributes
   2607    - process namespace declarations (check and report them)
   2608    - generate namespace aware element name (URI, prefix)
   2609 */
   2610 static enum XML_Error
   2611 storeAtts(XML_Parser parser, const ENCODING *enc,
   2612           const char *attStr, TAG_NAME *tagNamePtr,
   2613           BINDING **bindingsPtr)
   2614 {
   2615   DTD * const dtd = _dtd;  /* save one level of indirection */
   2616   ELEMENT_TYPE *elementType;
   2617   int nDefaultAtts;
   2618   const XML_Char **appAtts;   /* the attribute list for the application */
   2619   int attIndex = 0;
   2620   int prefixLen;
   2621   int i;
   2622   int n;
   2623   XML_Char *uri;
   2624   int nPrefixes = 0;
   2625   BINDING *binding;
   2626   const XML_Char *localPart;
   2627 
   2628   /* lookup the element type name */
   2629   elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0);
   2630   if (!elementType) {
   2631     const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
   2632     if (!name)
   2633       return XML_ERROR_NO_MEMORY;
   2634     elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name,
   2635                                          sizeof(ELEMENT_TYPE));
   2636     if (!elementType)
   2637       return XML_ERROR_NO_MEMORY;
   2638     if (ns && !setElementTypePrefix(parser, elementType))
   2639       return XML_ERROR_NO_MEMORY;
   2640   }
   2641   nDefaultAtts = elementType->nDefaultAtts;
   2642 
   2643   /* get the attributes from the tokenizer */
   2644   n = XmlGetAttributes(enc, attStr, attsSize, atts);
   2645   if (n + nDefaultAtts > attsSize) {
   2646     int oldAttsSize = attsSize;
   2647     ATTRIBUTE *temp;
   2648     attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
   2649     temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
   2650     if (temp == NULL)
   2651       return XML_ERROR_NO_MEMORY;
   2652     atts = temp;
   2653     if (n > oldAttsSize)
   2654       XmlGetAttributes(enc, attStr, n, atts);
   2655   }
   2656 
   2657   appAtts = (const XML_Char **)atts;
   2658   for (i = 0; i < n; i++) {
   2659     /* add the name and value to the attribute list */
   2660     ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
   2661                                          atts[i].name
   2662                                          + XmlNameLength(enc, atts[i].name));
   2663     if (!attId)
   2664       return XML_ERROR_NO_MEMORY;
   2665     /* Detect duplicate attributes by their QNames. This does not work when
   2666        namespace processing is turned on and different prefixes for the same
   2667        namespace are used. For this case we have a check further down.
   2668     */
   2669     if ((attId->name)[-1]) {
   2670       if (enc == encoding)
   2671         eventPtr = atts[i].name;
   2672       return XML_ERROR_DUPLICATE_ATTRIBUTE;
   2673     }
   2674     (attId->name)[-1] = 1;
   2675     appAtts[attIndex++] = attId->name;
   2676     if (!atts[i].normalized) {
   2677       enum XML_Error result;
   2678       XML_Bool isCdata = XML_TRUE;
   2679 
   2680       /* figure out whether declared as other than CDATA */
   2681       if (attId->maybeTokenized) {
   2682         int j;
   2683         for (j = 0; j < nDefaultAtts; j++) {
   2684           if (attId == elementType->defaultAtts[j].id) {
   2685             isCdata = elementType->defaultAtts[j].isCdata;
   2686             break;
   2687           }
   2688         }
   2689       }
   2690 
   2691       /* normalize the attribute value */
   2692       result = storeAttributeValue(parser, enc, isCdata,
   2693                                    atts[i].valuePtr, atts[i].valueEnd,
   2694                                    &tempPool);
   2695       if (result)
   2696         return result;
   2697       appAtts[attIndex] = poolStart(&tempPool);
   2698       poolFinish(&tempPool);
   2699     }
   2700     else {
   2701       /* the value did not need normalizing */
   2702       appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
   2703                                           atts[i].valueEnd);
   2704       if (appAtts[attIndex] == 0)
   2705         return XML_ERROR_NO_MEMORY;
   2706       poolFinish(&tempPool);
   2707     }
   2708     /* handle prefixed attribute names */
   2709     if (attId->prefix) {
   2710       if (attId->xmlns) {
   2711         /* deal with namespace declarations here */
   2712         enum XML_Error result = addBinding(parser, attId->prefix, attId,
   2713                                            appAtts[attIndex], bindingsPtr);
   2714         if (result)
   2715           return result;
   2716         --attIndex;
   2717       }
   2718       else {
   2719         /* deal with other prefixed names later */
   2720         attIndex++;
   2721         nPrefixes++;
   2722         (attId->name)[-1] = 2;
   2723       }
   2724     }
   2725     else
   2726       attIndex++;
   2727   }
   2728 
   2729   /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
   2730   nSpecifiedAtts = attIndex;
   2731   if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
   2732     for (i = 0; i < attIndex; i += 2)
   2733       if (appAtts[i] == elementType->idAtt->name) {
   2734         idAttIndex = i;
   2735         break;
   2736       }
   2737   }
   2738   else
   2739     idAttIndex = -1;
   2740 
   2741   /* do attribute defaulting */
   2742   for (i = 0; i < nDefaultAtts; i++) {
   2743     const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
   2744     if (!(da->id->name)[-1] && da->value) {
   2745       if (da->id->prefix) {
   2746         if (da->id->xmlns) {
   2747           enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
   2748                                              da->value, bindingsPtr);
   2749           if (result)
   2750             return result;
   2751         }
   2752         else {
   2753           (da->id->name)[-1] = 2;
   2754           nPrefixes++;
   2755           appAtts[attIndex++] = da->id->name;
   2756           appAtts[attIndex++] = da->value;
   2757         }
   2758       }
   2759       else {
   2760         (da->id->name)[-1] = 1;
   2761         appAtts[attIndex++] = da->id->name;
   2762         appAtts[attIndex++] = da->value;
   2763       }
   2764     }
   2765   }
   2766   appAtts[attIndex] = 0;
   2767 
   2768   /* expand prefixed attribute names, check for duplicates,
   2769      and clear flags that say whether attributes were specified */
   2770   i = 0;
   2771   if (nPrefixes) {
   2772     int j;  /* hash table index */
   2773     unsigned long version = nsAttsVersion;
   2774     int nsAttsSize = (int)1 << nsAttsPower;
   2775     /* size of hash table must be at least 2 * (# of prefixed attributes) */
   2776     if ((nPrefixes << 1) >> nsAttsPower) {  /* true for nsAttsPower = 0 */
   2777       NS_ATT *temp;
   2778       /* hash table size must also be a power of 2 and >= 8 */
   2779       while (nPrefixes >> nsAttsPower++);
   2780       if (nsAttsPower < 3)
   2781         nsAttsPower = 3;
   2782       nsAttsSize = (int)1 << nsAttsPower;
   2783       temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
   2784       if (!temp)
   2785         return XML_ERROR_NO_MEMORY;
   2786       nsAtts = temp;
   2787       version = 0;  /* force re-initialization of nsAtts hash table */
   2788     }
   2789     /* using a version flag saves us from initializing nsAtts every time */
   2790     if (!version) {  /* initialize version flags when version wraps around */
   2791       version = INIT_ATTS_VERSION;
   2792       for (j = nsAttsSize; j != 0; )
   2793         nsAtts[--j].version = version;
   2794     }
   2795     nsAttsVersion = --version;
   2796 
   2797     /* expand prefixed names and check for duplicates */
   2798     for (; i < attIndex; i += 2) {
   2799       const XML_Char *s = appAtts[i];
   2800       if (s[-1] == 2) {  /* prefixed */
   2801         ATTRIBUTE_ID *id;
   2802         const BINDING *b;
   2803         unsigned long uriHash = 0;
   2804         ((XML_Char *)s)[-1] = 0;  /* clear flag */
   2805         id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);
   2806         if (!id)
   2807           return XML_ERROR_NO_MEMORY;
   2808         b = id->prefix->binding;
   2809         if (!b)
   2810           return XML_ERROR_UNBOUND_PREFIX;
   2811 
   2812         /* as we expand the name we also calculate its hash value */
   2813         for (j = 0; j < b->uriLen; j++) {
   2814           const XML_Char c = b->uri[j];
   2815           if (!poolAppendChar(&tempPool, c))
   2816             return XML_ERROR_NO_MEMORY;
   2817           uriHash = CHAR_HASH(uriHash, c);
   2818         }
   2819         while (*s++ != XML_T(':'))
   2820           ;
   2821         do {  /* copies null terminator */
   2822           const XML_Char c = *s;
   2823           if (!poolAppendChar(&tempPool, *s))
   2824             return XML_ERROR_NO_MEMORY;
   2825           uriHash = CHAR_HASH(uriHash, c);
   2826         } while (*s++);
   2827 
   2828         { /* Check hash table for duplicate of expanded name (uriName).
   2829              Derived from code in lookup(HASH_TABLE *table, ...).
   2830           */
   2831           unsigned char step = 0;
   2832           unsigned long mask = nsAttsSize - 1;
   2833           j = uriHash & mask;  /* index into hash table */
   2834           while (nsAtts[j].version == version) {
   2835             /* for speed we compare stored hash values first */
   2836             if (uriHash == nsAtts[j].hash) {
   2837               const XML_Char *s1 = poolStart(&tempPool);
   2838               const XML_Char *s2 = nsAtts[j].uriName;
   2839               /* s1 is null terminated, but not s2 */
   2840               for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
   2841               if (*s1 == 0)
   2842                 return XML_ERROR_DUPLICATE_ATTRIBUTE;
   2843             }
   2844             if (!step)
   2845               step = PROBE_STEP(uriHash, mask, nsAttsPower);
   2846             j < step ? (j += nsAttsSize - step) : (j -= step);
   2847           }
   2848         }
   2849 
   2850         if (ns_triplets) {  /* append namespace separator and prefix */
   2851           tempPool.ptr[-1] = namespaceSeparator;
   2852           s = b->prefix->name;
   2853           do {
   2854             if (!poolAppendChar(&tempPool, *s))
   2855               return XML_ERROR_NO_MEMORY;
   2856           } while (*s++);
   2857         }
   2858 
   2859         /* store expanded name in attribute list */
   2860         s = poolStart(&tempPool);
   2861         poolFinish(&tempPool);
   2862         appAtts[i] = s;
   2863 
   2864         /* fill empty slot with new version, uriName and hash value */
   2865         nsAtts[j].version = version;
   2866         nsAtts[j].hash = uriHash;
   2867         nsAtts[j].uriName = s;
   2868 
   2869         if (!--nPrefixes) {
   2870           i += 2;
   2871           break;
   2872         }
   2873       }
   2874       else  /* not prefixed */
   2875         ((XML_Char *)s)[-1] = 0;  /* clear flag */
   2876     }
   2877   }
   2878   /* clear flags for the remaining attributes */
   2879   for (; i < attIndex; i += 2)
   2880     ((XML_Char *)(appAtts[i]))[-1] = 0;
   2881   for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
   2882     binding->attId->name[-1] = 0;
   2883 
   2884   if (!ns)
   2885     return XML_ERROR_NONE;
   2886 
   2887   /* expand the element type name */
   2888   if (elementType->prefix) {
   2889     binding = elementType->prefix->binding;
   2890     if (!binding)
   2891       return XML_ERROR_UNBOUND_PREFIX;
   2892     localPart = tagNamePtr->str;
   2893     while (*localPart++ != XML_T(':'))
   2894       ;
   2895   }
   2896   else if (dtd->defaultPrefix.binding) {
   2897     binding = dtd->defaultPrefix.binding;
   2898     localPart = tagNamePtr->str;
   2899   }
   2900   else
   2901     return XML_ERROR_NONE;
   2902   prefixLen = 0;
   2903   if (ns_triplets && binding->prefix->name) {
   2904     for (; binding->prefix->name[prefixLen++];)
   2905       ;  /* prefixLen includes null terminator */
   2906   }
   2907   tagNamePtr->localPart = localPart;
   2908   tagNamePtr->uriLen = binding->uriLen;
   2909   tagNamePtr->prefix = binding->prefix->name;
   2910   tagNamePtr->prefixLen = prefixLen;
   2911   for (i = 0; localPart[i++];)
   2912     ;  /* i includes null terminator */
   2913   n = i + binding->uriLen + prefixLen;
   2914   if (n > binding->uriAlloc) {
   2915     TAG *p;
   2916     uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
   2917     if (!uri)
   2918       return XML_ERROR_NO_MEMORY;
   2919     binding->uriAlloc = n + EXPAND_SPARE;
   2920     memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
   2921     for (p = tagStack; p; p = p->parent)
   2922       if (p->name.str == binding->uri)
   2923         p->name.str = uri;
   2924     FREE(binding->uri);
   2925     binding->uri = uri;
   2926   }
   2927   /* if namespaceSeparator != '\0' then uri includes it already */
   2928   uri = binding->uri + binding->uriLen;
   2929   memcpy(uri, localPart, i * sizeof(XML_Char));
   2930   /* we always have a namespace separator between localPart and prefix */
   2931   if (prefixLen) {
   2932     uri += i - 1;
   2933     *uri = namespaceSeparator;  /* replace null terminator */
   2934     memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
   2935   }
   2936   tagNamePtr->str = binding->uri;
   2937   return XML_ERROR_NONE;
   2938 }
   2939 
   2940 /* addBinding() overwrites the value of prefix->binding without checking.
   2941    Therefore one must keep track of the old value outside of addBinding().
   2942 */
   2943 static enum XML_Error
   2944 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
   2945            const XML_Char *uri, BINDING **bindingsPtr)
   2946 {
   2947   static const XML_Char xmlNamespace[] = {
   2948     'h', 't', 't', 'p', ':', '/', '/',
   2949     'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
   2950     'X', 'M', 'L', '/', '1', '9', '9', '8', '/',
   2951     'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0'
   2952   };
   2953   static const int xmlLen =
   2954     (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
   2955   static const XML_Char xmlnsNamespace[] = {
   2956     'h', 't', 't', 'p', ':', '/', '/',
   2957     'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
   2958     '2', '0', '0', '0', '/', 'x', 'm', 'l', 'n', 's', '/', '\0'
   2959   };
   2960   static const int xmlnsLen =
   2961     (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
   2962 
   2963   XML_Bool mustBeXML = XML_FALSE;
   2964   XML_Bool isXML = XML_TRUE;
   2965   XML_Bool isXMLNS = XML_TRUE;
   2966 
   2967   BINDING *b;
   2968   int len;
   2969 
   2970   /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
   2971   if (*uri == XML_T('\0') && prefix->name)
   2972     return XML_ERROR_UNDECLARING_PREFIX;
   2973 
   2974   if (prefix->name
   2975       && prefix->name[0] == XML_T('x')
   2976       && prefix->name[1] == XML_T('m')
   2977       && prefix->name[2] == XML_T('l')) {
   2978 
   2979     /* Not allowed to bind xmlns */
   2980     if (prefix->name[3] == XML_T('n')
   2981         && prefix->name[4] == XML_T('s')
   2982         && prefix->name[5] == XML_T('\0'))
   2983       return XML_ERROR_RESERVED_PREFIX_XMLNS;
   2984 
   2985     if (prefix->name[3] == XML_T('\0'))
   2986       mustBeXML = XML_TRUE;
   2987   }
   2988 
   2989   for (len = 0; uri[len]; len++) {
   2990     if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
   2991       isXML = XML_FALSE;
   2992 
   2993     if (!mustBeXML && isXMLNS
   2994         && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
   2995       isXMLNS = XML_FALSE;
   2996   }
   2997   isXML = isXML && len == xmlLen;
   2998   isXMLNS = isXMLNS && len == xmlnsLen;
   2999 
   3000   if (mustBeXML != isXML)
   3001     return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
   3002                      : XML_ERROR_RESERVED_NAMESPACE_URI;
   3003 
   3004   if (isXMLNS)
   3005     return XML_ERROR_RESERVED_NAMESPACE_URI;
   3006 
   3007   if (namespaceSeparator)
   3008     len++;
   3009   if (freeBindingList) {
   3010     b = freeBindingList;
   3011     if (len > b->uriAlloc) {
   3012       XML_Char *temp = (XML_Char *)REALLOC(b->uri,
   3013                           sizeof(XML_Char) * (len + EXPAND_SPARE));
   3014       if (temp == NULL)
   3015         return XML_ERROR_NO_MEMORY;
   3016       b->uri = temp;
   3017       b->uriAlloc = len + EXPAND_SPARE;
   3018     }
   3019     freeBindingList = b->nextTagBinding;
   3020   }
   3021   else {
   3022     b = (BINDING *)MALLOC(sizeof(BINDING));
   3023     if (!b)
   3024       return XML_ERROR_NO_MEMORY;
   3025     b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
   3026     if (!b->uri) {
   3027       FREE(b);
   3028       return XML_ERROR_NO_MEMORY;
   3029     }
   3030     b->uriAlloc = len + EXPAND_SPARE;
   3031   }
   3032   b->uriLen = len;
   3033   memcpy(b->uri, uri, len * sizeof(XML_Char));
   3034   if (namespaceSeparator)
   3035     b->uri[len - 1] = namespaceSeparator;
   3036   b->prefix = prefix;
   3037   b->attId = attId;
   3038   b->prevPrefixBinding = prefix->binding;
   3039   /* NULL binding when default namespace undeclared */
   3040   if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
   3041     prefix->binding = NULL;
   3042   else
   3043     prefix->binding = b;
   3044   b->nextTagBinding = *bindingsPtr;
   3045   *bindingsPtr = b;
   3046   /* if attId == NULL then we are not starting a namespace scope */
   3047   if (attId && startNamespaceDeclHandler)
   3048     startNamespaceDeclHandler(handlerArg, prefix->name,
   3049                               prefix->binding ? uri : 0);
   3050   return XML_ERROR_NONE;
   3051 }
   3052 
   3053 /* The idea here is to avoid using stack for each CDATA section when
   3054    the whole file is parsed with one call.
   3055 */
   3056 static enum XML_Error PTRCALL
   3057 cdataSectionProcessor(XML_Parser parser,
   3058                       const char *start,
   3059                       const char *end,
   3060                       const char **endPtr)
   3061 {
   3062   enum XML_Error result = doCdataSection(parser, encoding, &start, end,
   3063                                          endPtr, (XML_Bool)!ps_finalBuffer);
   3064   if (result != XML_ERROR_NONE)
   3065     return result;
   3066   if (start) {
   3067     if (parentParser) {  /* we are parsing an external entity */
   3068       processor = externalEntityContentProcessor;
   3069       return externalEntityContentProcessor(parser, start, end, endPtr);
   3070     }
   3071     else {
   3072       processor = contentProcessor;
   3073       return contentProcessor(parser, start, end, endPtr);
   3074     }
   3075   }
   3076   return result;
   3077 }
   3078 
   3079 /* startPtr gets set to non-null if the section is closed, and to null if
   3080    the section is not yet closed.
   3081 */
   3082 static enum XML_Error
   3083 doCdataSection(XML_Parser parser,
   3084                const ENCODING *enc,
   3085                const char **startPtr,
   3086                const char *end,
   3087                const char **nextPtr,
   3088                XML_Bool haveMore)
   3089 {
   3090   const char *s = *startPtr;
   3091   const char **eventPP;
   3092   const char **eventEndPP;
   3093   if (enc == encoding) {
   3094     eventPP = &eventPtr;
   3095     *eventPP = s;
   3096     eventEndPP = &eventEndPtr;
   3097   }
   3098   else {
   3099     eventPP = &(openInternalEntities->internalEventPtr);
   3100     eventEndPP = &(openInternalEntities->internalEventEndPtr);
   3101   }
   3102   *eventPP = s;
   3103   *startPtr = NULL;
   3104 
   3105   for (;;) {
   3106     const char *next;
   3107     int tok = XmlCdataSectionTok(enc, s, end, &next);
   3108     *eventEndPP = next;
   3109     switch (tok) {
   3110     case XML_TOK_CDATA_SECT_CLOSE:
   3111       if (endCdataSectionHandler)
   3112         endCdataSectionHandler(handlerArg);
   3113 #if 0
   3114       /* see comment under XML_TOK_CDATA_SECT_OPEN */
   3115       else if (characterDataHandler)
   3116         characterDataHandler(handlerArg, dataBuf, 0);
   3117 #endif
   3118       else if (defaultHandler)
   3119         reportDefault(parser, enc, s, next);
   3120       *startPtr = next;
   3121       *nextPtr = next;
   3122       if (ps_parsing == XML_FINISHED)
   3123         return XML_ERROR_ABORTED;
   3124       else
   3125         return XML_ERROR_NONE;
   3126     case XML_TOK_DATA_NEWLINE:
   3127       if (characterDataHandler) {
   3128         XML_Char c = 0xA;
   3129         characterDataHandler(handlerArg, &c, 1);
   3130       }
   3131       else if (defaultHandler)
   3132         reportDefault(parser, enc, s, next);
   3133       break;
   3134     case XML_TOK_DATA_CHARS:
   3135       if (characterDataHandler) {
   3136         if (MUST_CONVERT(enc, s)) {
   3137           for (;;) {
   3138             ICHAR *dataPtr = (ICHAR *)dataBuf;
   3139             XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
   3140             *eventEndPP = next;
   3141             characterDataHandler(handlerArg, dataBuf,
   3142                                  (int)(dataPtr - (ICHAR *)dataBuf));
   3143             if (s == next)
   3144               break;
   3145             *eventPP = s;
   3146           }
   3147         }
   3148         else
   3149           characterDataHandler(handlerArg,
   3150                                (XML_Char *)s,
   3151                                (int)((XML_Char *)next - (XML_Char *)s));
   3152       }
   3153       else if (defaultHandler)
   3154         reportDefault(parser, enc, s, next);
   3155       break;
   3156     case XML_TOK_INVALID:
   3157       *eventPP = next;
   3158       return XML_ERROR_INVALID_TOKEN;
   3159     case XML_TOK_PARTIAL_CHAR:
   3160       if (haveMore) {
   3161         *nextPtr = s;
   3162         return XML_ERROR_NONE;
   3163       }
   3164       return XML_ERROR_PARTIAL_CHAR;
   3165     case XML_TOK_PARTIAL:
   3166     case XML_TOK_NONE:
   3167       if (haveMore) {
   3168         *nextPtr = s;
   3169         return XML_ERROR_NONE;
   3170       }
   3171       return XML_ERROR_UNCLOSED_CDATA_SECTION;
   3172     default:
   3173       *eventPP = next;
   3174       return XML_ERROR_UNEXPECTED_STATE;
   3175     }
   3176 
   3177     *eventPP = s = next;
   3178     switch (ps_parsing) {
   3179     case XML_SUSPENDED:
   3180       *nextPtr = next;
   3181       return XML_ERROR_NONE;
   3182     case XML_FINISHED:
   3183       return XML_ERROR_ABORTED;
   3184     default: ;
   3185     }
   3186   }
   3187   /* not reached */
   3188 }
   3189 
   3190 #ifdef XML_DTD
   3191 
   3192 /* The idea here is to avoid using stack for each IGNORE section when
   3193    the whole file is parsed with one call.
   3194 */
   3195 static enum XML_Error PTRCALL
   3196 ignoreSectionProcessor(XML_Parser parser,
   3197                        const char *start,
   3198                        const char *end,
   3199                        const char **endPtr)
   3200 {
   3201   enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
   3202                                           endPtr, (XML_Bool)!ps_finalBuffer);
   3203   if (result != XML_ERROR_NONE)
   3204     return result;
   3205   if (start) {
   3206     processor = prologProcessor;
   3207     return prologProcessor(parser, start, end, endPtr);
   3208   }
   3209   return result;
   3210 }
   3211 
   3212 /* startPtr gets set to non-null is the section is closed, and to null
   3213    if the section is not yet closed.
   3214 */
   3215 static enum XML_Error
   3216 doIgnoreSection(XML_Parser parser,
   3217                 const ENCODING *enc,
   3218                 const char **startPtr,
   3219                 const char *end,
   3220                 const char **nextPtr,
   3221                 XML_Bool haveMore)
   3222 {
   3223   const char *next;
   3224   int tok;
   3225   const char *s = *startPtr;
   3226   const char **eventPP;
   3227   const char **eventEndPP;
   3228   if (enc == encoding) {
   3229     eventPP = &eventPtr;
   3230     *eventPP = s;
   3231     eventEndPP = &eventEndPtr;
   3232   }
   3233   else {
   3234     eventPP = &(openInternalEntities->internalEventPtr);
   3235     eventEndPP = &(openInternalEntities->internalEventEndPtr);
   3236   }
   3237   *eventPP = s;
   3238   *startPtr = NULL;
   3239   tok = XmlIgnoreSectionTok(enc, s, end, &next);
   3240   *eventEndPP = next;
   3241   switch (tok) {
   3242   case XML_TOK_IGNORE_SECT:
   3243     if (defaultHandler)
   3244       reportDefault(parser, enc, s, next);
   3245     *startPtr = next;
   3246     *nextPtr = next;
   3247     if (ps_parsing == XML_FINISHED)
   3248       return XML_ERROR_ABORTED;
   3249     else
   3250       return XML_ERROR_NONE;
   3251   case XML_TOK_INVALID:
   3252     *eventPP = next;
   3253     return XML_ERROR_INVALID_TOKEN;
   3254   case XML_TOK_PARTIAL_CHAR:
   3255     if (haveMore) {
   3256       *nextPtr = s;
   3257       return XML_ERROR_NONE;
   3258     }
   3259     return XML_ERROR_PARTIAL_CHAR;
   3260   case XML_TOK_PARTIAL:
   3261   case XML_TOK_NONE:
   3262     if (haveMore) {
   3263       *nextPtr = s;
   3264       return XML_ERROR_NONE;
   3265     }
   3266     return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
   3267   default:
   3268     *eventPP = next;
   3269     return XML_ERROR_UNEXPECTED_STATE;
   3270   }
   3271   /* not reached */
   3272 }
   3273 
   3274 #endif /* XML_DTD */
   3275 
   3276 static enum XML_Error
   3277 initializeEncoding(XML_Parser parser)
   3278 {
   3279   const char *s;
   3280 #ifdef XML_UNICODE
   3281   char encodingBuf[128];
   3282   if (!protocolEncodingName)
   3283     s = NULL;
   3284   else {
   3285     int i;
   3286     for (i = 0; protocolEncodingName[i]; i++) {
   3287       if (i == sizeof(encodingBuf) - 1
   3288           || (protocolEncodingName[i] & ~0x7f) != 0) {
   3289         encodingBuf[0] = '\0';
   3290         break;
   3291       }
   3292       encodingBuf[i] = (char)protocolEncodingName[i];
   3293     }
   3294     encodingBuf[i] = '\0';
   3295     s = encodingBuf;
   3296   }
   3297 #else
   3298   s = protocolEncodingName;
   3299 #endif
   3300   if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
   3301     return XML_ERROR_NONE;
   3302   return handleUnknownEncoding(parser, protocolEncodingName);
   3303 }
   3304 
   3305 static enum XML_Error
   3306 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
   3307                const char *s, const char *next)
   3308 {
   3309   const char *encodingName = NULL;
   3310   const XML_Char *storedEncName = NULL;
   3311   const ENCODING *newEncoding = NULL;
   3312   const char *version = NULL;
   3313   const char *versionend;
   3314   const XML_Char *storedversion = NULL;
   3315   int standalone = -1;
   3316   if (!(ns
   3317         ? XmlParseXmlDeclNS
   3318         : XmlParseXmlDecl)(isGeneralTextEntity,
   3319                            encoding,
   3320                            s,
   3321                            next,
   3322                            &eventPtr,
   3323                            &version,
   3324                            &versionend,
   3325                            &encodingName,
   3326                            &newEncoding,
   3327                            &standalone)) {
   3328     if (isGeneralTextEntity)
   3329       return XML_ERROR_TEXT_DECL;
   3330     else
   3331       return XML_ERROR_XML_DECL;
   3332   }
   3333   if (!isGeneralTextEntity && standalone == 1) {
   3334     _dtd->standalone = XML_TRUE;
   3335 #ifdef XML_DTD
   3336     if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
   3337       paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
   3338 #endif /* XML_DTD */
   3339   }
   3340   if (xmlDeclHandler) {
   3341     if (encodingName != NULL) {
   3342       storedEncName = poolStoreString(&temp2Pool,
   3343                                       encoding,
   3344                                       encodingName,
   3345                                       encodingName
   3346                                       + XmlNameLength(encoding, encodingName));
   3347       if (!storedEncName)
   3348               return XML_ERROR_NO_MEMORY;
   3349       poolFinish(&temp2Pool);
   3350     }
   3351     if (version) {
   3352       storedversion = poolStoreString(&temp2Pool,
   3353                                       encoding,
   3354                                       version,
   3355                                       versionend - encoding->minBytesPerChar);
   3356       if (!storedversion)
   3357         return XML_ERROR_NO_MEMORY;
   3358     }
   3359     xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
   3360   }
   3361   else if (defaultHandler)
   3362     reportDefault(parser, encoding, s, next);
   3363   if (protocolEncodingName == NULL) {
   3364     if (newEncoding) {
   3365       if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
   3366         eventPtr = encodingName;
   3367         return XML_ERROR_INCORRECT_ENCODING;
   3368       }
   3369       encoding = newEncoding;
   3370     }
   3371     else if (encodingName) {
   3372       enum XML_Error result;
   3373       if (!storedEncName) {
   3374         storedEncName = poolStoreString(
   3375           &temp2Pool, encoding, encodingName,
   3376           encodingName + XmlNameLength(encoding, encodingName));
   3377         if (!storedEncName)
   3378           return XML_ERROR_NO_MEMORY;
   3379       }
   3380       result = handleUnknownEncoding(parser, storedEncName);
   3381       poolClear(&temp2Pool);
   3382       if (result == XML_ERROR_UNKNOWN_ENCODING)
   3383         eventPtr = encodingName;
   3384       return result;
   3385     }
   3386   }
   3387 
   3388   if (storedEncName || storedversion)
   3389     poolClear(&temp2Pool);
   3390 
   3391   return XML_ERROR_NONE;
   3392 }
   3393 
   3394 static enum XML_Error
   3395 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
   3396 {
   3397   if (unknownEncodingHandler) {
   3398     XML_Encoding info;
   3399     int i;
   3400     for (i = 0; i < 256; i++)
   3401       info.map[i] = -1;
   3402     info.convert = NULL;
   3403     info.data = NULL;
   3404     info.release = NULL;
   3405     if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
   3406                                &info)) {
   3407       ENCODING *enc;
   3408       unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
   3409       if (!unknownEncodingMem) {
   3410         if (info.release)
   3411           info.release(info.data);
   3412         return XML_ERROR_NO_MEMORY;
   3413       }
   3414       enc = (ns
   3415              ? XmlInitUnknownEncodingNS
   3416              : XmlInitUnknownEncoding)(unknownEncodingMem,
   3417                                        info.map,
   3418                                        info.convert,
   3419                                        info.data);
   3420       if (enc) {
   3421         unknownEncodingData = info.data;
   3422         unknownEncodingRelease = info.release;
   3423         encoding = enc;
   3424         return XML_ERROR_NONE;
   3425       }
   3426     }
   3427     if (info.release != NULL)
   3428       info.release(info.data);
   3429   }
   3430   return XML_ERROR_UNKNOWN_ENCODING;
   3431 }
   3432 
   3433 static enum XML_Error PTRCALL
   3434 prologInitProcessor(XML_Parser parser,
   3435                     const char *s,
   3436                     const char *end,
   3437                     const char **nextPtr)
   3438 {
   3439   enum XML_Error result = initializeEncoding(parser);
   3440   if (result != XML_ERROR_NONE)
   3441     return result;
   3442   processor = prologProcessor;
   3443   return prologProcessor(parser, s, end, nextPtr);
   3444 }
   3445 
   3446 #ifdef XML_DTD
   3447 
   3448 static enum XML_Error PTRCALL
   3449 externalParEntInitProcessor(XML_Parser parser,
   3450                             const char *s,
   3451                             const char *end,
   3452                             const char **nextPtr)
   3453 {
   3454   enum XML_Error result = initializeEncoding(parser);
   3455   if (result != XML_ERROR_NONE)
   3456     return result;
   3457 
   3458   /* we know now that XML_Parse(Buffer) has been called,
   3459      so we consider the external parameter entity read */
   3460   _dtd->paramEntityRead = XML_TRUE;
   3461 
   3462   if (prologState.inEntityValue) {
   3463     processor = entityValueInitProcessor;
   3464     return entityValueInitProcessor(parser, s, end, nextPtr);
   3465   }
   3466   else {
   3467     processor = externalParEntProcessor;
   3468     return externalParEntProcessor(parser, s, end, nextPtr);
   3469   }
   3470 }
   3471 
   3472 static enum XML_Error PTRCALL
   3473 entityValueInitProcessor(XML_Parser parser,
   3474                          const char *s,
   3475                          const char *end,
   3476                          const char **nextPtr)
   3477 {
   3478   int tok;
   3479   const char *start = s;
   3480   const char *next = start;
   3481   eventPtr = start;
   3482 
   3483   for (;;) {
   3484     tok = XmlPrologTok(encoding, start, end, &next);
   3485     eventEndPtr = next;
   3486     if (tok <= 0) {
   3487       if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
   3488         *nextPtr = s;
   3489         return XML_ERROR_NONE;
   3490       }
   3491       switch (tok) {
   3492       case XML_TOK_INVALID:
   3493         return XML_ERROR_INVALID_TOKEN;
   3494       case XML_TOK_PARTIAL:
   3495         return XML_ERROR_UNCLOSED_TOKEN;
   3496       case XML_TOK_PARTIAL_CHAR:
   3497         return XML_ERROR_PARTIAL_CHAR;
   3498       case XML_TOK_NONE:   /* start == end */
   3499       default:
   3500         break;
   3501       }
   3502       /* found end of entity value - can store it now */
   3503       return storeEntityValue(parser, encoding, s, end);
   3504     }
   3505     else if (tok == XML_TOK_XML_DECL) {
   3506       enum XML_Error result;
   3507       result = processXmlDecl(parser, 0, start, next);
   3508       if (result != XML_ERROR_NONE)
   3509         return result;
   3510       switch (ps_parsing) {
   3511       case XML_SUSPENDED:
   3512         *nextPtr = next;
   3513         return XML_ERROR_NONE;
   3514       case XML_FINISHED:
   3515         return XML_ERROR_ABORTED;
   3516       default:
   3517         *nextPtr = next;
   3518       }
   3519       /* stop scanning for text declaration - we found one */
   3520       processor = entityValueProcessor;
   3521       return entityValueProcessor(parser, next, end, nextPtr);
   3522     }
   3523     /* If we are at the end of the buffer, this would cause XmlPrologTok to
   3524        return XML_TOK_NONE on the next call, which would then cause the
   3525        function to exit with *nextPtr set to s - that is what we want for other
   3526        tokens, but not for the BOM - we would rather like to skip it;
   3527        then, when this routine is entered the next time, XmlPrologTok will
   3528        return XML_TOK_INVALID, since the BOM is still in the buffer
   3529     */
   3530     else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
   3531       *nextPtr = next;
   3532       return XML_ERROR_NONE;
   3533     }
   3534     start = next;
   3535     eventPtr = start;
   3536   }
   3537 }
   3538 
   3539 static enum XML_Error PTRCALL
   3540 externalParEntProcessor(XML_Parser parser,
   3541                         const char *s,
   3542                         const char *end,
   3543                         const char **nextPtr)
   3544 {
   3545   const char *next = s;
   3546   int tok;
   3547 
   3548   tok = XmlPrologTok(encoding, s, end, &next);
   3549   if (tok <= 0) {
   3550     if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
   3551       *nextPtr = s;
   3552       return XML_ERROR_NONE;
   3553     }
   3554     switch (tok) {
   3555     case XML_TOK_INVALID:
   3556       return XML_ERROR_INVALID_TOKEN;
   3557     case XML_TOK_PARTIAL:
   3558       return XML_ERROR_UNCLOSED_TOKEN;
   3559     case XML_TOK_PARTIAL_CHAR:
   3560       return XML_ERROR_PARTIAL_CHAR;
   3561     case XML_TOK_NONE:   /* start == end */
   3562     default:
   3563       break;
   3564     }
   3565   }
   3566   /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
   3567      However, when parsing an external subset, doProlog will not accept a BOM
   3568      as valid, and report a syntax error, so we have to skip the BOM
   3569   */
   3570   else if (tok == XML_TOK_BOM) {
   3571     s = next;
   3572     tok = XmlPrologTok(encoding, s, end, &next);
   3573   }
   3574 
   3575   processor = prologProcessor;
   3576   return doProlog(parser, encoding, s, end, tok, next,
   3577                   nextPtr, (XML_Bool)!ps_finalBuffer);
   3578 }
   3579 
   3580 static enum XML_Error PTRCALL
   3581 entityValueProcessor(XML_Parser parser,
   3582                      const char *s,
   3583                      const char *end,
   3584                      const char **nextPtr)
   3585 {
   3586   const char *start = s;
   3587   const char *next = s;
   3588   const ENCODING *enc = encoding;
   3589   int tok;
   3590 
   3591   for (;;) {
   3592     tok = XmlPrologTok(enc, start, end, &next);
   3593     if (tok <= 0) {
   3594       if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
   3595         *nextPtr = s;
   3596         return XML_ERROR_NONE;
   3597       }
   3598       switch (tok) {
   3599       case XML_TOK_INVALID:
   3600         return XML_ERROR_INVALID_TOKEN;
   3601       case XML_TOK_PARTIAL:
   3602         return XML_ERROR_UNCLOSED_TOKEN;
   3603       case XML_TOK_PARTIAL_CHAR:
   3604         return XML_ERROR_PARTIAL_CHAR;
   3605       case XML_TOK_NONE:   /* start == end */
   3606       default:
   3607         break;
   3608       }
   3609       /* found end of entity value - can store it now */
   3610       return storeEntityValue(parser, enc, s, end);
   3611     }
   3612     start = next;
   3613   }
   3614 }
   3615 
   3616 #endif /* XML_DTD */
   3617 
   3618 static enum XML_Error PTRCALL
   3619 prologProcessor(XML_Parser parser,
   3620                 const char *s,
   3621                 const char *end,
   3622                 const char **nextPtr)
   3623 {
   3624   const char *next = s;
   3625   int tok = XmlPrologTok(encoding, s, end, &next);
   3626   return doProlog(parser, encoding, s, end, tok, next,
   3627                   nextPtr, (XML_Bool)!ps_finalBuffer);
   3628 }
   3629 
   3630 static enum XML_Error
   3631 doProlog(XML_Parser parser,
   3632          const ENCODING *enc,
   3633          const char *s,
   3634          const char *end,
   3635          int tok,
   3636          const char *next,
   3637          const char **nextPtr,
   3638          XML_Bool haveMore)
   3639 {
   3640 #ifdef XML_DTD
   3641   static const XML_Char externalSubsetName[] = { '#' , '\0' };
   3642 #endif /* XML_DTD */
   3643   static const XML_Char atypeCDATA[] = { 'C', 'D', 'A', 'T', 'A', '\0' };
   3644   static const XML_Char atypeID[] = { 'I', 'D', '\0' };
   3645   static const XML_Char atypeIDREF[] = { 'I', 'D', 'R', 'E', 'F', '\0' };
   3646   static const XML_Char atypeIDREFS[] = { 'I', 'D', 'R', 'E', 'F', 'S', '\0' };
   3647   static const XML_Char atypeENTITY[] = { 'E', 'N', 'T', 'I', 'T', 'Y', '\0' };
   3648   static const XML_Char atypeENTITIES[] =
   3649       { 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S', '\0' };
   3650   static const XML_Char atypeNMTOKEN[] = {
   3651       'N', 'M', 'T', 'O', 'K', 'E', 'N', '\0' };
   3652   static const XML_Char atypeNMTOKENS[] = {
   3653       'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S', '\0' };
   3654   static const XML_Char notationPrefix[] = {
   3655       'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', '(', '\0' };
   3656   static const XML_Char enumValueSep[] = { '|', '\0' };
   3657   static const XML_Char enumValueStart[] = { '(', '\0' };
   3658 
   3659   /* save one level of indirection */
   3660   DTD * const dtd = _dtd;
   3661 
   3662   const char **eventPP;
   3663   const char **eventEndPP;
   3664   enum XML_Content_Quant quant;
   3665 
   3666   if (enc == encoding) {
   3667     eventPP = &eventPtr;
   3668     eventEndPP = &eventEndPtr;
   3669   }
   3670   else {
   3671     eventPP = &(openInternalEntities->internalEventPtr);
   3672     eventEndPP = &(openInternalEntities->internalEventEndPtr);
   3673   }
   3674 
   3675   for (;;) {
   3676     int role;
   3677     XML_Bool handleDefault = XML_TRUE;
   3678     *eventPP = s;
   3679     *eventEndPP = next;
   3680     if (tok <= 0) {
   3681       if (haveMore && tok != XML_TOK_INVALID) {
   3682         *nextPtr = s;
   3683         return XML_ERROR_NONE;
   3684       }
   3685       switch (tok) {
   3686       case XML_TOK_INVALID:
   3687         *eventPP = next;
   3688         return XML_ERROR_INVALID_TOKEN;
   3689       case XML_TOK_PARTIAL:
   3690         return XML_ERROR_UNCLOSED_TOKEN;
   3691       case XML_TOK_PARTIAL_CHAR:
   3692         return XML_ERROR_PARTIAL_CHAR;
   3693       case -XML_TOK_PROLOG_S:
   3694         tok = -tok;
   3695         break;
   3696       case XML_TOK_NONE:
   3697 #ifdef XML_DTD
   3698         /* for internal PE NOT referenced between declarations */
   3699         if (enc != encoding && !openInternalEntities->betweenDecl) {
   3700           *nextPtr = s;
   3701           return XML_ERROR_NONE;
   3702         }
   3703         /* WFC: PE Between Declarations - must check that PE contains
   3704            complete markup, not only for external PEs, but also for
   3705            internal PEs if the reference occurs between declarations.
   3706         */
   3707         if (isParamEntity || enc != encoding) {
   3708           if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
   3709               == XML_ROLE_ERROR)
   3710             return XML_ERROR_INCOMPLETE_PE;
   3711           *nextPtr = s;
   3712           return XML_ERROR_NONE;
   3713         }
   3714 #endif /* XML_DTD */
   3715         return XML_ERROR_NO_ELEMENTS;
   3716       default:
   3717         tok = -tok;
   3718         next = end;
   3719         break;
   3720       }
   3721     }
   3722     role = XmlTokenRole(&prologState, tok, s, next, enc);
   3723     switch (role) {
   3724     case XML_ROLE_XML_DECL:
   3725       {
   3726         enum XML_Error result = processXmlDecl(parser, 0, s, next);
   3727         if (result != XML_ERROR_NONE)
   3728           return result;
   3729         enc = encoding;
   3730         handleDefault = XML_FALSE;
   3731       }
   3732       break;
   3733     case XML_ROLE_DOCTYPE_NAME:
   3734       if (startDoctypeDeclHandler) {
   3735         doctypeName = poolStoreString(&tempPool, enc, s, next);
   3736         if (!doctypeName)
   3737           return XML_ERROR_NO_MEMORY;
   3738         poolFinish(&tempPool);
   3739         doctypePubid = NULL;
   3740         handleDefault = XML_FALSE;
   3741       }
   3742       doctypeSysid = NULL; /* always initialize to NULL */
   3743       break;
   3744     case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
   3745       if (startDoctypeDeclHandler) {
   3746         startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
   3747                                 doctypePubid, 1);
   3748         doctypeName = NULL;
   3749         poolClear(&tempPool);
   3750         handleDefault = XML_FALSE;
   3751       }
   3752       break;
   3753 #ifdef XML_DTD
   3754     case XML_ROLE_TEXT_DECL:
   3755       {
   3756         enum XML_Error result = processXmlDecl(parser, 1, s, next);
   3757         if (result != XML_ERROR_NONE)
   3758           return result;
   3759         enc = encoding;
   3760         handleDefault = XML_FALSE;
   3761       }
   3762       break;
   3763 #endif /* XML_DTD */
   3764     case XML_ROLE_DOCTYPE_PUBLIC_ID:
   3765 #ifdef XML_DTD
   3766       useForeignDTD = XML_FALSE;
   3767       declEntity = (ENTITY *)lookup(&dtd->paramEntities,
   3768                                     externalSubsetName,
   3769                                     sizeof(ENTITY));
   3770       if (!declEntity)
   3771         return XML_ERROR_NO_MEMORY;
   3772 #endif /* XML_DTD */
   3773       dtd->hasParamEntityRefs = XML_TRUE;
   3774       if (startDoctypeDeclHandler) {
   3775         if (!XmlIsPublicId(enc, s, next, eventPP))
   3776           return XML_ERROR_PUBLICID;
   3777         doctypePubid = poolStoreString(&tempPool, enc,
   3778                                        s + enc->minBytesPerChar,
   3779                                        next - enc->minBytesPerChar);
   3780         if (!doctypePubid)
   3781           return XML_ERROR_NO_MEMORY;
   3782         normalizePublicId((XML_Char *)doctypePubid);
   3783         poolFinish(&tempPool);
   3784         handleDefault = XML_FALSE;
   3785         goto alreadyChecked;
   3786       }
   3787       /* fall through */
   3788     case XML_ROLE_ENTITY_PUBLIC_ID:
   3789       if (!XmlIsPublicId(enc, s, next, eventPP))
   3790         return XML_ERROR_PUBLICID;
   3791     alreadyChecked:
   3792       if (dtd->keepProcessing && declEntity) {
   3793         XML_Char *tem = poolStoreString(&dtd->pool,
   3794                                         enc,
   3795                                         s + enc->minBytesPerChar,
   3796                                         next - enc->minBytesPerChar);
   3797         if (!tem)
   3798           return XML_ERROR_NO_MEMORY;
   3799         normalizePublicId(tem);
   3800         declEntity->publicId = tem;
   3801         poolFinish(&dtd->pool);
   3802         if (entityDeclHandler)
   3803           handleDefault = XML_FALSE;
   3804       }
   3805       break;
   3806     case XML_ROLE_DOCTYPE_CLOSE:
   3807       if (doctypeName) {
   3808         startDoctypeDeclHandler(handlerArg, doctypeName,
   3809                                 doctypeSysid, doctypePubid, 0);
   3810         poolClear(&tempPool);
   3811         handleDefault = XML_FALSE;
   3812       }
   3813       /* doctypeSysid will be non-NULL in the case of a previous
   3814          XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
   3815          was not set, indicating an external subset
   3816       */
   3817 #ifdef XML_DTD
   3818       if (doctypeSysid || useForeignDTD) {
   3819         XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
   3820         dtd->hasParamEntityRefs = XML_TRUE;
   3821         if (paramEntityParsing && externalEntityRefHandler) {
   3822           ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
   3823                                             externalSubsetName,
   3824                                             sizeof(ENTITY));
   3825           if (!entity)
   3826             return XML_ERROR_NO_MEMORY;
   3827           if (useForeignDTD)
   3828             entity->base = curBase;
   3829           dtd->paramEntityRead = XML_FALSE;
   3830           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
   3831                                         0,
   3832                                         entity->base,
   3833                                         entity->systemId,
   3834                                         entity->publicId))
   3835             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
   3836           if (dtd->paramEntityRead) {
   3837             if (!dtd->standalone &&
   3838                 notStandaloneHandler &&
   3839                 !notStandaloneHandler(handlerArg))
   3840               return XML_ERROR_NOT_STANDALONE;
   3841           }
   3842           /* if we didn't read the foreign DTD then this means that there
   3843              is no external subset and we must reset dtd->hasParamEntityRefs
   3844           */
   3845           else if (!doctypeSysid)
   3846             dtd->hasParamEntityRefs = hadParamEntityRefs;
   3847           /* end of DTD - no need to update dtd->keepProcessing */
   3848         }
   3849         useForeignDTD = XML_FALSE;
   3850       }
   3851 #endif /* XML_DTD */
   3852       if (endDoctypeDeclHandler) {
   3853         endDoctypeDeclHandler(handlerArg);
   3854         handleDefault = XML_FALSE;
   3855       }
   3856       break;
   3857     case XML_ROLE_INSTANCE_START:
   3858 #ifdef XML_DTD
   3859       /* if there is no DOCTYPE declaration then now is the
   3860          last chance to read the foreign DTD
   3861       */
   3862       if (useForeignDTD) {
   3863         XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
   3864         dtd->hasParamEntityRefs = XML_TRUE;
   3865         if (paramEntityParsing && externalEntityRefHandler) {
   3866           ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
   3867                                             externalSubsetName,
   3868                                             sizeof(ENTITY));
   3869           if (!entity)
   3870             return XML_ERROR_NO_MEMORY;
   3871           entity->base = curBase;
   3872           dtd->paramEntityRead = XML_FALSE;
   3873           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
   3874                                         0,
   3875                                         entity->base,
   3876                                         entity->systemId,
   3877                                         entity->publicId))
   3878             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
   3879           if (dtd->paramEntityRead) {
   3880             if (!dtd->standalone &&
   3881                 notStandaloneHandler &&
   3882                 !notStandaloneHandler(handlerArg))
   3883               return XML_ERROR_NOT_STANDALONE;
   3884           }
   3885           /* if we didn't read the foreign DTD then this means that there
   3886              is no external subset and we must reset dtd->hasParamEntityRefs
   3887           */
   3888           else
   3889             dtd->hasParamEntityRefs = hadParamEntityRefs;
   3890           /* end of DTD - no need to update dtd->keepProcessing */
   3891         }
   3892       }
   3893 #endif /* XML_DTD */
   3894       processor = contentProcessor;
   3895       return contentProcessor(parser, s, end, nextPtr);
   3896     case XML_ROLE_ATTLIST_ELEMENT_NAME:
   3897       declElementType = getElementType(parser, enc, s, next);
   3898       if (!declElementType)
   3899         return XML_ERROR_NO_MEMORY;
   3900       goto checkAttListDeclHandler;
   3901     case XML_ROLE_ATTRIBUTE_NAME:
   3902       declAttributeId = getAttributeId(parser, enc, s, next);
   3903       if (!declAttributeId)
   3904         return XML_ERROR_NO_MEMORY;
   3905       declAttributeIsCdata = XML_FALSE;
   3906       declAttributeType = NULL;
   3907       declAttributeIsId = XML_FALSE;
   3908       goto checkAttListDeclHandler;
   3909     case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
   3910       declAttributeIsCdata = XML_TRUE;
   3911       declAttributeType = atypeCDATA;
   3912       goto checkAttListDeclHandler;
   3913     case XML_ROLE_ATTRIBUTE_TYPE_ID:
   3914       declAttributeIsId = XML_TRUE;
   3915       declAttributeType = atypeID;
   3916       goto checkAttListDeclHandler;
   3917     case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
   3918       declAttributeType = atypeIDREF;
   3919       goto checkAttListDeclHandler;
   3920     case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
   3921       declAttributeType = atypeIDREFS;
   3922       goto checkAttListDeclHandler;
   3923     case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
   3924       declAttributeType = atypeENTITY;
   3925       goto checkAttListDeclHandler;
   3926     case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
   3927       declAttributeType = atypeENTITIES;
   3928       goto checkAttListDeclHandler;
   3929     case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
   3930       declAttributeType = atypeNMTOKEN;
   3931       goto checkAttListDeclHandler;
   3932     case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
   3933       declAttributeType = atypeNMTOKENS;
   3934     checkAttListDeclHandler:
   3935       if (dtd->keepProcessing && attlistDeclHandler)
   3936         handleDefault = XML_FALSE;
   3937       break;
   3938     case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
   3939     case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
   3940       if (dtd->keepProcessing && attlistDeclHandler) {
   3941         const XML_Char *prefix;
   3942         if (declAttributeType) {
   3943           prefix = enumValueSep;
   3944         }
   3945         else {
   3946           prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
   3947                     ? notationPrefix
   3948                     : enumValueStart);
   3949         }
   3950         if (!poolAppendString(&tempPool, prefix))
   3951           return XML_ERROR_NO_MEMORY;
   3952         if (!poolAppend(&tempPool, enc, s, next))
   3953           return XML_ERROR_NO_MEMORY;
   3954         declAttributeType = tempPool.start;
   3955         handleDefault = XML_FALSE;
   3956       }
   3957       break;
   3958     case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
   3959     case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
   3960       if (dtd->keepProcessing) {
   3961         if (!defineAttribute(declElementType, declAttributeId,
   3962                              declAttributeIsCdata, declAttributeIsId,
   3963                              0, parser))
   3964           return XML_ERROR_NO_MEMORY;
   3965         if (attlistDeclHandler && declAttributeType) {
   3966           if (*declAttributeType == XML_T('(')
   3967               || (*declAttributeType == XML_T('N')
   3968                   && declAttributeType[1] == XML_T('O'))) {
   3969             /* Enumerated or Notation type */
   3970             if (!poolAppendChar(&tempPool, XML_T(')'))
   3971                 || !poolAppendChar(&tempPool, XML_T('\0')))
   3972               return XML_ERROR_NO_MEMORY;
   3973             declAttributeType = tempPool.start;
   3974             poolFinish(&tempPool);
   3975           }
   3976           *eventEndPP = s;
   3977           attlistDeclHandler(handlerArg, declElementType->name,
   3978                              declAttributeId->name, declAttributeType,
   3979                              0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
   3980           poolClear(&tempPool);
   3981           handleDefault = XML_FALSE;
   3982         }
   3983       }
   3984       break;
   3985     case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
   3986     case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
   3987       if (dtd->keepProcessing) {
   3988         const XML_Char *attVal;
   3989         enum XML_Error result =
   3990           storeAttributeValue(parser, enc, declAttributeIsCdata,
   3991                               s + enc->minBytesPerChar,
   3992                               next - enc->minBytesPerChar,
   3993                               &dtd->pool);
   3994         if (result)
   3995           return result;
   3996         attVal = poolStart(&dtd->pool);
   3997         poolFinish(&dtd->pool);
   3998         /* ID attributes aren't allowed to have a default */
   3999         if (!defineAttribute(declElementType, declAttributeId,
   4000                              declAttributeIsCdata, XML_FALSE, attVal, parser))
   4001           return XML_ERROR_NO_MEMORY;
   4002         if (attlistDeclHandler && declAttributeType) {
   4003           if (*declAttributeType == XML_T('(')
   4004               || (*declAttributeType == XML_T('N')
   4005                   && declAttributeType[1] == XML_T('O'))) {
   4006             /* Enumerated or Notation type */
   4007             if (!poolAppendChar(&tempPool, XML_T(')'))
   4008                 || !poolAppendChar(&tempPool, XML_T('\0')))
   4009               return XML_ERROR_NO_MEMORY;
   4010             declAttributeType = tempPool.start;
   4011             poolFinish(&tempPool);
   4012           }
   4013           *eventEndPP = s;
   4014           attlistDeclHandler(handlerArg, declElementType->name,
   4015                              declAttributeId->name, declAttributeType,
   4016                              attVal,
   4017                              role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
   4018           poolClear(&tempPool);
   4019           handleDefault = XML_FALSE;
   4020         }
   4021       }
   4022       break;
   4023     case XML_ROLE_ENTITY_VALUE:
   4024       if (dtd->keepProcessing) {
   4025         enum XML_Error result = storeEntityValue(parser, enc,
   4026                                             s + enc->minBytesPerChar,
   4027                                             next - enc->minBytesPerChar);
   4028         if (declEntity) {
   4029           declEntity->textPtr = poolStart(&dtd->entityValuePool);
   4030           declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
   4031           poolFinish(&dtd->entityValuePool);
   4032           if (entityDeclHandler) {
   4033             *eventEndPP = s;
   4034             entityDeclHandler(handlerArg,
   4035                               declEntity->name,
   4036                               declEntity->is_param,
   4037                               declEntity->textPtr,
   4038                               declEntity->textLen,
   4039                               curBase, 0, 0, 0);
   4040             handleDefault = XML_FALSE;
   4041           }
   4042         }
   4043         else
   4044           poolDiscard(&dtd->entityValuePool);
   4045         if (result != XML_ERROR_NONE)
   4046           return result;
   4047       }
   4048       break;
   4049     case XML_ROLE_DOCTYPE_SYSTEM_ID:
   4050 #ifdef XML_DTD
   4051       useForeignDTD = XML_FALSE;
   4052 #endif /* XML_DTD */
   4053       dtd->hasParamEntityRefs = XML_TRUE;
   4054       if (startDoctypeDeclHandler) {
   4055         doctypeSysid = poolStoreString(&tempPool, enc,
   4056                                        s + enc->minBytesPerChar,
   4057                                        next - enc->minBytesPerChar);
   4058         if (doctypeSysid == NULL)
   4059           return XML_ERROR_NO_MEMORY;
   4060         poolFinish(&tempPool);
   4061         handleDefault = XML_FALSE;
   4062       }
   4063 #ifdef XML_DTD
   4064       else
   4065         /* use externalSubsetName to make doctypeSysid non-NULL
   4066            for the case where no startDoctypeDeclHandler is set */
   4067         doctypeSysid = externalSubsetName;
   4068 #endif /* XML_DTD */
   4069       if (!dtd->standalone
   4070 #ifdef XML_DTD
   4071           && !paramEntityParsing
   4072 #endif /* XML_DTD */
   4073           && notStandaloneHandler
   4074           && !notStandaloneHandler(handlerArg))
   4075         return XML_ERROR_NOT_STANDALONE;
   4076 #ifndef XML_DTD
   4077       break;
   4078 #else /* XML_DTD */
   4079       if (!declEntity) {
   4080         declEntity = (ENTITY *)lookup(&dtd->paramEntities,
   4081                                       externalSubsetName,
   4082                                       sizeof(ENTITY));
   4083         if (!declEntity)
   4084           return XML_ERROR_NO_MEMORY;
   4085         declEntity->publicId = NULL;
   4086       }
   4087       /* fall through */
   4088 #endif /* XML_DTD */
   4089     case XML_ROLE_ENTITY_SYSTEM_ID:
   4090       if (dtd->keepProcessing && declEntity) {
   4091         declEntity->systemId = poolStoreString(&dtd->pool, enc,
   4092                                                s + enc->minBytesPerChar,
   4093                                                next - enc->minBytesPerChar);
   4094         if (!declEntity->systemId)
   4095           return XML_ERROR_NO_MEMORY;
   4096         declEntity->base = curBase;
   4097         poolFinish(&dtd->pool);
   4098         if (entityDeclHandler)
   4099           handleDefault = XML_FALSE;
   4100       }
   4101       break;
   4102     case XML_ROLE_ENTITY_COMPLETE:
   4103       if (dtd->keepProcessing && declEntity && entityDeclHandler) {
   4104         *eventEndPP = s;
   4105         entityDeclHandler(handlerArg,
   4106                           declEntity->name,
   4107                           declEntity->is_param,
   4108                           0,0,
   4109                           declEntity->base,
   4110                           declEntity->systemId,
   4111                           declEntity->publicId,
   4112                           0);
   4113         handleDefault = XML_FALSE;
   4114       }
   4115       break;
   4116     case XML_ROLE_ENTITY_NOTATION_NAME:
   4117       if (dtd->keepProcessing && declEntity) {
   4118         declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
   4119         if (!declEntity->notation)
   4120           return XML_ERROR_NO_MEMORY;
   4121         poolFinish(&dtd->pool);
   4122         if (unparsedEntityDeclHandler) {
   4123           *eventEndPP = s;
   4124           unparsedEntityDeclHandler(handlerArg,
   4125                                     declEntity->name,
   4126                                     declEntity->base,
   4127                                     declEntity->systemId,
   4128                                     declEntity->publicId,
   4129                                     declEntity->notation);
   4130           handleDefault = XML_FALSE;
   4131         }
   4132         else if (entityDeclHandler) {
   4133           *eventEndPP = s;
   4134           entityDeclHandler(handlerArg,
   4135                             declEntity->name,
   4136                             0,0,0,
   4137                             declEntity->base,
   4138                             declEntity->systemId,
   4139                             declEntity->publicId,
   4140                             declEntity->notation);
   4141           handleDefault = XML_FALSE;
   4142         }
   4143       }
   4144       break;
   4145     case XML_ROLE_GENERAL_ENTITY_NAME:
   4146       {
   4147         if (XmlPredefinedEntityName(enc, s, next)) {
   4148           declEntity = NULL;
   4149           break;
   4150         }
   4151         if (dtd->keepProcessing) {
   4152           const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
   4153           if (!name)
   4154             return XML_ERROR_NO_MEMORY;
   4155           declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
   4156                                         sizeof(ENTITY));
   4157           if (!declEntity)
   4158             return XML_ERROR_NO_MEMORY;
   4159           if (declEntity->name != name) {
   4160             poolDiscard(&dtd->pool);
   4161             declEntity = NULL;
   4162           }
   4163           else {
   4164             poolFinish(&dtd->pool);
   4165             declEntity->publicId = NULL;
   4166             declEntity->is_param = XML_FALSE;
   4167             /* if we have a parent parser or are reading an internal parameter
   4168                entity, then the entity declaration is not considered "internal"
   4169             */
   4170             declEntity->is_internal = !(parentParser || openInternalEntities);
   4171             if (entityDeclHandler)
   4172               handleDefault = XML_FALSE;
   4173           }
   4174         }
   4175         else {
   4176           poolDiscard(&dtd->pool);
   4177           declEntity = NULL;
   4178         }
   4179       }
   4180       break;
   4181     case XML_ROLE_PARAM_ENTITY_NAME:
   4182 #ifdef XML_DTD
   4183       if (dtd->keepProcessing) {
   4184         const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
   4185         if (!name)
   4186           return XML_ERROR_NO_MEMORY;
   4187         declEntity = (ENTITY *)lookup(&dtd->paramEntities,
   4188                                            name, sizeof(ENTITY));
   4189         if (!declEntity)
   4190           return XML_ERROR_NO_MEMORY;
   4191         if (declEntity->name != name) {
   4192           poolDiscard(&dtd->pool);
   4193           declEntity = NULL;
   4194         }
   4195         else {
   4196           poolFinish(&dtd->pool);
   4197           declEntity->publicId = NULL;
   4198           declEntity->is_param = XML_TRUE;
   4199           /* if we have a parent parser or are reading an internal parameter
   4200              entity, then the entity declaration is not considered "internal"
   4201           */
   4202           declEntity->is_internal = !(parentParser || openInternalEntities);
   4203           if (entityDeclHandler)
   4204             handleDefault = XML_FALSE;
   4205         }
   4206       }
   4207       else {
   4208         poolDiscard(&dtd->pool);
   4209         declEntity = NULL;
   4210       }
   4211 #else /* not XML_DTD */
   4212       declEntity = NULL;
   4213 #endif /* XML_DTD */
   4214       break;
   4215     case XML_ROLE_NOTATION_NAME:
   4216       declNotationPublicId = NULL;
   4217       declNotationName = NULL;
   4218       if (notationDeclHandler) {
   4219         declNotationName = poolStoreString(&tempPool, enc, s, next);
   4220         if (!declNotationName)
   4221           return XML_ERROR_NO_MEMORY;
   4222         poolFinish(&tempPool);
   4223         handleDefault = XML_FALSE;
   4224       }
   4225       break;
   4226     case XML_ROLE_NOTATION_PUBLIC_ID:
   4227       if (!XmlIsPublicId(enc, s, next, eventPP))
   4228         return XML_ERROR_PUBLICID;
   4229       if (declNotationName) {  /* means notationDeclHandler != NULL */
   4230         XML_Char *tem = poolStoreString(&tempPool,
   4231                                         enc,
   4232                                         s + enc->minBytesPerChar,
   4233                                         next - enc->minBytesPerChar);
   4234         if (!tem)
   4235           return XML_ERROR_NO_MEMORY;
   4236         normalizePublicId(tem);
   4237         declNotationPublicId = tem;
   4238         poolFinish(&tempPool);
   4239         handleDefault = XML_FALSE;
   4240       }
   4241       break;
   4242     case XML_ROLE_NOTATION_SYSTEM_ID:
   4243       if (declNotationName && notationDeclHandler) {
   4244         const XML_Char *systemId
   4245           = poolStoreString(&tempPool, enc,
   4246                             s + enc->minBytesPerChar,
   4247                             next - enc->minBytesPerChar);
   4248         if (!systemId)
   4249           return XML_ERROR_NO_MEMORY;
   4250         *eventEndPP = s;
   4251         notationDeclHandler(handlerArg,
   4252                             declNotationName,
   4253                             curBase,
   4254                             systemId,
   4255                             declNotationPublicId);
   4256         handleDefault = XML_FALSE;
   4257       }
   4258       poolClear(&tempPool);
   4259       break;
   4260     case XML_ROLE_NOTATION_NO_SYSTEM_ID:
   4261       if (declNotationPublicId && notationDeclHandler) {
   4262         *eventEndPP = s;
   4263         notationDeclHandler(handlerArg,
   4264                             declNotationName,
   4265                             curBase,
   4266                             0,
   4267                             declNotationPublicId);
   4268         handleDefault = XML_FALSE;
   4269       }
   4270       poolClear(&tempPool);
   4271       break;
   4272     case XML_ROLE_ERROR:
   4273       switch (tok) {
   4274       case XML_TOK_PARAM_ENTITY_REF:
   4275         /* PE references in internal subset are
   4276            not allowed within declarations. */
   4277         return XML_ERROR_PARAM_ENTITY_REF;
   4278       case XML_TOK_XML_DECL:
   4279         return XML_ERROR_MISPLACED_XML_PI;
   4280       default:
   4281         return XML_ERROR_SYNTAX;
   4282       }
   4283 #ifdef XML_DTD
   4284     case XML_ROLE_IGNORE_SECT:
   4285       {
   4286         enum XML_Error result;
   4287         if (defaultHandler)
   4288           reportDefault(parser, enc, s, next);
   4289         handleDefault = XML_FALSE;
   4290         result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
   4291         if (result != XML_ERROR_NONE)
   4292           return result;
   4293         else if (!next) {
   4294           processor = ignoreSectionProcessor;
   4295           return result;
   4296         }
   4297       }
   4298       break;
   4299 #endif /* XML_DTD */
   4300     case XML_ROLE_GROUP_OPEN:
   4301       if (prologState.level >= groupSize) {
   4302         if (groupSize) {
   4303           char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
   4304           if (temp == NULL)
   4305             return XML_ERROR_NO_MEMORY;
   4306           groupConnector = temp;
   4307           if (dtd->scaffIndex) {
   4308             int *temp = (int *)REALLOC(dtd->scaffIndex,
   4309                           groupSize * sizeof(int));
   4310             if (temp == NULL)
   4311               return XML_ERROR_NO_MEMORY;
   4312             dtd->scaffIndex = temp;
   4313           }
   4314         }
   4315         else {
   4316           groupConnector = (char *)MALLOC(groupSize = 32);
   4317           if (!groupConnector)
   4318             return XML_ERROR_NO_MEMORY;
   4319         }
   4320       }
   4321       groupConnector[prologState.level] = 0;
   4322       if (dtd->in_eldecl) {
   4323         int myindex = nextScaffoldPart(parser);
   4324         if (myindex < 0)
   4325           return XML_ERROR_NO_MEMORY;
   4326         dtd->scaffIndex[dtd->scaffLevel] = myindex;
   4327         dtd->scaffLevel++;
   4328         dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
   4329         if (elementDeclHandler)
   4330           handleDefault = XML_FALSE;
   4331       }
   4332       break;
   4333     case XML_ROLE_GROUP_SEQUENCE:
   4334       if (groupConnector[prologState.level] == '|')
   4335         return XML_ERROR_SYNTAX;
   4336       groupConnector[prologState.level] = ',';
   4337       if (dtd->in_eldecl && elementDeclHandler)
   4338         handleDefault = XML_FALSE;
   4339       break;
   4340     case XML_ROLE_GROUP_CHOICE:
   4341       if (groupConnector[prologState.level] == ',')
   4342         return XML_ERROR_SYNTAX;
   4343       if (dtd->in_eldecl
   4344           && !groupConnector[prologState.level]
   4345           && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
   4346               != XML_CTYPE_MIXED)
   4347           ) {
   4348         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
   4349             = XML_CTYPE_CHOICE;
   4350         if (elementDeclHandler)
   4351           handleDefault = XML_FALSE;
   4352       }
   4353       groupConnector[prologState.level] = '|';
   4354       break;
   4355     case XML_ROLE_PARAM_ENTITY_REF:
   4356 #ifdef XML_DTD
   4357     case XML_ROLE_INNER_PARAM_ENTITY_REF:
   4358       dtd->hasParamEntityRefs = XML_TRUE;
   4359       if (!paramEntityParsing)
   4360         dtd->keepProcessing = dtd->standalone;
   4361       else {
   4362         const XML_Char *name;
   4363         ENTITY *entity;
   4364         name = poolStoreString(&dtd->pool, enc,
   4365                                 s + enc->minBytesPerChar,
   4366                                 next - enc->minBytesPerChar);
   4367         if (!name)
   4368           return XML_ERROR_NO_MEMORY;
   4369         entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
   4370         poolDiscard(&dtd->pool);
   4371         /* first, determine if a check for an existing declaration is needed;
   4372            if yes, check that the entity exists, and that it is internal,
   4373            otherwise call the skipped entity handler
   4374         */
   4375         if (prologState.documentEntity &&
   4376             (dtd->standalone
   4377              ? !openInternalEntities
   4378              : !dtd->hasParamEntityRefs)) {
   4379           if (!entity)
   4380             return XML_ERROR_UNDEFINED_ENTITY;
   4381           else if (!entity->is_internal)
   4382             return XML_ERROR_ENTITY_DECLARED_IN_PE;
   4383         }
   4384         else if (!entity) {
   4385           dtd->keepProcessing = dtd->standalone;
   4386           /* cannot report skipped entities in declarations */
   4387           if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
   4388             skippedEntityHandler(handlerArg, name, 1);
   4389             handleDefault = XML_FALSE;
   4390           }
   4391           break;
   4392         }
   4393         if (entity->open)
   4394           return XML_ERROR_RECURSIVE_ENTITY_REF;
   4395         if (entity->textPtr) {
   4396           enum XML_Error result;
   4397           XML_Bool betweenDecl =
   4398             (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
   4399           result = processInternalEntity(parser, entity, betweenDecl);
   4400           if (result != XML_ERROR_NONE)
   4401             return result;
   4402           handleDefault = XML_FALSE;
   4403           break;
   4404         }
   4405         if (externalEntityRefHandler) {
   4406           dtd->paramEntityRead = XML_FALSE;
   4407           entity->open = XML_TRUE;
   4408           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
   4409                                         0,
   4410                                         entity->base,
   4411                                         entity->systemId,
   4412                                         entity->publicId)) {
   4413             entity->open = XML_FALSE;
   4414             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
   4415           }
   4416           entity->open = XML_FALSE;
   4417           handleDefault = XML_FALSE;
   4418           if (!dtd->paramEntityRead) {
   4419             dtd->keepProcessing = dtd->standalone;
   4420             break;
   4421           }
   4422         }
   4423         else {
   4424           dtd->keepProcessing = dtd->standalone;
   4425           break;
   4426         }
   4427       }
   4428 #endif /* XML_DTD */
   4429       if (!dtd->standalone &&
   4430           notStandaloneHandler &&
   4431           !notStandaloneHandler(handlerArg))
   4432         return XML_ERROR_NOT_STANDALONE;
   4433       break;
   4434 
   4435     /* Element declaration stuff */
   4436 
   4437     case XML_ROLE_ELEMENT_NAME:
   4438       if (elementDeclHandler) {
   4439         declElementType = getElementType(parser, enc, s, next);
   4440         if (!declElementType)
   4441           return XML_ERROR_NO_MEMORY;
   4442         dtd->scaffLevel = 0;
   4443         dtd->scaffCount = 0;
   4444         dtd->in_eldecl = XML_TRUE;
   4445         handleDefault = XML_FALSE;
   4446       }
   4447       break;
   4448 
   4449     case XML_ROLE_CONTENT_ANY:
   4450     case XML_ROLE_CONTENT_EMPTY:
   4451       if (dtd->in_eldecl) {
   4452         if (elementDeclHandler) {
   4453           XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
   4454           if (!content)
   4455             return XML_ERROR_NO_MEMORY;
   4456           content->quant = XML_CQUANT_NONE;
   4457           content->name = NULL;
   4458           content->numchildren = 0;
   4459           content->children = NULL;
   4460           content->type = ((role == XML_ROLE_CONTENT_ANY) ?
   4461                            XML_CTYPE_ANY :
   4462                            XML_CTYPE_EMPTY);
   4463           *eventEndPP = s;
   4464           elementDeclHandler(handlerArg, declElementType->name, content);
   4465           handleDefault = XML_FALSE;
   4466         }
   4467         dtd->in_eldecl = XML_FALSE;
   4468       }
   4469       break;
   4470 
   4471     case XML_ROLE_CONTENT_PCDATA:
   4472       if (dtd->in_eldecl) {
   4473         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
   4474             = XML_CTYPE_MIXED;
   4475         if (elementDeclHandler)
   4476           handleDefault = XML_FALSE;
   4477       }
   4478       break;
   4479 
   4480     case XML_ROLE_CONTENT_ELEMENT:
   4481       quant = XML_CQUANT_NONE;
   4482       goto elementContent;
   4483     case XML_ROLE_CONTENT_ELEMENT_OPT:
   4484       quant = XML_CQUANT_OPT;
   4485       goto elementContent;
   4486     case XML_ROLE_CONTENT_ELEMENT_REP:
   4487       quant = XML_CQUANT_REP;
   4488       goto elementContent;
   4489     case XML_ROLE_CONTENT_ELEMENT_PLUS:
   4490       quant = XML_CQUANT_PLUS;
   4491     elementContent:
   4492       if (dtd->in_eldecl) {
   4493         ELEMENT_TYPE *el;
   4494         const XML_Char *name;
   4495         int nameLen;
   4496         const char *nxt = (quant == XML_CQUANT_NONE
   4497                            ? next
   4498                            : next - enc->minBytesPerChar);
   4499         int myindex = nextScaffoldPart(parser);
   4500         if (myindex < 0)
   4501           return XML_ERROR_NO_MEMORY;
   4502         dtd->scaffold[myindex].type = XML_CTYPE_NAME;
   4503         dtd->scaffold[myindex].quant = quant;
   4504         el = getElementType(parser, enc, s, nxt);
   4505         if (!el)
   4506           return XML_ERROR_NO_MEMORY;
   4507         name = el->name;
   4508         dtd->scaffold[myindex].name = name;
   4509         nameLen = 0;
   4510         for (; name[nameLen++]; );
   4511         dtd->contentStringLen +=  nameLen;
   4512         if (elementDeclHandler)
   4513           handleDefault = XML_FALSE;
   4514       }
   4515       break;
   4516 
   4517     case XML_ROLE_GROUP_CLOSE:
   4518       quant = XML_CQUANT_NONE;
   4519       goto closeGroup;
   4520     case XML_ROLE_GROUP_CLOSE_OPT:
   4521       quant = XML_CQUANT_OPT;
   4522       goto closeGroup;
   4523     case XML_ROLE_GROUP_CLOSE_REP:
   4524       quant = XML_CQUANT_REP;
   4525       goto closeGroup;
   4526     case XML_ROLE_GROUP_CLOSE_PLUS:
   4527       quant = XML_CQUANT_PLUS;
   4528     closeGroup:
   4529       if (dtd->in_eldecl) {
   4530         if (elementDeclHandler)
   4531           handleDefault = XML_FALSE;
   4532         dtd->scaffLevel--;
   4533         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
   4534         if (dtd->scaffLevel == 0) {
   4535           if (!handleDefault) {
   4536             XML_Content *model = build_model(parser);
   4537             if (!model)
   4538               return XML_ERROR_NO_MEMORY;
   4539             *eventEndPP = s;
   4540             elementDeclHandler(handlerArg, declElementType->name, model);
   4541           }
   4542           dtd->in_eldecl = XML_FALSE;
   4543           dtd->contentStringLen = 0;
   4544         }
   4545       }
   4546       break;
   4547       /* End element declaration stuff */
   4548 
   4549     case XML_ROLE_PI:
   4550       if (!reportProcessingInstruction(parser, enc, s, next))
   4551         return XML_ERROR_NO_MEMORY;
   4552       handleDefault = XML_FALSE;
   4553       break;
   4554     case XML_ROLE_COMMENT:
   4555       if (!reportComment(parser, enc, s, next))
   4556         return XML_ERROR_NO_MEMORY;
   4557       handleDefault = XML_FALSE;
   4558       break;
   4559     case XML_ROLE_NONE:
   4560       switch (tok) {
   4561       case XML_TOK_BOM:
   4562         handleDefault = XML_FALSE;
   4563         break;
   4564       }
   4565       break;
   4566     case XML_ROLE_DOCTYPE_NONE:
   4567       if (startDoctypeDeclHandler)
   4568         handleDefault = XML_FALSE;
   4569       break;
   4570     case XML_ROLE_ENTITY_NONE:
   4571       if (dtd->keepProcessing && entityDeclHandler)
   4572         handleDefault = XML_FALSE;
   4573       break;
   4574     case XML_ROLE_NOTATION_NONE:
   4575       if (notationDeclHandler)
   4576         handleDefault = XML_FALSE;
   4577       break;
   4578     case XML_ROLE_ATTLIST_NONE:
   4579       if (dtd->keepProcessing && attlistDeclHandler)
   4580         handleDefault = XML_FALSE;
   4581       break;
   4582     case XML_ROLE_ELEMENT_NONE:
   4583       if (elementDeclHandler)
   4584         handleDefault = XML_FALSE;
   4585       break;
   4586     } /* end of big switch */
   4587 
   4588     if (handleDefault && defaultHandler)
   4589       reportDefault(parser, enc, s, next);
   4590 
   4591     switch (ps_parsing) {
   4592     case XML_SUSPENDED:
   4593       *nextPtr = next;
   4594       return XML_ERROR_NONE;
   4595     case XML_FINISHED:
   4596       return XML_ERROR_ABORTED;
   4597     default:
   4598       s = next;
   4599       tok = XmlPrologTok(enc, s, end, &next);
   4600     }
   4601   }
   4602   /* not reached */
   4603 }
   4604 
   4605 static enum XML_Error PTRCALL
   4606 epilogProcessor(XML_Parser parser,
   4607                 const char *s,
   4608                 const char *end,
   4609                 const char **nextPtr)
   4610 {
   4611   processor = epilogProcessor;
   4612   eventPtr = s;
   4613   for (;;) {
   4614     const char *next = NULL;
   4615     int tok = XmlPrologTok(encoding, s, end, &next);
   4616     eventEndPtr = next;
   4617     switch (tok) {
   4618     /* report partial linebreak - it might be the last token */
   4619     case -XML_TOK_PROLOG_S:
   4620       if (defaultHandler) {
   4621         reportDefault(parser, encoding, s, next);
   4622         if (ps_parsing == XML_FINISHED)
   4623           return XML_ERROR_ABORTED;
   4624       }
   4625       *nextPtr = next;
   4626       return XML_ERROR_NONE;
   4627     case XML_TOK_NONE:
   4628       *nextPtr = s;
   4629       return XML_ERROR_NONE;
   4630     case XML_TOK_PROLOG_S:
   4631       if (defaultHandler)
   4632         reportDefault(parser, encoding, s, next);
   4633       break;
   4634     case XML_TOK_PI:
   4635       if (!reportProcessingInstruction(parser, encoding, s, next))
   4636         return XML_ERROR_NO_MEMORY;
   4637       break;
   4638     case XML_TOK_COMMENT:
   4639       if (!reportComment(parser, encoding, s, next))
   4640         return XML_ERROR_NO_MEMORY;
   4641       break;
   4642     case XML_TOK_INVALID:
   4643       eventPtr = next;
   4644       return XML_ERROR_INVALID_TOKEN;
   4645     case XML_TOK_PARTIAL:
   4646       if (!ps_finalBuffer) {
   4647         *nextPtr = s;
   4648         return XML_ERROR_NONE;
   4649       }
   4650       return XML_ERROR_UNCLOSED_TOKEN;
   4651     case XML_TOK_PARTIAL_CHAR:
   4652       if (!ps_finalBuffer) {
   4653         *nextPtr = s;
   4654         return XML_ERROR_NONE;
   4655       }
   4656       return XML_ERROR_PARTIAL_CHAR;
   4657     default:
   4658       return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
   4659     }
   4660     eventPtr = s = next;
   4661     switch (ps_parsing) {
   4662     case XML_SUSPENDED:
   4663       *nextPtr = next;
   4664       return XML_ERROR_NONE;
   4665     case XML_FINISHED:
   4666       return XML_ERROR_ABORTED;
   4667     default: ;
   4668     }
   4669   }
   4670 }
   4671 
   4672 static enum XML_Error
   4673 processInternalEntity(XML_Parser parser, ENTITY *entity,
   4674                       XML_Bool betweenDecl)
   4675 {
   4676   const char *textStart, *textEnd;
   4677   const char *next;
   4678   enum XML_Error result;
   4679   OPEN_INTERNAL_ENTITY *openEntity;
   4680 
   4681   if (freeInternalEntities) {
   4682     openEntity = freeInternalEntities;
   4683     freeInternalEntities = openEntity->next;
   4684   }
   4685   else {
   4686     openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
   4687     if (!openEntity)
   4688       return XML_ERROR_NO_MEMORY;
   4689   }
   4690   entity->open = XML_TRUE;
   4691   entity->processed = 0;
   4692   openEntity->next = openInternalEntities;
   4693   openInternalEntities = openEntity;
   4694   openEntity->entity = entity;
   4695   openEntity->startTagLevel = tagLevel;
   4696   openEntity->betweenDecl = betweenDecl;
   4697   openEntity->internalEventPtr = NULL;
   4698   openEntity->internalEventEndPtr = NULL;
   4699   textStart = (char *)entity->textPtr;
   4700   textEnd = (char *)(entity->textPtr + entity->textLen);
   4701 
   4702 #ifdef XML_DTD
   4703   if (entity->is_param) {
   4704     int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
   4705     result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
   4706                       next, &next, XML_FALSE);
   4707   }
   4708   else
   4709 #endif /* XML_DTD */
   4710     result = doContent(parser, tagLevel, internalEncoding, textStart,
   4711                        textEnd, &next, XML_FALSE);
   4712 
   4713   if (result == XML_ERROR_NONE) {
   4714     if (textEnd != next && ps_parsing == XML_SUSPENDED) {
   4715       entity->processed = (int)(next - textStart);
   4716       processor = internalEntityProcessor;
   4717     }
   4718     else {
   4719       entity->open = XML_FALSE;
   4720       openInternalEntities = openEntity->next;
   4721       /* put openEntity back in list of free instances */
   4722       openEntity->next = freeInternalEntities;
   4723       freeInternalEntities = openEntity;
   4724     }
   4725   }
   4726   return result;
   4727 }
   4728 
   4729 static enum XML_Error PTRCALL
   4730 internalEntityProcessor(XML_Parser parser,
   4731                         const char *s,
   4732                         const char *end,
   4733                         const char **nextPtr)
   4734 {
   4735   ENTITY *entity;
   4736   const char *textStart, *textEnd;
   4737   const char *next;
   4738   enum XML_Error result;
   4739   OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
   4740   if (!openEntity)
   4741     return XML_ERROR_UNEXPECTED_STATE;
   4742 
   4743   entity = openEntity->entity;
   4744   textStart = ((char *)entity->textPtr) + entity->processed;
   4745   textEnd = (char *)(entity->textPtr + entity->textLen);
   4746 
   4747 #ifdef XML_DTD
   4748   if (entity->is_param) {
   4749     int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
   4750     result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
   4751                       next, &next, XML_FALSE);
   4752   }
   4753   else
   4754 #endif /* XML_DTD */
   4755     result = doContent(parser, openEntity->startTagLevel, internalEncoding,
   4756                        textStart, textEnd, &next, XML_FALSE);
   4757 
   4758   if (result != XML_ERROR_NONE)
   4759     return result;
   4760   else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
   4761     entity->processed = (int)(next - (char *)entity->textPtr);
   4762     return result;
   4763   }
   4764   else {
   4765     entity->open = XML_FALSE;
   4766     openInternalEntities = openEntity->next;
   4767     /* put openEntity back in list of free instances */
   4768     openEntity->next = freeInternalEntities;
   4769     freeInternalEntities = openEntity;
   4770   }
   4771 
   4772 #ifdef XML_DTD
   4773   if (entity->is_param) {
   4774     int tok;
   4775     processor = prologProcessor;
   4776     tok = XmlPrologTok(encoding, s, end, &next);
   4777     return doProlog(parser, encoding, s, end, tok, next, nextPtr,
   4778                     (XML_Bool)!ps_finalBuffer);
   4779   }
   4780   else
   4781 #endif /* XML_DTD */
   4782   {
   4783     processor = contentProcessor;
   4784     /* see externalEntityContentProcessor vs contentProcessor */
   4785     return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
   4786                      nextPtr, (XML_Bool)!ps_finalBuffer);
   4787   }
   4788 }
   4789 
   4790 static enum XML_Error PTRCALL
   4791 errorProcessor(XML_Parser parser,
   4792                const char *s,
   4793                const char *end,
   4794                const char **nextPtr)
   4795 {
   4796   return errorCode;
   4797 }
   4798 
   4799 static enum XML_Error
   4800 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
   4801                     const char *ptr, const char *end,
   4802                     STRING_POOL *pool)
   4803 {
   4804   enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
   4805                                                end, pool);
   4806   if (result)
   4807     return result;
   4808   if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
   4809     poolChop(pool);
   4810   if (!poolAppendChar(pool, XML_T('\0')))
   4811     return XML_ERROR_NO_MEMORY;
   4812   return XML_ERROR_NONE;
   4813 }
   4814 
   4815 static enum XML_Error
   4816 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
   4817                      const char *ptr, const char *end,
   4818                      STRING_POOL *pool)
   4819 {
   4820   DTD * const dtd = _dtd;  /* save one level of indirection */
   4821   for (;;) {
   4822     const char *next;
   4823     int tok = XmlAttributeValueTok(enc, ptr, end, &next);
   4824     switch (tok) {
   4825     case XML_TOK_NONE:
   4826       return XML_ERROR_NONE;
   4827     case XML_TOK_INVALID:
   4828       if (enc == encoding)
   4829         eventPtr = next;
   4830       return XML_ERROR_INVALID_TOKEN;
   4831     case XML_TOK_PARTIAL:
   4832       if (enc == encoding)
   4833         eventPtr = ptr;
   4834       return XML_ERROR_INVALID_TOKEN;
   4835     case XML_TOK_CHAR_REF:
   4836       {
   4837         XML_Char buf[XML_ENCODE_MAX];
   4838         int i;
   4839         int n = XmlCharRefNumber(enc, ptr);
   4840         if (n < 0) {
   4841           if (enc == encoding)
   4842             eventPtr = ptr;
   4843           return XML_ERROR_BAD_CHAR_REF;
   4844         }
   4845         if (!isCdata
   4846             && n == 0x20 /* space */
   4847             && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
   4848           break;
   4849         n = XmlEncode(n, (ICHAR *)buf);
   4850         if (!n) {
   4851           if (enc == encoding)
   4852             eventPtr = ptr;
   4853           return XML_ERROR_BAD_CHAR_REF;
   4854         }
   4855         for (i = 0; i < n; i++) {
   4856           if (!poolAppendChar(pool, buf[i]))
   4857             return XML_ERROR_NO_MEMORY;
   4858         }
   4859       }
   4860       break;
   4861     case XML_TOK_DATA_CHARS:
   4862       if (!poolAppend(pool, enc, ptr, next))
   4863         return XML_ERROR_NO_MEMORY;
   4864       break;
   4865     case XML_TOK_TRAILING_CR:
   4866       next = ptr + enc->minBytesPerChar;
   4867       /* fall through */
   4868     case XML_TOK_ATTRIBUTE_VALUE_S:
   4869     case XML_TOK_DATA_NEWLINE:
   4870       if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
   4871         break;
   4872       if (!poolAppendChar(pool, 0x20))
   4873         return XML_ERROR_NO_MEMORY;
   4874       break;
   4875     case XML_TOK_ENTITY_REF:
   4876       {
   4877         const XML_Char *name;
   4878         ENTITY *entity;
   4879         char checkEntityDecl;
   4880         XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
   4881                                               ptr + enc->minBytesPerChar,
   4882                                               next - enc->minBytesPerChar);
   4883         if (ch) {
   4884           if (!poolAppendChar(pool, ch))
   4885                 return XML_ERROR_NO_MEMORY;
   4886           break;
   4887         }
   4888         name = poolStoreString(&temp2Pool, enc,
   4889                                ptr + enc->minBytesPerChar,
   4890                                next - enc->minBytesPerChar);
   4891         if (!name)
   4892           return XML_ERROR_NO_MEMORY;
   4893         entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
   4894         poolDiscard(&temp2Pool);
   4895         /* First, determine if a check for an existing declaration is needed;
   4896            if yes, check that the entity exists, and that it is internal.
   4897         */
   4898         if (pool == &dtd->pool)  /* are we called from prolog? */
   4899           checkEntityDecl =
   4900 #ifdef XML_DTD
   4901               prologState.documentEntity &&
   4902 #endif /* XML_DTD */
   4903               (dtd->standalone
   4904                ? !openInternalEntities
   4905                : !dtd->hasParamEntityRefs);
   4906         else /* if (pool == &tempPool): we are called from content */
   4907           checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
   4908         if (checkEntityDecl) {
   4909           if (!entity)
   4910             return XML_ERROR_UNDEFINED_ENTITY;
   4911           else if (!entity->is_internal)
   4912             return XML_ERROR_ENTITY_DECLARED_IN_PE;
   4913         }
   4914         else if (!entity) {
   4915           /* Cannot report skipped entity here - see comments on
   4916              skippedEntityHandler.
   4917           if (skippedEntityHandler)
   4918             skippedEntityHandler(handlerArg, name, 0);
   4919           */
   4920           /* Cannot call the default handler because this would be
   4921              out of sync with the call to the startElementHandler.
   4922           if ((pool == &tempPool) && defaultHandler)
   4923             reportDefault(parser, enc, ptr, next);
   4924           */
   4925           break;
   4926         }
   4927         if (entity->open) {
   4928           if (enc == encoding)
   4929             eventPtr = ptr;
   4930           return XML_ERROR_RECURSIVE_ENTITY_REF;
   4931         }
   4932         if (entity->notation) {
   4933           if (enc == encoding)
   4934             eventPtr = ptr;
   4935           return XML_ERROR_BINARY_ENTITY_REF;
   4936         }
   4937         if (!entity->textPtr) {
   4938           if (enc == encoding)
   4939             eventPtr = ptr;
   4940               return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
   4941         }
   4942         else {
   4943           enum XML_Error result;
   4944           const XML_Char *textEnd = entity->textPtr + entity->textLen;
   4945           entity->open = XML_TRUE;
   4946           result = appendAttributeValue(parser, internalEncoding, isCdata,
   4947                                         (char *)entity->textPtr,
   4948                                         (char *)textEnd, pool);
   4949           entity->open = XML_FALSE;
   4950           if (result)
   4951             return result;
   4952         }
   4953       }
   4954       break;
   4955     default:
   4956       if (enc == encoding)
   4957         eventPtr = ptr;
   4958       return XML_ERROR_UNEXPECTED_STATE;
   4959     }
   4960     ptr = next;
   4961   }
   4962   /* not reached */
   4963 }
   4964 
   4965 static enum XML_Error
   4966 storeEntityValue(XML_Parser parser,
   4967                  const ENCODING *enc,
   4968                  const char *entityTextPtr,
   4969                  const char *entityTextEnd)
   4970 {
   4971   DTD * const dtd = _dtd;  /* save one level of indirection */
   4972   STRING_POOL *pool = &(dtd->entityValuePool);
   4973   enum XML_Error result = XML_ERROR_NONE;
   4974 #ifdef XML_DTD
   4975   int oldInEntityValue = prologState.inEntityValue;
   4976   prologState.inEntityValue = 1;
   4977 #endif /* XML_DTD */
   4978   /* never return Null for the value argument in EntityDeclHandler,
   4979      since this would indicate an external entity; therefore we
   4980      have to make sure that entityValuePool.start is not null */
   4981   if (!pool->blocks) {
   4982     if (!poolGrow(pool))
   4983       return XML_ERROR_NO_MEMORY;
   4984   }
   4985 
   4986   for (;;) {
   4987     const char *next;
   4988     int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
   4989     switch (tok) {
   4990     case XML_TOK_PARAM_ENTITY_REF:
   4991 #ifdef XML_DTD
   4992       if (isParamEntity || enc != encoding) {
   4993         const XML_Char *name;
   4994         ENTITY *entity;
   4995         name = poolStoreString(&tempPool, enc,
   4996                                entityTextPtr + enc->minBytesPerChar,
   4997                                next - enc->minBytesPerChar);
   4998         if (!name) {
   4999           result = XML_ERROR_NO_MEMORY;
   5000           goto endEntityValue;
   5001         }
   5002         entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
   5003         poolDiscard(&tempPool);
   5004         if (!entity) {
   5005           /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
   5006           /* cannot report skipped entity here - see comments on
   5007              skippedEntityHandler
   5008           if (skippedEntityHandler)
   5009             skippedEntityHandler(handlerArg, name, 0);
   5010           */
   5011           dtd->keepProcessing = dtd->standalone;
   5012           goto endEntityValue;
   5013         }
   5014         if (entity->open) {
   5015           if (enc == encoding)
   5016             eventPtr = entityTextPtr;
   5017           result = XML_ERROR_RECURSIVE_ENTITY_REF;
   5018           goto endEntityValue;
   5019         }
   5020         if (entity->systemId) {
   5021           if (externalEntityRefHandler) {
   5022             dtd->paramEntityRead = XML_FALSE;
   5023             entity->open = XML_TRUE;
   5024             if (!externalEntityRefHandler(externalEntityRefHandlerArg,
   5025                                           0,
   5026                                           entity->base,
   5027                                           entity->systemId,
   5028                                           entity->publicId)) {
   5029               entity->open = XML_FALSE;
   5030               result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
   5031               goto endEntityValue;
   5032             }
   5033             entity->open = XML_FALSE;
   5034             if (!dtd->paramEntityRead)
   5035               dtd->keepProcessing = dtd->standalone;
   5036           }
   5037           else
   5038             dtd->keepProcessing = dtd->standalone;
   5039         }
   5040         else {
   5041           entity->open = XML_TRUE;
   5042           result = storeEntityValue(parser,
   5043                                     internalEncoding,
   5044                                     (char *)entity->textPtr,
   5045                                     (char *)(entity->textPtr
   5046                                              + entity->textLen));
   5047           entity->open = XML_FALSE;
   5048           if (result)
   5049             goto endEntityValue;
   5050         }
   5051         break;
   5052       }
   5053 #endif /* XML_DTD */
   5054       /* In the internal subset, PE references are not legal
   5055          within markup declarations, e.g entity values in this case. */
   5056       eventPtr = entityTextPtr;
   5057       result = XML_ERROR_PARAM_ENTITY_REF;
   5058       goto endEntityValue;
   5059     case XML_TOK_NONE:
   5060       result = XML_ERROR_NONE;
   5061       goto endEntityValue;
   5062     case XML_TOK_ENTITY_REF:
   5063     case XML_TOK_DATA_CHARS:
   5064       if (!poolAppend(pool, enc, entityTextPtr, next)) {
   5065         result = XML_ERROR_NO_MEMORY;
   5066         goto endEntityValue;
   5067       }
   5068       break;
   5069     case XML_TOK_TRAILING_CR:
   5070       next = entityTextPtr + enc->minBytesPerChar;
   5071       /* fall through */
   5072     case XML_TOK_DATA_NEWLINE:
   5073       if (pool->end == pool->ptr && !poolGrow(pool)) {
   5074               result = XML_ERROR_NO_MEMORY;
   5075         goto endEntityValue;
   5076       }
   5077       *(pool->ptr)++ = 0xA;
   5078       break;
   5079     case XML_TOK_CHAR_REF:
   5080       {
   5081         XML_Char buf[XML_ENCODE_MAX];
   5082         int i;
   5083         int n = XmlCharRefNumber(enc, entityTextPtr);
   5084         if (n < 0) {
   5085           if (enc == encoding)
   5086             eventPtr = entityTextPtr;
   5087           result = XML_ERROR_BAD_CHAR_REF;
   5088           goto endEntityValue;
   5089         }
   5090         n = XmlEncode(n, (ICHAR *)buf);
   5091         if (!n) {
   5092           if (enc == encoding)
   5093             eventPtr = entityTextPtr;
   5094           result = XML_ERROR_BAD_CHAR_REF;
   5095           goto endEntityValue;
   5096         }
   5097         for (i = 0; i < n; i++) {
   5098           if (pool->end == pool->ptr && !poolGrow(pool)) {
   5099             result = XML_ERROR_NO_MEMORY;
   5100             goto endEntityValue;
   5101           }
   5102           *(pool->ptr)++ = buf[i];
   5103         }
   5104       }
   5105       break;
   5106     case XML_TOK_PARTIAL:
   5107       if (enc == encoding)
   5108         eventPtr = entityTextPtr;
   5109       result = XML_ERROR_INVALID_TOKEN;
   5110       goto endEntityValue;
   5111     case XML_TOK_INVALID:
   5112       if (enc == encoding)
   5113         eventPtr = next;
   5114       result = XML_ERROR_INVALID_TOKEN;
   5115       goto endEntityValue;
   5116     default:
   5117       if (enc == encoding)
   5118         eventPtr = entityTextPtr;
   5119       result = XML_ERROR_UNEXPECTED_STATE;
   5120       goto endEntityValue;
   5121     }
   5122     entityTextPtr = next;
   5123   }
   5124 endEntityValue:
   5125 #ifdef XML_DTD
   5126   prologState.inEntityValue = oldInEntityValue;
   5127 #endif /* XML_DTD */
   5128   return result;
   5129 }
   5130 
   5131 static void FASTCALL
   5132 normalizeLines(XML_Char *s)
   5133 {
   5134   XML_Char *p;
   5135   for (;; s++) {
   5136     if (*s == XML_T('\0'))
   5137       return;
   5138     if (*s == 0xD)
   5139       break;
   5140   }
   5141   p = s;
   5142   do {
   5143     if (*s == 0xD) {
   5144       *p++ = 0xA;
   5145       if (*++s == 0xA)
   5146         s++;
   5147     }
   5148     else
   5149       *p++ = *s++;
   5150   } while (*s);
   5151   *p = XML_T('\0');
   5152 }
   5153 
   5154 static int
   5155 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
   5156                             const char *start, const char *end)
   5157 {
   5158   const XML_Char *target;
   5159   XML_Char *data;
   5160   const char *tem;
   5161   if (!processingInstructionHandler) {
   5162     if (defaultHandler)
   5163       reportDefault(parser, enc, start, end);
   5164     return 1;
   5165   }
   5166   start += enc->minBytesPerChar * 2;
   5167   tem = start + XmlNameLength(enc, start);
   5168   target = poolStoreString(&tempPool, enc, start, tem);
   5169   if (!target)
   5170     return 0;
   5171   poolFinish(&tempPool);
   5172   data = poolStoreString(&tempPool, enc,
   5173                         XmlSkipS(enc, tem),
   5174                         end - enc->minBytesPerChar*2);
   5175   if (!data)
   5176     return 0;
   5177   normalizeLines(data);
   5178   processingInstructionHandler(handlerArg, target, data);
   5179   poolClear(&tempPool);
   5180   return 1;
   5181 }
   5182 
   5183 static int
   5184 reportComment(XML_Parser parser, const ENCODING *enc,
   5185               const char *start, const char *end)
   5186 {
   5187   XML_Char *data;
   5188   if (!commentHandler) {
   5189     if (defaultHandler)
   5190       reportDefault(parser, enc, start, end);
   5191     return 1;
   5192   }
   5193   data = poolStoreString(&tempPool,
   5194                          enc,
   5195                          start + enc->minBytesPerChar * 4,
   5196                          end - enc->minBytesPerChar * 3);
   5197   if (!data)
   5198     return 0;
   5199   normalizeLines(data);
   5200   commentHandler(handlerArg, data);
   5201   poolClear(&tempPool);
   5202   return 1;
   5203 }
   5204 
   5205 static void
   5206 reportDefault(XML_Parser parser, const ENCODING *enc,
   5207               const char *s, const char *end)
   5208 {
   5209   if (MUST_CONVERT(enc, s)) {
   5210     const char **eventPP;
   5211     const char **eventEndPP;
   5212     if (enc == encoding) {
   5213       eventPP = &eventPtr;
   5214       eventEndPP = &eventEndPtr;
   5215     }
   5216     else {
   5217       eventPP = &(openInternalEntities->internalEventPtr);
   5218       eventEndPP = &(openInternalEntities->internalEventEndPtr);
   5219     }
   5220     do {
   5221       ICHAR *dataPtr = (ICHAR *)dataBuf;
   5222       XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
   5223       *eventEndPP = s;
   5224       defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
   5225       *eventPP = s;
   5226     } while (s != end);
   5227   }
   5228   else
   5229     defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
   5230 }
   5231 
   5232 
   5233 static int
   5234 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
   5235                 XML_Bool isId, const XML_Char *value, XML_Parser parser)
   5236 {
   5237   DEFAULT_ATTRIBUTE *att;
   5238   if (value || isId) {
   5239     /* The handling of default attributes gets messed up if we have
   5240        a default which duplicates a non-default. */
   5241     int i;
   5242     for (i = 0; i < type->nDefaultAtts; i++)
   5243       if (attId == type->defaultAtts[i].id)
   5244         return 1;
   5245     if (isId && !type->idAtt && !attId->xmlns)
   5246       type->idAtt = attId;
   5247   }
   5248   if (type->nDefaultAtts == type->allocDefaultAtts) {
   5249     if (type->allocDefaultAtts == 0) {
   5250       type->allocDefaultAtts = 8;
   5251       type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
   5252                             * sizeof(DEFAULT_ATTRIBUTE));
   5253       if (!type->defaultAtts)
   5254         return 0;
   5255     }
   5256     else {
   5257       DEFAULT_ATTRIBUTE *temp;
   5258       int count = type->allocDefaultAtts * 2;
   5259       temp = (DEFAULT_ATTRIBUTE *)
   5260         REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
   5261       if (temp == NULL)
   5262         return 0;
   5263       type->allocDefaultAtts = count;
   5264       type->defaultAtts = temp;
   5265     }
   5266   }
   5267   att = type->defaultAtts + type->nDefaultAtts;
   5268   att->id = attId;
   5269   att->value = value;
   5270   att->isCdata = isCdata;
   5271   if (!isCdata)
   5272     attId->maybeTokenized = XML_TRUE;
   5273   type->nDefaultAtts += 1;
   5274   return 1;
   5275 }
   5276 
   5277 static int
   5278 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
   5279 {
   5280   DTD * const dtd = _dtd;  /* save one level of indirection */
   5281   const XML_Char *name;
   5282   for (name = elementType->name; *name; name++) {
   5283     if (*name == XML_T(':')) {
   5284       PREFIX *prefix;
   5285       const XML_Char *s;
   5286       for (s = elementType->name; s != name; s++) {
   5287         if (!poolAppendChar(&dtd->pool, *s))
   5288           return 0;
   5289       }
   5290       if (!poolAppendChar(&dtd->pool, XML_T('\0')))
   5291         return 0;
   5292       prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
   5293                                 sizeof(PREFIX));
   5294       if (!prefix)
   5295         return 0;
   5296       if (prefix->name == poolStart(&dtd->pool))
   5297         poolFinish(&dtd->pool);
   5298       else
   5299         poolDiscard(&dtd->pool);
   5300       elementType->prefix = prefix;
   5301 
   5302     }
   5303   }
   5304   return 1;
   5305 }
   5306 
   5307 static ATTRIBUTE_ID *
   5308 getAttributeId(XML_Parser parser, const ENCODING *enc,
   5309                const char *start, const char *end)
   5310 {
   5311   DTD * const dtd = _dtd;  /* save one level of indirection */
   5312   ATTRIBUTE_ID *id;
   5313   const XML_Char *name;
   5314   if (!poolAppendChar(&dtd->pool, XML_T('\0')))
   5315     return NULL;
   5316   name = poolStoreString(&dtd->pool, enc, start, end);
   5317   if (!name)
   5318     return NULL;
   5319   /* skip quotation mark - its storage will be re-used (like in name[-1]) */
   5320   ++name;
   5321   id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
   5322   if (!id)
   5323     return NULL;
   5324   if (id->name != name)
   5325     poolDiscard(&dtd->pool);
   5326   else {
   5327     poolFinish(&dtd->pool);
   5328     if (!ns)
   5329       ;
   5330     else if (name[0] == XML_T('x')
   5331         && name[1] == XML_T('m')
   5332         && name[2] == XML_T('l')
   5333         && name[3] == XML_T('n')
   5334         && name[4] == XML_T('s')
   5335         && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
   5336       if (name[5] == XML_T('\0'))
   5337         id->prefix = &dtd->defaultPrefix;
   5338       else
   5339         id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
   5340       id->xmlns = XML_TRUE;
   5341     }
   5342     else {
   5343       int i;
   5344       for (i = 0; name[i]; i++) {
   5345         /* attributes without prefix are *not* in the default namespace */
   5346         if (name[i] == XML_T(':')) {
   5347           int j;
   5348           for (j = 0; j < i; j++) {
   5349             if (!poolAppendChar(&dtd->pool, name[j]))
   5350               return NULL;
   5351           }
   5352           if (!poolAppendChar(&dtd->pool, XML_T('\0')))
   5353             return NULL;
   5354           id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
   5355                                         sizeof(PREFIX));
   5356           if (!id->prefix)
   5357             return NULL;
   5358           if (id->prefix->name == poolStart(&dtd->pool))
   5359             poolFinish(&dtd->pool);
   5360           else
   5361             poolDiscard(&dtd->pool);
   5362           break;
   5363         }
   5364       }
   5365     }
   5366   }
   5367   return id;
   5368 }
   5369 
   5370 #define CONTEXT_SEP XML_T('\f')
   5371 
   5372 static const XML_Char *
   5373 getContext(XML_Parser parser)
   5374 {
   5375   DTD * const dtd = _dtd;  /* save one level of indirection */
   5376   HASH_TABLE_ITER iter;
   5377   XML_Bool needSep = XML_FALSE;
   5378 
   5379   if (dtd->defaultPrefix.binding) {
   5380     int i;
   5381     int len;
   5382     if (!poolAppendChar(&tempPool, XML_T('=')))
   5383       return NULL;
   5384     len = dtd->defaultPrefix.binding->uriLen;
   5385     if (namespaceSeparator)
   5386       len--;
   5387     for (i = 0; i < len; i++)
   5388       if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
   5389         return NULL;
   5390     needSep = XML_TRUE;
   5391   }
   5392 
   5393   hashTableIterInit(&iter, &(dtd->prefixes));
   5394   for (;;) {
   5395     int i;
   5396     int len;
   5397     const XML_Char *s;
   5398     PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
   5399     if (!prefix)
   5400       break;
   5401     if (!prefix->binding)
   5402       continue;
   5403     if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
   5404       return NULL;
   5405     for (s = prefix->name; *s; s++)
   5406       if (!poolAppendChar(&tempPool, *s))
   5407         return NULL;
   5408     if (!poolAppendChar(&tempPool, XML_T('=')))
   5409       return NULL;
   5410     len = prefix->binding->uriLen;
   5411     if (namespaceSeparator)
   5412       len--;
   5413     for (i = 0; i < len; i++)
   5414       if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
   5415         return NULL;
   5416     needSep = XML_TRUE;
   5417   }
   5418 
   5419 
   5420   hashTableIterInit(&iter, &(dtd->generalEntities));
   5421   for (;;) {
   5422     const XML_Char *s;
   5423     ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
   5424     if (!e)
   5425       break;
   5426     if (!e->open)
   5427       continue;
   5428     if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
   5429       return NULL;
   5430     for (s = e->name; *s; s++)
   5431       if (!poolAppendChar(&tempPool, *s))
   5432         return 0;
   5433     needSep = XML_TRUE;
   5434   }
   5435 
   5436   if (!poolAppendChar(&tempPool, XML_T('\0')))
   5437     return NULL;
   5438   return tempPool.start;
   5439 }
   5440 
   5441 static XML_Bool
   5442 setContext(XML_Parser parser, const XML_Char *context)
   5443 {
   5444   DTD * const dtd = _dtd;  /* save one level of indirection */
   5445   const XML_Char *s = context;
   5446 
   5447   while (*context != XML_T('\0')) {
   5448     if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
   5449       ENTITY *e;
   5450       if (!poolAppendChar(&tempPool, XML_T('\0')))
   5451         return XML_FALSE;
   5452       e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
   5453       if (e)
   5454         e->open = XML_TRUE;
   5455       if (*s != XML_T('\0'))
   5456         s++;
   5457       context = s;
   5458       poolDiscard(&tempPool);
   5459     }
   5460     else if (*s == XML_T('=')) {
   5461       PREFIX *prefix;
   5462       if (poolLength(&tempPool) == 0)
   5463         prefix = &dtd->defaultPrefix;
   5464       else {
   5465         if (!poolAppendChar(&tempPool, XML_T('\0')))
   5466           return XML_FALSE;
   5467         prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
   5468                                   sizeof(PREFIX));
   5469         if (!prefix)
   5470           return XML_FALSE;
   5471         if (prefix->name == poolStart(&tempPool)) {
   5472           prefix->name = poolCopyString(&dtd->pool, prefix->name);
   5473           if (!prefix->name)
   5474             return XML_FALSE;
   5475         }
   5476         poolDiscard(&tempPool);
   5477       }
   5478       for (context = s + 1;
   5479            *context != CONTEXT_SEP && *context != XML_T('\0');
   5480            context++)
   5481         if (!poolAppendChar(&tempPool, *context))
   5482           return XML_FALSE;
   5483       if (!poolAppendChar(&tempPool, XML_T('\0')))
   5484         return XML_FALSE;
   5485       if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
   5486                      &inheritedBindings) != XML_ERROR_NONE)
   5487         return XML_FALSE;
   5488       poolDiscard(&tempPool);
   5489       if (*context != XML_T('\0'))
   5490         ++context;
   5491       s = context;
   5492     }
   5493     else {
   5494       if (!poolAppendChar(&tempPool, *s))
   5495         return XML_FALSE;
   5496       s++;
   5497     }
   5498   }
   5499   return XML_TRUE;
   5500 }
   5501 
   5502 static void FASTCALL
   5503 normalizePublicId(XML_Char *publicId)
   5504 {
   5505   XML_Char *p = publicId;
   5506   XML_Char *s;
   5507   for (s = publicId; *s; s++) {
   5508     switch (*s) {
   5509     case 0x20:
   5510     case 0xD:
   5511     case 0xA:
   5512       if (p != publicId && p[-1] != 0x20)
   5513         *p++ = 0x20;
   5514       break;
   5515     default:
   5516       *p++ = *s;
   5517     }
   5518   }
   5519   if (p != publicId && p[-1] == 0x20)
   5520     --p;
   5521   *p = XML_T('\0');
   5522 }
   5523 
   5524 static DTD *
   5525 dtdCreate(const XML_Memory_Handling_Suite *ms)
   5526 {
   5527   DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
   5528   if (p == NULL)
   5529     return p;
   5530   poolInit(&(p->pool), ms);
   5531   poolInit(&(p->entityValuePool), ms);
   5532   hashTableInit(&(p->generalEntities), ms);
   5533   hashTableInit(&(p->elementTypes), ms);
   5534   hashTableInit(&(p->attributeIds), ms);
   5535   hashTableInit(&(p->prefixes), ms);
   5536 #ifdef XML_DTD
   5537   p->paramEntityRead = XML_FALSE;
   5538   hashTableInit(&(p->paramEntities), ms);
   5539 #endif /* XML_DTD */
   5540   p->defaultPrefix.name = NULL;
   5541   p->defaultPrefix.binding = NULL;
   5542 
   5543   p->in_eldecl = XML_FALSE;
   5544   p->scaffIndex = NULL;
   5545   p->scaffold = NULL;
   5546   p->scaffLevel = 0;
   5547   p->scaffSize = 0;
   5548   p->scaffCount = 0;
   5549   p->contentStringLen = 0;
   5550 
   5551   p->keepProcessing = XML_TRUE;
   5552   p->hasParamEntityRefs = XML_FALSE;
   5553   p->standalone = XML_FALSE;
   5554   return p;
   5555 }
   5556 
   5557 static void
   5558 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
   5559 {
   5560   HASH_TABLE_ITER iter;
   5561   hashTableIterInit(&iter, &(p->elementTypes));
   5562   for (;;) {
   5563     ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
   5564     if (!e)
   5565       break;
   5566     if (e->allocDefaultAtts != 0)
   5567       ms->free_fcn(e->defaultAtts);
   5568   }
   5569   hashTableClear(&(p->generalEntities));
   5570 #ifdef XML_DTD
   5571   p->paramEntityRead = XML_FALSE;
   5572   hashTableClear(&(p->paramEntities));
   5573 #endif /* XML_DTD */
   5574   hashTableClear(&(p->elementTypes));
   5575   hashTableClear(&(p->attributeIds));
   5576   hashTableClear(&(p->prefixes));
   5577   poolClear(&(p->pool));
   5578   poolClear(&(p->entityValuePool));
   5579   p->defaultPrefix.name = NULL;
   5580   p->defaultPrefix.binding = NULL;
   5581 
   5582   p->in_eldecl = XML_FALSE;
   5583 
   5584   ms->free_fcn(p->scaffIndex);
   5585   p->scaffIndex = NULL;
   5586   ms->free_fcn(p->scaffold);
   5587   p->scaffold = NULL;
   5588 
   5589   p->scaffLevel = 0;
   5590   p->scaffSize = 0;
   5591   p->scaffCount = 0;
   5592   p->contentStringLen = 0;
   5593 
   5594   p->keepProcessing = XML_TRUE;
   5595   p->hasParamEntityRefs = XML_FALSE;
   5596   p->standalone = XML_FALSE;
   5597 }
   5598 
   5599 static void
   5600 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
   5601 {
   5602   HASH_TABLE_ITER iter;
   5603   hashTableIterInit(&iter, &(p->elementTypes));
   5604   for (;;) {
   5605     ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
   5606     if (!e)
   5607       break;
   5608     if (e->allocDefaultAtts != 0)
   5609       ms->free_fcn(e->defaultAtts);
   5610   }
   5611   hashTableDestroy(&(p->generalEntities));
   5612 #ifdef XML_DTD
   5613   hashTableDestroy(&(p->paramEntities));
   5614 #endif /* XML_DTD */
   5615   hashTableDestroy(&(p->elementTypes));
   5616   hashTableDestroy(&(p->attributeIds));
   5617   hashTableDestroy(&(p->prefixes));
   5618   poolDestroy(&(p->pool));
   5619   poolDestroy(&(p->entityValuePool));
   5620   if (isDocEntity) {
   5621     ms->free_fcn(p->scaffIndex);
   5622     ms->free_fcn(p->scaffold);
   5623   }
   5624   ms->free_fcn(p);
   5625 }
   5626 
   5627 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
   5628    The new DTD has already been initialized.
   5629 */
   5630 static int
   5631 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
   5632 {
   5633   HASH_TABLE_ITER iter;
   5634 
   5635   /* Copy the prefix table. */
   5636 
   5637   hashTableIterInit(&iter, &(oldDtd->prefixes));
   5638   for (;;) {
   5639     const XML_Char *name;
   5640     const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
   5641     if (!oldP)
   5642       break;
   5643     name = poolCopyString(&(newDtd->pool), oldP->name);
   5644     if (!name)
   5645       return 0;
   5646     if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
   5647       return 0;
   5648   }
   5649 
   5650   hashTableIterInit(&iter, &(oldDtd->attributeIds));
   5651 
   5652   /* Copy the attribute id table. */
   5653 
   5654   for (;;) {
   5655     ATTRIBUTE_ID *newA;
   5656     const XML_Char *name;
   5657     const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
   5658 
   5659     if (!oldA)
   5660       break;
   5661     /* Remember to allocate the scratch byte before the name. */
   5662     if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
   5663       return 0;
   5664     name = poolCopyString(&(newDtd->pool), oldA->name);
   5665     if (!name)
   5666       return 0;
   5667     ++name;
   5668     newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
   5669                                   sizeof(ATTRIBUTE_ID));
   5670     if (!newA)
   5671       return 0;
   5672     newA->maybeTokenized = oldA->maybeTokenized;
   5673     if (oldA->prefix) {
   5674       newA->xmlns = oldA->xmlns;
   5675       if (oldA->prefix == &oldDtd->defaultPrefix)
   5676         newA->prefix = &newDtd->defaultPrefix;
   5677       else
   5678         newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
   5679                                         oldA->prefix->name, 0);
   5680     }
   5681   }
   5682 
   5683   /* Copy the element type table. */
   5684 
   5685   hashTableIterInit(&iter, &(oldDtd->elementTypes));
   5686 
   5687   for (;;) {
   5688     int i;
   5689     ELEMENT_TYPE *newE;
   5690     const XML_Char *name;
   5691     const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
   5692     if (!oldE)
   5693       break;
   5694     name = poolCopyString(&(newDtd->pool), oldE->name);
   5695     if (!name)
   5696       return 0;
   5697     newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
   5698                                   sizeof(ELEMENT_TYPE));
   5699     if (!newE)
   5700       return 0;
   5701     if (oldE->nDefaultAtts) {
   5702       newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
   5703           ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
   5704       if (!newE->defaultAtts) {
   5705         ms->free_fcn(newE);
   5706         return 0;
   5707       }
   5708     }
   5709     if (oldE->idAtt)
   5710       newE->idAtt = (ATTRIBUTE_ID *)
   5711           lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
   5712     newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
   5713     if (oldE->prefix)
   5714       newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
   5715                                       oldE->prefix->name, 0);
   5716     for (i = 0; i < newE->nDefaultAtts; i++) {
   5717       newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
   5718           lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
   5719       newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
   5720       if (oldE->defaultAtts[i].value) {
   5721         newE->defaultAtts[i].value
   5722             = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
   5723         if (!newE->defaultAtts[i].value)
   5724           return 0;
   5725       }
   5726       else
   5727         newE->defaultAtts[i].value = NULL;
   5728     }
   5729   }
   5730 
   5731   /* Copy the entity tables. */
   5732   if (!copyEntityTable(&(newDtd->generalEntities),
   5733                        &(newDtd->pool),
   5734                        &(oldDtd->generalEntities)))
   5735       return 0;
   5736 
   5737 #ifdef XML_DTD
   5738   if (!copyEntityTable(&(newDtd->paramEntities),
   5739                        &(newDtd->pool),
   5740                        &(oldDtd->paramEntities)))
   5741       return 0;
   5742   newDtd->paramEntityRead = oldDtd->paramEntityRead;
   5743 #endif /* XML_DTD */
   5744 
   5745   newDtd->keepProcessing = oldDtd->keepProcessing;
   5746   newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
   5747   newDtd->standalone = oldDtd->standalone;
   5748 
   5749   /* Don't want deep copying for scaffolding */
   5750   newDtd->in_eldecl = oldDtd->in_eldecl;
   5751   newDtd->scaffold = oldDtd->scaffold;
   5752   newDtd->contentStringLen = oldDtd->contentStringLen;
   5753   newDtd->scaffSize = oldDtd->scaffSize;
   5754   newDtd->scaffLevel = oldDtd->scaffLevel;
   5755   newDtd->scaffIndex = oldDtd->scaffIndex;
   5756 
   5757   return 1;
   5758 }  /* End dtdCopy */
   5759 
   5760 static int
   5761 copyEntityTable(HASH_TABLE *newTable,
   5762                 STRING_POOL *newPool,
   5763                 const HASH_TABLE *oldTable)
   5764 {
   5765   HASH_TABLE_ITER iter;
   5766   const XML_Char *cachedOldBase = NULL;
   5767   const XML_Char *cachedNewBase = NULL;
   5768 
   5769   hashTableIterInit(&iter, oldTable);
   5770 
   5771   for (;;) {
   5772     ENTITY *newE;
   5773     const XML_Char *name;
   5774     const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
   5775     if (!oldE)
   5776       break;
   5777     name = poolCopyString(newPool, oldE->name);
   5778     if (!name)
   5779       return 0;
   5780     newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
   5781     if (!newE)
   5782       return 0;
   5783     if (oldE->systemId) {
   5784       const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
   5785       if (!tem)
   5786         return 0;
   5787       newE->systemId = tem;
   5788       if (oldE->base) {
   5789         if (oldE->base == cachedOldBase)
   5790           newE->base = cachedNewBase;
   5791         else {
   5792           cachedOldBase = oldE->base;
   5793           tem = poolCopyString(newPool, cachedOldBase);
   5794           if (!tem)
   5795             return 0;
   5796           cachedNewBase = newE->base = tem;
   5797         }
   5798       }
   5799       if (oldE->publicId) {
   5800         tem = poolCopyString(newPool, oldE->publicId);
   5801         if (!tem)
   5802           return 0;
   5803         newE->publicId = tem;
   5804       }
   5805     }
   5806     else {
   5807       const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
   5808                                             oldE->textLen);
   5809       if (!tem)
   5810         return 0;
   5811       newE->textPtr = tem;
   5812       newE->textLen = oldE->textLen;
   5813     }
   5814     if (oldE->notation) {
   5815       const XML_Char *tem = poolCopyString(newPool, oldE->notation);
   5816       if (!tem)
   5817         return 0;
   5818       newE->notation = tem;
   5819     }
   5820     newE->is_param = oldE->is_param;
   5821     newE->is_internal = oldE->is_internal;
   5822   }
   5823   return 1;
   5824 }
   5825 
   5826 #define INIT_POWER 6
   5827 
   5828 static XML_Bool FASTCALL
   5829 keyeq(KEY s1, KEY s2)
   5830 {
   5831   for (; *s1 == *s2; s1++, s2++)
   5832     if (*s1 == 0)
   5833       return XML_TRUE;
   5834   return XML_FALSE;
   5835 }
   5836 
   5837 static unsigned long FASTCALL
   5838 hash(KEY s)
   5839 {
   5840   unsigned long h = 0;
   5841   while (*s)
   5842     h = CHAR_HASH(h, *s++);
   5843   return h;
   5844 }
   5845 
   5846 static NAMED *
   5847 lookup(HASH_TABLE *table, KEY name, size_t createSize)
   5848 {
   5849   size_t i;
   5850   if (table->size == 0) {
   5851     size_t tsize;
   5852     if (!createSize)
   5853       return NULL;
   5854     table->power = INIT_POWER;
   5855     /* table->size is a power of 2 */
   5856     table->size = (size_t)1 << INIT_POWER;
   5857     tsize = table->size * sizeof(NAMED *);
   5858     table->v = (NAMED **)table->mem->malloc_fcn(tsize);
   5859     if (!table->v) {
   5860       table->size = 0;
   5861       return NULL;
   5862     }
   5863     memset(table->v, 0, tsize);
   5864     i = hash(name) & ((unsigned long)table->size - 1);
   5865   }
   5866   else {
   5867     unsigned long h = hash(name);
   5868     unsigned long mask = (unsigned long)table->size - 1;
   5869     unsigned char step = 0;
   5870     i = h & mask;
   5871     while (table->v[i]) {
   5872       if (keyeq(name, table->v[i]->name))
   5873         return table->v[i];
   5874       if (!step)
   5875         step = PROBE_STEP(h, mask, table->power);
   5876       i < step ? (i += table->size - step) : (i -= step);
   5877     }
   5878     if (!createSize)
   5879       return NULL;
   5880 
   5881     /* check for overflow (table is half full) */
   5882     if (table->used >> (table->power - 1)) {
   5883       unsigned char newPower = table->power + 1;
   5884       size_t newSize = (size_t)1 << newPower;
   5885       unsigned long newMask = (unsigned long)newSize - 1;
   5886       size_t tsize = newSize * sizeof(NAMED *);
   5887       NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
   5888       if (!newV)
   5889         return NULL;
   5890       memset(newV, 0, tsize);
   5891       for (i = 0; i < table->size; i++)
   5892         if (table->v[i]) {
   5893           unsigned long newHash = hash(table->v[i]->name);
   5894           size_t j = newHash & newMask;
   5895           step = 0;
   5896           while (newV[j]) {
   5897             if (!step)
   5898               step = PROBE_STEP(newHash, newMask, newPower);
   5899             j < step ? (j += newSize - step) : (j -= step);
   5900           }
   5901           newV[j] = table->v[i];
   5902         }
   5903       table->mem->free_fcn(table->v);
   5904       table->v = newV;
   5905       table->power = newPower;
   5906       table->size = newSize;
   5907       i = h & newMask;
   5908       step = 0;
   5909       while (table->v[i]) {
   5910         if (!step)
   5911           step = PROBE_STEP(h, newMask, newPower);
   5912         i < step ? (i += newSize - step) : (i -= step);
   5913       }
   5914     }
   5915   }
   5916   table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
   5917   if (!table->v[i])
   5918     return NULL;
   5919   memset(table->v[i], 0, createSize);
   5920   table->v[i]->name = name;
   5921   (table->used)++;
   5922   return table->v[i];
   5923 }
   5924 
   5925 static void FASTCALL
   5926 hashTableClear(HASH_TABLE *table)
   5927 {
   5928   size_t i;
   5929   for (i = 0; i < table->size; i++) {
   5930     table->mem->free_fcn(table->v[i]);
   5931     table->v[i] = NULL;
   5932   }
   5933   table->used = 0;
   5934 }
   5935 
   5936 static void FASTCALL
   5937 hashTableDestroy(HASH_TABLE *table)
   5938 {
   5939   size_t i;
   5940   for (i = 0; i < table->size; i++)
   5941     table->mem->free_fcn(table->v[i]);
   5942   table->mem->free_fcn(table->v);
   5943 }
   5944 
   5945 static void FASTCALL
   5946 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
   5947 {
   5948   p->power = 0;
   5949   p->size = 0;
   5950   p->used = 0;
   5951   p->v = NULL;
   5952   p->mem = ms;
   5953 }
   5954 
   5955 static void FASTCALL
   5956 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
   5957 {
   5958   iter->p = table->v;
   5959   iter->end = iter->p + table->size;
   5960 }
   5961 
   5962 static NAMED * FASTCALL
   5963 hashTableIterNext(HASH_TABLE_ITER *iter)
   5964 {
   5965   while (iter->p != iter->end) {
   5966     NAMED *tem = *(iter->p)++;
   5967     if (tem)
   5968       return tem;
   5969   }
   5970   return NULL;
   5971 }
   5972 
   5973 static void FASTCALL
   5974 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
   5975 {
   5976   pool->blocks = NULL;
   5977   pool->freeBlocks = NULL;
   5978   pool->start = NULL;
   5979   pool->ptr = NULL;
   5980   pool->end = NULL;
   5981   pool->mem = ms;
   5982 }
   5983 
   5984 static void FASTCALL
   5985 poolClear(STRING_POOL *pool)
   5986 {
   5987   if (!pool->freeBlocks)
   5988     pool->freeBlocks = pool->blocks;
   5989   else {
   5990     BLOCK *p = pool->blocks;
   5991     while (p) {
   5992       BLOCK *tem = p->next;
   5993       p->next = pool->freeBlocks;
   5994       pool->freeBlocks = p;
   5995       p = tem;
   5996     }
   5997   }
   5998   pool->blocks = NULL;
   5999   pool->start = NULL;
   6000   pool->ptr = NULL;
   6001   pool->end = NULL;
   6002 }
   6003 
   6004 static void FASTCALL
   6005 poolDestroy(STRING_POOL *pool)
   6006 {
   6007   BLOCK *p = pool->blocks;
   6008   while (p) {
   6009     BLOCK *tem = p->next;
   6010     pool->mem->free_fcn(p);
   6011     p = tem;
   6012   }
   6013   p = pool->freeBlocks;
   6014   while (p) {
   6015     BLOCK *tem = p->next;
   6016     pool->mem->free_fcn(p);
   6017     p = tem;
   6018   }
   6019 }
   6020 
   6021 static XML_Char *
   6022 poolAppend(STRING_POOL *pool, const ENCODING *enc,
   6023            const char *ptr, const char *end)
   6024 {
   6025   if (!pool->ptr && !poolGrow(pool))
   6026     return NULL;
   6027   for (;;) {
   6028     XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
   6029     if (ptr == end)
   6030       break;
   6031     if (!poolGrow(pool))
   6032       return NULL;
   6033   }
   6034   return pool->start;
   6035 }
   6036 
   6037 static const XML_Char * FASTCALL
   6038 poolCopyString(STRING_POOL *pool, const XML_Char *s)
   6039 {
   6040   do {
   6041     if (!poolAppendChar(pool, *s))
   6042       return NULL;
   6043   } while (*s++);
   6044   s = pool->start;
   6045   poolFinish(pool);
   6046   return s;
   6047 }
   6048 
   6049 static const XML_Char *
   6050 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
   6051 {
   6052   if (!pool->ptr && !poolGrow(pool))
   6053     return NULL;
   6054   for (; n > 0; --n, s++) {
   6055     if (!poolAppendChar(pool, *s))
   6056       return NULL;
   6057   }
   6058   s = pool->start;
   6059   poolFinish(pool);
   6060   return s;
   6061 }
   6062 
   6063 static const XML_Char * FASTCALL
   6064 poolAppendString(STRING_POOL *pool, const XML_Char *s)
   6065 {
   6066   while (*s) {
   6067     if (!poolAppendChar(pool, *s))
   6068       return NULL;
   6069     s++;
   6070   }
   6071   return pool->start;
   6072 }
   6073 
   6074 static XML_Char *
   6075 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
   6076                 const char *ptr, const char *end)
   6077 {
   6078   if (!poolAppend(pool, enc, ptr, end))
   6079     return NULL;
   6080   if (pool->ptr == pool->end && !poolGrow(pool))
   6081     return NULL;
   6082   *(pool->ptr)++ = 0;
   6083   return pool->start;
   6084 }
   6085 
   6086 static XML_Bool FASTCALL
   6087 poolGrow(STRING_POOL *pool)
   6088 {
   6089   if (pool->freeBlocks) {
   6090     if (pool->start == 0) {
   6091       pool->blocks = pool->freeBlocks;
   6092       pool->freeBlocks = pool->freeBlocks->next;
   6093       pool->blocks->next = NULL;
   6094       pool->start = pool->blocks->s;
   6095       pool->end = pool->start + pool->blocks->size;
   6096       pool->ptr = pool->start;
   6097       return XML_TRUE;
   6098     }
   6099     if (pool->end - pool->start < pool->freeBlocks->size) {
   6100       BLOCK *tem = pool->freeBlocks->next;
   6101       pool->freeBlocks->next = pool->blocks;
   6102       pool->blocks = pool->freeBlocks;
   6103       pool->freeBlocks = tem;
   6104       memcpy(pool->blocks->s, pool->start,
   6105              (pool->end - pool->start) * sizeof(XML_Char));
   6106       pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
   6107       pool->start = pool->blocks->s;
   6108       pool->end = pool->start + pool->blocks->size;
   6109       return XML_TRUE;
   6110     }
   6111   }
   6112   if (pool->blocks && pool->start == pool->blocks->s) {
   6113     int blockSize = (int)(pool->end - pool->start)*2;
   6114     pool->blocks = (BLOCK *)
   6115       pool->mem->realloc_fcn(pool->blocks,
   6116                              (offsetof(BLOCK, s)
   6117                               + blockSize * sizeof(XML_Char)));
   6118     if (pool->blocks == NULL)
   6119       return XML_FALSE;
   6120     pool->blocks->size = blockSize;
   6121     pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
   6122     pool->start = pool->blocks->s;
   6123     pool->end = pool->start + blockSize;
   6124   }
   6125   else {
   6126     BLOCK *tem;
   6127     int blockSize = (int)(pool->end - pool->start);
   6128     if (blockSize < INIT_BLOCK_SIZE)
   6129       blockSize = INIT_BLOCK_SIZE;
   6130     else
   6131       blockSize *= 2;
   6132     tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
   6133                                         + blockSize * sizeof(XML_Char));
   6134     if (!tem)
   6135       return XML_FALSE;
   6136     tem->size = blockSize;
   6137     tem->next = pool->blocks;
   6138     pool->blocks = tem;
   6139     if (pool->ptr != pool->start)
   6140       memcpy(tem->s, pool->start,
   6141              (pool->ptr - pool->start) * sizeof(XML_Char));
   6142     pool->ptr = tem->s + (pool->ptr - pool->start);
   6143     pool->start = tem->s;
   6144     pool->end = tem->s + blockSize;
   6145   }
   6146   return XML_TRUE;
   6147 }
   6148 
   6149 static int FASTCALL
   6150 nextScaffoldPart(XML_Parser parser)
   6151 {
   6152   DTD * const dtd = _dtd;  /* save one level of indirection */
   6153   CONTENT_SCAFFOLD * me;
   6154   int next;
   6155 
   6156   if (!dtd->scaffIndex) {
   6157     dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
   6158     if (!dtd->scaffIndex)
   6159       return -1;
   6160     dtd->scaffIndex[0] = 0;
   6161   }
   6162 
   6163   if (dtd->scaffCount >= dtd->scaffSize) {
   6164     CONTENT_SCAFFOLD *temp;
   6165     if (dtd->scaffold) {
   6166       temp = (CONTENT_SCAFFOLD *)
   6167         REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
   6168       if (temp == NULL)
   6169         return -1;
   6170       dtd->scaffSize *= 2;
   6171     }
   6172     else {
   6173       temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
   6174                                         * sizeof(CONTENT_SCAFFOLD));
   6175       if (temp == NULL)
   6176         return -1;
   6177       dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
   6178     }
   6179     dtd->scaffold = temp;
   6180   }
   6181   next = dtd->scaffCount++;
   6182   me = &dtd->scaffold[next];
   6183   if (dtd->scaffLevel) {
   6184     CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
   6185     if (parent->lastchild) {
   6186       dtd->scaffold[parent->lastchild].nextsib = next;
   6187     }
   6188     if (!parent->childcnt)
   6189       parent->firstchild = next;
   6190     parent->lastchild = next;
   6191     parent->childcnt++;
   6192   }
   6193   me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
   6194   return next;
   6195 }
   6196 
   6197 static void
   6198 build_node(XML_Parser parser,
   6199            int src_node,
   6200            XML_Content *dest,
   6201            XML_Content **contpos,
   6202            XML_Char **strpos)
   6203 {
   6204   DTD * const dtd = _dtd;  /* save one level of indirection */
   6205   dest->type = dtd->scaffold[src_node].type;
   6206   dest->quant = dtd->scaffold[src_node].quant;
   6207   if (dest->type == XML_CTYPE_NAME) {
   6208     const XML_Char *src;
   6209     dest->name = *strpos;
   6210     src = dtd->scaffold[src_node].name;
   6211     for (;;) {
   6212       *(*strpos)++ = *src;
   6213       if (!*src)
   6214         break;
   6215       src++;
   6216     }
   6217     dest->numchildren = 0;
   6218     dest->children = NULL;
   6219   }
   6220   else {
   6221     unsigned int i;
   6222     int cn;
   6223     dest->numchildren = dtd->scaffold[src_node].childcnt;
   6224     dest->children = *contpos;
   6225     *contpos += dest->numchildren;
   6226     for (i = 0, cn = dtd->scaffold[src_node].firstchild;
   6227          i < dest->numchildren;
   6228          i++, cn = dtd->scaffold[cn].nextsib) {
   6229       build_node(parser, cn, &(dest->children[i]), contpos, strpos);
   6230     }
   6231     dest->name = NULL;
   6232   }
   6233 }
   6234 
   6235 static XML_Content *
   6236 build_model (XML_Parser parser)
   6237 {
   6238   DTD * const dtd = _dtd;  /* save one level of indirection */
   6239   XML_Content *ret;
   6240   XML_Content *cpos;
   6241   XML_Char * str;
   6242   int allocsize = (dtd->scaffCount * sizeof(XML_Content)
   6243                    + (dtd->contentStringLen * sizeof(XML_Char)));
   6244 
   6245   ret = (XML_Content *)MALLOC(allocsize);
   6246   if (!ret)
   6247     return NULL;
   6248 
   6249   str =  (XML_Char *) (&ret[dtd->scaffCount]);
   6250   cpos = &ret[1];
   6251 
   6252   build_node(parser, 0, ret, &cpos, &str);
   6253   return ret;
   6254 }
   6255 
   6256 static ELEMENT_TYPE *
   6257 getElementType(XML_Parser parser,
   6258                const ENCODING *enc,
   6259                const char *ptr,
   6260                const char *end)
   6261 {
   6262   DTD * const dtd = _dtd;  /* save one level of indirection */
   6263   const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
   6264   ELEMENT_TYPE *ret;
   6265 
   6266   if (!name)
   6267     return NULL;
   6268   ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
   6269   if (!ret)
   6270     return NULL;
   6271   if (ret->name != name)
   6272     poolDiscard(&dtd->pool);
   6273   else {
   6274     poolFinish(&dtd->pool);
   6275     if (!setElementTypePrefix(parser, ret))
   6276       return NULL;
   6277   }
   6278   return ret;
   6279 }
   6280