Back to index

lightning-sunbird  0.9+nobinonly
xmlparse.c
Go to the documentation of this file.
00001 /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
00002    See the file COPYING for copying permission.
00003 */
00004 
00005 #include <stddef.h>
00006 #include <string.h>                     /* memset(), memcpy() */
00007 
00008 #define XML_BUILDING_EXPAT 1
00009 
00010 #ifdef COMPILED_FROM_DSP
00011 #include "winconfig.h"
00012 #elif defined(MACOS_CLASSIC)
00013 #include "macconfig.h"
00014 #else
00015 #ifdef HAVE_EXPAT_CONFIG_H
00016 #include <expat_config.h>
00017 #endif
00018 #endif /* ndef COMPILED_FROM_DSP */
00019 
00020 #include "expat.h"
00021 
00022 #ifdef XML_UNICODE
00023 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
00024 #define XmlConvert XmlUtf16Convert
00025 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
00026 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
00027 #define XmlEncode XmlUtf16Encode
00028 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
00029 typedef unsigned short ICHAR;
00030 #else
00031 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
00032 #define XmlConvert XmlUtf8Convert
00033 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
00034 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
00035 #define XmlEncode XmlUtf8Encode
00036 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
00037 typedef char ICHAR;
00038 #endif
00039 
00040 
00041 #ifndef XML_NS
00042 
00043 #define XmlInitEncodingNS XmlInitEncoding
00044 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
00045 #undef XmlGetInternalEncodingNS
00046 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
00047 #define XmlParseXmlDeclNS XmlParseXmlDecl
00048 
00049 #endif
00050 
00051 /* BEGIN MOZILLA CHANGE (typedef XML_Char to PRUnichar) */
00052 #if 0
00053 
00054 #ifdef XML_UNICODE
00055 
00056 #ifdef XML_UNICODE_WCHAR_T
00057 #define XML_T(x) (const wchar_t)x
00058 #define XML_L(x) L ## x
00059 #else
00060 #define XML_T(x) (const unsigned short)x
00061 #define XML_L(x) x
00062 #endif
00063 
00064 #else
00065 
00066 #define XML_T(x) x
00067 #define XML_L(x) x
00068 
00069 #endif
00070 
00071 #endif
00072 /* END MOZILLA CHANGE */
00073 
00074 /* Round up n to be a multiple of sz, where sz is a power of 2. */
00075 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
00076 
00077 /* Handle the case where memmove() doesn't exist. */
00078 #ifndef HAVE_MEMMOVE
00079 #ifdef HAVE_BCOPY
00080 #define memmove(d,s,l) bcopy((s),(d),(l))
00081 #else
00082 #error memmove does not exist on this platform, nor is a substitute available
00083 #endif /* HAVE_BCOPY */
00084 #endif /* HAVE_MEMMOVE */
00085 
00086 #include "internal.h"
00087 #include "xmltok.h"
00088 #include "xmlrole.h"
00089 
00090 typedef const XML_Char *KEY;
00091 
00092 typedef struct {
00093   KEY name;
00094 } NAMED;
00095 
00096 typedef struct {
00097   NAMED **v;
00098   unsigned char power;
00099   size_t size;
00100   size_t used;
00101   const XML_Memory_Handling_Suite *mem;
00102 } HASH_TABLE;
00103 
00104 /* Basic character hash algorithm, taken from Python's string hash:
00105    h = h * 1000003 ^ character, the constant being a prime number.
00106 
00107 */
00108 #ifdef XML_UNICODE
00109 #define CHAR_HASH(h, c) \
00110   (((h) * 0xF4243) ^ (unsigned short)(c))
00111 #else
00112 #define CHAR_HASH(h, c) \
00113   (((h) * 0xF4243) ^ (unsigned char)(c))
00114 #endif
00115 
00116 /* For probing (after a collision) we need a step size relative prime
00117    to the hash table size, which is a power of 2. We use double-hashing,
00118    since we can calculate a second hash value cheaply by taking those bits
00119    of the first hash value that were discarded (masked out) when the table
00120    index was calculated: index = hash & mask, where mask = table->size - 1.
00121    We limit the maximum step size to table->size / 4 (mask >> 2) and make
00122    it odd, since odd numbers are always relative prime to a power of 2.
00123 */
00124 #define SECOND_HASH(hash, mask, power) \
00125   ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
00126 #define PROBE_STEP(hash, mask, power) \
00127   ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
00128 
00129 typedef struct {
00130   NAMED **p;
00131   NAMED **end;
00132 } HASH_TABLE_ITER;
00133 
00134 #define INIT_TAG_BUF_SIZE 32  /* must be a multiple of sizeof(XML_Char) */
00135 #define INIT_DATA_BUF_SIZE 1024
00136 #define INIT_ATTS_SIZE 16
00137 #define INIT_ATTS_VERSION 0xFFFFFFFF
00138 #define INIT_BLOCK_SIZE 1024
00139 #define INIT_BUFFER_SIZE 1024
00140 
00141 #define EXPAND_SPARE 24
00142 
00143 typedef struct binding {
00144   struct prefix *prefix;
00145   struct binding *nextTagBinding;
00146   struct binding *prevPrefixBinding;
00147   const struct attribute_id *attId;
00148   XML_Char *uri;
00149   int uriLen;
00150   int uriAlloc;
00151 } BINDING;
00152 
00153 typedef struct prefix {
00154   const XML_Char *name;
00155   BINDING *binding;
00156 } PREFIX;
00157 
00158 typedef struct {
00159   const XML_Char *str;
00160   const XML_Char *localPart;
00161   const XML_Char *prefix;
00162   int strLen;
00163   int uriLen;
00164   int prefixLen;
00165 } TAG_NAME;
00166 
00167 /* TAG represents an open element.
00168    The name of the element is stored in both the document and API
00169    encodings.  The memory buffer 'buf' is a separately-allocated
00170    memory area which stores the name.  During the XML_Parse()/
00171    XMLParseBuffer() when the element is open, the memory for the 'raw'
00172    version of the name (in the document encoding) is shared with the
00173    document buffer.  If the element is open across calls to
00174    XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
00175    contain the 'raw' name as well.
00176 
00177    A parser re-uses these structures, maintaining a list of allocated
00178    TAG objects in a free list.
00179 */
00180 typedef struct tag {
00181   struct tag *parent;           /* parent of this element */
00182   const char *rawName;          /* tagName in the original encoding */
00183   int rawNameLength;
00184   TAG_NAME name;                /* tagName in the API encoding */
00185   char *buf;                    /* buffer for name components */
00186   char *bufEnd;                 /* end of the buffer */
00187   BINDING *bindings;
00188 } TAG;
00189 
00190 typedef struct {
00191   const XML_Char *name;
00192   const XML_Char *textPtr;
00193   int textLen;
00194   const XML_Char *systemId;
00195   const XML_Char *base;
00196   const XML_Char *publicId;
00197   const XML_Char *notation;
00198   XML_Bool open;
00199   XML_Bool is_param;
00200   XML_Bool is_internal; /* true if declared in internal subset outside PE */
00201 } ENTITY;
00202 
00203 typedef struct {
00204   enum XML_Content_Type         type;
00205   enum XML_Content_Quant        quant;
00206   const XML_Char *              name;
00207   int                           firstchild;
00208   int                           lastchild;
00209   int                           childcnt;
00210   int                           nextsib;
00211 } CONTENT_SCAFFOLD;
00212 
00213 #define INIT_SCAFFOLD_ELEMENTS 32
00214 
00215 typedef struct block {
00216   struct block *next;
00217   int size;
00218   XML_Char s[1];
00219 } BLOCK;
00220 
00221 typedef struct {
00222   BLOCK *blocks;
00223   BLOCK *freeBlocks;
00224   const XML_Char *end;
00225   XML_Char *ptr;
00226   XML_Char *start;
00227   const XML_Memory_Handling_Suite *mem;
00228 } STRING_POOL;
00229 
00230 /* The XML_Char before the name is used to determine whether
00231    an attribute has been specified. */
00232 typedef struct attribute_id {
00233   XML_Char *name;
00234   PREFIX *prefix;
00235   XML_Bool maybeTokenized;
00236   XML_Bool xmlns;
00237 } ATTRIBUTE_ID;
00238 
00239 typedef struct {
00240   const ATTRIBUTE_ID *id;
00241   XML_Bool isCdata;
00242   const XML_Char *value;
00243 } DEFAULT_ATTRIBUTE;
00244 
00245 typedef struct {
00246   unsigned long version;
00247   unsigned long hash;
00248   const XML_Char *uriName;
00249 } NS_ATT;
00250 
00251 typedef struct {
00252   const XML_Char *name;
00253   PREFIX *prefix;
00254   const ATTRIBUTE_ID *idAtt;
00255   int nDefaultAtts;
00256   int allocDefaultAtts;
00257   DEFAULT_ATTRIBUTE *defaultAtts;
00258 } ELEMENT_TYPE;
00259 
00260 typedef struct {
00261   HASH_TABLE generalEntities;
00262   HASH_TABLE elementTypes;
00263   HASH_TABLE attributeIds;
00264   HASH_TABLE prefixes;
00265   STRING_POOL pool;
00266   STRING_POOL entityValuePool;
00267   /* false once a parameter entity reference has been skipped */
00268   XML_Bool keepProcessing;
00269   /* true once an internal or external PE reference has been encountered;
00270      this includes the reference to an external subset */
00271   XML_Bool hasParamEntityRefs;
00272   XML_Bool standalone;
00273 #ifdef XML_DTD
00274   /* indicates if external PE has been read */
00275   XML_Bool paramEntityRead;
00276   HASH_TABLE paramEntities;
00277 #endif /* XML_DTD */
00278   PREFIX defaultPrefix;
00279   /* === scaffolding for building content model === */
00280   XML_Bool in_eldecl;
00281   CONTENT_SCAFFOLD *scaffold;
00282   unsigned contentStringLen;
00283   unsigned scaffSize;
00284   unsigned scaffCount;
00285   int scaffLevel;
00286   int *scaffIndex;
00287 } DTD;
00288 
00289 typedef struct open_internal_entity {
00290   const char *internalEventPtr;
00291   const char *internalEventEndPtr;
00292   struct open_internal_entity *next;
00293   ENTITY *entity;
00294 } OPEN_INTERNAL_ENTITY;
00295 
00296 typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
00297                                          const char *start,
00298                                          const char *end,
00299                                          const char **endPtr);
00300 
00301 static Processor prologProcessor;
00302 static Processor prologInitProcessor;
00303 static Processor contentProcessor;
00304 static Processor cdataSectionProcessor;
00305 #ifdef XML_DTD
00306 static Processor ignoreSectionProcessor;
00307 static Processor externalParEntProcessor;
00308 static Processor externalParEntInitProcessor;
00309 static Processor entityValueProcessor;
00310 static Processor entityValueInitProcessor;
00311 #endif /* XML_DTD */
00312 static Processor epilogProcessor;
00313 static Processor errorProcessor;
00314 static Processor externalEntityInitProcessor;
00315 static Processor externalEntityInitProcessor2;
00316 static Processor externalEntityInitProcessor3;
00317 static Processor externalEntityContentProcessor;
00318 
00319 static enum XML_Error
00320 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
00321 static enum XML_Error
00322 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
00323                const char *, const char *);
00324 static enum XML_Error
00325 initializeEncoding(XML_Parser parser);
00326 static enum XML_Error
00327 doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
00328          const char *end, int tok, const char *next, const char **nextPtr);
00329 static enum XML_Error
00330 processInternalParamEntity(XML_Parser parser, ENTITY *entity);
00331 static enum XML_Error
00332 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
00333           const char *start, const char *end, const char **endPtr);
00334 static enum XML_Error
00335 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
00336                const char *end, const char **nextPtr);
00337 #ifdef XML_DTD
00338 static enum XML_Error
00339 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
00340                 const char *end, const char **nextPtr);
00341 #endif /* XML_DTD */
00342 
00343 static enum XML_Error
00344 storeAtts(XML_Parser parser, const ENCODING *, const char *s,
00345           TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
00346 static enum XML_Error
00347 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
00348            const XML_Char *uri, BINDING **bindingsPtr);
00349 static int
00350 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *,
00351                 XML_Bool isCdata, XML_Bool isId, const XML_Char *dfltValue,
00352                 XML_Parser parser);
00353 static enum XML_Error
00354 storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
00355                     const char *, const char *, STRING_POOL *);
00356 static enum XML_Error
00357 appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
00358                      const char *, const char *, STRING_POOL *);
00359 static ATTRIBUTE_ID *
00360 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
00361                const char *end);
00362 static int
00363 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
00364 static enum XML_Error
00365 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
00366                  const char *end);
00367 static int
00368 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
00369                             const char *start, const char *end);
00370 static int
00371 reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
00372               const char *end);
00373 static void
00374 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
00375               const char *end);
00376 
00377 static const XML_Char * getContext(XML_Parser parser);
00378 static XML_Bool
00379 setContext(XML_Parser parser, const XML_Char *context);
00380 
00381 static void FASTCALL normalizePublicId(XML_Char *s);
00382 
00383 static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
00384 /* do not call if parentParser != NULL */
00385 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
00386 static void
00387 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
00388 static int
00389 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
00390 static int
00391 copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
00392 
00393 static NAMED *
00394 lookup(HASH_TABLE *table, KEY name, size_t createSize);
00395 static void FASTCALL
00396 hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
00397 static void FASTCALL hashTableClear(HASH_TABLE *);
00398 static void FASTCALL hashTableDestroy(HASH_TABLE *);
00399 static void FASTCALL
00400 hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
00401 static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
00402 
00403 static void FASTCALL
00404 poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
00405 static void FASTCALL poolClear(STRING_POOL *);
00406 static void FASTCALL poolDestroy(STRING_POOL *);
00407 static XML_Char *
00408 poolAppend(STRING_POOL *pool, const ENCODING *enc,
00409            const char *ptr, const char *end);
00410 static XML_Char *
00411 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
00412                 const char *ptr, const char *end);
00413 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
00414 static const XML_Char * FASTCALL
00415 poolCopyString(STRING_POOL *pool, const XML_Char *s);
00416 static const XML_Char *
00417 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
00418 static const XML_Char * FASTCALL
00419 poolAppendString(STRING_POOL *pool, const XML_Char *s);
00420 
00421 static int FASTCALL nextScaffoldPart(XML_Parser parser);
00422 static XML_Content * build_model(XML_Parser parser);
00423 static ELEMENT_TYPE *
00424 getElementType(XML_Parser parser, const ENCODING *enc,
00425                const char *ptr, const char *end);
00426 
00427 static XML_Parser
00428 parserCreate(const XML_Char *encodingName,
00429              const XML_Memory_Handling_Suite *memsuite,
00430              const XML_Char *nameSep,
00431              DTD *dtd);
00432 static void
00433 parserInit(XML_Parser parser, const XML_Char *encodingName);
00434 
00435 #define poolStart(pool) ((pool)->start)
00436 #define poolEnd(pool) ((pool)->ptr)
00437 #define poolLength(pool) ((pool)->ptr - (pool)->start)
00438 #define poolChop(pool) ((void)--(pool->ptr))
00439 #define poolLastChar(pool) (((pool)->ptr)[-1])
00440 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
00441 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
00442 #define poolAppendChar(pool, c) \
00443   (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
00444    ? 0 \
00445    : ((*((pool)->ptr)++ = c), 1))
00446 
00447 struct XML_ParserStruct {
00448   /* The first member must be userData so that the XML_GetUserData
00449      macro works. */
00450   void *m_userData;
00451   void *m_handlerArg;
00452   char *m_buffer;
00453   const XML_Memory_Handling_Suite m_mem;
00454   /* first character to be parsed */
00455   const char *m_bufferPtr;
00456   /* past last character to be parsed */
00457   char *m_bufferEnd;
00458   /* allocated end of buffer */
00459   const char *m_bufferLim;
00460   long m_parseEndByteIndex;
00461   const char *m_parseEndPtr;
00462   XML_Char *m_dataBuf;
00463   XML_Char *m_dataBufEnd;
00464   XML_StartElementHandler m_startElementHandler;
00465   XML_EndElementHandler m_endElementHandler;
00466   XML_CharacterDataHandler m_characterDataHandler;
00467   XML_ProcessingInstructionHandler m_processingInstructionHandler;
00468   XML_CommentHandler m_commentHandler;
00469   XML_StartCdataSectionHandler m_startCdataSectionHandler;
00470   XML_EndCdataSectionHandler m_endCdataSectionHandler;
00471   XML_DefaultHandler m_defaultHandler;
00472   XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
00473   XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
00474   XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
00475   XML_NotationDeclHandler m_notationDeclHandler;
00476   XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
00477   XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
00478   XML_NotStandaloneHandler m_notStandaloneHandler;
00479   XML_ExternalEntityRefHandler m_externalEntityRefHandler;
00480   XML_Parser m_externalEntityRefHandlerArg;
00481   XML_SkippedEntityHandler m_skippedEntityHandler;
00482   XML_UnknownEncodingHandler m_unknownEncodingHandler;
00483   XML_ElementDeclHandler m_elementDeclHandler;
00484   XML_AttlistDeclHandler m_attlistDeclHandler;
00485   XML_EntityDeclHandler m_entityDeclHandler;
00486   XML_XmlDeclHandler m_xmlDeclHandler;
00487   const ENCODING *m_encoding;
00488   INIT_ENCODING m_initEncoding;
00489   const ENCODING *m_internalEncoding;
00490   const XML_Char *m_protocolEncodingName;
00491   XML_Bool m_ns;
00492   XML_Bool m_ns_triplets;
00493   void *m_unknownEncodingMem;
00494   void *m_unknownEncodingData;
00495   void *m_unknownEncodingHandlerData;
00496   void (*m_unknownEncodingRelease)(void *);
00497   PROLOG_STATE m_prologState;
00498   Processor *m_processor;
00499   enum XML_Error m_errorCode;
00500   const char *m_eventPtr;
00501   const char *m_eventEndPtr;
00502   const char *m_positionPtr;
00503   OPEN_INTERNAL_ENTITY *m_openInternalEntities;
00504   XML_Bool m_defaultExpandInternalEntities;
00505   int m_tagLevel;
00506   ENTITY *m_declEntity;
00507   const XML_Char *m_doctypeName;
00508   const XML_Char *m_doctypeSysid;
00509   const XML_Char *m_doctypePubid;
00510   const XML_Char *m_declAttributeType;
00511   const XML_Char *m_declNotationName;
00512   const XML_Char *m_declNotationPublicId;
00513   ELEMENT_TYPE *m_declElementType;
00514   ATTRIBUTE_ID *m_declAttributeId;
00515   XML_Bool m_declAttributeIsCdata;
00516   XML_Bool m_declAttributeIsId;
00517   DTD *m_dtd;
00518   const XML_Char *m_curBase;
00519   TAG *m_tagStack;
00520   TAG *m_freeTagList;
00521   BINDING *m_inheritedBindings;
00522   BINDING *m_freeBindingList;
00523   int m_attsSize;
00524   int m_nSpecifiedAtts;
00525   int m_idAttIndex;
00526   ATTRIBUTE *m_atts;
00527   NS_ATT *m_nsAtts;
00528   unsigned long m_nsAttsVersion;
00529   unsigned char m_nsAttsPower;
00530   POSITION m_position;
00531   STRING_POOL m_tempPool;
00532   STRING_POOL m_temp2Pool;
00533   char *m_groupConnector;
00534   unsigned int m_groupSize;
00535   XML_Char m_namespaceSeparator;
00536   XML_Parser m_parentParser;
00537 #ifdef XML_DTD
00538   XML_Bool m_isParamEntity;
00539   XML_Bool m_useForeignDTD;
00540   enum XML_ParamEntityParsing m_paramEntityParsing;
00541 #endif
00542 /* BEGIN MOZILLA CHANGE (Blocking parser) */
00543   XML_Bool m_blocked;
00544 /* END MOZILLA CHANGE */
00545 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
00546   const XML_Char* m_mismatch;
00547 /* END MOZILLA CHANGE */
00548 };
00549 
00550 #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
00551 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
00552 #define FREE(p) (parser->m_mem.free_fcn((p)))
00553 
00554 #define userData (parser->m_userData)
00555 #define handlerArg (parser->m_handlerArg)
00556 #define startElementHandler (parser->m_startElementHandler)
00557 #define endElementHandler (parser->m_endElementHandler)
00558 #define characterDataHandler (parser->m_characterDataHandler)
00559 #define processingInstructionHandler \
00560         (parser->m_processingInstructionHandler)
00561 #define commentHandler (parser->m_commentHandler)
00562 #define startCdataSectionHandler \
00563         (parser->m_startCdataSectionHandler)
00564 #define endCdataSectionHandler (parser->m_endCdataSectionHandler)
00565 #define defaultHandler (parser->m_defaultHandler)
00566 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
00567 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
00568 #define unparsedEntityDeclHandler \
00569         (parser->m_unparsedEntityDeclHandler)
00570 #define notationDeclHandler (parser->m_notationDeclHandler)
00571 #define startNamespaceDeclHandler \
00572         (parser->m_startNamespaceDeclHandler)
00573 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
00574 #define notStandaloneHandler (parser->m_notStandaloneHandler)
00575 #define externalEntityRefHandler \
00576         (parser->m_externalEntityRefHandler)
00577 #define externalEntityRefHandlerArg \
00578         (parser->m_externalEntityRefHandlerArg)
00579 #define internalEntityRefHandler \
00580         (parser->m_internalEntityRefHandler)
00581 #define skippedEntityHandler (parser->m_skippedEntityHandler)
00582 #define unknownEncodingHandler (parser->m_unknownEncodingHandler)
00583 #define elementDeclHandler (parser->m_elementDeclHandler)
00584 #define attlistDeclHandler (parser->m_attlistDeclHandler)
00585 #define entityDeclHandler (parser->m_entityDeclHandler)
00586 #define xmlDeclHandler (parser->m_xmlDeclHandler)
00587 #define encoding (parser->m_encoding)
00588 #define initEncoding (parser->m_initEncoding)
00589 #define internalEncoding (parser->m_internalEncoding)
00590 #define unknownEncodingMem (parser->m_unknownEncodingMem)
00591 #define unknownEncodingData (parser->m_unknownEncodingData)
00592 #define unknownEncodingHandlerData \
00593   (parser->m_unknownEncodingHandlerData)
00594 #define unknownEncodingRelease (parser->m_unknownEncodingRelease)
00595 #define protocolEncodingName (parser->m_protocolEncodingName)
00596 #define ns (parser->m_ns)
00597 #define ns_triplets (parser->m_ns_triplets)
00598 #define prologState (parser->m_prologState)
00599 #define processor (parser->m_processor)
00600 #define errorCode (parser->m_errorCode)
00601 #define eventPtr (parser->m_eventPtr)
00602 #define eventEndPtr (parser->m_eventEndPtr)
00603 #define positionPtr (parser->m_positionPtr)
00604 #define position (parser->m_position)
00605 #define openInternalEntities (parser->m_openInternalEntities)
00606 #define defaultExpandInternalEntities \
00607         (parser->m_defaultExpandInternalEntities)
00608 #define tagLevel (parser->m_tagLevel)
00609 #define buffer (parser->m_buffer)
00610 #define bufferPtr (parser->m_bufferPtr)
00611 #define bufferEnd (parser->m_bufferEnd)
00612 #define parseEndByteIndex (parser->m_parseEndByteIndex)
00613 #define parseEndPtr (parser->m_parseEndPtr)
00614 #define bufferLim (parser->m_bufferLim)
00615 #define dataBuf (parser->m_dataBuf)
00616 #define dataBufEnd (parser->m_dataBufEnd)
00617 #define _dtd (parser->m_dtd)
00618 #define curBase (parser->m_curBase)
00619 #define declEntity (parser->m_declEntity)
00620 #define doctypeName (parser->m_doctypeName)
00621 #define doctypeSysid (parser->m_doctypeSysid)
00622 #define doctypePubid (parser->m_doctypePubid)
00623 #define declAttributeType (parser->m_declAttributeType)
00624 #define declNotationName (parser->m_declNotationName)
00625 #define declNotationPublicId (parser->m_declNotationPublicId)
00626 #define declElementType (parser->m_declElementType)
00627 #define declAttributeId (parser->m_declAttributeId)
00628 #define declAttributeIsCdata (parser->m_declAttributeIsCdata)
00629 #define declAttributeIsId (parser->m_declAttributeIsId)
00630 #define freeTagList (parser->m_freeTagList)
00631 #define freeBindingList (parser->m_freeBindingList)
00632 #define inheritedBindings (parser->m_inheritedBindings)
00633 #define tagStack (parser->m_tagStack)
00634 #define atts (parser->m_atts)
00635 #define attsSize (parser->m_attsSize)
00636 #define nSpecifiedAtts (parser->m_nSpecifiedAtts)
00637 #define idAttIndex (parser->m_idAttIndex)
00638 #define nsAtts (parser->m_nsAtts)
00639 #define nsAttsVersion (parser->m_nsAttsVersion)
00640 #define nsAttsPower (parser->m_nsAttsPower)
00641 #define tempPool (parser->m_tempPool)
00642 #define temp2Pool (parser->m_temp2Pool)
00643 #define groupConnector (parser->m_groupConnector)
00644 #define groupSize (parser->m_groupSize)
00645 #define namespaceSeparator (parser->m_namespaceSeparator)
00646 #define parentParser (parser->m_parentParser)
00647 #ifdef XML_DTD
00648 #define isParamEntity (parser->m_isParamEntity)
00649 #define useForeignDTD (parser->m_useForeignDTD)
00650 #define paramEntityParsing (parser->m_paramEntityParsing)
00651 #endif /* XML_DTD */
00652 /* BEGIN MOZILLA CHANGE (Blocking parser) */
00653 #define blocked (parser->m_blocked)
00654 /* END MOZILLA CHANGE */
00655 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
00656 #define mismatch (parser->m_mismatch)
00657 /* END MOZILLA CHANGE */
00658 
00659 #ifdef XML_DTD
00660 #define parsing \
00661   (parentParser \
00662     ? \
00663     (isParamEntity \
00664       ? \
00665       (processor != externalParEntInitProcessor) \
00666       : \
00667       (processor != externalEntityInitProcessor)) \
00668     : \
00669     (processor != prologInitProcessor))
00670 #else
00671 #define parsing \
00672   (parentParser \
00673     ? \
00674     (processor != externalEntityInitProcessor) \
00675     : \
00676     (processor != prologInitProcessor))
00677 #endif /* XML_DTD */
00678 
00679 /* BEGIN MOZILLA CHANGE (unused API) */
00680 #ifdef TX_EXE
00681 XML_Parser XMLCALL
00682 XML_ParserCreate(const XML_Char *encodingName)
00683 {
00684   return XML_ParserCreate_MM(encodingName, NULL, NULL);
00685 }
00686 #endif
00687 
00688 #if 0
00689 XML_Parser XMLCALL
00690 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
00691 {
00692   XML_Char tmp[2];
00693   *tmp = nsSep;
00694   return XML_ParserCreate_MM(encodingName, NULL, tmp);
00695 }
00696 #endif
00697 /* END MOZILLA CHANGE */
00698 
00699 static const XML_Char implicitContext[] = {
00700   'x', 'm', 'l', '=', 'h', 't', 't', 'p', ':', '/', '/',
00701   'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
00702   'X', 'M', 'L', '/', '1', '9', '9', '8', '/',
00703   'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0'
00704 };
00705 
00706 XML_Parser XMLCALL
00707 XML_ParserCreate_MM(const XML_Char *encodingName,
00708                     const XML_Memory_Handling_Suite *memsuite,
00709                     const XML_Char *nameSep)
00710 {
00711   XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL);
00712   if (parser != NULL && ns) {
00713     /* implicit context only set for root parser, since child
00714        parsers (i.e. external entity parsers) will inherit it
00715     */
00716     if (!setContext(parser, implicitContext)) {
00717       XML_ParserFree(parser);
00718       return NULL;
00719     }
00720   }
00721   return parser;
00722 }
00723 
00724 static XML_Parser
00725 parserCreate(const XML_Char *encodingName,
00726              const XML_Memory_Handling_Suite *memsuite,
00727              const XML_Char *nameSep,
00728              DTD *dtd)
00729 {
00730   XML_Parser parser;
00731 
00732   if (memsuite) {
00733     XML_Memory_Handling_Suite *mtemp;
00734     parser = (XML_Parser)
00735       memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
00736     if (parser != NULL) {
00737       mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
00738       mtemp->malloc_fcn = memsuite->malloc_fcn;
00739       mtemp->realloc_fcn = memsuite->realloc_fcn;
00740       mtemp->free_fcn = memsuite->free_fcn;
00741     }
00742   }
00743   else {
00744     XML_Memory_Handling_Suite *mtemp;
00745     parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
00746     if (parser != NULL) {
00747       mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
00748       mtemp->malloc_fcn = malloc;
00749       mtemp->realloc_fcn = realloc;
00750       mtemp->free_fcn = free;
00751     }
00752   }
00753 
00754   if (!parser)
00755     return parser;
00756 
00757   buffer = NULL;
00758   bufferLim = NULL;
00759 
00760   attsSize = INIT_ATTS_SIZE;
00761   atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
00762   if (atts == NULL) {
00763     FREE(parser);
00764     return NULL;
00765   }
00766   dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
00767   if (dataBuf == NULL) {
00768     FREE(atts);
00769     FREE(parser);
00770     return NULL;
00771   }
00772   dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
00773 
00774   if (dtd)
00775     _dtd = dtd;
00776   else {
00777     _dtd = dtdCreate(&parser->m_mem);
00778     if (_dtd == NULL) {
00779       FREE(dataBuf);
00780       FREE(atts);
00781       FREE(parser);
00782       return NULL;
00783     }
00784   }
00785 
00786   freeBindingList = NULL;
00787   freeTagList = NULL;
00788 
00789   groupSize = 0;
00790   groupConnector = NULL;
00791 
00792   unknownEncodingHandler = NULL;
00793   unknownEncodingHandlerData = NULL;
00794 
00795   namespaceSeparator = '!';
00796   ns = XML_FALSE;
00797   ns_triplets = XML_FALSE;
00798 
00799   nsAtts = NULL;
00800   nsAttsVersion = 0;
00801   nsAttsPower = 0;
00802 
00803   poolInit(&tempPool, &(parser->m_mem));
00804   poolInit(&temp2Pool, &(parser->m_mem));
00805   parserInit(parser, encodingName);
00806 
00807   if (encodingName && !protocolEncodingName) {
00808     XML_ParserFree(parser);
00809     return NULL;
00810   }
00811 
00812   if (nameSep) {
00813     ns = XML_TRUE;
00814     internalEncoding = XmlGetInternalEncodingNS();
00815     namespaceSeparator = *nameSep;
00816   }
00817   else {
00818     internalEncoding = XmlGetInternalEncoding();
00819   }
00820 
00821 /* BEGIN MOZILLA CHANGE (Blocking parser) */
00822   blocked = XML_FALSE;
00823 /* END MOZILLA CHANGE */
00824 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
00825   mismatch = NULL;
00826 /* END MOZILLA CHANGE */
00827 
00828   return parser;
00829 }
00830 
00831 static void
00832 parserInit(XML_Parser parser, const XML_Char *encodingName)
00833 {
00834   processor = prologInitProcessor;
00835   XmlPrologStateInit(&prologState);
00836   protocolEncodingName = (encodingName != NULL
00837                           ? poolCopyString(&tempPool, encodingName)
00838                           : NULL);
00839   curBase = NULL;
00840   XmlInitEncoding(&initEncoding, &encoding, 0);
00841   userData = NULL;
00842   handlerArg = NULL;
00843   startElementHandler = NULL;
00844   endElementHandler = NULL;
00845   characterDataHandler = NULL;
00846   processingInstructionHandler = NULL;
00847   commentHandler = NULL;
00848   startCdataSectionHandler = NULL;
00849   endCdataSectionHandler = NULL;
00850   defaultHandler = NULL;
00851   startDoctypeDeclHandler = NULL;
00852   endDoctypeDeclHandler = NULL;
00853   unparsedEntityDeclHandler = NULL;
00854   notationDeclHandler = NULL;
00855   startNamespaceDeclHandler = NULL;
00856   endNamespaceDeclHandler = NULL;
00857   notStandaloneHandler = NULL;
00858   externalEntityRefHandler = NULL;
00859   externalEntityRefHandlerArg = parser;
00860   skippedEntityHandler = NULL;
00861   elementDeclHandler = NULL;
00862   attlistDeclHandler = NULL;
00863   entityDeclHandler = NULL;
00864   xmlDeclHandler = NULL;
00865   bufferPtr = buffer;
00866   bufferEnd = buffer;
00867   parseEndByteIndex = 0;
00868   parseEndPtr = NULL;
00869   declElementType = NULL;
00870   declAttributeId = NULL;
00871   declEntity = NULL;
00872   doctypeName = NULL;
00873   doctypeSysid = NULL;
00874   doctypePubid = NULL;
00875   declAttributeType = NULL;
00876   declNotationName = NULL;
00877   declNotationPublicId = NULL;
00878   declAttributeIsCdata = XML_FALSE;
00879   declAttributeIsId = XML_FALSE;
00880   memset(&position, 0, sizeof(POSITION));
00881   errorCode = XML_ERROR_NONE;
00882   eventPtr = NULL;
00883   eventEndPtr = NULL;
00884   positionPtr = NULL;
00885   openInternalEntities = 0;
00886   defaultExpandInternalEntities = XML_TRUE;
00887   tagLevel = 0;
00888   tagStack = NULL;
00889   inheritedBindings = NULL;
00890   nSpecifiedAtts = 0;
00891   unknownEncodingMem = NULL;
00892   unknownEncodingRelease = NULL;
00893   unknownEncodingData = NULL;
00894   parentParser = NULL;
00895 #ifdef XML_DTD
00896   isParamEntity = XML_FALSE;
00897   useForeignDTD = XML_FALSE;
00898   paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
00899 #endif
00900 }
00901 
00902 /* moves list of bindings to freeBindingList */
00903 static void FASTCALL
00904 moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
00905 {
00906   while (bindings) {
00907     BINDING *b = bindings;
00908     bindings = bindings->nextTagBinding;
00909     b->nextTagBinding = freeBindingList;
00910     freeBindingList = b;
00911   }
00912 }
00913 
00914 /* BEGIN MOZILLA CHANGE (unused API) */
00915 #if 0
00916 XML_Bool XMLCALL
00917 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
00918 {
00919   TAG *tStk;
00920   if (parentParser)
00921     return XML_FALSE;
00922   /* move tagStack to freeTagList */
00923   tStk = tagStack;
00924   while (tStk) {
00925     TAG *tag = tStk;
00926     tStk = tStk->parent;
00927     tag->parent = freeTagList;
00928     moveToFreeBindingList(parser, tag->bindings);
00929     tag->bindings = NULL;
00930     freeTagList = tag;
00931   }
00932   moveToFreeBindingList(parser, inheritedBindings);
00933   FREE(unknownEncodingMem);
00934   if (unknownEncodingRelease)
00935     unknownEncodingRelease(unknownEncodingData);
00936   poolClear(&tempPool);
00937   poolClear(&temp2Pool);
00938   parserInit(parser, encodingName);
00939   dtdReset(_dtd, &parser->m_mem);
00940   return setContext(parser, implicitContext);
00941 }
00942 
00943 enum XML_Status XMLCALL
00944 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
00945 {
00946   /* Block after XML_Parse()/XML_ParseBuffer() has been called.
00947      XXX There's no way for the caller to determine which of the
00948      XXX possible error cases caused the XML_STATUS_ERROR return.
00949   */
00950   if (parsing)
00951     return XML_STATUS_ERROR;
00952   if (encodingName == NULL)
00953     protocolEncodingName = NULL;
00954   else {
00955     protocolEncodingName = poolCopyString(&tempPool, encodingName);
00956     if (!protocolEncodingName)
00957       return XML_STATUS_ERROR;
00958   }
00959   return XML_STATUS_OK;
00960 }
00961 #endif
00962 /* END MOZILLA CHANGE */
00963 
00964 XML_Parser XMLCALL
00965 XML_ExternalEntityParserCreate(XML_Parser oldParser,
00966                                const XML_Char *context,
00967                                const XML_Char *encodingName)
00968 {
00969   XML_Parser parser = oldParser;
00970   DTD *newDtd = NULL;
00971   DTD *oldDtd = _dtd;
00972   XML_StartElementHandler oldStartElementHandler = startElementHandler;
00973   XML_EndElementHandler oldEndElementHandler = endElementHandler;
00974   XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
00975   XML_ProcessingInstructionHandler oldProcessingInstructionHandler
00976       = processingInstructionHandler;
00977   XML_CommentHandler oldCommentHandler = commentHandler;
00978   XML_StartCdataSectionHandler oldStartCdataSectionHandler
00979       = startCdataSectionHandler;
00980   XML_EndCdataSectionHandler oldEndCdataSectionHandler
00981       = endCdataSectionHandler;
00982   XML_DefaultHandler oldDefaultHandler = defaultHandler;
00983   XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
00984       = unparsedEntityDeclHandler;
00985   XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
00986   XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
00987       = startNamespaceDeclHandler;
00988   XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
00989       = endNamespaceDeclHandler;
00990   XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
00991   XML_ExternalEntityRefHandler oldExternalEntityRefHandler
00992       = externalEntityRefHandler;
00993   XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
00994   XML_UnknownEncodingHandler oldUnknownEncodingHandler
00995       = unknownEncodingHandler;
00996   XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
00997   XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
00998   XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
00999   XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
01000   ELEMENT_TYPE * oldDeclElementType = declElementType;
01001 
01002   void *oldUserData = userData;
01003   void *oldHandlerArg = handlerArg;
01004   XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
01005   XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
01006 #ifdef XML_DTD
01007   enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
01008   int oldInEntityValue = prologState.inEntityValue;
01009 #endif
01010   XML_Bool oldns_triplets = ns_triplets;
01011 
01012 #ifdef XML_DTD
01013   if (!context)
01014     newDtd = oldDtd;
01015 #endif /* XML_DTD */
01016 
01017   /* Note that the magical uses of the pre-processor to make field
01018      access look more like C++ require that `parser' be overwritten
01019      here.  This makes this function more painful to follow than it
01020      would be otherwise.
01021   */
01022   if (ns) {
01023     XML_Char tmp[2];
01024     *tmp = namespaceSeparator;
01025     parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
01026   }
01027   else {
01028     parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
01029   }
01030 
01031   if (!parser)
01032     return NULL;
01033 
01034   startElementHandler = oldStartElementHandler;
01035   endElementHandler = oldEndElementHandler;
01036   characterDataHandler = oldCharacterDataHandler;
01037   processingInstructionHandler = oldProcessingInstructionHandler;
01038   commentHandler = oldCommentHandler;
01039   startCdataSectionHandler = oldStartCdataSectionHandler;
01040   endCdataSectionHandler = oldEndCdataSectionHandler;
01041   defaultHandler = oldDefaultHandler;
01042   unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
01043   notationDeclHandler = oldNotationDeclHandler;
01044   startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
01045   endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
01046   notStandaloneHandler = oldNotStandaloneHandler;
01047   externalEntityRefHandler = oldExternalEntityRefHandler;
01048   skippedEntityHandler = oldSkippedEntityHandler;
01049   unknownEncodingHandler = oldUnknownEncodingHandler;
01050   elementDeclHandler = oldElementDeclHandler;
01051   attlistDeclHandler = oldAttlistDeclHandler;
01052   entityDeclHandler = oldEntityDeclHandler;
01053   xmlDeclHandler = oldXmlDeclHandler;
01054   declElementType = oldDeclElementType;
01055   userData = oldUserData;
01056   if (oldUserData == oldHandlerArg)
01057     handlerArg = userData;
01058   else
01059     handlerArg = parser;
01060   if (oldExternalEntityRefHandlerArg != oldParser)
01061     externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
01062   defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
01063   ns_triplets = oldns_triplets;
01064   parentParser = oldParser;
01065 #ifdef XML_DTD
01066   paramEntityParsing = oldParamEntityParsing;
01067   prologState.inEntityValue = oldInEntityValue;
01068   if (context) {
01069 #endif /* XML_DTD */
01070     if (!dtdCopy(_dtd, oldDtd, &parser->m_mem)
01071       || !setContext(parser, context)) {
01072       XML_ParserFree(parser);
01073       return NULL;
01074     }
01075     processor = externalEntityInitProcessor;
01076 #ifdef XML_DTD
01077   }
01078   else {
01079     /* The DTD instance referenced by _dtd is shared between the document's
01080        root parser and external PE parsers, therefore one does not need to
01081        call setContext. In addition, one also *must* not call setContext,
01082        because this would overwrite existing prefix->binding pointers in
01083        _dtd with ones that get destroyed with the external PE parser.
01084        This would leave those prefixes with dangling pointers.
01085     */
01086     isParamEntity = XML_TRUE;
01087     XmlPrologStateInitExternalEntity(&prologState);
01088     processor = externalParEntInitProcessor;
01089   }
01090 #endif /* XML_DTD */
01091   return parser;
01092 }
01093 
01094 static void FASTCALL
01095 destroyBindings(BINDING *bindings, XML_Parser parser)
01096 {
01097   for (;;) {
01098     BINDING *b = bindings;
01099     if (!b)
01100       break;
01101     bindings = b->nextTagBinding;
01102     FREE(b->uri);
01103     FREE(b);
01104   }
01105 }
01106 
01107 void XMLCALL
01108 XML_ParserFree(XML_Parser parser)
01109 {
01110   for (;;) {
01111     TAG *p;
01112     if (tagStack == NULL) {
01113       if (freeTagList == NULL)
01114         break;
01115       tagStack = freeTagList;
01116       freeTagList = NULL;
01117     }
01118     p = tagStack;
01119     tagStack = tagStack->parent;
01120     FREE(p->buf);
01121     destroyBindings(p->bindings, parser);
01122     FREE(p);
01123   }
01124   destroyBindings(freeBindingList, parser);
01125   destroyBindings(inheritedBindings, parser);
01126   poolDestroy(&tempPool);
01127   poolDestroy(&temp2Pool);
01128 #ifdef XML_DTD
01129   /* external parameter entity parsers share the DTD structure
01130      parser->m_dtd with the root parser, so we must not destroy it
01131   */
01132   if (!isParamEntity && _dtd)
01133 #else
01134   if (_dtd)
01135 #endif /* XML_DTD */
01136     dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
01137   FREE((void *)atts);
01138   FREE(groupConnector);
01139   FREE(buffer);
01140   FREE(dataBuf);
01141   FREE(nsAtts);
01142   FREE(unknownEncodingMem);
01143   if (unknownEncodingRelease)
01144     unknownEncodingRelease(unknownEncodingData);
01145   FREE(parser);
01146 }
01147 
01148 void XMLCALL
01149 XML_UseParserAsHandlerArg(XML_Parser parser)
01150 {
01151   handlerArg = parser;
01152 }
01153 
01154 /* BEGIN MOZILLA CHANGE (unused API) */
01155 #if 0
01156 enum XML_Error XMLCALL
01157 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
01158 {
01159 #ifdef XML_DTD
01160   /* block after XML_Parse()/XML_ParseBuffer() has been called */
01161   if (parsing)
01162     return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
01163   useForeignDTD = useDTD;
01164   return XML_ERROR_NONE;
01165 #else
01166   return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
01167 #endif
01168 }
01169 #endif
01170 /* END MOZILLA CHANGE */
01171 
01172 void XMLCALL
01173 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
01174 {
01175   /* block after XML_Parse()/XML_ParseBuffer() has been called */
01176   if (parsing)
01177     return;
01178   ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
01179 }
01180 
01181 void XMLCALL
01182 XML_SetUserData(XML_Parser parser, void *p)
01183 {
01184   if (handlerArg == userData)
01185     handlerArg = userData = p;
01186   else
01187     userData = p;
01188 }
01189 
01190 enum XML_Status XMLCALL
01191 XML_SetBase(XML_Parser parser, const XML_Char *p)
01192 {
01193   if (p) {
01194     p = poolCopyString(&_dtd->pool, p);
01195     if (!p)
01196       return XML_STATUS_ERROR;
01197     curBase = p;
01198   }
01199   else
01200     curBase = NULL;
01201   return XML_STATUS_OK;
01202 }
01203 
01204 const XML_Char * XMLCALL
01205 XML_GetBase(XML_Parser parser)
01206 {
01207   return curBase;
01208 }
01209 
01210 int XMLCALL
01211 XML_GetSpecifiedAttributeCount(XML_Parser parser)
01212 {
01213   return nSpecifiedAtts;
01214 }
01215 
01216 int XMLCALL
01217 XML_GetIdAttributeIndex(XML_Parser parser)
01218 {
01219   return idAttIndex;
01220 }
01221 
01222 void XMLCALL
01223 XML_SetElementHandler(XML_Parser parser,
01224                       XML_StartElementHandler start,
01225                       XML_EndElementHandler end)
01226 {
01227   startElementHandler = start;
01228   endElementHandler = end;
01229 }
01230 
01231 /* BEGIN MOZILLA CHANGE (unused API) */
01232 #if 0
01233 void XMLCALL
01234 XML_SetStartElementHandler(XML_Parser parser,
01235                            XML_StartElementHandler start) {
01236   startElementHandler = start;
01237 }
01238 
01239 void XMLCALL
01240 XML_SetEndElementHandler(XML_Parser parser,
01241                          XML_EndElementHandler end) {
01242   endElementHandler = end;
01243 }
01244 #endif
01245 /* END MOZILLA CHANGE */
01246 
01247 void XMLCALL
01248 XML_SetCharacterDataHandler(XML_Parser parser,
01249                             XML_CharacterDataHandler handler)
01250 {
01251   characterDataHandler = handler;
01252 }
01253 
01254 void XMLCALL
01255 XML_SetProcessingInstructionHandler(XML_Parser parser,
01256                                     XML_ProcessingInstructionHandler handler)
01257 {
01258   processingInstructionHandler = handler;
01259 }
01260 
01261 void XMLCALL
01262 XML_SetCommentHandler(XML_Parser parser,
01263                       XML_CommentHandler handler)
01264 {
01265   commentHandler = handler;
01266 }
01267 
01268 void XMLCALL
01269 XML_SetCdataSectionHandler(XML_Parser parser,
01270                            XML_StartCdataSectionHandler start,
01271                            XML_EndCdataSectionHandler end)
01272 {
01273   startCdataSectionHandler = start;
01274   endCdataSectionHandler = end;
01275 }
01276 
01277 /* BEGIN MOZILLA CHANGE (unused API) */
01278 #if 0
01279 void XMLCALL
01280 XML_SetStartCdataSectionHandler(XML_Parser parser,
01281                                 XML_StartCdataSectionHandler start) {
01282   startCdataSectionHandler = start;
01283 }
01284 
01285 void XMLCALL
01286 XML_SetEndCdataSectionHandler(XML_Parser parser,
01287                               XML_EndCdataSectionHandler end) {
01288   endCdataSectionHandler = end;
01289 }
01290 
01291 void XMLCALL
01292 XML_SetDefaultHandler(XML_Parser parser,
01293                       XML_DefaultHandler handler)
01294 {
01295   defaultHandler = handler;
01296   defaultExpandInternalEntities = XML_FALSE;
01297 }
01298 #endif
01299 /* END MOZILLA CHANGE */
01300 
01301 void XMLCALL
01302 XML_SetDefaultHandlerExpand(XML_Parser parser,
01303                             XML_DefaultHandler handler)
01304 {
01305   defaultHandler = handler;
01306   defaultExpandInternalEntities = XML_TRUE;
01307 }
01308 
01309 void XMLCALL
01310 XML_SetDoctypeDeclHandler(XML_Parser parser,
01311                           XML_StartDoctypeDeclHandler start,
01312                           XML_EndDoctypeDeclHandler end)
01313 {
01314   startDoctypeDeclHandler = start;
01315   endDoctypeDeclHandler = end;
01316 }
01317 
01318 /* BEGIN MOZILLA CHANGE (unused API) */
01319 #if 0
01320 void XMLCALL
01321 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
01322                                XML_StartDoctypeDeclHandler start) {
01323   startDoctypeDeclHandler = start;
01324 }
01325 
01326 void XMLCALL
01327 XML_SetEndDoctypeDeclHandler(XML_Parser parser,
01328                              XML_EndDoctypeDeclHandler end) {
01329   endDoctypeDeclHandler = end;
01330 }
01331 #endif
01332 /* END MOZILLA CHANGE */
01333 
01334 void XMLCALL
01335 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
01336                                  XML_UnparsedEntityDeclHandler handler)
01337 {
01338   unparsedEntityDeclHandler = handler;
01339 }
01340 
01341 void XMLCALL
01342 XML_SetNotationDeclHandler(XML_Parser parser,
01343                            XML_NotationDeclHandler handler)
01344 {
01345   notationDeclHandler = handler;
01346 }
01347 
01348 void XMLCALL
01349 XML_SetNamespaceDeclHandler(XML_Parser parser,
01350                             XML_StartNamespaceDeclHandler start,
01351                             XML_EndNamespaceDeclHandler end)
01352 {
01353   startNamespaceDeclHandler = start;
01354   endNamespaceDeclHandler = end;
01355 }
01356 
01357 
01358 /* BEGIN MOZILLA CHANGE (unused API) */
01359 #if 0
01360 void XMLCALL
01361 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
01362                                  XML_StartNamespaceDeclHandler start) {
01363   startNamespaceDeclHandler = start;
01364 }
01365 
01366 void XMLCALL
01367 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
01368                                XML_EndNamespaceDeclHandler end) {
01369   endNamespaceDeclHandler = end;
01370 }
01371 
01372 void XMLCALL
01373 XML_SetNotStandaloneHandler(XML_Parser parser,
01374                             XML_NotStandaloneHandler handler)
01375 {
01376   notStandaloneHandler = handler;
01377 }
01378 #endif
01379 /* END MOZILLA CHANGE */
01380 
01381 void XMLCALL
01382 XML_SetExternalEntityRefHandler(XML_Parser parser,
01383                                 XML_ExternalEntityRefHandler handler)
01384 {
01385   externalEntityRefHandler = handler;
01386 }
01387 
01388 void XMLCALL
01389 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
01390 {
01391   if (arg)
01392     externalEntityRefHandlerArg = (XML_Parser)arg;
01393   else
01394     externalEntityRefHandlerArg = parser;
01395 }
01396 
01397 /* BEGIN MOZILLA CHANGE (unused API) */
01398 #if 0
01399 void XMLCALL
01400 XML_SetSkippedEntityHandler(XML_Parser parser,
01401                             XML_SkippedEntityHandler handler)
01402 {
01403   skippedEntityHandler = handler;
01404 }
01405 
01406 void XMLCALL
01407 XML_SetUnknownEncodingHandler(XML_Parser parser,
01408                               XML_UnknownEncodingHandler handler,
01409                               void *data)
01410 {
01411   unknownEncodingHandler = handler;
01412   unknownEncodingHandlerData = data;
01413 }
01414 
01415 void XMLCALL
01416 XML_SetElementDeclHandler(XML_Parser parser,
01417                           XML_ElementDeclHandler eldecl)
01418 {
01419   elementDeclHandler = eldecl;
01420 }
01421 
01422 void XMLCALL
01423 XML_SetAttlistDeclHandler(XML_Parser parser,
01424                           XML_AttlistDeclHandler attdecl)
01425 {
01426   attlistDeclHandler = attdecl;
01427 }
01428 
01429 void XMLCALL
01430 XML_SetEntityDeclHandler(XML_Parser parser,
01431                          XML_EntityDeclHandler handler)
01432 {
01433   entityDeclHandler = handler;
01434 }
01435 #endif
01436 /* END MOZILLA CHANGE */
01437 
01438 void XMLCALL
01439 XML_SetXmlDeclHandler(XML_Parser parser,
01440                       XML_XmlDeclHandler handler) {
01441   xmlDeclHandler = handler;
01442 }
01443 
01444 int XMLCALL
01445 XML_SetParamEntityParsing(XML_Parser parser,
01446                           enum XML_ParamEntityParsing peParsing)
01447 {
01448   /* block after XML_Parse()/XML_ParseBuffer() has been called */
01449   if (parsing)
01450     return 0;
01451 #ifdef XML_DTD
01452   paramEntityParsing = peParsing;
01453   return 1;
01454 #else
01455   return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
01456 #endif
01457 }
01458 
01459 enum XML_Status XMLCALL
01460 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
01461 {
01462 /* BEGIN MOZILLA CHANGE (Blocking parser) */
01463   if (blocked) {
01464     /* First unblock parser */
01465     return XML_STATUS_ERROR;
01466   }
01467 /* END MOZILLA CHANGE */
01468 
01469   if (len == 0) {
01470     if (!isFinal)
01471       return XML_STATUS_OK;
01472     positionPtr = bufferPtr;
01473     errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0);
01474     if (errorCode == XML_ERROR_NONE)
01475       return XML_STATUS_OK;
01476 /* BEGIN MOZILLA CHANGE (Blocking parser) */
01477     if (errorCode == XML_ERROR_SUSPENDED) {
01478       parseEndByteIndex -= parseEndPtr - eventPtr; /* Remove what we haven't read. */
01479       parseEndPtr = bufferPtr = eventPtr;
01480       bufferEnd = (char*)bufferPtr; /* We'll pass in the same data again later. */
01481       XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
01482       return XML_STATUS_ERROR;
01483     }
01484 /* END MOZILLA CHANGE */
01485     eventEndPtr = eventPtr;
01486     processor = errorProcessor;
01487     return XML_STATUS_ERROR;
01488   }
01489 #ifndef XML_CONTEXT_BYTES
01490   else if (bufferPtr == bufferEnd) {
01491     const char *end;
01492     int nLeftOver;
01493     parseEndByteIndex += len;
01494     positionPtr = s;
01495     if (isFinal) {
01496       errorCode = processor(parser, s, parseEndPtr = s + len, 0);
01497       if (errorCode == XML_ERROR_NONE)
01498         return XML_STATUS_OK;
01499       eventEndPtr = eventPtr;
01500       processor = errorProcessor;
01501       return XML_STATUS_ERROR;
01502     }
01503     errorCode = processor(parser, s, parseEndPtr = s + len, &end);
01504     if (errorCode != XML_ERROR_NONE) {
01505 /* BEGIN MOZILLA CHANGE (Blocking parser) */
01506       if (blocked) {
01507         parseEndByteIndex -= parseEndPtr - eventPtr; /* Remove what we haven't read. */
01508         parseEndPtr = eventPtr;
01509         XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
01510         eventEndPtr = eventPtr;
01511         return XML_STATUS_ERROR;
01512       }
01513 /* END MOZILLA CHANGE */
01514       eventEndPtr = eventPtr;
01515       processor = errorProcessor;
01516       return XML_STATUS_ERROR;
01517     }
01518     XmlUpdatePosition(encoding, positionPtr, end, &position);
01519     positionPtr = end;
01520     nLeftOver = s + len - end;
01521     if (nLeftOver) {
01522       if (buffer == NULL || nLeftOver > bufferLim - buffer) {
01523         /* FIXME avoid integer overflow */
01524         char *temp;
01525         temp = (buffer == NULL
01526                 ? (char *)MALLOC(len * 2)
01527                 : (char *)REALLOC(buffer, len * 2));
01528         if (temp == NULL) {
01529           errorCode = XML_ERROR_NO_MEMORY;
01530           return XML_STATUS_ERROR;
01531         }
01532         buffer = temp;
01533         if (!buffer) {
01534           errorCode = XML_ERROR_NO_MEMORY;
01535           eventPtr = eventEndPtr = NULL;
01536           processor = errorProcessor;
01537           return XML_STATUS_ERROR;
01538         }
01539         bufferLim = buffer + len * 2;
01540       }
01541       memcpy(buffer, end, nLeftOver);
01542       bufferPtr = buffer;
01543       bufferEnd = buffer + nLeftOver;
01544     }
01545     return XML_STATUS_OK;
01546   }
01547 #endif  /* not defined XML_CONTEXT_BYTES */
01548   else {
01549     void *buff = XML_GetBuffer(parser, len);
01550     if (buff == NULL)
01551       return XML_STATUS_ERROR;
01552     else {
01553       memcpy(buff, s, len);
01554       return XML_ParseBuffer(parser, len, isFinal);
01555     }
01556   }
01557 }
01558 
01559 enum XML_Status XMLCALL
01560 XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
01561 {
01562   const char *start = bufferPtr;
01563   positionPtr = start;
01564   bufferEnd += len;
01565   parseEndByteIndex += len;
01566   errorCode = processor(parser, start, parseEndPtr = bufferEnd,
01567                         isFinal ? (const char **)NULL : &bufferPtr);
01568   if (errorCode == XML_ERROR_NONE) {
01569     if (!isFinal) {
01570       XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
01571       positionPtr = bufferPtr;
01572     }
01573     return XML_STATUS_OK;
01574   }
01575 /* BEGIN MOZILLA CHANGE (Blocking parser) */
01576   else if (errorCode == XML_ERROR_SUSPENDED) {
01577     parseEndByteIndex -= parseEndPtr - eventPtr; /* Remove what we haven't read. */
01578     parseEndPtr = bufferPtr = eventPtr;
01579     bufferEnd = (char*)bufferPtr; /* We'll pass in the same data again later. */
01580     XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
01581     return XML_STATUS_ERROR;
01582   }
01583 /* END MOZILLA CHANGE */
01584   else {
01585     eventEndPtr = eventPtr;
01586     processor = errorProcessor;
01587     return XML_STATUS_ERROR;
01588   }
01589 }
01590 
01591 void * XMLCALL
01592 XML_GetBuffer(XML_Parser parser, int len)
01593 {
01594   if (len > bufferLim - bufferEnd) {
01595     /* FIXME avoid integer overflow */
01596     int neededSize = len + (bufferEnd - bufferPtr);
01597 #ifdef XML_CONTEXT_BYTES
01598     int keep = bufferPtr - buffer;
01599 
01600     if (keep > XML_CONTEXT_BYTES)
01601       keep = XML_CONTEXT_BYTES;
01602     neededSize += keep;
01603 #endif  /* defined XML_CONTEXT_BYTES */
01604     if (neededSize  <= bufferLim - buffer) {
01605 #ifdef XML_CONTEXT_BYTES
01606       if (keep < bufferPtr - buffer) {
01607         int offset = (bufferPtr - buffer) - keep;
01608         memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
01609         bufferEnd -= offset;
01610         bufferPtr -= offset;
01611       }
01612 #else
01613       memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
01614       bufferEnd = buffer + (bufferEnd - bufferPtr);
01615       bufferPtr = buffer;
01616 #endif  /* not defined XML_CONTEXT_BYTES */
01617     }
01618     else {
01619       char *newBuf;
01620       int bufferSize = bufferLim - bufferPtr;
01621       if (bufferSize == 0)
01622         bufferSize = INIT_BUFFER_SIZE;
01623       do {
01624         bufferSize *= 2;
01625       } while (bufferSize < neededSize);
01626       newBuf = (char *)MALLOC(bufferSize);
01627       if (newBuf == 0) {
01628         errorCode = XML_ERROR_NO_MEMORY;
01629         return NULL;
01630       }
01631       bufferLim = newBuf + bufferSize;
01632 #ifdef XML_CONTEXT_BYTES
01633       if (bufferPtr) {
01634         int keep = bufferPtr - buffer;
01635         if (keep > XML_CONTEXT_BYTES)
01636           keep = XML_CONTEXT_BYTES;
01637         memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
01638         FREE(buffer);
01639         buffer = newBuf;
01640         bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
01641         bufferPtr = buffer + keep;
01642       }
01643       else {
01644         bufferEnd = newBuf + (bufferEnd - bufferPtr);
01645         bufferPtr = buffer = newBuf;
01646       }
01647 #else
01648       if (bufferPtr) {
01649         memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
01650         FREE(buffer);
01651       }
01652       bufferEnd = newBuf + (bufferEnd - bufferPtr);
01653       bufferPtr = buffer = newBuf;
01654 #endif  /* not defined XML_CONTEXT_BYTES */
01655     }
01656   }
01657   return bufferEnd;
01658 }
01659 
01660 /* BEGIN MOZILLA CHANGE (Blocking parser) */
01661 enum XML_Status XMLCALL
01662 MOZ_XML_StopParser(XML_Parser parser, XML_Bool resumable)
01663 {
01664   blocked = XML_TRUE;
01665   return XML_STATUS_OK;
01666 }
01667 
01668 enum XML_Status XMLCALL
01669 MOZ_XML_ResumeParser(XML_Parser parser)
01670 {
01671   blocked = XML_FALSE;
01672   return XML_STATUS_OK;
01673 }
01674 /* END MOZILLA CHANGE */
01675 
01676 enum XML_Error XMLCALL
01677 XML_GetErrorCode(XML_Parser parser)
01678 {
01679   return errorCode;
01680 }
01681 
01682 long XMLCALL
01683 XML_GetCurrentByteIndex(XML_Parser parser)
01684 {
01685   if (eventPtr)
01686     return parseEndByteIndex - (parseEndPtr - eventPtr);
01687   return -1;
01688 }
01689 
01690 /* BEGIN MOZILLA CHANGE (unused API) */
01691 #if 0
01692 int XMLCALL
01693 XML_GetCurrentByteCount(XML_Parser parser)
01694 {
01695   if (eventEndPtr && eventPtr)
01696     return eventEndPtr - eventPtr;
01697   return 0;
01698 }
01699 
01700 const char * XMLCALL
01701 XML_GetInputContext(XML_Parser parser, int *offset, int *size)
01702 {
01703 #ifdef XML_CONTEXT_BYTES
01704   if (eventPtr && buffer) {
01705     *offset = eventPtr - buffer;
01706     *size   = bufferEnd - buffer;
01707     return buffer;
01708   }
01709 #endif /* defined XML_CONTEXT_BYTES */
01710   return (char *) 0;
01711 }
01712 #endif
01713 /* END MOZILLA CHANGE */
01714 
01715 int XMLCALL
01716 XML_GetCurrentLineNumber(XML_Parser parser)
01717 {
01718   if (eventPtr) {
01719     XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
01720     positionPtr = eventPtr;
01721   }
01722   return position.lineNumber + 1;
01723 }
01724 
01725 int XMLCALL
01726 XML_GetCurrentColumnNumber(XML_Parser parser)
01727 {
01728   if (eventPtr) {
01729     XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
01730     positionPtr = eventPtr;
01731   }
01732   return position.columnNumber;
01733 }
01734 
01735 /* BEGIN MOZILLA CHANGE (unused API) */
01736 #if 0
01737 void XMLCALL
01738 XML_FreeContentModel(XML_Parser parser, XML_Content *model)
01739 {
01740   FREE(model);
01741 }
01742 
01743 void * XMLCALL
01744 XML_MemMalloc(XML_Parser parser, size_t size)
01745 {
01746   return MALLOC(size);
01747 }
01748 
01749 void * XMLCALL
01750 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
01751 {
01752   return REALLOC(ptr, size);
01753 }
01754 
01755 void XMLCALL
01756 XML_MemFree(XML_Parser parser, void *ptr)
01757 {
01758   FREE(ptr);
01759 }
01760 
01761 void XMLCALL
01762 XML_DefaultCurrent(XML_Parser parser)
01763 {
01764   if (defaultHandler) {
01765     if (openInternalEntities)
01766       reportDefault(parser,
01767                     internalEncoding,
01768                     openInternalEntities->internalEventPtr,
01769                     openInternalEntities->internalEventEndPtr);
01770     else
01771       reportDefault(parser, encoding, eventPtr, eventEndPtr);
01772   }
01773 }
01774 #endif
01775 
01776 #ifdef TX_EXE
01777 const XML_LChar * XMLCALL
01778 XML_ErrorString(enum XML_Error code)
01779 {
01780   static const XML_LChar *message[] = {
01781     0,
01782     XML_L("out of memory"),
01783     XML_L("syntax error"),
01784     XML_L("no element found"),
01785     XML_L("not well-formed (invalid token)"),
01786     XML_L("unclosed token"),
01787     XML_L("partial character"),
01788     XML_L("mismatched tag"),
01789     XML_L("duplicate attribute"),
01790     XML_L("junk after document element"),
01791     XML_L("illegal parameter entity reference"),
01792     XML_L("undefined entity"),
01793     XML_L("recursive entity reference"),
01794     XML_L("asynchronous entity"),
01795     XML_L("reference to invalid character number"),
01796     XML_L("reference to binary entity"),
01797     XML_L("reference to external entity in attribute"),
01798     XML_L("xml declaration not at start of external entity"),
01799     XML_L("unknown encoding"),
01800     XML_L("encoding specified in XML declaration is incorrect"),
01801     XML_L("unclosed CDATA section"),
01802     XML_L("error in processing external entity reference"),
01803     XML_L("document is not standalone"),
01804     XML_L("unexpected parser state - please send a bug report"),
01805     XML_L("entity declared in parameter entity"),
01806     XML_L("requested feature requires XML_DTD support in Expat"),
01807     XML_L("cannot change setting once parsing has begun"),
01808     XML_L("unbound prefix")
01809   };
01810   if (code > 0 && code < sizeof(message)/sizeof(message[0]))
01811     return message[code];
01812   return NULL;
01813 }
01814 #endif
01815 
01816 #if 0
01817 const XML_LChar * XMLCALL
01818 XML_ExpatVersion(void) {
01819 
01820   /* V1 is used to string-ize the version number. However, it would
01821      string-ize the actual version macro *names* unless we get them
01822      substituted before being passed to V1. CPP is defined to expand
01823      a macro, then rescan for more expansions. Thus, we use V2 to expand
01824      the version macros, then CPP will expand the resulting V1() macro
01825      with the correct numerals. */
01826   /* ### I'm assuming cpp is portable in this respect... */
01827 
01828 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
01829 #define V2(a,b,c) XML_L("expat_")V1(a,b,c)
01830 
01831   return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
01832 
01833 #undef V1
01834 #undef V2
01835 }
01836 
01837 XML_Expat_Version XMLCALL
01838 XML_ExpatVersionInfo(void)
01839 {
01840   XML_Expat_Version version;
01841 
01842   version.major = XML_MAJOR_VERSION;
01843   version.minor = XML_MINOR_VERSION;
01844   version.micro = XML_MICRO_VERSION;
01845 
01846   return version;
01847 }
01848 
01849 const XML_Feature * XMLCALL
01850 XML_GetFeatureList(void)
01851 {
01852   static XML_Feature features[] = {
01853     {XML_FEATURE_SIZEOF_XML_CHAR,  XML_L("sizeof(XML_Char)"), 0},
01854     {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"), 0},
01855 #ifdef XML_UNICODE
01856     {XML_FEATURE_UNICODE,          XML_L("XML_UNICODE"), 0},
01857 #endif
01858 #ifdef XML_UNICODE_WCHAR_T
01859     {XML_FEATURE_UNICODE_WCHAR_T,  XML_L("XML_UNICODE_WCHAR_T"), 0},
01860 #endif
01861 #ifdef XML_DTD
01862     {XML_FEATURE_DTD,              XML_L("XML_DTD"), 0},
01863 #endif
01864 #ifdef XML_CONTEXT_BYTES
01865     {XML_FEATURE_CONTEXT_BYTES,    XML_L("XML_CONTEXT_BYTES"),
01866      XML_CONTEXT_BYTES},
01867 #endif
01868 #ifdef XML_MIN_SIZE
01869     {XML_FEATURE_MIN_SIZE,         XML_L("XML_MIN_SIZE"), 0},
01870 #endif
01871     {XML_FEATURE_END,              NULL, 0}
01872   };
01873 
01874   features[0].value = sizeof(XML_Char);
01875   features[1].value = sizeof(XML_LChar);
01876   return features;
01877 }
01878 #endif
01879 /* END MOZILLA CHANGE */
01880 
01881 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
01882 const XML_Char * XMLCALL
01883 MOZ_XML_GetMismatchedTag(XML_Parser parser)
01884 {
01885   return mismatch;
01886 }
01887 /* END MOZILLA CHANGE */
01888 
01889 /* Initially tag->rawName always points into the parse buffer;
01890    for those TAG instances opened while the current parse buffer was
01891    processed, and not yet closed, we need to store tag->rawName in a more
01892    permanent location, since the parse buffer is about to be discarded.
01893 */
01894 static XML_Bool
01895 storeRawNames(XML_Parser parser)
01896 {
01897   TAG *tag = tagStack;
01898   while (tag) {
01899     int bufSize;
01900     int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
01901     char *rawNameBuf = tag->buf + nameLen;
01902     /* Stop if already stored.  Since tagStack is a stack, we can stop
01903        at the first entry that has already been copied; everything
01904        below it in the stack is already been accounted for in a
01905        previous call to this function.
01906     */
01907     if (tag->rawName == rawNameBuf)
01908       break;
01909     /* For re-use purposes we need to ensure that the
01910        size of tag->buf is a multiple of sizeof(XML_Char).
01911     */
01912     bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
01913     if (bufSize > tag->bufEnd - tag->buf) {
01914       char *temp = (char *)REALLOC(tag->buf, bufSize);
01915       if (temp == NULL)
01916         return XML_FALSE;
01917       /* if tag->name.str points to tag->buf (only when namespace
01918          processing is off) then we have to update it
01919       */
01920       if (tag->name.str == (XML_Char *)tag->buf)
01921         tag->name.str = (XML_Char *)temp;
01922       /* if tag->name.localPart is set (when namespace processing is on)
01923          then update it as well, since it will always point into tag->buf
01924       */
01925       if (tag->name.localPart)
01926         tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
01927                                                   (XML_Char *)tag->buf);
01928       tag->buf = temp;
01929       tag->bufEnd = temp + bufSize;
01930       rawNameBuf = temp + nameLen;
01931     }
01932     memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
01933     tag->rawName = rawNameBuf;
01934     tag = tag->parent;
01935   }
01936   return XML_TRUE;
01937 }
01938 
01939 static enum XML_Error PTRCALL
01940 contentProcessor(XML_Parser parser,
01941                  const char *start,
01942                  const char *end,
01943                  const char **endPtr)
01944 {
01945   enum XML_Error result =
01946     doContent(parser, 0, encoding, start, end, endPtr);
01947   if (result != XML_ERROR_NONE)
01948     return result;
01949   if (!storeRawNames(parser))
01950     return XML_ERROR_NO_MEMORY;
01951   return result;
01952 }
01953 
01954 static enum XML_Error PTRCALL
01955 externalEntityInitProcessor(XML_Parser parser,
01956                             const char *start,
01957                             const char *end,
01958                             const char **endPtr)
01959 {
01960   enum XML_Error result = initializeEncoding(parser);
01961   if (result != XML_ERROR_NONE)
01962     return result;
01963   processor = externalEntityInitProcessor2;
01964   return externalEntityInitProcessor2(parser, start, end, endPtr);
01965 }
01966 
01967 static enum XML_Error PTRCALL
01968 externalEntityInitProcessor2(XML_Parser parser,
01969                              const char *start,
01970                              const char *end,
01971                              const char **endPtr)
01972 {
01973   const char *next = start; /* XmlContentTok doesn't always set the last arg */
01974   int tok = XmlContentTok(encoding, start, end, &next);
01975   switch (tok) {
01976   case XML_TOK_BOM:
01977     /* If we are at the end of the buffer, this would cause the next stage,
01978        i.e. externalEntityInitProcessor3, to pass control directly to
01979        doContent (by detecting XML_TOK_NONE) without processing any xml text
01980        declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
01981     */
01982     if (next == end && endPtr) {
01983       *endPtr = next;
01984       return XML_ERROR_NONE;
01985     }
01986     start = next;
01987     break;
01988   case XML_TOK_PARTIAL:
01989     if (endPtr) {
01990       *endPtr = start;
01991       return XML_ERROR_NONE;
01992     }
01993     eventPtr = start;
01994     return XML_ERROR_UNCLOSED_TOKEN;
01995   case XML_TOK_PARTIAL_CHAR:
01996     if (endPtr) {
01997       *endPtr = start;
01998       return XML_ERROR_NONE;
01999     }
02000     eventPtr = start;
02001     return XML_ERROR_PARTIAL_CHAR;
02002   }
02003   processor = externalEntityInitProcessor3;
02004   return externalEntityInitProcessor3(parser, start, end, endPtr);
02005 }
02006 
02007 static enum XML_Error PTRCALL
02008 externalEntityInitProcessor3(XML_Parser parser,
02009                              const char *start,
02010                              const char *end,
02011                              const char **endPtr)
02012 {
02013   const char *next = start; /* XmlContentTok doesn't always set the last arg */
02014   int tok = XmlContentTok(encoding, start, end, &next);
02015   switch (tok) {
02016   case XML_TOK_XML_DECL:
02017     {
02018       enum XML_Error result = processXmlDecl(parser, 1, start, next);
02019       if (result != XML_ERROR_NONE)
02020         return result;
02021       start = next;
02022     }
02023     break;
02024   case XML_TOK_PARTIAL:
02025     if (endPtr) {
02026       *endPtr = start;
02027       return XML_ERROR_NONE;
02028     }
02029     eventPtr = start;
02030     return XML_ERROR_UNCLOSED_TOKEN;
02031   case XML_TOK_PARTIAL_CHAR:
02032     if (endPtr) {
02033       *endPtr = start;
02034       return XML_ERROR_NONE;
02035     }
02036     eventPtr = start;
02037     return XML_ERROR_PARTIAL_CHAR;
02038   }
02039   processor = externalEntityContentProcessor;
02040   tagLevel = 1;
02041   return externalEntityContentProcessor(parser, start, end, endPtr);
02042 }
02043 
02044 static enum XML_Error PTRCALL
02045 externalEntityContentProcessor(XML_Parser parser,
02046                                const char *start,
02047                                const char *end,
02048                                const char **endPtr)
02049 {
02050   enum XML_Error result =
02051     doContent(parser, 1, encoding, start, end, endPtr);
02052   if (result != XML_ERROR_NONE)
02053     return result;
02054   if (!storeRawNames(parser))
02055     return XML_ERROR_NO_MEMORY;
02056   return result;
02057 }
02058 
02059 static enum XML_Error
02060 doContent(XML_Parser parser,
02061           int startTagLevel,
02062           const ENCODING *enc,
02063           const char *s,
02064           const char *end,
02065           const char **nextPtr)
02066 {
02067   DTD * const dtd = _dtd;  /* save one level of indirection */
02068   const char **eventPP;
02069   const char **eventEndPP;
02070   if (enc == encoding) {
02071     eventPP = &eventPtr;
02072     eventEndPP = &eventEndPtr;
02073   }
02074   else {
02075     eventPP = &(openInternalEntities->internalEventPtr);
02076     eventEndPP = &(openInternalEntities->internalEventEndPtr);
02077   }
02078   *eventPP = s;
02079   for (;;) {
02080     const char *next = s; /* XmlContentTok doesn't always set the last arg */
02081     int tok = XmlContentTok(enc, s, end, &next);
02082     *eventEndPP = next;
02083     switch (tok) {
02084     case XML_TOK_TRAILING_CR:
02085       if (nextPtr) {
02086         *nextPtr = s;
02087         return XML_ERROR_NONE;
02088       }
02089       *eventEndPP = end;
02090       if (characterDataHandler) {
02091         XML_Char c = 0xA;
02092         characterDataHandler(handlerArg, &c, 1);
02093       }
02094       else if (defaultHandler)
02095         reportDefault(parser, enc, s, end);
02096       if (startTagLevel == 0)
02097         return XML_ERROR_NO_ELEMENTS;
02098       if (tagLevel != startTagLevel)
02099         return XML_ERROR_ASYNC_ENTITY;
02100       return XML_ERROR_NONE;
02101     case XML_TOK_NONE:
02102       if (nextPtr) {
02103         *nextPtr = s;
02104         return XML_ERROR_NONE;
02105       }
02106       if (startTagLevel > 0) {
02107         if (tagLevel != startTagLevel)
02108           return XML_ERROR_ASYNC_ENTITY;
02109         return XML_ERROR_NONE;
02110       }
02111       return XML_ERROR_NO_ELEMENTS;
02112     case XML_TOK_INVALID:
02113       *eventPP = next;
02114       return XML_ERROR_INVALID_TOKEN;
02115     case XML_TOK_PARTIAL:
02116       if (nextPtr) {
02117         *nextPtr = s;
02118         return XML_ERROR_NONE;
02119       }
02120       return XML_ERROR_UNCLOSED_TOKEN;
02121     case XML_TOK_PARTIAL_CHAR:
02122       if (nextPtr) {
02123         *nextPtr = s;
02124         return XML_ERROR_NONE;
02125       }
02126       return XML_ERROR_PARTIAL_CHAR;
02127     case XML_TOK_ENTITY_REF:
02128       {
02129         const XML_Char *name;
02130         ENTITY *entity;
02131         XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
02132                                               s + enc->minBytesPerChar,
02133                                               next - enc->minBytesPerChar);
02134         if (ch) {
02135           if (characterDataHandler)
02136             characterDataHandler(handlerArg, &ch, 1);
02137           else if (defaultHandler)
02138             reportDefault(parser, enc, s, next);
02139           break;
02140         }
02141         name = poolStoreString(&dtd->pool, enc,
02142                                 s + enc->minBytesPerChar,
02143                                 next - enc->minBytesPerChar);
02144         if (!name)
02145           return XML_ERROR_NO_MEMORY;
02146         entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
02147         poolDiscard(&dtd->pool);
02148         /* First, determine if a check for an existing declaration is needed;
02149            if yes, check that the entity exists, and that it is internal,
02150            otherwise call the skipped entity or default handler.
02151         */
02152         if (!dtd->hasParamEntityRefs || dtd->standalone) {
02153           if (!entity)
02154             return XML_ERROR_UNDEFINED_ENTITY;
02155           else if (!entity->is_internal)
02156             return XML_ERROR_ENTITY_DECLARED_IN_PE;
02157         }
02158         else if (!entity) {
02159           if (skippedEntityHandler)
02160             skippedEntityHandler(handlerArg, name, 0);
02161 /* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=35984) */
02162 #if 0
02163           else if (defaultHandler)
02164             reportDefault(parser, enc, s, next);
02165           break;
02166 #else
02167           return XML_ERROR_UNDEFINED_ENTITY;
02168 #endif
02169 /* END MOZILLA CHANGE */
02170         }
02171         if (entity->open)
02172           return XML_ERROR_RECURSIVE_ENTITY_REF;
02173         if (entity->notation)
02174           return XML_ERROR_BINARY_ENTITY_REF;
02175         if (entity->textPtr) {
02176           enum XML_Error result;
02177           OPEN_INTERNAL_ENTITY openEntity;
02178           if (!defaultExpandInternalEntities) {
02179             if (skippedEntityHandler)
02180               skippedEntityHandler(handlerArg, entity->name, 0);
02181             else if (defaultHandler)
02182               reportDefault(parser, enc, s, next);
02183             break;
02184           }
02185           entity->open = XML_TRUE;
02186           openEntity.next = openInternalEntities;
02187           openInternalEntities = &openEntity;
02188           openEntity.entity = entity;
02189           openEntity.internalEventPtr = NULL;
02190           openEntity.internalEventEndPtr = NULL;
02191           result = doContent(parser,
02192                              tagLevel,
02193                              internalEncoding,
02194                              (char *)entity->textPtr,
02195                              (char *)(entity->textPtr + entity->textLen),
02196                              0);
02197           entity->open = XML_FALSE;
02198           openInternalEntities = openEntity.next;
02199           if (result)
02200             return result;
02201         }
02202         else if (externalEntityRefHandler) {
02203           const XML_Char *context;
02204           entity->open = XML_TRUE;
02205           context = getContext(parser);
02206           entity->open = XML_FALSE;
02207           if (!context)
02208             return XML_ERROR_NO_MEMORY;
02209           if (!externalEntityRefHandler((XML_Parser)externalEntityRefHandlerArg,
02210                                         context,
02211                                         entity->base,
02212                                         entity->systemId,
02213                                         entity->publicId))
02214             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
02215           poolDiscard(&tempPool);
02216         }
02217         else if (defaultHandler)
02218           reportDefault(parser, enc, s, next);
02219         break;
02220       }
02221     case XML_TOK_START_TAG_NO_ATTS:
02222       /* fall through */
02223     case XML_TOK_START_TAG_WITH_ATTS:
02224       {
02225         TAG *tag;
02226         enum XML_Error result;
02227         XML_Char *toPtr;
02228         if (freeTagList) {
02229           tag = freeTagList;
02230           freeTagList = freeTagList->parent;
02231         }
02232         else {
02233           tag = (TAG *)MALLOC(sizeof(TAG));
02234           if (!tag)
02235             return XML_ERROR_NO_MEMORY;
02236           tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
02237           if (!tag->buf) {
02238             FREE(tag);
02239             return XML_ERROR_NO_MEMORY;
02240           }
02241           tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
02242         }
02243         tag->bindings = NULL;
02244         tag->parent = tagStack;
02245         tagStack = tag;
02246         tag->name.localPart = NULL;
02247         tag->name.prefix = NULL;
02248         tag->rawName = s + enc->minBytesPerChar;
02249         tag->rawNameLength = XmlNameLength(enc, tag->rawName);
02250         ++tagLevel;
02251         {
02252           const char *rawNameEnd = tag->rawName + tag->rawNameLength;
02253           const char *fromPtr = tag->rawName;
02254           toPtr = (XML_Char *)tag->buf;
02255           for (;;) {
02256             int bufSize;
02257             int convLen;
02258             XmlConvert(enc,
02259                        &fromPtr, rawNameEnd,
02260                        (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
02261             convLen = toPtr - (XML_Char *)tag->buf;
02262             if (fromPtr == rawNameEnd) {
02263               tag->name.strLen = convLen;
02264               break;
02265             }
02266             bufSize = (tag->bufEnd - tag->buf) << 1;
02267             {
02268               char *temp = (char *)REALLOC(tag->buf, bufSize);
02269               if (temp == NULL)
02270                 return XML_ERROR_NO_MEMORY;
02271               tag->buf = temp;
02272               tag->bufEnd = temp + bufSize;
02273               toPtr = (XML_Char *)temp + convLen;
02274             }
02275           }
02276         }
02277         tag->name.str = (XML_Char *)tag->buf;
02278         *toPtr = XML_T('\0');
02279         result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
02280         if (result)
02281           return result;
02282         if (startElementHandler)
02283           startElementHandler(handlerArg, tag->name.str,
02284                               (const XML_Char **)atts);
02285         else if (defaultHandler)
02286           reportDefault(parser, enc, s, next);
02287         poolClear(&tempPool);
02288 /* BEGIN MOZILLA CHANGE (Blocking parser) */
02289         if (blocked) {
02290           *eventPP = *eventEndPP;
02291           return XML_ERROR_SUSPENDED;
02292         }
02293 /* END MOZILLA CHANGE */
02294         break;
02295       }
02296     case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
02297       /* fall through */
02298     case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
02299       {
02300         const char *rawName = s + enc->minBytesPerChar;
02301         enum XML_Error result;
02302         BINDING *bindings = NULL;
02303         XML_Bool noElmHandlers = XML_TRUE;
02304         TAG_NAME name;
02305         name.str = poolStoreString(&tempPool, enc, rawName,
02306                                    rawName + XmlNameLength(enc, rawName));
02307         if (!name.str)
02308           return XML_ERROR_NO_MEMORY;
02309         poolFinish(&tempPool);
02310         result = storeAtts(parser, enc, s, &name, &bindings);
02311         if (result)
02312           return result;
02313         poolFinish(&tempPool);
02314         if (startElementHandler) {
02315           startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
02316 /* BEGIN MOZILLA CHANGE (Blocking parser) */
02317           if (blocked) {
02318             /* Hopefully this won't happen, since we can't really call  */
02319             /* endElementHandler seperately from startElementHandler in */
02320             /* this case. */
02321             return XML_ERROR_SUSPENDED;
02322           }
02323 /* END MOZILLA CHANGE */
02324           noElmHandlers = XML_FALSE;
02325         }
02326         if (endElementHandler) {
02327           if (startElementHandler)
02328             *eventPP = *eventEndPP;
02329           endElementHandler(handlerArg, name.str);
02330           noElmHandlers = XML_FALSE;
02331         }
02332         if (noElmHandlers && defaultHandler)
02333           reportDefault(parser, enc, s, next);
02334         poolClear(&tempPool);
02335         while (bindings) {
02336           BINDING *b = bindings;
02337           if (endNamespaceDeclHandler)
02338             endNamespaceDeclHandler(handlerArg, b->prefix->name);
02339           bindings = bindings->nextTagBinding;
02340           b->nextTagBinding = freeBindingList;
02341           freeBindingList = b;
02342           b->prefix->binding = b->prevPrefixBinding;
02343         }
02344 /* BEGIN MOZILLA CHANGE (Blocking parser) */
02345         if (blocked) {
02346           return XML_ERROR_SUSPENDED;
02347         }
02348 /* END MOZILLA CHANGE */
02349       }
02350       if (tagLevel == 0)
02351         return epilogProcessor(parser, next, end, nextPtr);
02352       break;
02353     case XML_TOK_END_TAG:
02354       if (tagLevel == startTagLevel)
02355         return XML_ERROR_ASYNC_ENTITY;
02356       else {
02357         int len;
02358         const char *rawName;
02359         TAG *tag = tagStack;
02360         tagStack = tag->parent;
02361         tag->parent = freeTagList;
02362         freeTagList = tag;
02363         rawName = s + enc->minBytesPerChar*2;
02364         len = XmlNameLength(enc, rawName);
02365         if (len != tag->rawNameLength
02366             || memcmp(tag->rawName, rawName, len) != 0) {
02367 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
02368          /* This code is copied from the |if (endElementHandler)| block below */
02369           const XML_Char *localPart;
02370           const XML_Char *prefix;
02371           XML_Char *uri;
02372           localPart = tag->name.localPart;
02373           if (ns && localPart) {
02374             /* localPart and prefix may have been overwritten in
02375                tag->name.str, since this points to the binding->uri
02376                buffer which gets re-used; so we have to add them again
02377             */
02378             uri = (XML_Char *)tag->name.str + tag->name.uriLen;
02379             /* don't need to check for space - already done in storeAtts() */
02380             while (*localPart) *uri++ = *localPart++;
02381             prefix = (XML_Char *)tag->name.prefix;
02382             if (ns_triplets && prefix) {
02383               *uri++ = namespaceSeparator;
02384               while (*prefix) *uri++ = *prefix++;
02385              }
02386             *uri = XML_T('\0');
02387           }
02388           mismatch = tag->name.str;
02389 /* END MOZILLA CHANGE */
02390           *eventPP = rawName;
02391           return XML_ERROR_TAG_MISMATCH;
02392         }
02393         --tagLevel;
02394         if (endElementHandler) {
02395           const XML_Char *localPart;
02396           const XML_Char *prefix;
02397           XML_Char *uri;
02398           localPart = tag->name.localPart;
02399           if (ns && localPart) {
02400             /* localPart and prefix may have been overwritten in
02401                tag->name.str, since this points to the binding->uri
02402                buffer which gets re-used; so we have to add them again
02403             */
02404             uri = (XML_Char *)tag->name.str + tag->name.uriLen;
02405             /* don't need to check for space - already done in storeAtts() */
02406             while (*localPart) *uri++ = *localPart++;
02407             prefix = (XML_Char *)tag->name.prefix;
02408             if (ns_triplets && prefix) {
02409               *uri++ = namespaceSeparator;
02410               while (*prefix) *uri++ = *prefix++;
02411              }
02412             *uri = XML_T('\0');
02413           }
02414           endElementHandler(handlerArg, tag->name.str);
02415         }
02416         else if (defaultHandler)
02417           reportDefault(parser, enc, s, next);
02418         while (tag->bindings) {
02419           BINDING *b = tag->bindings;
02420           if (endNamespaceDeclHandler)
02421             endNamespaceDeclHandler(handlerArg, b->prefix->name);
02422           tag->bindings = tag->bindings->nextTagBinding;
02423           b->nextTagBinding = freeBindingList;
02424           freeBindingList = b;
02425           b->prefix->binding = b->prevPrefixBinding;
02426         }
02427 /* BEGIN MOZILLA CHANGE (Blocking parser) */
02428         if (blocked) {
02429           *eventPP = next; /* fix bug 119727 */
02430           return XML_ERROR_SUSPENDED;
02431         }
02432 /* END MOZILLA CHANGE */
02433         if (tagLevel == 0)
02434           return epilogProcessor(parser, next, end, nextPtr);
02435       }
02436       break;
02437     case XML_TOK_CHAR_REF:
02438       {
02439         int n = XmlCharRefNumber(enc, s);
02440         if (n < 0)
02441           return XML_ERROR_BAD_CHAR_REF;
02442         if (characterDataHandler) {
02443           XML_Char buf[XML_ENCODE_MAX];
02444           characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
02445         }
02446         else if (defaultHandler)
02447           reportDefault(parser, enc, s, next);
02448       }
02449       break;
02450     case XML_TOK_XML_DECL:
02451       return XML_ERROR_MISPLACED_XML_PI;
02452     case XML_TOK_DATA_NEWLINE:
02453       if (characterDataHandler) {
02454         XML_Char c = 0xA;
02455         characterDataHandler(handlerArg, &c, 1);
02456       }
02457       else if (defaultHandler)
02458         reportDefault(parser, enc, s, next);
02459       break;
02460     case XML_TOK_CDATA_SECT_OPEN:
02461       {
02462         enum XML_Error result;
02463         if (startCdataSectionHandler)
02464           startCdataSectionHandler(handlerArg);
02465 #if 0
02466         /* Suppose you doing a transformation on a document that involves
02467            changing only the character data.  You set up a defaultHandler
02468            and a characterDataHandler.  The defaultHandler simply copies
02469            characters through.  The characterDataHandler does the
02470            transformation and writes the characters out escaping them as
02471            necessary.  This case will fail to work if we leave out the
02472            following two lines (because & and < inside CDATA sections will
02473            be incorrectly escaped).
02474 
02475            However, now we have a start/endCdataSectionHandler, so it seems
02476            easier to let the user deal with this.
02477         */
02478         else if (characterDataHandler)
02479           characterDataHandler(handlerArg, dataBuf, 0);
02480 #endif
02481         else if (defaultHandler)
02482           reportDefault(parser, enc, s, next);
02483         result = doCdataSection(parser, enc, &next, end, nextPtr);
02484         if (!next) {
02485           processor = cdataSectionProcessor;
02486           return result;
02487         }
02488       }
02489       break;
02490     case XML_TOK_TRAILING_RSQB:
02491       if (nextPtr) {
02492         *nextPtr = s;
02493         return XML_ERROR_NONE;
02494       }
02495       if (characterDataHandler) {
02496         if (MUST_CONVERT(enc, s)) {
02497           ICHAR *dataPtr = (ICHAR *)dataBuf;
02498           XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
02499           characterDataHandler(handlerArg, dataBuf,
02500                                dataPtr - (ICHAR *)dataBuf);
02501         }
02502         else
02503           characterDataHandler(handlerArg,
02504                                (XML_Char *)s,
02505                                (XML_Char *)end - (XML_Char *)s);
02506       }
02507       else if (defaultHandler)
02508         reportDefault(parser, enc, s, end);
02509       if (startTagLevel == 0) {
02510         *eventPP = end;
02511         return XML_ERROR_NO_ELEMENTS;
02512       }
02513       if (tagLevel != startTagLevel) {
02514         *eventPP = end;
02515         return XML_ERROR_ASYNC_ENTITY;
02516       }
02517       return XML_ERROR_NONE;
02518     case XML_TOK_DATA_CHARS:
02519       if (characterDataHandler) {
02520         if (MUST_CONVERT(enc, s)) {
02521           for (;;) {
02522             ICHAR *dataPtr = (ICHAR *)dataBuf;
02523             XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
02524             *eventEndPP = s;
02525             characterDataHandler(handlerArg, dataBuf,
02526                                  dataPtr - (ICHAR *)dataBuf);
02527             if (s == next)
02528               break;
02529             *eventPP = s;
02530           }
02531         }
02532         else
02533           characterDataHandler(handlerArg,
02534                                (XML_Char *)s,
02535                                (XML_Char *)next - (XML_Char *)s);
02536       }
02537       else if (defaultHandler)
02538         reportDefault(parser, enc, s, next);
02539       break;
02540     case XML_TOK_PI:
02541 /* BEGIN MOZILLA CHANGE (Blocking parser) */
02542 #if 0
02543       if (!reportProcessingInstruction(parser, enc, s, next))
02544         return XML_ERROR_NO_MEMORY;
02545 #else
02546       if (!reportProcessingInstruction(parser, enc, s, next)) {
02547         if (blocked) {
02548           *eventPP = next;
02549           return XML_ERROR_SUSPENDED;
02550         }
02551         return XML_ERROR_NO_MEMORY;
02552       }
02553 #endif
02554 /* END MOZILLA CHANGE */
02555       break;
02556     case XML_TOK_COMMENT:
02557       if (!reportComment(parser, enc, s, next))
02558         return XML_ERROR_NO_MEMORY;
02559       break;
02560     default:
02561       if (defaultHandler)
02562         reportDefault(parser, enc, s, next);
02563       break;
02564     }
02565     *eventPP = s = next;
02566   }
02567   /* not reached */
02568 }
02569 
02570 /* Precondition: all arguments must be non-NULL;
02571    Purpose:
02572    - normalize attributes
02573    - check attributes for well-formedness
02574    - generate namespace aware attribute names (URI, prefix)
02575    - build list of attributes for startElementHandler
02576    - default attributes
02577    - process namespace declarations (check and report them)
02578    - generate namespace aware element name (URI, prefix)
02579 */
02580 static enum XML_Error
02581 storeAtts(XML_Parser parser, const ENCODING *enc,
02582           const char *attStr, TAG_NAME *tagNamePtr,
02583           BINDING **bindingsPtr)
02584 {
02585   DTD * const dtd = _dtd;  /* save one level of indirection */
02586   ELEMENT_TYPE *elementType;
02587   int nDefaultAtts;
02588   const XML_Char **appAtts;   /* the attribute list for the application */
02589   int attIndex = 0;
02590   int prefixLen;
02591   int i;
02592   int n;
02593   XML_Char *uri;
02594   int nPrefixes = 0;
02595 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
02596   int nXMLNSDeclarations = 0;
02597 /* END MOZILLA CHANGE */
02598   BINDING *binding;
02599   const XML_Char *localPart;
02600 
02601   /* lookup the element type name */
02602   elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0);
02603   if (!elementType) {
02604     const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
02605     if (!name)
02606       return XML_ERROR_NO_MEMORY;
02607     elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name,
02608                                          sizeof(ELEMENT_TYPE));
02609     if (!elementType)
02610       return XML_ERROR_NO_MEMORY;
02611     if (ns && !setElementTypePrefix(parser, elementType))
02612       return XML_ERROR_NO_MEMORY;
02613   }
02614   nDefaultAtts = elementType->nDefaultAtts;
02615 
02616   /* get the attributes from the tokenizer */
02617   n = XmlGetAttributes(enc, attStr, attsSize, atts);
02618   if (n + nDefaultAtts > attsSize) {
02619     int oldAttsSize = attsSize;
02620     ATTRIBUTE *temp;
02621     attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
02622     temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
02623     if (temp == NULL)
02624       return XML_ERROR_NO_MEMORY;
02625     atts = temp;
02626     if (n > oldAttsSize)
02627       XmlGetAttributes(enc, attStr, n, atts);
02628   }
02629 
02630   appAtts = (const XML_Char **)atts;
02631   for (i = 0; i < n; i++) {
02632     /* add the name and value to the attribute list */
02633     ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
02634                                          atts[i].name
02635                                          + XmlNameLength(enc, atts[i].name));
02636     if (!attId)
02637       return XML_ERROR_NO_MEMORY;
02638     /* Detect duplicate attributes by their QNames. This does not work when
02639        namespace processing is turned on and different prefixes for the same
02640        namespace are used. For this case we have a check further down.
02641     */
02642     if ((attId->name)[-1]) {
02643       if (enc == encoding)
02644         eventPtr = atts[i].name;
02645       return XML_ERROR_DUPLICATE_ATTRIBUTE;
02646     }
02647     (attId->name)[-1] = 1;
02648     appAtts[attIndex++] = attId->name;
02649     if (!atts[i].normalized) {
02650       enum XML_Error result;
02651       XML_Bool isCdata = XML_TRUE;
02652 
02653       /* figure out whether declared as other than CDATA */
02654       if (attId->maybeTokenized) {
02655         int j;
02656         for (j = 0; j < nDefaultAtts; j++) {
02657           if (attId == elementType->defaultAtts[j].id) {
02658             isCdata = elementType->defaultAtts[j].isCdata;
02659             break;
02660           }
02661         }
02662       }
02663 
02664       /* normalize the attribute value */
02665       result = storeAttributeValue(parser, enc, isCdata,
02666                                    atts[i].valuePtr, atts[i].valueEnd,
02667                                    &tempPool);
02668       if (result)
02669         return result;
02670       appAtts[attIndex] = poolStart(&tempPool);
02671       poolFinish(&tempPool);
02672     }
02673     else {
02674       /* the value did not need normalizing */
02675       appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
02676                                           atts[i].valueEnd);
02677       if (appAtts[attIndex] == 0)
02678         return XML_ERROR_NO_MEMORY;
02679       poolFinish(&tempPool);
02680     }
02681     /* handle prefixed attribute names */
02682     if (attId->prefix) {
02683       if (attId->xmlns) {
02684         /* deal with namespace declarations here */
02685         enum XML_Error result = addBinding(parser, attId->prefix, attId,
02686                                            appAtts[attIndex], bindingsPtr);
02687         if (result)
02688           return result;
02689 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
02690 #if 0
02691         --attIndex;
02692 #else
02693         attIndex++;
02694         nXMLNSDeclarations++;
02695         (attId->name)[-1] = 3;
02696 #endif
02697 /* END MOZILLA CHANGE */
02698       }
02699       else {
02700         /* deal with other prefixed names later */
02701         attIndex++;
02702         nPrefixes++;
02703         (attId->name)[-1] = 2;
02704       }
02705     }
02706     else
02707       attIndex++;
02708   }
02709 
02710   /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
02711   nSpecifiedAtts = attIndex;
02712   if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
02713     for (i = 0; i < attIndex; i += 2)
02714       if (appAtts[i] == elementType->idAtt->name) {
02715         idAttIndex = i;
02716         break;
02717       }
02718   }
02719   else
02720     idAttIndex = -1;
02721 
02722   /* do attribute defaulting */
02723   for (i = 0; i < nDefaultAtts; i++) {
02724     const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
02725     if (!(da->id->name)[-1] && da->value) {
02726       if (da->id->prefix) {
02727         if (da->id->xmlns) {
02728           enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
02729                                              da->value, bindingsPtr);
02730           if (result)
02731             return result;
02732 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
02733           (da->id->name)[-1] = 3;
02734           nXMLNSDeclarations++;
02735           appAtts[attIndex++] = da->id->name;
02736           appAtts[attIndex++] = da->value;
02737 /* END MOZILLA CHANGE */
02738         }
02739         else {
02740           (da->id->name)[-1] = 2;
02741           nPrefixes++;
02742           appAtts[attIndex++] = da->id->name;
02743           appAtts[attIndex++] = da->value;
02744         }
02745       }
02746       else {
02747         (da->id->name)[-1] = 1;
02748         appAtts[attIndex++] = da->id->name;
02749         appAtts[attIndex++] = da->value;
02750       }
02751     }
02752   }
02753   appAtts[attIndex] = 0;
02754 
02755   /* expand prefixed attribute names, check for duplicates,
02756      and clear flags that say whether attributes were specified */
02757   i = 0;
02758 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
02759 #if 0
02760   if (nPrefixes) {
02761 #else
02762   if (nPrefixes || nXMLNSDeclarations) {
02763 #endif
02764 /* END MOZILLA CHANGE */
02765     int j;  /* hash table index */
02766     unsigned long version = nsAttsVersion;
02767     int nsAttsSize = (int)1 << nsAttsPower;
02768 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
02769     if (nPrefixes) {
02770 /* END MOZILLA CHANGE */
02771     /* size of hash table must be at least 2 * (# of prefixed attributes) */
02772     if ((nPrefixes << 1) >> nsAttsPower) {  /* true for nsAttsPower = 0 */
02773       NS_ATT *temp;
02774       /* hash table size must also be a power of 2 and >= 8 */
02775       while (nPrefixes >> nsAttsPower++);
02776       if (nsAttsPower < 3)
02777         nsAttsPower = 3;
02778       nsAttsSize = (int)1 << nsAttsPower;
02779       temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
02780       if (!temp)
02781         return XML_ERROR_NO_MEMORY;
02782       nsAtts = temp;
02783       version = 0;  /* force re-initialization of nsAtts hash table */
02784     }
02785     /* using a version flag saves us from initializing nsAtts every time */
02786     if (!version) {  /* initialize version flags when version wraps around */
02787       version = INIT_ATTS_VERSION;
02788       for (j = nsAttsSize; j != 0; )
02789         nsAtts[--j].version = version;
02790     }
02791     nsAttsVersion = --version;
02792 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
02793     }
02794 /* END MOZILLA CHANGE */
02795 
02796     /* expand prefixed names and check for duplicates */
02797     for (; i < attIndex; i += 2) {
02798       const XML_Char *s = appAtts[i];
02799       if (s[-1] == 2) {  /* prefixed */
02800         ATTRIBUTE_ID *id;
02801         const BINDING *b;
02802         unsigned long uriHash = 0;
02803         ((XML_Char *)s)[-1] = 0;  /* clear flag */
02804         id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);
02805         b = id->prefix->binding;
02806         if (!b)
02807           return XML_ERROR_UNBOUND_PREFIX;
02808 
02809         /* as we expand the name we also calculate its hash value */
02810         for (j = 0; j < b->uriLen; j++) {
02811           const XML_Char c = b->uri[j];
02812           if (!poolAppendChar(&tempPool, c))
02813             return XML_ERROR_NO_MEMORY;
02814           uriHash = CHAR_HASH(uriHash, c);
02815         }
02816         while (*s++ != XML_T(':'))
02817           ;
02818         do {  /* copies null terminator */
02819           const XML_Char c = *s;
02820           if (!poolAppendChar(&tempPool, *s))
02821             return XML_ERROR_NO_MEMORY;
02822           uriHash = CHAR_HASH(uriHash, c);
02823         } while (*s++);
02824 
02825         { /* Check hash table for duplicate of expanded name (uriName).
02826              Derived from code in lookup(HASH_TABLE *table, ...).
02827           */
02828           unsigned char step = 0;
02829           unsigned long mask = nsAttsSize - 1;
02830           j = uriHash & mask;  /* index into hash table */
02831           while (nsAtts[j].version == version) {
02832             /* for speed we compare stored hash values first */
02833             if (uriHash == nsAtts[j].hash) {
02834               const XML_Char *s1 = poolStart(&tempPool);
02835               const XML_Char *s2 = nsAtts[j].uriName;
02836               /* s1 is null terminated, but not s2 */
02837               for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
02838               if (*s1 == 0)
02839                 return XML_ERROR_DUPLICATE_ATTRIBUTE;
02840             }
02841             if (!step)
02842               step = PROBE_STEP(uriHash, mask, nsAttsPower);
02843             j < step ? ( j += nsAttsSize - step) : (j -= step);
02844           }
02845         }
02846 
02847         if (ns_triplets) {  /* append namespace separator and prefix */
02848           tempPool.ptr[-1] = namespaceSeparator;
02849           s = b->prefix->name;
02850           do {
02851             if (!poolAppendChar(&tempPool, *s))
02852               return XML_ERROR_NO_MEMORY;
02853           } while (*s++);
02854         }
02855 
02856         /* store expanded name in attribute list */
02857         s = poolStart(&tempPool);
02858         poolFinish(&tempPool);
02859         appAtts[i] = s;
02860 
02861         /* fill empty slot with new version, uriName and hash value */
02862         nsAtts[j].version = version;
02863         nsAtts[j].hash = uriHash;
02864         nsAtts[j].uriName = s;
02865 
02866 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
02867 #if 0
02868         if (!--nPrefixes)
02869           break;
02870 #else
02871         if (!--nPrefixes && !nXMLNSDeclarations) {
02872           i += 2;
02873           break;
02874         }
02875 #endif
02876 /* END MOZILLA CHANGE */
02877       }
02878 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
02879       else if (s[-1] == 3) { /* xmlns attribute */
02880         static const XML_Char xmlnsNamespace[] = {
02881           'h', 't', 't', 'p', ':', '/', '/',
02882           'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
02883           '2', '0', '0', '0', '/', 'x', 'm', 'l', 'n', 's', '/', '\0'
02884         };
02885         static const XML_Char xmlnsPrefix[] = {
02886           'x', 'm', 'l', 'n', 's', '\0'
02887         };
02888         XML_Bool appendXMLNS = XML_TRUE;
02889 
02890         ((XML_Char *)s)[-1] = 0;  /* clear flag */
02891         if (!poolAppendString(&tempPool, xmlnsNamespace)
02892             || !poolAppendChar(&tempPool, namespaceSeparator))
02893           return XML_ERROR_NO_MEMORY;
02894         s += sizeof(xmlnsPrefix) / sizeof(xmlnsPrefix[0]) - 1;
02895         if (*s == XML_T(':')) {
02896           ++s;
02897           do {  /* copies null terminator */
02898             if (!poolAppendChar(&tempPool, *s))
02899               return XML_ERROR_NO_MEMORY;
02900           } while (*s++);
02901           if (ns_triplets) { /* append namespace separator and prefix */
02902             tempPool.ptr[-1] = namespaceSeparator;
02903             if (!poolAppendString(&tempPool, xmlnsPrefix)
02904                 || !poolAppendChar(&tempPool, '\0'))
02905               return XML_ERROR_NO_MEMORY;
02906           }
02907         }
02908         else {
02909           /* xlmns attribute without a prefix. */
02910           if (!poolAppendString(&tempPool, xmlnsPrefix)
02911               || !poolAppendChar(&tempPool, '\0'))
02912             return XML_ERROR_NO_MEMORY;
02913         }
02914 
02915         /* store expanded name in attribute list */
02916         s = poolStart(&tempPool);
02917         poolFinish(&tempPool);
02918         appAtts[i] = s;
02919 
02920         if (!--nXMLNSDeclarations && !nPrefixes) {
02921           i += 2;
02922           break;
02923         }
02924       }
02925 /* END MOZILLA CHANGE */
02926       else  /* not prefixed */
02927         ((XML_Char *)s)[-1] = 0;  /* clear flag */
02928     }
02929   }
02930   /* clear flags for the remaining attributes */
02931   for (; i < attIndex; i += 2)
02932     ((XML_Char *)(appAtts[i]))[-1] = 0;
02933   for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
02934     binding->attId->name[-1] = 0;
02935 
02936   if (!ns)
02937     return XML_ERROR_NONE;
02938 
02939   /* expand the element type name */
02940   if (elementType->prefix) {
02941     binding = elementType->prefix->binding;
02942     if (!binding)
02943       return XML_ERROR_UNBOUND_PREFIX;
02944     localPart = tagNamePtr->str;
02945     while (*localPart++ != XML_T(':'))
02946       ;
02947   }
02948   else if (dtd->defaultPrefix.binding) {
02949     binding = dtd->defaultPrefix.binding;
02950     localPart = tagNamePtr->str;
02951   }
02952   else
02953     return XML_ERROR_NONE;
02954   prefixLen = 0;
02955   if (ns_triplets && binding->prefix->name) {
02956     for (; binding->prefix->name[prefixLen++];)
02957       ;
02958   }
02959   tagNamePtr->localPart = localPart;
02960   tagNamePtr->uriLen = binding->uriLen;
02961   tagNamePtr->prefix = binding->prefix->name;
02962   tagNamePtr->prefixLen = prefixLen;
02963   for (i = 0; localPart[i++];)
02964     ;
02965   n = i + binding->uriLen + prefixLen;
02966   if (n > binding->uriAlloc) {
02967     TAG *p;
02968     uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
02969     if (!uri)
02970       return XML_ERROR_NO_MEMORY;
02971     binding->uriAlloc = n + EXPAND_SPARE;
02972     memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
02973     for (p = tagStack; p; p = p->parent)
02974       if (p->name.str == binding->uri)
02975         p->name.str = uri;
02976     FREE(binding->uri);
02977     binding->uri = uri;
02978   }
02979   uri = binding->uri + binding->uriLen;
02980   memcpy(uri, localPart, i * sizeof(XML_Char));
02981   if (prefixLen) {
02982     uri = uri + (i - 1);
02983     if (namespaceSeparator)
02984       *uri = namespaceSeparator;
02985     memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
02986   }
02987   tagNamePtr->str = binding->uri;
02988   return XML_ERROR_NONE;
02989 }
02990 
02991 /* addBinding() overwrites the value of prefix->binding without checking.
02992    Therefore one must keep track of the old value outside of addBinding().
02993 */
02994 static enum XML_Error
02995 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
02996            const XML_Char *uri, BINDING **bindingsPtr)
02997 {
02998 /* BEGIN MOZILLA CHANGE (backport of bug fix from Expat trunk) */
02999   static const XML_Char xmlNamespace[] = {
03000     'h', 't', 't', 'p', ':', '/', '/',
03001     'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
03002     'X', 'M', 'L', '/', '1', '9', '9', '8', '/',
03003     'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0'
03004   };
03005   static const int xmlLen = 
03006     (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
03007   static const XML_Char xmlnsNamespace[] = {
03008     'h', 't', 't', 'p', ':', '/', '/',
03009     'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
03010     '2', '0', '0', '0', '/', 'x', 'm', 'l', 'n', 's', '/', '\0'
03011   };
03012   static const int xmlnsLen = 
03013     (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
03014 
03015   XML_Bool mustBeXML = XML_FALSE;
03016   XML_Bool isXML = XML_TRUE;
03017   XML_Bool isXMLNS = XML_TRUE;
03018 /* END MOZILLA CHANGE */
03019 
03020   BINDING *b;
03021   int len;
03022 
03023   /* empty string is only valid when there is no prefix per XML NS 1.0 */
03024   if (*uri == XML_T('\0') && prefix->name)
03025     return XML_ERROR_SYNTAX;
03026 
03027 /* BEGIN MOZILLA CHANGE (backport of bug fix from Expat trunk) */
03028   if (prefix->name
03029       && prefix->name[0] == XML_T('x')
03030       && prefix->name[1] == XML_T('m')
03031       && prefix->name[2] == XML_T('l')) {
03032 
03033     /* Not allowed to bind xmlns */
03034     if (prefix->name[3] == XML_T('n')
03035         && prefix->name[4] == XML_T('s')
03036         && prefix->name[5] == XML_T('\0'))
03037       return XML_ERROR_RESERVED_PREFIX_XMLNS;
03038 
03039     if (prefix->name[3] == XML_T('\0'))
03040       mustBeXML = XML_TRUE;
03041   }
03042 
03043   for (len = 0; uri[len]; len++) {
03044     if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
03045       isXML = XML_FALSE;
03046 
03047     if (!mustBeXML && isXMLNS 
03048         && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
03049       isXMLNS = XML_FALSE;
03050   }
03051   isXML = isXML && len == xmlLen;
03052   isXMLNS = isXMLNS && len == xmlnsLen;
03053 
03054   if (mustBeXML != isXML)
03055     return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
03056                      : XML_ERROR_RESERVED_NAMESPACE_URI;
03057 
03058   if (isXMLNS)
03059     return XML_ERROR_RESERVED_NAMESPACE_URI;
03060 /* END MOZILLA CHANGE */
03061 
03062   if (namespaceSeparator)
03063     len++;
03064   if (freeBindingList) {
03065     b = freeBindingList;
03066     if (len > b->uriAlloc) {
03067       XML_Char *temp = (XML_Char *)REALLOC(b->uri,
03068                           sizeof(XML_Char) * (len + EXPAND_SPARE));
03069       if (temp == NULL)
03070         return XML_ERROR_NO_MEMORY;
03071       b->uri = temp;
03072       b->uriAlloc = len + EXPAND_SPARE;
03073     }
03074     freeBindingList = b->nextTagBinding;
03075   }
03076   else {
03077     b = (BINDING *)MALLOC(sizeof(BINDING));
03078     if (!b)
03079       return XML_ERROR_NO_MEMORY;
03080     b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
03081     if (!b->uri) {
03082       FREE(b);
03083       return XML_ERROR_NO_MEMORY;
03084     }
03085     b->uriAlloc = len + EXPAND_SPARE;
03086   }
03087   b->uriLen = len;
03088   memcpy(b->uri, uri, len * sizeof(XML_Char));
03089   if (namespaceSeparator)
03090     b->uri[len - 1] = namespaceSeparator;
03091   b->prefix = prefix;
03092   b->attId = attId;
03093   b->prevPrefixBinding = prefix->binding;
03094   /* NULL binding when default namespace undeclared */
03095   if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
03096     prefix->binding = NULL;
03097   else
03098     prefix->binding = b;
03099   b->nextTagBinding = *bindingsPtr;
03100   *bindingsPtr = b;
03101   if (startNamespaceDeclHandler)
03102     startNamespaceDeclHandler(handlerArg, prefix->name,
03103                               prefix->binding ? uri : 0);
03104   return XML_ERROR_NONE;
03105 }
03106 
03107 /* The idea here is to avoid using stack for each CDATA section when
03108    the whole file is parsed with one call.
03109 */
03110 static enum XML_Error PTRCALL
03111 cdataSectionProcessor(XML_Parser parser,
03112                       const char *start,
03113                       const char *end,
03114                       const char **endPtr)
03115 {
03116   enum XML_Error result = doCdataSection(parser, encoding, &start,
03117                                          end, endPtr);
03118   if (start) {
03119     if (parentParser) {  /* we are parsing an external entity */
03120       processor = externalEntityContentProcessor;
03121       return externalEntityContentProcessor(parser, start, end, endPtr);
03122     }
03123     else {
03124       processor = contentProcessor;
03125       return contentProcessor(parser, start, end, endPtr);
03126     }
03127   }
03128   return result;
03129 }
03130 
03131 /* startPtr gets set to non-null is the section is closed, and to null if
03132    the section is not yet closed.
03133 */
03134 static enum XML_Error
03135 doCdataSection(XML_Parser parser,
03136                const ENCODING *enc,
03137                const char **startPtr,
03138                const char *end,
03139                const char **nextPtr)
03140 {
03141   const char *s = *startPtr;
03142   const char **eventPP;
03143   const char **eventEndPP;
03144   if (enc == encoding) {
03145     eventPP = &eventPtr;
03146     *eventPP = s;
03147     eventEndPP = &eventEndPtr;
03148   }
03149   else {
03150     eventPP = &(openInternalEntities->internalEventPtr);
03151     eventEndPP = &(openInternalEntities->internalEventEndPtr);
03152   }
03153   *eventPP = s;
03154   *startPtr = NULL;
03155   for (;;) {
03156     const char *next;
03157     int tok = XmlCdataSectionTok(enc, s, end, &next);
03158     *eventEndPP = next;
03159     switch (tok) {
03160     case XML_TOK_CDATA_SECT_CLOSE:
03161       if (endCdataSectionHandler)
03162         endCdataSectionHandler(handlerArg);
03163 #if 0
03164       /* see comment under XML_TOK_CDATA_SECT_OPEN */
03165       else if (characterDataHandler)
03166         characterDataHandler(handlerArg, dataBuf, 0);
03167 #endif
03168       else if (defaultHandler)
03169         reportDefault(parser, enc, s, next);
03170       *startPtr = next;
03171       return XML_ERROR_NONE;
03172     case XML_TOK_DATA_NEWLINE:
03173       if (characterDataHandler) {
03174         XML_Char c = 0xA;
03175         characterDataHandler(handlerArg, &c, 1);
03176       }
03177       else if (defaultHandler)
03178         reportDefault(parser, enc, s, next);
03179       break;
03180     case XML_TOK_DATA_CHARS:
03181       if (characterDataHandler) {
03182         if (MUST_CONVERT(enc, s)) {
03183           for (;;) {
03184             ICHAR *dataPtr = (ICHAR *)dataBuf;
03185             XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
03186             *eventEndPP = next;
03187             characterDataHandler(handlerArg, dataBuf,
03188                                  dataPtr - (ICHAR *)dataBuf);
03189             if (s == next)
03190               break;
03191             *eventPP = s;
03192           }
03193         }
03194         else
03195           characterDataHandler(handlerArg,
03196                                (XML_Char *)s,
03197                                (XML_Char *)next - (XML_Char *)s);
03198       }
03199       else if (defaultHandler)
03200         reportDefault(parser, enc, s, next);
03201       break;
03202     case XML_TOK_INVALID:
03203       *eventPP = next;
03204       return XML_ERROR_INVALID_TOKEN;
03205     case XML_TOK_PARTIAL_CHAR:
03206       if (nextPtr) {
03207         *nextPtr = s;
03208         return XML_ERROR_NONE;
03209       }
03210       return XML_ERROR_PARTIAL_CHAR;
03211     case XML_TOK_PARTIAL:
03212     case XML_TOK_NONE:
03213       if (nextPtr) {
03214         *nextPtr = s;
03215         return XML_ERROR_NONE;
03216       }
03217       return XML_ERROR_UNCLOSED_CDATA_SECTION;
03218     default:
03219       *eventPP = next;
03220       return XML_ERROR_UNEXPECTED_STATE;
03221     }
03222     *eventPP = s = next;
03223   }
03224   /* not reached */
03225 }
03226 
03227 #ifdef XML_DTD
03228 
03229 /* The idea here is to avoid using stack for each IGNORE section when
03230    the whole file is parsed with one call.
03231 */
03232 static enum XML_Error PTRCALL
03233 ignoreSectionProcessor(XML_Parser parser,
03234                        const char *start,
03235                        const char *end,
03236                        const char **endPtr)
03237 {
03238   enum XML_Error result = doIgnoreSection(parser, encoding, &start,
03239                                           end, endPtr);
03240   if (start) {
03241     processor = prologProcessor;
03242     return prologProcessor(parser, start, end, endPtr);
03243   }
03244   return result;
03245 }
03246 
03247 /* startPtr gets set to non-null is the section is closed, and to null
03248    if the section is not yet closed.
03249 */
03250 static enum XML_Error
03251 doIgnoreSection(XML_Parser parser,
03252                 const ENCODING *enc,
03253                 const char **startPtr,
03254                 const char *end,
03255                 const char **nextPtr)
03256 {
03257   const char *next;
03258   int tok;
03259   const char *s = *startPtr;
03260   const char **eventPP;
03261   const char **eventEndPP;
03262   if (enc == encoding) {
03263     eventPP = &eventPtr;
03264     *eventPP = s;
03265     eventEndPP = &eventEndPtr;
03266   }
03267   else {
03268     eventPP = &(openInternalEntities->internalEventPtr);
03269     eventEndPP = &(openInternalEntities->internalEventEndPtr);
03270   }
03271   *eventPP = s;
03272   *startPtr = NULL;
03273   tok = XmlIgnoreSectionTok(enc, s, end, &next);
03274   *eventEndPP = next;
03275   switch (tok) {
03276   case XML_TOK_IGNORE_SECT:
03277     if (defaultHandler)
03278       reportDefault(parser, enc, s, next);
03279     *startPtr = next;
03280     return XML_ERROR_NONE;
03281   case XML_TOK_INVALID:
03282     *eventPP = next;
03283     return XML_ERROR_INVALID_TOKEN;
03284   case XML_TOK_PARTIAL_CHAR:
03285     if (nextPtr) {
03286       *nextPtr = s;
03287       return XML_ERROR_NONE;
03288     }
03289     return XML_ERROR_PARTIAL_CHAR;
03290   case XML_TOK_PARTIAL:
03291   case XML_TOK_NONE:
03292     if (nextPtr) {
03293       *nextPtr = s;
03294       return XML_ERROR_NONE;
03295     }
03296     return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
03297   default:
03298     *eventPP = next;
03299     return XML_ERROR_UNEXPECTED_STATE;
03300   }
03301   /* not reached */
03302 }
03303 
03304 #endif /* XML_DTD */
03305 
03306 static enum XML_Error
03307 initializeEncoding(XML_Parser parser)
03308 {
03309   const char *s;
03310 #ifdef XML_UNICODE
03311   char encodingBuf[128];
03312   if (!protocolEncodingName)
03313     s = NULL;
03314   else {
03315     int i;
03316     for (i = 0; protocolEncodingName[i]; i++) {
03317       if (i == sizeof(encodingBuf) - 1
03318           || (protocolEncodingName[i] & ~0x7f) != 0) {
03319         encodingBuf[0] = '\0';
03320         break;
03321       }
03322       encodingBuf[i] = (char)protocolEncodingName[i];
03323     }
03324     encodingBuf[i] = '\0';
03325     s = encodingBuf;
03326   }
03327 #else
03328   s = protocolEncodingName;
03329 #endif
03330   if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
03331     return XML_ERROR_NONE;
03332   return handleUnknownEncoding(parser, protocolEncodingName);
03333 }
03334 
03335 static enum XML_Error
03336 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
03337                const char *s, const char *next)
03338 {
03339   const char *encodingName = NULL;
03340   const XML_Char *storedEncName = NULL;
03341   const ENCODING *newEncoding = NULL;
03342   const char *version = NULL;
03343   const char *versionend;
03344   const XML_Char *storedversion = NULL;
03345   int standalone = -1;
03346   if (!(ns
03347         ? XmlParseXmlDeclNS
03348         : XmlParseXmlDecl)(isGeneralTextEntity,
03349                            encoding,
03350                            s,
03351                            next,
03352                            &eventPtr,
03353                            &version,
03354                            &versionend,
03355                            &encodingName,
03356                            &newEncoding,
03357                            &standalone))
03358     return XML_ERROR_SYNTAX;
03359   if (!isGeneralTextEntity && standalone == 1) {
03360     _dtd->standalone = XML_TRUE;
03361 #ifdef XML_DTD
03362     if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
03363       paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
03364 #endif /* XML_DTD */
03365   }
03366   if (xmlDeclHandler) {
03367     if (encodingName != NULL) {
03368       storedEncName = poolStoreString(&temp2Pool,
03369                                       encoding,
03370                                       encodingName,
03371                                       encodingName
03372                                       + XmlNameLength(encoding, encodingName));
03373       if (!storedEncName)
03374               return XML_ERROR_NO_MEMORY;
03375       poolFinish(&temp2Pool);
03376     }
03377     if (version) {
03378       storedversion = poolStoreString(&temp2Pool,
03379                                       encoding,
03380                                       version,
03381                                       versionend - encoding->minBytesPerChar);
03382       if (!storedversion)
03383         return XML_ERROR_NO_MEMORY;
03384     }
03385     xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
03386   }
03387   else if (defaultHandler)
03388     reportDefault(parser, encoding, s, next);
03389   if (protocolEncodingName == NULL) {
03390     if (newEncoding) {
03391       if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
03392         eventPtr = encodingName;
03393         return XML_ERROR_INCORRECT_ENCODING;
03394       }
03395       encoding = newEncoding;
03396     }
03397     else if (encodingName) {
03398       enum XML_Error result;
03399       if (!storedEncName) {
03400         storedEncName = poolStoreString(
03401           &temp2Pool, encoding, encodingName,
03402           encodingName + XmlNameLength(encoding, encodingName));
03403         if (!storedEncName)
03404           return XML_ERROR_NO_MEMORY;
03405       }
03406       result = handleUnknownEncoding(parser, storedEncName);
03407       poolClear(&temp2Pool);
03408       if (result == XML_ERROR_UNKNOWN_ENCODING)
03409         eventPtr = encodingName;
03410       return result;
03411     }
03412   }
03413 
03414   if (storedEncName || storedversion)
03415     poolClear(&temp2Pool);
03416 
03417   return XML_ERROR_NONE;
03418 }
03419 
03420 static enum XML_Error
03421 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
03422 {
03423   if (unknownEncodingHandler) {
03424     XML_Encoding info;
03425     int i;
03426     for (i = 0; i < 256; i++)
03427       info.map[i] = -1;
03428     info.convert = NULL;
03429     info.data = NULL;
03430     info.release = NULL;
03431     if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
03432                                &info)) {
03433       ENCODING *enc;
03434       unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
03435       if (!unknownEncodingMem) {
03436         if (info.release)
03437           info.release(info.data);
03438         return XML_ERROR_NO_MEMORY;
03439       }
03440       enc = (ns
03441              ? XmlInitUnknownEncodingNS
03442              : XmlInitUnknownEncoding)(unknownEncodingMem,
03443                                        info.map,
03444                                        info.convert,
03445                                        info.data);
03446       if (enc) {
03447         unknownEncodingData = info.data;
03448         unknownEncodingRelease = info.release;
03449         encoding = enc;
03450         return XML_ERROR_NONE;
03451       }
03452     }
03453     if (info.release != NULL)
03454       info.release(info.data);
03455   }
03456   return XML_ERROR_UNKNOWN_ENCODING;
03457 }
03458 
03459 static enum XML_Error PTRCALL
03460 prologInitProcessor(XML_Parser parser,
03461                     const char *s,
03462                     const char *end,
03463                     const char **nextPtr)
03464 {
03465   enum XML_Error result = initializeEncoding(parser);
03466   if (result != XML_ERROR_NONE)
03467     return result;
03468   processor = prologProcessor;
03469   return prologProcessor(parser, s, end, nextPtr);
03470 }
03471 
03472 #ifdef XML_DTD
03473 
03474 static enum XML_Error PTRCALL
03475 externalParEntInitProcessor(XML_Parser parser,
03476                             const char *s,
03477                             const char *end,
03478                             const char **nextPtr)
03479 {
03480   enum XML_Error result = initializeEncoding(parser);
03481   if (result != XML_ERROR_NONE)
03482     return result;
03483 
03484   /* we know now that XML_Parse(Buffer) has been called,
03485      so we consider the external parameter entity read */
03486   _dtd->paramEntityRead = XML_TRUE;
03487 
03488   if (prologState.inEntityValue) {
03489     processor = entityValueInitProcessor;
03490     return entityValueInitProcessor(parser, s, end, nextPtr);
03491   }
03492   else {
03493     processor = externalParEntProcessor;
03494     return externalParEntProcessor(parser, s, end, nextPtr);
03495   }
03496 }
03497 
03498 static enum XML_Error PTRCALL
03499 entityValueInitProcessor(XML_Parser parser,
03500                          const char *s,
03501                          const char *end,
03502                          const char **nextPtr)
03503 {
03504   const char *start = s;
03505   const char *next = s;
03506   int tok;
03507 
03508   for (;;) {
03509     tok = XmlPrologTok(encoding, start, end, &next);
03510     if (tok <= 0) {
03511       if (nextPtr != 0 && tok != XML_TOK_INVALID) {
03512               *nextPtr = s;
03513               return XML_ERROR_NONE;
03514       }
03515       switch (tok) {
03516       case XML_TOK_INVALID:
03517               return XML_ERROR_INVALID_TOKEN;
03518       case XML_TOK_PARTIAL:
03519               return XML_ERROR_UNCLOSED_TOKEN;
03520       case XML_TOK_PARTIAL_CHAR:
03521               return XML_ERROR_PARTIAL_CHAR;
03522       case XML_TOK_NONE:   /* start == end */
03523       default:
03524         break;
03525       }
03526       return storeEntityValue(parser, encoding, s, end);
03527     }
03528     else if (tok == XML_TOK_XML_DECL) {
03529       enum XML_Error result = processXmlDecl(parser, 0, start, next);
03530             if (result != XML_ERROR_NONE)
03531               return result;
03532       if (nextPtr) *nextPtr = next;
03533       /* stop scanning for text declaration - we found one */
03534       processor = entityValueProcessor;
03535       return entityValueProcessor(parser, next, end, nextPtr);
03536     }
03537     /* If we are at the end of the buffer, this would cause XmlPrologTok to
03538        return XML_TOK_NONE on the next call, which would then cause the
03539        function to exit with *nextPtr set to s - that is what we want for other
03540        tokens, but not for the BOM - we would rather like to skip it;
03541        then, when this routine is entered the next time, XmlPrologTok will
03542        return XML_TOK_INVALID, since the BOM is still in the buffer
03543     */
03544     else if (tok == XML_TOK_BOM && next == end && nextPtr) {
03545       *nextPtr = next;
03546       return XML_ERROR_NONE;
03547     }
03548     start = next;
03549   }
03550 }
03551 
03552 static enum XML_Error PTRCALL
03553 externalParEntProcessor(XML_Parser parser,
03554                         const char *s,
03555                         const char *end,
03556                         const char **nextPtr)
03557 {
03558   const char *start = s;
03559   const char *next = s;
03560   int tok;
03561 
03562   tok = XmlPrologTok(encoding, start, end, &next);
03563   if (tok <= 0) {
03564     if (nextPtr != 0 && tok != XML_TOK_INVALID) {
03565       *nextPtr = s;
03566       return XML_ERROR_NONE;
03567     }
03568     switch (tok) {
03569     case XML_TOK_INVALID:
03570       return XML_ERROR_INVALID_TOKEN;
03571     case XML_TOK_PARTIAL:
03572       return XML_ERROR_UNCLOSED_TOKEN;
03573     case XML_TOK_PARTIAL_CHAR:
03574       return XML_ERROR_PARTIAL_CHAR;
03575     case XML_TOK_NONE:   /* start == end */
03576     default:
03577       break;
03578     }
03579   }
03580   /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
03581      However, when parsing an external subset, doProlog will not accept a BOM
03582      as valid, and report a syntax error, so we have to skip the BOM
03583   */
03584   else if (tok == XML_TOK_BOM) {
03585     s = next;
03586     tok = XmlPrologTok(encoding, s, end, &next);
03587   }
03588 
03589   processor = prologProcessor;
03590   return doProlog(parser, encoding, s, end, tok, next, nextPtr);
03591 }
03592 
03593 static enum XML_Error PTRCALL
03594 entityValueProcessor(XML_Parser parser,
03595                      const char *s,
03596                      const char *end,
03597                      const char **nextPtr)
03598 {
03599   const char *start = s;
03600   const char *next = s;
03601   const ENCODING *enc = encoding;
03602   int tok;
03603 
03604   for (;;) {
03605     tok = XmlPrologTok(enc, start, end, &next);
03606     if (tok <= 0) {
03607       if (nextPtr != 0 && tok != XML_TOK_INVALID) {
03608         *nextPtr = s;
03609         return XML_ERROR_NONE;
03610       }
03611       switch (tok) {
03612       case XML_TOK_INVALID:
03613               return XML_ERROR_INVALID_TOKEN;
03614       case XML_TOK_PARTIAL:
03615               return XML_ERROR_UNCLOSED_TOKEN;
03616       case XML_TOK_PARTIAL_CHAR:
03617               return XML_ERROR_PARTIAL_CHAR;
03618       case XML_TOK_NONE:   /* start == end */
03619       default:
03620         break;
03621       }
03622       return storeEntityValue(parser, enc, s, end);
03623     }
03624     start = next;
03625   }
03626 }
03627 
03628 #endif /* XML_DTD */
03629 
03630 static enum XML_Error PTRCALL
03631 prologProcessor(XML_Parser parser,
03632                 const char *s,
03633                 const char *end,
03634                 const char **nextPtr)
03635 {
03636   const char *next = s;
03637   int tok = XmlPrologTok(encoding, s, end, &next);
03638   return doProlog(parser, encoding, s, end, tok, next, nextPtr);
03639 }
03640 
03641 static enum XML_Error
03642 doProlog(XML_Parser parser,
03643          const ENCODING *enc,
03644          const char *s,
03645          const char *end,
03646          int tok,
03647          const char *next,
03648          const char **nextPtr)
03649 {
03650 #ifdef XML_DTD
03651   static const XML_Char externalSubsetName[] = { '#' , '\0' };
03652 #endif /* XML_DTD */
03653   static const XML_Char atypeCDATA[] = { 'C', 'D', 'A', 'T', 'A', '\0' };
03654   static const XML_Char atypeID[] = { 'I', 'D', '\0' };
03655   static const XML_Char atypeIDREF[] = { 'I', 'D', 'R', 'E', 'F', '\0' };
03656   static const XML_Char atypeIDREFS[] = { 'I', 'D', 'R', 'E', 'F', 'S', '\0' };
03657   static const XML_Char atypeENTITY[] = { 'E', 'N', 'T', 'I', 'T', 'Y', '\0' };
03658   static const XML_Char atypeENTITIES[] =
03659       { 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S', '\0' };
03660   static const XML_Char atypeNMTOKEN[] = {
03661       'N', 'M', 'T', 'O', 'K', 'E', 'N', '\0' };
03662   static const XML_Char atypeNMTOKENS[] = {
03663       'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S', '\0' };
03664   static const XML_Char notationPrefix[] = {
03665       'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', '(', '\0' };
03666   static const XML_Char enumValueSep[] = { '|', '\0' };
03667   static const XML_Char enumValueStart[] = { '(', '\0' };
03668 
03669   DTD * const dtd = _dtd;  /* save one level of indirection */
03670 
03671   const char **eventPP;
03672   const char **eventEndPP;
03673   enum XML_Content_Quant quant;
03674 
03675   if (enc == encoding) {
03676     eventPP = &eventPtr;
03677     eventEndPP = &eventEndPtr;
03678   }
03679   else {
03680     eventPP = &(openInternalEntities->internalEventPtr);
03681     eventEndPP = &(openInternalEntities->internalEventEndPtr);
03682   }
03683   for (;;) {
03684     int role;
03685     XML_Bool handleDefault = XML_TRUE;
03686     *eventPP = s;
03687     *eventEndPP = next;
03688     if (tok <= 0) {
03689       if (nextPtr != 0 && tok != XML_TOK_INVALID) {
03690         *nextPtr = s;
03691         return XML_ERROR_NONE;
03692       }
03693       switch (tok) {
03694       case XML_TOK_INVALID:
03695         *eventPP = next;
03696         return XML_ERROR_INVALID_TOKEN;
03697       case XML_TOK_PARTIAL:
03698         return XML_ERROR_UNCLOSED_TOKEN;
03699       case XML_TOK_PARTIAL_CHAR:
03700         return XML_ERROR_PARTIAL_CHAR;
03701       case XML_TOK_NONE:
03702 #ifdef XML_DTD
03703         if (enc != encoding)
03704           return XML_ERROR_NONE;
03705         if (isParamEntity) {
03706           if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
03707               == XML_ROLE_ERROR)
03708             return XML_ERROR_SYNTAX;
03709           return XML_ERROR_NONE;
03710         }
03711 #endif /* XML_DTD */
03712         return XML_ERROR_NO_ELEMENTS;
03713       default:
03714         tok = -tok;
03715         next = end;
03716         break;
03717       }
03718     }
03719     role = XmlTokenRole(&prologState, tok, s, next, enc);
03720     switch (role) {
03721     case XML_ROLE_XML_DECL:
03722       {
03723         enum XML_Error result = processXmlDecl(parser, 0, s, next);
03724         if (result != XML_ERROR_NONE)
03725           return result;
03726         enc = encoding;
03727         handleDefault = XML_FALSE;
03728       }
03729       break;
03730     case XML_ROLE_DOCTYPE_NAME:
03731       if (startDoctypeDeclHandler) {
03732         doctypeName = poolStoreString(&tempPool, enc, s, next);
03733         if (!doctypeName)
03734           return XML_ERROR_NO_MEMORY;
03735         poolFinish(&tempPool);
03736         doctypePubid = NULL;
03737         handleDefault = XML_FALSE;
03738       }
03739       doctypeSysid = NULL; /* always initialize to NULL */
03740       break;
03741     case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
03742       if (startDoctypeDeclHandler) {
03743         startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
03744                                 doctypePubid, 1);
03745         doctypeName = NULL;
03746         poolClear(&tempPool);
03747         handleDefault = XML_FALSE;
03748       }
03749       break;
03750 #ifdef XML_DTD
03751     case XML_ROLE_TEXT_DECL:
03752       {
03753         enum XML_Error result = processXmlDecl(parser, 1, s, next);
03754         if (result != XML_ERROR_NONE)
03755           return result;
03756         enc = encoding;
03757         handleDefault = XML_FALSE;
03758       }
03759       break;
03760 #endif /* XML_DTD */
03761     case XML_ROLE_DOCTYPE_PUBLIC_ID:
03762 #ifdef XML_DTD
03763       useForeignDTD = XML_FALSE;
03764 #endif /* XML_DTD */
03765       dtd->hasParamEntityRefs = XML_TRUE;
03766       if (startDoctypeDeclHandler) {
03767         doctypePubid = poolStoreString(&tempPool, enc,
03768                                        s + enc->minBytesPerChar,
03769                                        next - enc->minBytesPerChar);
03770         if (!doctypePubid)
03771           return XML_ERROR_NO_MEMORY;
03772         poolFinish(&tempPool);
03773         handleDefault = XML_FALSE;
03774       }
03775 #ifdef XML_DTD
03776       declEntity = (ENTITY *)lookup(&dtd->paramEntities,
03777                                     externalSubsetName,
03778                                     sizeof(ENTITY));
03779       if (!declEntity)
03780         return XML_ERROR_NO_MEMORY;
03781 #endif /* XML_DTD */
03782       /* fall through */
03783     case XML_ROLE_ENTITY_PUBLIC_ID:
03784       if (!XmlIsPublicId(enc, s, next, eventPP))
03785         return XML_ERROR_SYNTAX;
03786       if (dtd->keepProcessing && declEntity) {
03787         XML_Char *tem = poolStoreString(&dtd->pool,
03788                                         enc,
03789                                         s + enc->minBytesPerChar,
03790                                         next - enc->minBytesPerChar);
03791         if (!tem)
03792           return XML_ERROR_NO_MEMORY;
03793         normalizePublicId(tem);
03794         declEntity->publicId = tem;
03795         poolFinish(&dtd->pool);
03796         if (entityDeclHandler)
03797           handleDefault = XML_FALSE;
03798       }
03799       break;
03800     case XML_ROLE_DOCTYPE_CLOSE:
03801       if (doctypeName) {
03802         startDoctypeDeclHandler(handlerArg, doctypeName,
03803                                 doctypeSysid, doctypePubid, 0);
03804         poolClear(&tempPool);
03805         handleDefault = XML_FALSE;
03806       }
03807       /* doctypeSysid will be non-NULL in the case of a previous
03808          XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
03809          was not set, indicating an external subset
03810       */
03811 #ifdef XML_DTD
03812       if (doctypeSysid || useForeignDTD) {
03813         dtd->hasParamEntityRefs = XML_TRUE; /* when docTypeSysid == NULL */
03814         if (paramEntityParsing && externalEntityRefHandler) {
03815           ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
03816                                             externalSubsetName,
03817                                             sizeof(ENTITY));
03818           if (!entity)
03819             return XML_ERROR_NO_MEMORY;
03820           if (useForeignDTD)
03821             entity->base = curBase;
03822           dtd->paramEntityRead = XML_FALSE;
03823           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
03824                                         0,
03825                                         entity->base,
03826                                         entity->systemId,
03827                                         entity->publicId))
03828             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
03829           if (dtd->paramEntityRead &&
03830               !dtd->standalone &&
03831               notStandaloneHandler &&
03832               !notStandaloneHandler(handlerArg))
03833             return XML_ERROR_NOT_STANDALONE;
03834           /* end of DTD - no need to update dtd->keepProcessing */
03835         }
03836         useForeignDTD = XML_FALSE;
03837       }
03838 #endif /* XML_DTD */
03839       if (endDoctypeDeclHandler) {
03840         endDoctypeDeclHandler(handlerArg);
03841         handleDefault = XML_FALSE;
03842       }
03843       break;
03844     case XML_ROLE_INSTANCE_START:
03845 #ifdef XML_DTD
03846       /* if there is no DOCTYPE declaration then now is the
03847          last chance to read the foreign DTD
03848       */
03849       if (useForeignDTD) {
03850         dtd->hasParamEntityRefs = XML_TRUE;
03851         if (paramEntityParsing && externalEntityRefHandler) {
03852           ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
03853                                             externalSubsetName,
03854                                             sizeof(ENTITY));
03855           if (!entity)
03856             return XML_ERROR_NO_MEMORY;
03857           entity->base = curBase;
03858           dtd->paramEntityRead = XML_FALSE;
03859           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
03860                                         0,
03861                                         entity->base,
03862                                         entity->systemId,
03863                                         entity->publicId))
03864             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
03865           if (dtd->paramEntityRead &&
03866               !dtd->standalone &&
03867               notStandaloneHandler &&
03868               !notStandaloneHandler(handlerArg))
03869             return XML_ERROR_NOT_STANDALONE;
03870           /* end of DTD - no need to update dtd->keepProcessing */
03871         }
03872       }
03873 #endif /* XML_DTD */
03874       processor = contentProcessor;
03875       return contentProcessor(parser, s, end, nextPtr);
03876     case XML_ROLE_ATTLIST_ELEMENT_NAME:
03877       declElementType = getElementType(parser, enc, s, next);
03878       if (!declElementType)
03879         return XML_ERROR_NO_MEMORY;
03880       goto checkAttListDeclHandler;
03881     case XML_ROLE_ATTRIBUTE_NAME:
03882       declAttributeId = getAttributeId(parser, enc, s, next);
03883       if (!declAttributeId)
03884         return XML_ERROR_NO_MEMORY;
03885       declAttributeIsCdata = XML_FALSE;
03886       declAttributeType = NULL;
03887       declAttributeIsId = XML_FALSE;
03888       goto checkAttListDeclHandler;
03889     case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
03890       declAttributeIsCdata = XML_TRUE;
03891       declAttributeType = atypeCDATA;
03892       goto checkAttListDeclHandler;
03893     case XML_ROLE_ATTRIBUTE_TYPE_ID:
03894       declAttributeIsId = XML_TRUE;
03895       declAttributeType = atypeID;
03896       goto checkAttListDeclHandler;
03897     case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
03898       declAttributeType = atypeIDREF;
03899       goto checkAttListDeclHandler;
03900     case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
03901       declAttributeType = atypeIDREFS;
03902       goto checkAttListDeclHandler;
03903     case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
03904       declAttributeType = atypeENTITY;
03905       goto checkAttListDeclHandler;
03906     case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
03907       declAttributeType = atypeENTITIES;
03908       goto checkAttListDeclHandler;
03909     case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
03910       declAttributeType = atypeNMTOKEN;
03911       goto checkAttListDeclHandler;
03912     case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
03913       declAttributeType = atypeNMTOKENS;
03914     checkAttListDeclHandler:
03915       if (dtd->keepProcessing && attlistDeclHandler)
03916         handleDefault = XML_FALSE;
03917       break;
03918     case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
03919     case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
03920       if (dtd->keepProcessing && attlistDeclHandler) {
03921         const XML_Char *prefix;
03922         if (declAttributeType) {
03923           prefix = enumValueSep;
03924         }
03925         else {
03926           prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
03927                     ? notationPrefix
03928                     : enumValueStart);
03929         }
03930         if (!poolAppendString(&tempPool, prefix))
03931           return XML_ERROR_NO_MEMORY;
03932         if (!poolAppend(&tempPool, enc, s, next))
03933           return XML_ERROR_NO_MEMORY;
03934         declAttributeType = tempPool.start;
03935         handleDefault = XML_FALSE;
03936       }
03937       break;
03938     case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
03939     case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
03940       if (dtd->keepProcessing) {
03941         if (!defineAttribute(declElementType, declAttributeId,
03942                              declAttributeIsCdata, declAttributeIsId,
03943                              0, parser))
03944           return XML_ERROR_NO_MEMORY;
03945         if (attlistDeclHandler && declAttributeType) {
03946           if (*declAttributeType == XML_T('(')
03947               || (*declAttributeType == XML_T('N')
03948                   && declAttributeType[1] == XML_T('O'))) {
03949             /* Enumerated or Notation type */
03950             if (!poolAppendChar(&tempPool, XML_T(')'))
03951                 || !poolAppendChar(&tempPool, XML_T('\0')))
03952               return XML_ERROR_NO_MEMORY;
03953             declAttributeType = tempPool.start;
03954             poolFinish(&tempPool);
03955           }
03956           *eventEndPP = s;
03957           attlistDeclHandler(handlerArg, declElementType->name,
03958                              declAttributeId->name, declAttributeType,
03959                              0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
03960           poolClear(&tempPool);
03961           handleDefault = XML_FALSE;
03962         }
03963       }
03964       break;
03965     case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
03966     case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
03967       if (dtd->keepProcessing) {
03968         const XML_Char *attVal;
03969         enum XML_Error result =
03970           storeAttributeValue(parser, enc, declAttributeIsCdata,
03971                               s + enc->minBytesPerChar,
03972                               next - enc->minBytesPerChar,
03973                               &dtd->pool);
03974         if (result)
03975           return result;
03976         attVal = poolStart(&dtd->pool);
03977         poolFinish(&dtd->pool);
03978         /* ID attributes aren't allowed to have a default */
03979         if (!defineAttribute(declElementType, declAttributeId,
03980                              declAttributeIsCdata, XML_FALSE, attVal, parser))
03981           return XML_ERROR_NO_MEMORY;
03982         if (attlistDeclHandler && declAttributeType) {
03983           if (*declAttributeType == XML_T('(')
03984               || (*declAttributeType == XML_T('N')
03985                   && declAttributeType[1] == XML_T('O'))) {
03986             /* Enumerated or Notation type */
03987             if (!poolAppendChar(&tempPool, XML_T(')'))
03988                 || !poolAppendChar(&tempPool, XML_T('\0')))
03989               return XML_ERROR_NO_MEMORY;
03990             declAttributeType = tempPool.start;
03991             poolFinish(&tempPool);
03992           }
03993           *eventEndPP = s;
03994           attlistDeclHandler(handlerArg, declElementType->name,
03995                              declAttributeId->name, declAttributeType,
03996                              attVal,
03997                              role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
03998           poolClear(&tempPool);
03999           handleDefault = XML_FALSE;
04000         }
04001       }
04002       break;
04003     case XML_ROLE_ENTITY_VALUE:
04004       if (dtd->keepProcessing) {
04005         enum XML_Error result = storeEntityValue(parser, enc,
04006                                             s + enc->minBytesPerChar,
04007                                             next - enc->minBytesPerChar);
04008         if (declEntity) {
04009           declEntity->textPtr = poolStart(&dtd->entityValuePool);
04010           declEntity->textLen = poolLength(&dtd->entityValuePool);
04011           poolFinish(&dtd->entityValuePool);
04012           if (entityDeclHandler) {
04013             *eventEndPP = s;
04014             entityDeclHandler(handlerArg,
04015                               declEntity->name,
04016                               declEntity->is_param,
04017                               declEntity->textPtr,
04018                               declEntity->textLen,
04019                               curBase, 0, 0, 0);
04020             handleDefault = XML_FALSE;
04021           }
04022         }
04023         else
04024           poolDiscard(&dtd->entityValuePool);
04025         if (result != XML_ERROR_NONE)
04026           return result;
04027       }
04028       break;
04029     case XML_ROLE_DOCTYPE_SYSTEM_ID:
04030 #ifdef XML_DTD
04031       useForeignDTD = XML_FALSE;
04032 #endif /* XML_DTD */
04033       dtd->hasParamEntityRefs = XML_TRUE;
04034       if (startDoctypeDeclHandler) {
04035         doctypeSysid = poolStoreString(&tempPool, enc,
04036                                        s + enc->minBytesPerChar,
04037                                        next - enc->minBytesPerChar);
04038         if (doctypeSysid == NULL)
04039           return XML_ERROR_NO_MEMORY;
04040         poolFinish(&tempPool);
04041         handleDefault = XML_FALSE;
04042       }
04043 #ifdef XML_DTD
04044       else
04045         /* use externalSubsetName to make doctypeSysid non-NULL
04046            for the case where no startDoctypeDeclHandler is set */
04047         doctypeSysid = externalSubsetName;
04048 #endif /* XML_DTD */
04049       if (!dtd->standalone
04050 #ifdef XML_DTD
04051           && !paramEntityParsing
04052 #endif /* XML_DTD */
04053           && notStandaloneHandler
04054           && !notStandaloneHandler(handlerArg))
04055         return XML_ERROR_NOT_STANDALONE;
04056 #ifndef XML_DTD
04057       break;
04058 #else /* XML_DTD */
04059       if (!declEntity) {
04060         declEntity = (ENTITY *)lookup(&dtd->paramEntities,
04061                                       externalSubsetName,
04062                                       sizeof(ENTITY));
04063         if (!declEntity)
04064           return XML_ERROR_NO_MEMORY;
04065         declEntity->publicId = NULL;
04066       }
04067       /* fall through */
04068 #endif /* XML_DTD */
04069     case XML_ROLE_ENTITY_SYSTEM_ID:
04070       if (dtd->keepProcessing && declEntity) {
04071         declEntity->systemId = poolStoreString(&dtd->pool, enc,
04072                                                s + enc->minBytesPerChar,
04073                                                next - enc->minBytesPerChar);
04074         if (!declEntity->systemId)
04075           return XML_ERROR_NO_MEMORY;
04076         declEntity->base = curBase;
04077         poolFinish(&dtd->pool);
04078         if (entityDeclHandler)
04079           handleDefault = XML_FALSE;
04080       }
04081       break;
04082     case XML_ROLE_ENTITY_COMPLETE:
04083       if (dtd->keepProcessing && declEntity && entityDeclHandler) {
04084         *eventEndPP = s;
04085         entityDeclHandler(handlerArg,
04086                           declEntity->name,
04087                           declEntity->is_param,
04088                           0,0,
04089                           declEntity->base,
04090                           declEntity->systemId,
04091                           declEntity->publicId,
04092                           0);
04093         handleDefault = XML_FALSE;
04094       }
04095       break;
04096     case XML_ROLE_ENTITY_NOTATION_NAME:
04097       if (dtd->keepProcessing && declEntity) {
04098         declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
04099         if (!declEntity->notation)
04100           return XML_ERROR_NO_MEMORY;
04101         poolFinish(&dtd->pool);
04102         if (unparsedEntityDeclHandler) {
04103           *eventEndPP = s;
04104           unparsedEntityDeclHandler(handlerArg,
04105                                     declEntity->name,
04106                                     declEntity->base,
04107                                     declEntity->systemId,
04108                                     declEntity->publicId,
04109                                     declEntity->notation);
04110           handleDefault = XML_FALSE;
04111         }
04112         else if (entityDeclHandler) {
04113           *eventEndPP = s;
04114           entityDeclHandler(handlerArg,
04115                             declEntity->name,
04116                             0,0,0,
04117                             declEntity->base,
04118                             declEntity->systemId,
04119                             declEntity->publicId,
04120                             declEntity->notation);
04121           handleDefault = XML_FALSE;
04122         }
04123       }
04124       break;
04125     case XML_ROLE_GENERAL_ENTITY_NAME:
04126       {
04127         if (XmlPredefinedEntityName(enc, s, next)) {
04128           declEntity = NULL;
04129           break;
04130         }
04131         if (dtd->keepProcessing) {
04132           const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
04133           if (!name)
04134             return XML_ERROR_NO_MEMORY;
04135           declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
04136                                         sizeof(ENTITY));
04137           if (!declEntity)
04138             return XML_ERROR_NO_MEMORY;
04139           if (declEntity->name != name) {
04140             poolDiscard(&dtd->pool);
04141             declEntity = NULL;
04142           }
04143           else {
04144             poolFinish(&dtd->pool);
04145             declEntity->publicId = NULL;
04146             declEntity->is_param = XML_FALSE;
04147             /* if we have a parent parser or are reading an internal parameter
04148                entity, then the entity declaration is not considered "internal"
04149             */
04150             declEntity->is_internal = !(parentParser || openInternalEntities);
04151             if (entityDeclHandler)
04152               handleDefault = XML_FALSE;
04153           }
04154         }
04155         else {
04156           poolDiscard(&dtd->pool);
04157           declEntity = NULL;
04158         }
04159       }
04160       break;
04161     case XML_ROLE_PARAM_ENTITY_NAME:
04162 #ifdef XML_DTD
04163       if (dtd->keepProcessing) {
04164         const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
04165         if (!name)
04166           return XML_ERROR_NO_MEMORY;
04167         declEntity = (ENTITY *)lookup(&dtd->paramEntities,
04168                                            name, sizeof(ENTITY));
04169         if (!declEntity)
04170           return XML_ERROR_NO_MEMORY;
04171         if (declEntity->name != name) {
04172           poolDiscard(&dtd->pool);
04173           declEntity = NULL;
04174         }
04175         else {
04176           poolFinish(&dtd->pool);
04177           declEntity->publicId = NULL;
04178           declEntity->is_param = XML_TRUE;
04179           /* if we have a parent parser or are reading an internal parameter
04180              entity, then the entity declaration is not considered "internal"
04181           */
04182           declEntity->is_internal = !(parentParser || openInternalEntities);
04183           if (entityDeclHandler)
04184             handleDefault = XML_FALSE;
04185         }
04186       }
04187       else {
04188         poolDiscard(&dtd->pool);
04189         declEntity = NULL;
04190       }
04191 #else /* not XML_DTD */
04192       declEntity = NULL;
04193 #endif /* XML_DTD */
04194       break;
04195     case XML_ROLE_NOTATION_NAME:
04196       declNotationPublicId = NULL;
04197       declNotationName = NULL;
04198       if (notationDeclHandler) {
04199         declNotationName = poolStoreString(&tempPool, enc, s, next);
04200         if (!declNotationName)
04201           return XML_ERROR_NO_MEMORY;
04202         poolFinish(&tempPool);
04203         handleDefault = XML_FALSE;
04204       }
04205       break;
04206     case XML_ROLE_NOTATION_PUBLIC_ID:
04207       if (!XmlIsPublicId(enc, s, next, eventPP))
04208         return XML_ERROR_SYNTAX;
04209       if (declNotationName) {  /* means notationDeclHandler != NULL */
04210         XML_Char *tem = poolStoreString(&tempPool,
04211                                         enc,
04212                                         s + enc->minBytesPerChar,
04213                                         next - enc->minBytesPerChar);
04214         if (!tem)
04215           return XML_ERROR_NO_MEMORY;
04216         normalizePublicId(tem);
04217         declNotationPublicId = tem;
04218         poolFinish(&tempPool);
04219         handleDefault = XML_FALSE;
04220       }
04221       break;
04222     case XML_ROLE_NOTATION_SYSTEM_ID:
04223       if (declNotationName && notationDeclHandler) {
04224         const XML_Char *systemId
04225           = poolStoreString(&tempPool, enc,
04226                             s + enc->minBytesPerChar,
04227                             next - enc->minBytesPerChar);
04228         if (!systemId)
04229           return XML_ERROR_NO_MEMORY;
04230         *eventEndPP = s;
04231         notationDeclHandler(handlerArg,
04232                             declNotationName,
04233                             curBase,
04234                             systemId,
04235                             declNotationPublicId);
04236         handleDefault = XML_FALSE;
04237       }
04238       poolClear(&tempPool);
04239       break;
04240     case XML_ROLE_NOTATION_NO_SYSTEM_ID:
04241       if (declNotationPublicId && notationDeclHandler) {
04242         *eventEndPP = s;
04243         notationDeclHandler(handlerArg,
04244                             declNotationName,
04245                             curBase,
04246                             0,
04247                             declNotationPublicId);
04248         handleDefault = XML_FALSE;
04249       }
04250       poolClear(&tempPool);
04251       break;
04252     case XML_ROLE_ERROR:
04253       switch (tok) {
04254       case XML_TOK_PARAM_ENTITY_REF:
04255         return XML_ERROR_PARAM_ENTITY_REF;
04256       case XML_TOK_XML_DECL:
04257         return XML_ERROR_MISPLACED_XML_PI;
04258       default:
04259         return XML_ERROR_SYNTAX;
04260       }
04261 #ifdef XML_DTD
04262     case XML_ROLE_IGNORE_SECT:
04263       {
04264         enum XML_Error result;
04265         if (defaultHandler)
04266           reportDefault(parser, enc, s, next);
04267         handleDefault = XML_FALSE;
04268         result = doIgnoreSection(parser, enc, &next, end, nextPtr);
04269         if (!next) {
04270           processor = ignoreSectionProcessor;
04271           return result;
04272         }
04273       }
04274       break;
04275 #endif /* XML_DTD */
04276     case XML_ROLE_GROUP_OPEN:
04277       if (prologState.level >= groupSize) {
04278         if (groupSize) {
04279           char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
04280           if (temp == NULL)
04281             return XML_ERROR_NO_MEMORY;
04282           groupConnector = temp;
04283           if (dtd->scaffIndex) {
04284             int *temp = (int *)REALLOC(dtd->scaffIndex,
04285                           groupSize * sizeof(int));
04286             if (temp == NULL)
04287               return XML_ERROR_NO_MEMORY;
04288             dtd->scaffIndex = temp;
04289           }
04290         }
04291         else {
04292           groupConnector = (char *)MALLOC(groupSize = 32);
04293           if (!groupConnector)
04294             return XML_ERROR_NO_MEMORY;
04295         }
04296       }
04297       groupConnector[prologState.level] = 0;
04298       if (dtd->in_eldecl) {
04299         int myindex = nextScaffoldPart(parser);
04300         if (myindex < 0)
04301           return XML_ERROR_NO_MEMORY;
04302         dtd->scaffIndex[dtd->scaffLevel] = myindex;
04303         dtd->scaffLevel++;
04304         dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
04305         if (elementDeclHandler)
04306           handleDefault = XML_FALSE;
04307       }
04308       break;
04309     case XML_ROLE_GROUP_SEQUENCE:
04310       if (groupConnector[prologState.level] == '|')
04311         return XML_ERROR_SYNTAX;
04312       groupConnector[prologState.level] = ',';
04313       if (dtd->in_eldecl && elementDeclHandler)
04314         handleDefault = XML_FALSE;
04315       break;
04316     case XML_ROLE_GROUP_CHOICE:
04317       if (groupConnector[prologState.level] == ',')
04318         return XML_ERROR_SYNTAX;
04319       if (dtd->in_eldecl
04320           && !groupConnector[prologState.level]
04321           && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
04322               != XML_CTYPE_MIXED)
04323           ) {
04324         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
04325             = XML_CTYPE_CHOICE;
04326         if (elementDeclHandler)
04327           handleDefault = XML_FALSE;
04328       }
04329       groupConnector[prologState.level] = '|';
04330       break;
04331     case XML_ROLE_PARAM_ENTITY_REF:
04332 #ifdef XML_DTD
04333     case XML_ROLE_INNER_PARAM_ENTITY_REF:
04334       /* PE references in internal subset are
04335          not allowed within declarations      */
04336       if (prologState.documentEntity &&
04337           role == XML_ROLE_INNER_PARAM_ENTITY_REF)
04338         return XML_ERROR_PARAM_ENTITY_REF;
04339       dtd->hasParamEntityRefs = XML_TRUE;
04340       if (!paramEntityParsing)
04341         dtd->keepProcessing = dtd->standalone;
04342       else {
04343         const XML_Char *name;
04344         ENTITY *entity;
04345         name = poolStoreString(&dtd->pool, enc,
04346                                 s + enc->minBytesPerChar,
04347                                 next - enc->minBytesPerChar);
04348         if (!name)
04349           return XML_ERROR_NO_MEMORY;
04350         entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
04351         poolDiscard(&dtd->pool);
04352         /* first, determine if a check for an existing declaration is needed;
04353            if yes, check that the entity exists, and that it is internal,
04354            otherwise call the skipped entity handler
04355         */
04356         if (prologState.documentEntity &&
04357             (dtd->standalone
04358              ? !openInternalEntities
04359              : !dtd->hasParamEntityRefs)) {
04360           if (!entity)
04361             return XML_ERROR_UNDEFINED_ENTITY;
04362           else if (!entity->is_internal)
04363             return XML_ERROR_ENTITY_DECLARED_IN_PE;
04364         }
04365         else if (!entity) {
04366           dtd->keepProcessing = dtd->standalone;
04367           /* cannot report skipped entities in declarations */
04368           if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
04369             skippedEntityHandler(handlerArg, name, 1);
04370             handleDefault = XML_FALSE;
04371           }
04372           break;
04373         }
04374         if (entity->open)
04375           return XML_ERROR_RECURSIVE_ENTITY_REF;
04376         if (entity->textPtr) {
04377           enum XML_Error result;
04378           result = processInternalParamEntity(parser, entity);
04379           if (result != XML_ERROR_NONE)
04380             return result;
04381           handleDefault = XML_FALSE;
04382           break;
04383         }
04384         if (externalEntityRefHandler) {
04385           dtd->paramEntityRead = XML_FALSE;
04386           entity->open = XML_TRUE;
04387           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
04388 /* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=191482) */
04389 #if 0
04390                                         0,
04391 #else
04392                                         entity->name,
04393 #endif
04394 /* END MOZILLA CHANGE */
04395                                         entity->base,
04396                                         entity->systemId,
04397                                         entity->publicId)) {
04398             entity->open = XML_FALSE;
04399             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
04400           }
04401           entity->open = XML_FALSE;
04402           handleDefault = XML_FALSE;
04403           if (!dtd->paramEntityRead) {
04404             dtd->keepProcessing = dtd->standalone;
04405             break;
04406           }
04407         }
04408         else {
04409           dtd->keepProcessing = dtd->standalone;
04410           break;
04411         }
04412       }
04413 #endif /* XML_DTD */
04414       if (!dtd->standalone &&
04415           notStandaloneHandler &&
04416           !notStandaloneHandler(handlerArg))
04417         return XML_ERROR_NOT_STANDALONE;
04418       break;
04419 
04420     /* Element declaration stuff */
04421 
04422     case XML_ROLE_ELEMENT_NAME:
04423       if (elementDeclHandler) {
04424         declElementType = getElementType(parser, enc, s, next);
04425         if (!declElementType)
04426           return XML_ERROR_NO_MEMORY;
04427         dtd->scaffLevel = 0;
04428         dtd->scaffCount = 0;
04429         dtd->in_eldecl = XML_TRUE;
04430         handleDefault = XML_FALSE;
04431       }
04432       break;
04433 
04434     case XML_ROLE_CONTENT_ANY:
04435     case XML_ROLE_CONTENT_EMPTY:
04436       if (dtd->in_eldecl) {
04437         if (elementDeclHandler) {
04438           XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
04439           if (!content)
04440             return XML_ERROR_NO_MEMORY;
04441           content->quant = XML_CQUANT_NONE;
04442           content->name = NULL;
04443           content->numchildren = 0;
04444           content->children = NULL;
04445           content->type = ((role == XML_ROLE_CONTENT_ANY) ?
04446                            XML_CTYPE_ANY :
04447                            XML_CTYPE_EMPTY);
04448           *eventEndPP = s;
04449           elementDeclHandler(handlerArg, declElementType->name, content);
04450           handleDefault = XML_FALSE;
04451         }
04452         dtd->in_eldecl = XML_FALSE;
04453       }
04454       break;
04455 
04456     case XML_ROLE_CONTENT_PCDATA:
04457       if (dtd->in_eldecl) {
04458         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
04459             = XML_CTYPE_MIXED;
04460         if (elementDeclHandler)
04461           handleDefault = XML_FALSE;
04462       }
04463       break;
04464 
04465     case XML_ROLE_CONTENT_ELEMENT:
04466       quant = XML_CQUANT_NONE;
04467       goto elementContent;
04468     case XML_ROLE_CONTENT_ELEMENT_OPT:
04469       quant = XML_CQUANT_OPT;
04470       goto elementContent;
04471     case XML_ROLE_CONTENT_ELEMENT_REP:
04472       quant = XML_CQUANT_REP;
04473       goto elementContent;
04474     case XML_ROLE_CONTENT_ELEMENT_PLUS:
04475       quant = XML_CQUANT_PLUS;
04476     elementContent:
04477       if (dtd->in_eldecl) {
04478         ELEMENT_TYPE *el;
04479         const XML_Char *name;
04480         int nameLen;
04481         const char *nxt = (quant == XML_CQUANT_NONE
04482                            ? next
04483                            : next - enc->minBytesPerChar);
04484         int myindex = nextScaffoldPart(parser);
04485         if (myindex < 0)
04486           return XML_ERROR_NO_MEMORY;
04487         dtd->scaffold[myindex].type = XML_CTYPE_NAME;
04488         dtd->scaffold[myindex].quant = quant;
04489         el = getElementType(parser, enc, s, nxt);
04490         if (!el)
04491           return XML_ERROR_NO_MEMORY;
04492         name = el->name;
04493         dtd->scaffold[myindex].name = name;
04494         nameLen = 0;
04495         for (; name[nameLen++]; );
04496         dtd->contentStringLen +=  nameLen;
04497         if (elementDeclHandler)
04498           handleDefault = XML_FALSE;
04499       }
04500       break;
04501 
04502     case XML_ROLE_GROUP_CLOSE:
04503       quant = XML_CQUANT_NONE;
04504       goto closeGroup;
04505     case XML_ROLE_GROUP_CLOSE_OPT:
04506       quant = XML_CQUANT_OPT;
04507       goto closeGroup;
04508     case XML_ROLE_GROUP_CLOSE_REP:
04509       quant = XML_CQUANT_REP;
04510       goto closeGroup;
04511     case XML_ROLE_GROUP_CLOSE_PLUS:
04512       quant = XML_CQUANT_PLUS;
04513     closeGroup:
04514       if (dtd->in_eldecl) {
04515         if (elementDeclHandler)
04516           handleDefault = XML_FALSE;
04517         dtd->scaffLevel--;
04518         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
04519         if (dtd->scaffLevel == 0) {
04520           if (!handleDefault) {
04521             XML_Content *model = build_model(parser);
04522             if (!model)
04523               return XML_ERROR_NO_MEMORY;
04524             *eventEndPP = s;
04525             elementDeclHandler(handlerArg, declElementType->name, model);
04526           }
04527           dtd->in_eldecl = XML_FALSE;
04528           dtd->contentStringLen = 0;
04529         }
04530       }
04531       break;
04532       /* End element declaration stuff */
04533 
04534     case XML_ROLE_PI:
04535 /* BEGIN MOZILLA CHANGE (Blocking parser) */
04536 #if 0
04537       if (!reportProcessingInstruction(parser, enc, s, next))
04538         return XML_ERROR_NO_MEMORY;
04539 #else
04540       if (!reportProcessingInstruction(parser, enc, s, next)) {
04541         if (blocked) {
04542           eventPtr = next;
04543           return XML_ERROR_SUSPENDED;
04544         }
04545         return XML_ERROR_NO_MEMORY;
04546       }
04547 #endif
04548 /* END MOZILLA CHANGE */
04549       handleDefault = XML_FALSE;
04550       break;
04551     case XML_ROLE_COMMENT:
04552       if (!reportComment(parser, enc, s, next))
04553         return XML_ERROR_NO_MEMORY;
04554       handleDefault = XML_FALSE;
04555       break;
04556     case XML_ROLE_NONE:
04557       switch (tok) {
04558       case XML_TOK_BOM:
04559         handleDefault = XML_FALSE;
04560         break;
04561       }
04562       break;
04563     case XML_ROLE_DOCTYPE_NONE:
04564       if (startDoctypeDeclHandler)
04565         handleDefault = XML_FALSE;
04566       break;
04567     case XML_ROLE_ENTITY_NONE:
04568       if (dtd->keepProcessing && entityDeclHandler)
04569         handleDefault = XML_FALSE;
04570       break;
04571     case XML_ROLE_NOTATION_NONE:
04572       if (notationDeclHandler)
04573         handleDefault = XML_FALSE;
04574       break;
04575     case XML_ROLE_ATTLIST_NONE:
04576       if (dtd->keepProcessing && attlistDeclHandler)
04577         handleDefault = XML_FALSE;
04578       break;
04579     case XML_ROLE_ELEMENT_NONE:
04580       if (elementDeclHandler)
04581         handleDefault = XML_FALSE;
04582       break;
04583     } /* end of big switch */
04584 
04585     if (handleDefault && defaultHandler)
04586       reportDefault(parser, enc, s, next);
04587 
04588     s = next;
04589     tok = XmlPrologTok(enc, s, end, &next);
04590   }
04591   /* not reached */
04592 }
04593 
04594 static enum XML_Error PTRCALL
04595 epilogProcessor(XML_Parser parser,
04596                 const char *s,
04597                 const char *end,
04598                 const char **nextPtr)
04599 {
04600   processor = epilogProcessor;
04601   eventPtr = s;
04602   for (;;) {
04603     const char *next = NULL;
04604     int tok = XmlPrologTok(encoding, s, end, &next);
04605     eventEndPtr = next;
04606     switch (tok) {
04607     /* report partial linebreak - it might be the last token */
04608     case -XML_TOK_PROLOG_S:
04609       if (defaultHandler) {
04610         eventEndPtr = next;
04611         reportDefault(parser, encoding, s, next);
04612       }
04613       if (nextPtr)
04614         *nextPtr = next;
04615       return XML_ERROR_NONE;
04616     case XML_TOK_NONE:
04617       if (nextPtr)
04618         *nextPtr = s;
04619       return XML_ERROR_NONE;
04620     case XML_TOK_PROLOG_S:
04621       if (defaultHandler)
04622         reportDefault(parser, encoding, s, next);
04623       break;
04624     case XML_TOK_PI:
04625 /* BEGIN MOZILLA CHANGE (Blocking parser) */
04626 #if 0
04627       if (!reportProcessingInstruction(parser, encoding, s, next))
04628         return XML_ERROR_NO_MEMORY;
04629 #else
04630       if (!reportProcessingInstruction(parser, encoding, s, next)) {
04631         if (blocked) {
04632           eventPtr = next;
04633           return XML_ERROR_SUSPENDED;
04634         }
04635         return XML_ERROR_NO_MEMORY;
04636       }
04637 #endif
04638 /* END MOZILLA CHANGE */
04639       break;
04640     case XML_TOK_COMMENT:
04641       if (!reportComment(parser, encoding, s, next))
04642         return XML_ERROR_NO_MEMORY;
04643       break;
04644     case XML_TOK_INVALID:
04645       eventPtr = next;
04646       return XML_ERROR_INVALID_TOKEN;
04647     case XML_TOK_PARTIAL:
04648       if (nextPtr) {
04649         *nextPtr = s;
04650         return XML_ERROR_NONE;
04651       }
04652       return XML_ERROR_UNCLOSED_TOKEN;
04653     case XML_TOK_PARTIAL_CHAR:
04654       if (nextPtr) {
04655         *nextPtr = s;
04656         return XML_ERROR_NONE;
04657       }
04658       return XML_ERROR_PARTIAL_CHAR;
04659     default:
04660       return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
04661     }
04662     eventPtr = s = next;
04663   }
04664 }
04665 
04666 #ifdef XML_DTD
04667 
04668 static enum XML_Error
04669 processInternalParamEntity(XML_Parser parser, ENTITY *entity)
04670 {
04671   const char *s, *end, *next;
04672   int tok;
04673   enum XML_Error result;
04674   OPEN_INTERNAL_ENTITY openEntity;
04675   entity->open = XML_TRUE;
04676   openEntity.next = openInternalEntities;
04677   openInternalEntities = &openEntity;
04678   openEntity.entity = entity;
04679   openEntity.internalEventPtr = NULL;
04680   openEntity.internalEventEndPtr = NULL;
04681   s = (char *)entity->textPtr;
04682   end = (char *)(entity->textPtr + entity->textLen);
04683   tok = XmlPrologTok(internalEncoding, s, end, &next);
04684   result = doProlog(parser, internalEncoding, s, end, tok, next, 0);
04685   entity->open = XML_FALSE;
04686   openInternalEntities = openEntity.next;
04687   return result;
04688 }
04689 
04690 #endif /* XML_DTD */
04691 
04692 static enum XML_Error PTRCALL
04693 errorProcessor(XML_Parser parser,
04694                const char *s,
04695                const char *end,
04696                const char **nextPtr)
04697 {
04698   return errorCode;
04699 }
04700 
04701 static enum XML_Error
04702 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
04703                     const char *ptr, const char *end,
04704                     STRING_POOL *pool)
04705 {
04706   enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
04707                                                end, pool);
04708   if (result)
04709     return result;
04710   if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
04711     poolChop(pool);
04712   if (!poolAppendChar(pool, XML_T('\0')))
04713     return XML_ERROR_NO_MEMORY;
04714   return XML_ERROR_NONE;
04715 }
04716 
04717 static enum XML_Error
04718 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
04719                      const char *ptr, const char *end,
04720                      STRING_POOL *pool)
04721 {
04722   DTD * const dtd = _dtd;  /* save one level of indirection */
04723   for (;;) {
04724     const char *next;
04725     int tok = XmlAttributeValueTok(enc, ptr, end, &next);
04726     switch (tok) {
04727     case XML_TOK_NONE:
04728       return XML_ERROR_NONE;
04729     case XML_TOK_INVALID:
04730       if (enc == encoding)
04731         eventPtr = next;
04732       return XML_ERROR_INVALID_TOKEN;
04733     case XML_TOK_PARTIAL:
04734       if (enc == encoding)
04735         eventPtr = ptr;
04736       return XML_ERROR_INVALID_TOKEN;
04737     case XML_TOK_CHAR_REF:
04738       {
04739         XML_Char buf[XML_ENCODE_MAX];
04740         int i;
04741         int n = XmlCharRefNumber(enc, ptr);
04742         if (n < 0) {
04743           if (enc == encoding)
04744             eventPtr = ptr;
04745           return XML_ERROR_BAD_CHAR_REF;
04746         }
04747         if (!isCdata
04748             && n == 0x20 /* space */
04749             && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
04750           break;
04751         n = XmlEncode(n, (ICHAR *)buf);
04752         if (!n) {
04753           if (enc == encoding)
04754             eventPtr = ptr;
04755           return XML_ERROR_BAD_CHAR_REF;
04756         }
04757         for (i = 0; i < n; i++) {
04758           if (!poolAppendChar(pool, buf[i]))
04759             return XML_ERROR_NO_MEMORY;
04760         }
04761       }
04762       break;
04763     case XML_TOK_DATA_CHARS:
04764       if (!poolAppend(pool, enc, ptr, next))
04765         return XML_ERROR_NO_MEMORY;
04766       break;
04767     case XML_TOK_TRAILING_CR:
04768       next = ptr + enc->minBytesPerChar;
04769       /* fall through */
04770     case XML_TOK_ATTRIBUTE_VALUE_S:
04771     case XML_TOK_DATA_NEWLINE:
04772       if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
04773         break;
04774       if (!poolAppendChar(pool, 0x20))
04775         return XML_ERROR_NO_MEMORY;
04776       break;
04777     case XML_TOK_ENTITY_REF:
04778       {
04779         const XML_Char *name;
04780         ENTITY *entity;
04781         char checkEntityDecl;
04782         XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
04783                                               ptr + enc->minBytesPerChar,
04784                                               next - enc->minBytesPerChar);
04785         if (ch) {
04786           if (!poolAppendChar(pool, ch))
04787                 return XML_ERROR_NO_MEMORY;
04788           break;
04789         }
04790         name = poolStoreString(&temp2Pool, enc,
04791                                ptr + enc->minBytesPerChar,
04792                                next - enc->minBytesPerChar);
04793         if (!name)
04794           return XML_ERROR_NO_MEMORY;
04795         entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
04796         poolDiscard(&temp2Pool);
04797         /* first, determine if a check for an existing declaration is needed;
04798            if yes, check that the entity exists, and that it is internal,
04799            otherwise call the default handler (if called from content)
04800         */
04801         if (pool == &dtd->pool)  /* are we called from prolog? */
04802           checkEntityDecl =
04803 #ifdef XML_DTD
04804               prologState.documentEntity &&
04805 #endif /* XML_DTD */
04806               (dtd->standalone
04807                ? !openInternalEntities
04808                : !dtd->hasParamEntityRefs);
04809         else /* if (pool == &tempPool): we are called from content */
04810           checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
04811         if (checkEntityDecl) {
04812           if (!entity)
04813             return XML_ERROR_UNDEFINED_ENTITY;
04814           else if (!entity->is_internal)
04815             return XML_ERROR_ENTITY_DECLARED_IN_PE;
04816         }
04817         else if (!entity) {
04818           /* cannot report skipped entity here - see comments on
04819              skippedEntityHandler
04820           if (skippedEntityHandler)
04821             skippedEntityHandler(handlerArg, name, 0);
04822           */
04823 /* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=35984) */
04824 #if 0
04825           if ((pool == &tempPool) && defaultHandler)
04826             reportDefault(parser, enc, ptr, next);
04827           break;
04828 #else
04829           return XML_ERROR_UNDEFINED_ENTITY;
04830 #endif
04831 /* END MOZILLA CHANGE */
04832         }
04833         if (entity->open) {
04834           if (enc == encoding)
04835             eventPtr = ptr;
04836           return XML_ERROR_RECURSIVE_ENTITY_REF;
04837         }
04838         if (entity->notation) {
04839           if (enc == encoding)
04840             eventPtr = ptr;
04841           return XML_ERROR_BINARY_ENTITY_REF;
04842         }
04843         if (!entity->textPtr) {
04844           if (enc == encoding)
04845             eventPtr = ptr;
04846               return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
04847         }
04848         else {
04849           enum XML_Error result;
04850           const XML_Char *textEnd = entity->textPtr + entity->textLen;
04851           entity->open = XML_TRUE;
04852           result = appendAttributeValue(parser, internalEncoding, isCdata,
04853                                         (char *)entity->textPtr,
04854                                         (char *)textEnd, pool);
04855           entity->open = XML_FALSE;
04856           if (result)
04857             return result;
04858         }
04859       }
04860       break;
04861     default:
04862       if (enc == encoding)
04863         eventPtr = ptr;
04864       return XML_ERROR_UNEXPECTED_STATE;
04865     }
04866     ptr = next;
04867   }
04868   /* not reached */
04869 }
04870 
04871 static enum XML_Error
04872 storeEntityValue(XML_Parser parser,
04873                  const ENCODING *enc,
04874                  const char *entityTextPtr,
04875                  const char *entityTextEnd)
04876 {
04877   DTD * const dtd = _dtd;  /* save one level of indirection */
04878   STRING_POOL *pool = &(dtd->entityValuePool);
04879   enum XML_Error result = XML_ERROR_NONE;
04880 #ifdef XML_DTD
04881   int oldInEntityValue = prologState.inEntityValue;
04882   prologState.inEntityValue = 1;
04883 #endif /* XML_DTD */
04884   /* never return Null for the value argument in EntityDeclHandler,
04885      since this would indicate an external entity; therefore we
04886      have to make sure that entityValuePool.start is not null */
04887   if (!pool->blocks) {
04888     if (!poolGrow(pool))
04889       return XML_ERROR_NO_MEMORY;
04890   }
04891 
04892   for (;;) {
04893     const char *next;
04894     int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
04895     switch (tok) {
04896     case XML_TOK_PARAM_ENTITY_REF:
04897 #ifdef XML_DTD
04898       if (isParamEntity || enc != encoding) {
04899         const XML_Char *name;
04900         ENTITY *entity;
04901         name = poolStoreString(&tempPool, enc,
04902                                entityTextPtr + enc->minBytesPerChar,
04903                                next - enc->minBytesPerChar);
04904         if (!name) {
04905           result = XML_ERROR_NO_MEMORY;
04906           goto endEntityValue;
04907         }
04908         entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
04909         poolDiscard(&tempPool);
04910         if (!entity) {
04911           /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
04912           /* cannot report skipped entity here - see comments on
04913              skippedEntityHandler
04914           if (skippedEntityHandler)
04915             skippedEntityHandler(handlerArg, name, 0);
04916           */
04917           dtd->keepProcessing = dtd->standalone;
04918           goto endEntityValue;
04919         }
04920         if (entity->open) {
04921           if (enc == encoding)
04922             eventPtr = entityTextPtr;
04923           result = XML_ERROR_RECURSIVE_ENTITY_REF;
04924           goto endEntityValue;
04925         }
04926         if (entity->systemId) {
04927           if (externalEntityRefHandler) {
04928             dtd->paramEntityRead = XML_FALSE;
04929             entity->open = XML_TRUE;
04930             if (!externalEntityRefHandler(externalEntityRefHandlerArg,
04931                                           0,
04932                                           entity->base,
04933                                           entity->systemId,
04934                                           entity->publicId)) {
04935               entity->open = XML_FALSE;
04936               result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
04937               goto endEntityValue;
04938             }
04939             entity->open = XML_FALSE;
04940             if (!dtd->paramEntityRead)
04941               dtd->keepProcessing = dtd->standalone;
04942           }
04943           else
04944             dtd->keepProcessing = dtd->standalone;
04945         }
04946         else {
04947           entity->open = XML_TRUE;
04948           result = storeEntityValue(parser,
04949                                     internalEncoding,
04950                                     (char *)entity->textPtr,
04951                                     (char *)(entity->textPtr
04952                                              + entity->textLen));
04953           entity->open = XML_FALSE;
04954           if (result)
04955             goto endEntityValue;
04956         }
04957         break;
04958       }
04959 #endif /* XML_DTD */
04960       /* in the internal subset, PE references are not legal
04961          within markup declarations, e.g entity values in this case */
04962       eventPtr = entityTextPtr;
04963       result = XML_ERROR_PARAM_ENTITY_REF;
04964       goto endEntityValue;
04965     case XML_TOK_NONE:
04966       result = XML_ERROR_NONE;
04967       goto endEntityValue;
04968     case XML_TOK_ENTITY_REF:
04969     case XML_TOK_DATA_CHARS:
04970       if (!poolAppend(pool, enc, entityTextPtr, next)) {
04971         result = XML_ERROR_NO_MEMORY;
04972         goto endEntityValue;
04973       }
04974       break;
04975     case XML_TOK_TRAILING_CR:
04976       next = entityTextPtr + enc->minBytesPerChar;
04977       /* fall through */
04978     case XML_TOK_DATA_NEWLINE:
04979       if (pool->end == pool->ptr && !poolGrow(pool)) {
04980               result = XML_ERROR_NO_MEMORY;
04981         goto endEntityValue;
04982       }
04983       *(pool->ptr)++ = 0xA;
04984       break;
04985     case XML_TOK_CHAR_REF:
04986       {
04987         XML_Char buf[XML_ENCODE_MAX];
04988         int i;
04989         int n = XmlCharRefNumber(enc, entityTextPtr);
04990         if (n < 0) {
04991           if (enc == encoding)
04992             eventPtr = entityTextPtr;
04993           result = XML_ERROR_BAD_CHAR_REF;
04994           goto endEntityValue;
04995         }
04996         n = XmlEncode(n, (ICHAR *)buf);
04997         if (!n) {
04998           if (enc == encoding)
04999             eventPtr = entityTextPtr;
05000           result = XML_ERROR_BAD_CHAR_REF;
05001           goto endEntityValue;
05002         }
05003         for (i = 0; i < n; i++) {
05004           if (pool->end == pool->ptr && !poolGrow(pool)) {
05005             result = XML_ERROR_NO_MEMORY;
05006             goto endEntityValue;
05007           }
05008           *(pool->ptr)++ = buf[i];
05009         }
05010       }
05011       break;
05012     case XML_TOK_PARTIAL:
05013       if (enc == encoding)
05014         eventPtr = entityTextPtr;
05015       result = XML_ERROR_INVALID_TOKEN;
05016       goto endEntityValue;
05017     case XML_TOK_INVALID:
05018       if (enc == encoding)
05019         eventPtr = next;
05020       result = XML_ERROR_INVALID_TOKEN;
05021       goto endEntityValue;
05022     default:
05023       if (enc == encoding)
05024         eventPtr = entityTextPtr;
05025       result = XML_ERROR_UNEXPECTED_STATE;
05026       goto endEntityValue;
05027     }
05028     entityTextPtr = next;
05029   }
05030 endEntityValue:
05031 #ifdef XML_DTD
05032   prologState.inEntityValue = oldInEntityValue;
05033 #endif /* XML_DTD */
05034   return result;
05035 }
05036 
05037 static void FASTCALL
05038 normalizeLines(XML_Char *s)
05039 {
05040   XML_Char *p;
05041   for (;; s++) {
05042     if (*s == XML_T('\0'))
05043       return;
05044     if (*s == 0xD)
05045       break;
05046   }
05047   p = s;
05048   do {
05049     if (*s == 0xD) {
05050       *p++ = 0xA;
05051       if (*++s == 0xA)
05052         s++;
05053     }
05054     else
05055       *p++ = *s++;
05056   } while (*s);
05057   *p = XML_T('\0');
05058 }
05059 
05060 static int
05061 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
05062                             const char *start, const char *end)
05063 {
05064   const XML_Char *target;
05065   XML_Char *data;
05066   const char *tem;
05067   if (!processingInstructionHandler) {
05068     if (defaultHandler)
05069       reportDefault(parser, enc, start, end);
05070     return 1;
05071   }
05072   start += enc->minBytesPerChar * 2;
05073   tem = start + XmlNameLength(enc, start);
05074   target = poolStoreString(&tempPool, enc, start, tem);
05075   if (!target)
05076     return 0;
05077   poolFinish(&tempPool);
05078   data = poolStoreString(&tempPool, enc,
05079                         XmlSkipS(enc, tem),
05080                         end - enc->minBytesPerChar*2);
05081   if (!data)
05082     return 0;
05083   normalizeLines(data);
05084   processingInstructionHandler(handlerArg, target, data);
05085   poolClear(&tempPool);
05086 /* BEGIN MOZILLA CHANGE (Blocking parser) */
05087   if (blocked) {
05088     return 0;
05089   }
05090 /* END MOZILLA CHANGE */
05091   return 1;
05092 }
05093 
05094 static int
05095 reportComment(XML_Parser parser, const ENCODING *enc,
05096               const char *start, const char *end)
05097 {
05098   XML_Char *data;
05099   if (!commentHandler) {
05100     if (defaultHandler)
05101       reportDefault(parser, enc, start, end);
05102     return 1;
05103   }
05104   data = poolStoreString(&tempPool,
05105                          enc,
05106                          start + enc->minBytesPerChar * 4,
05107                          end - enc->minBytesPerChar * 3);
05108   if (!data)
05109     return 0;
05110   normalizeLines(data);
05111   commentHandler(handlerArg, data);
05112   poolClear(&tempPool);
05113   return 1;
05114 }
05115 
05116 static void
05117 reportDefault(XML_Parser parser, const ENCODING *enc,
05118               const char *s, const char *end)
05119 {
05120   if (MUST_CONVERT(enc, s)) {
05121     const char **eventPP;
05122     const char **eventEndPP;
05123     if (enc == encoding) {
05124       eventPP = &eventPtr;
05125       eventEndPP = &eventEndPtr;
05126     }
05127     else {
05128       eventPP = &(openInternalEntities->internalEventPtr);
05129       eventEndPP = &(openInternalEntities->internalEventEndPtr);
05130     }
05131     do {
05132       ICHAR *dataPtr = (ICHAR *)dataBuf;
05133       XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
05134       *eventEndPP = s;
05135       defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
05136       *eventPP = s;
05137     } while (s != end);
05138   }
05139   else
05140     defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
05141 }
05142 
05143 
05144 static int
05145 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
05146                 XML_Bool isId, const XML_Char *value, XML_Parser parser)
05147 {
05148   DEFAULT_ATTRIBUTE *att;
05149   if (value || isId) {
05150     /* The handling of default attributes gets messed up if we have
05151        a default which duplicates a non-default. */
05152     int i;
05153     for (i = 0; i < type->nDefaultAtts; i++)
05154       if (attId == type->defaultAtts[i].id)
05155         return 1;
05156     if (isId && !type->idAtt && !attId->xmlns)
05157       type->idAtt = attId;
05158   }
05159   if (type->nDefaultAtts == type->allocDefaultAtts) {
05160     if (type->allocDefaultAtts == 0) {
05161       type->allocDefaultAtts = 8;
05162       type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
05163                             * sizeof(DEFAULT_ATTRIBUTE));
05164       if (!type->defaultAtts)
05165         return 0;
05166     }
05167     else {
05168       DEFAULT_ATTRIBUTE *temp;
05169       int count = type->allocDefaultAtts * 2;
05170       temp = (DEFAULT_ATTRIBUTE *)
05171         REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
05172       if (temp == NULL)
05173         return 0;
05174       type->allocDefaultAtts = count;
05175       type->defaultAtts = temp;
05176     }
05177   }
05178   att = type->defaultAtts + type->nDefaultAtts;
05179   att->id = attId;
05180   att->value = value;
05181   att->isCdata = isCdata;
05182   if (!isCdata)
05183     attId->maybeTokenized = XML_TRUE;
05184   type->nDefaultAtts += 1;
05185   return 1;
05186 }
05187 
05188 static int
05189 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
05190 {
05191   DTD * const dtd = _dtd;  /* save one level of indirection */
05192   const XML_Char *name;
05193   for (name = elementType->name; *name; name++) {
05194     if (*name == XML_T(':')) {
05195       PREFIX *prefix;
05196       const XML_Char *s;
05197       for (s = elementType->name; s != name; s++) {
05198         if (!poolAppendChar(&dtd->pool, *s))
05199           return 0;
05200       }
05201       if (!poolAppendChar(&dtd->pool, XML_T('\0')))
05202         return 0;
05203       prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
05204                                 sizeof(PREFIX));
05205       if (!prefix)
05206         return 0;
05207       if (prefix->name == poolStart(&dtd->pool))
05208         poolFinish(&dtd->pool);
05209       else
05210         poolDiscard(&dtd->pool);
05211       elementType->prefix = prefix;
05212 
05213     }
05214   }
05215   return 1;
05216 }
05217 
05218 static ATTRIBUTE_ID *
05219 getAttributeId(XML_Parser parser, const ENCODING *enc,
05220                const char *start, const char *end)
05221 {
05222   DTD * const dtd = _dtd;  /* save one level of indirection */
05223   ATTRIBUTE_ID *id;
05224   const XML_Char *name;
05225   if (!poolAppendChar(&dtd->pool, XML_T('\0')))
05226     return NULL;
05227   name = poolStoreString(&dtd->pool, enc, start, end);
05228   if (!name)
05229     return NULL;
05230   /* skip quotation mark - its storage will be re-used (like in name[-1]) */
05231   ++name;
05232   id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
05233   if (!id)
05234     return NULL;
05235   if (id->name != name)
05236     poolDiscard(&dtd->pool);
05237   else {
05238     poolFinish(&dtd->pool);
05239     if (!ns)
05240       ;
05241     else if (name[0] == XML_T('x')
05242         && name[1] == XML_T('m')
05243         && name[2] == XML_T('l')
05244         && name[3] == XML_T('n')
05245         && name[4] == XML_T('s')
05246         && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
05247       if (name[5] == XML_T('\0'))
05248         id->prefix = &dtd->defaultPrefix;
05249       else
05250         id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
05251       id->xmlns = XML_TRUE;
05252     }
05253     else {
05254       int i;
05255       for (i = 0; name[i]; i++) {
05256         /* attributes without prefix are *not* in the default namespace */
05257         if (name[i] == XML_T(':')) {
05258           int j;
05259           for (j = 0; j < i; j++) {
05260             if (!poolAppendChar(&dtd->pool, name[j]))
05261               return NULL;
05262           }
05263           if (!poolAppendChar(&dtd->pool, XML_T('\0')))
05264             return NULL;
05265           id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
05266                                         sizeof(PREFIX));
05267           if (id->prefix->name == poolStart(&dtd->pool))
05268             poolFinish(&dtd->pool);
05269           else
05270             poolDiscard(&dtd->pool);
05271           break;
05272         }
05273       }
05274     }
05275   }
05276   return id;
05277 }
05278 
05279 #define CONTEXT_SEP XML_T('\f')
05280 
05281 static const XML_Char *
05282 getContext(XML_Parser parser)
05283 {
05284   DTD * const dtd = _dtd;  /* save one level of indirection */
05285   HASH_TABLE_ITER iter;
05286   XML_Bool needSep = XML_FALSE;
05287 
05288   if (dtd->defaultPrefix.binding) {
05289     int i;
05290     int len;
05291     if (!poolAppendChar(&tempPool, XML_T('=')))
05292       return NULL;
05293     len = dtd->defaultPrefix.binding->uriLen;
05294     if (namespaceSeparator != XML_T('\0'))
05295       len--;
05296     for (i = 0; i < len; i++)
05297       if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
05298         return NULL;
05299     needSep = XML_TRUE;
05300   }
05301 
05302   hashTableIterInit(&iter, &(dtd->prefixes));
05303   for (;;) {
05304     int i;
05305     int len;
05306     const XML_Char *s;
05307     PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
05308     if (!prefix)
05309       break;
05310     if (!prefix->binding)
05311       continue;
05312     if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
05313       return NULL;
05314     for (s = prefix->name; *s; s++)
05315       if (!poolAppendChar(&tempPool, *s))
05316         return NULL;
05317     if (!poolAppendChar(&tempPool, XML_T('=')))
05318       return NULL;
05319     len = prefix->binding->uriLen;
05320     if (namespaceSeparator != XML_T('\0'))
05321       len--;
05322     for (i = 0; i < len; i++)
05323       if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
05324         return NULL;
05325     needSep = XML_TRUE;
05326   }
05327 
05328 
05329   hashTableIterInit(&iter, &(dtd->generalEntities));
05330   for (;;) {
05331     const XML_Char *s;
05332     ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
05333     if (!e)
05334       break;
05335     if (!e->open)
05336       continue;
05337     if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
05338       return NULL;
05339     for (s = e->name; *s; s++)
05340       if (!poolAppendChar(&tempPool, *s))
05341         return 0;
05342     needSep = XML_TRUE;
05343   }
05344 
05345   if (!poolAppendChar(&tempPool, XML_T('\0')))
05346     return NULL;
05347   return tempPool.start;
05348 }
05349 
05350 static XML_Bool
05351 setContext(XML_Parser parser, const XML_Char *context)
05352 {
05353   DTD * const dtd = _dtd;  /* save one level of indirection */
05354   const XML_Char *s = context;
05355 
05356   while (*context != XML_T('\0')) {
05357     if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
05358       ENTITY *e;
05359       if (!poolAppendChar(&tempPool, XML_T('\0')))
05360         return XML_FALSE;
05361       e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
05362       if (e)
05363         e->open = XML_TRUE;
05364       if (*s != XML_T('\0'))
05365         s++;
05366       context = s;
05367       poolDiscard(&tempPool);
05368     }
05369     else if (*s == XML_T('=')) {
05370       PREFIX *prefix;
05371       if (poolLength(&tempPool) == 0)
05372         prefix = &dtd->defaultPrefix;
05373       else {
05374         if (!poolAppendChar(&tempPool, XML_T('\0')))
05375           return XML_FALSE;
05376         prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
05377                                   sizeof(PREFIX));
05378         if (!prefix)
05379           return XML_FALSE;
05380         if (prefix->name == poolStart(&tempPool)) {
05381           prefix->name = poolCopyString(&dtd->pool, prefix->name);
05382           if (!prefix->name)
05383             return XML_FALSE;
05384         }
05385         poolDiscard(&tempPool);
05386       }
05387       for (context = s + 1;
05388            *context != CONTEXT_SEP && *context != XML_T('\0');
05389            context++)
05390         if (!poolAppendChar(&tempPool, *context))
05391           return XML_FALSE;
05392       if (!poolAppendChar(&tempPool, XML_T('\0')))
05393         return XML_FALSE;
05394       if (addBinding(parser, prefix, 0, poolStart(&tempPool),
05395                      &inheritedBindings) != XML_ERROR_NONE)
05396         return XML_FALSE;
05397       poolDiscard(&tempPool);
05398       if (*context != XML_T('\0'))
05399         ++context;
05400       s = context;
05401     }
05402     else {
05403       if (!poolAppendChar(&tempPool, *s))
05404         return XML_FALSE;
05405       s++;
05406     }
05407   }
05408   return XML_TRUE;
05409 }
05410 
05411 static void FASTCALL
05412 normalizePublicId(XML_Char *publicId)
05413 {
05414   XML_Char *p = publicId;
05415   XML_Char *s;
05416   for (s = publicId; *s; s++) {
05417     switch (*s) {
05418     case 0x20:
05419     case 0xD:
05420     case 0xA:
05421       if (p != publicId && p[-1] != 0x20)
05422         *p++ = 0x20;
05423       break;
05424     default:
05425       *p++ = *s;
05426     }
05427   }
05428   if (p != publicId && p[-1] == 0x20)
05429     --p;
05430   *p = XML_T('\0');
05431 }
05432 
05433 static DTD *
05434 dtdCreate(const XML_Memory_Handling_Suite *ms)
05435 {
05436   DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
05437   if (p == NULL)
05438     return p;
05439   poolInit(&(p->pool), ms);
05440 #ifdef XML_DTD
05441   poolInit(&(p->entityValuePool), ms);
05442 #endif /* XML_DTD */
05443   hashTableInit(&(p->generalEntities), ms);
05444   hashTableInit(&(p->elementTypes), ms);
05445   hashTableInit(&(p->attributeIds), ms);
05446   hashTableInit(&(p->prefixes), ms);
05447 #ifdef XML_DTD
05448   p->paramEntityRead = XML_FALSE;
05449   hashTableInit(&(p->paramEntities), ms);
05450 #endif /* XML_DTD */
05451   p->defaultPrefix.name = NULL;
05452   p->defaultPrefix.binding = NULL;
05453 
05454   p->in_eldecl = XML_FALSE;
05455   p->scaffIndex = NULL;
05456   p->scaffold = NULL;
05457   p->scaffLevel = 0;
05458   p->scaffSize = 0;
05459   p->scaffCount = 0;
05460   p->contentStringLen = 0;
05461 
05462   p->keepProcessing = XML_TRUE;
05463   p->hasParamEntityRefs = XML_FALSE;
05464   p->standalone = XML_FALSE;
05465   return p;
05466 }
05467 
05468 static void
05469 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
05470 {
05471   HASH_TABLE_ITER iter;
05472   hashTableIterInit(&iter, &(p->elementTypes));
05473   for (;;) {
05474     ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
05475     if (!e)
05476       break;
05477     if (e->allocDefaultAtts != 0)
05478       ms->free_fcn(e->defaultAtts);
05479   }
05480   hashTableClear(&(p->generalEntities));
05481 #ifdef XML_DTD
05482   p->paramEntityRead = XML_FALSE;
05483   hashTableClear(&(p->paramEntities));
05484 #endif /* XML_DTD */
05485   hashTableClear(&(p->elementTypes));
05486   hashTableClear(&(p->attributeIds));
05487   hashTableClear(&(p->prefixes));
05488   poolClear(&(p->pool));
05489 #ifdef XML_DTD
05490   poolClear(&(p->entityValuePool));
05491 #endif /* XML_DTD */
05492   p->defaultPrefix.name = NULL;
05493   p->defaultPrefix.binding = NULL;
05494 
05495   p->in_eldecl = XML_FALSE;
05496 
05497   ms->free_fcn(p->scaffIndex);
05498   p->scaffIndex = NULL;
05499   ms->free_fcn(p->scaffold);
05500   p->scaffold = NULL;
05501 
05502   p->scaffLevel = 0;
05503   p->scaffSize = 0;
05504   p->scaffCount = 0;
05505   p->contentStringLen = 0;
05506 
05507   p->keepProcessing = XML_TRUE;
05508   p->hasParamEntityRefs = XML_FALSE;
05509   p->standalone = XML_FALSE;
05510 }
05511 
05512 static void
05513 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
05514 {
05515   HASH_TABLE_ITER iter;
05516   hashTableIterInit(&iter, &(p->elementTypes));
05517   for (;;) {
05518     ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
05519     if (!e)
05520       break;
05521     if (e->allocDefaultAtts != 0)
05522       ms->free_fcn(e->defaultAtts);
05523   }
05524   hashTableDestroy(&(p->generalEntities));
05525 #ifdef XML_DTD
05526   hashTableDestroy(&(p->paramEntities));
05527 #endif /* XML_DTD */
05528   hashTableDestroy(&(p->elementTypes));
05529   hashTableDestroy(&(p->attributeIds));
05530   hashTableDestroy(&(p->prefixes));
05531   poolDestroy(&(p->pool));
05532 #ifdef XML_DTD
05533   poolDestroy(&(p->entityValuePool));
05534 #endif /* XML_DTD */
05535   if (isDocEntity) {
05536     ms->free_fcn(p->scaffIndex);
05537     ms->free_fcn(p->scaffold);
05538   }
05539   ms->free_fcn(p);
05540 }
05541 
05542 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
05543    The new DTD has already been initialized.
05544 */
05545 static int
05546 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
05547 {
05548   HASH_TABLE_ITER iter;
05549 
05550   /* Copy the prefix table. */
05551 
05552   hashTableIterInit(&iter, &(oldDtd->prefixes));
05553   for (;;) {
05554     const XML_Char *name;
05555     const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
05556     if (!oldP)
05557       break;
05558     name = poolCopyString(&(newDtd->pool), oldP->name);
05559     if (!name)
05560       return 0;
05561     if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
05562       return 0;
05563   }
05564 
05565   hashTableIterInit(&iter, &(oldDtd->attributeIds));
05566 
05567   /* Copy the attribute id table. */
05568 
05569   for (;;) {
05570     ATTRIBUTE_ID *newA;
05571     const XML_Char *name;
05572     const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
05573 
05574     if (!oldA)
05575       break;
05576     /* Remember to allocate the scratch byte before the name. */
05577     if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
05578       return 0;
05579     name = poolCopyString(&(newDtd->pool), oldA->name);
05580     if (!name)
05581       return 0;
05582     ++name;
05583     newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
05584                                   sizeof(ATTRIBUTE_ID));
05585     if (!newA)
05586       return 0;
05587     newA->maybeTokenized = oldA->maybeTokenized;
05588     if (oldA->prefix) {
05589       newA->xmlns = oldA->xmlns;
05590       if (oldA->prefix == &oldDtd->defaultPrefix)
05591         newA->prefix = &newDtd->defaultPrefix;
05592       else
05593         newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
05594                                         oldA->prefix->name, 0);
05595     }
05596   }
05597 
05598   /* Copy the element type table. */
05599 
05600   hashTableIterInit(&iter, &(oldDtd->elementTypes));
05601 
05602   for (;;) {
05603     int i;
05604     ELEMENT_TYPE *newE;
05605     const XML_Char *name;
05606     const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
05607     if (!oldE)
05608       break;
05609     name = poolCopyString(&(newDtd->pool), oldE->name);
05610     if (!name)
05611       return 0;
05612     newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
05613                                   sizeof(ELEMENT_TYPE));
05614     if (!newE)
05615       return 0;
05616     if (oldE->nDefaultAtts) {
05617       newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
05618           ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
05619       if (!newE->defaultAtts) {
05620         ms->free_fcn(newE);
05621         return 0;
05622       }
05623     }
05624     if (oldE->idAtt)
05625       newE->idAtt = (ATTRIBUTE_ID *)
05626           lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
05627     newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
05628     if (oldE->prefix)
05629       newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
05630                                       oldE->prefix->name, 0);
05631     for (i = 0; i < newE->nDefaultAtts; i++) {
05632       newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
05633           lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
05634       newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
05635       if (oldE->defaultAtts[i].value) {
05636         newE->defaultAtts[i].value
05637             = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
05638         if (!newE->defaultAtts[i].value)
05639           return 0;
05640       }
05641       else
05642         newE->defaultAtts[i].value = NULL;
05643     }
05644   }
05645 
05646   /* Copy the entity tables. */
05647   if (!copyEntityTable(&(newDtd->generalEntities),
05648                        &(newDtd->pool),
05649                        &(oldDtd->generalEntities)))
05650       return 0;
05651 
05652 #ifdef XML_DTD
05653   if (!copyEntityTable(&(newDtd->paramEntities),
05654                        &(newDtd->pool),
05655                        &(oldDtd->paramEntities)))
05656       return 0;
05657   newDtd->paramEntityRead = oldDtd->paramEntityRead;
05658 #endif /* XML_DTD */
05659 
05660   newDtd->keepProcessing = oldDtd->keepProcessing;
05661   newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
05662   newDtd->standalone = oldDtd->standalone;
05663 
05664   /* Don't want deep copying for scaffolding */
05665   newDtd->in_eldecl = oldDtd->in_eldecl;
05666   newDtd->scaffold = oldDtd->scaffold;
05667   newDtd->contentStringLen = oldDtd->contentStringLen;
05668   newDtd->scaffSize = oldDtd->scaffSize;
05669   newDtd->scaffLevel = oldDtd->scaffLevel;
05670   newDtd->scaffIndex = oldDtd->scaffIndex;
05671 
05672   return 1;
05673 }  /* End dtdCopy */
05674 
05675 static int
05676 copyEntityTable(HASH_TABLE *newTable,
05677                 STRING_POOL *newPool,
05678                 const HASH_TABLE *oldTable)
05679 {
05680   HASH_TABLE_ITER iter;
05681   const XML_Char *cachedOldBase = NULL;
05682   const XML_Char *cachedNewBase = NULL;
05683 
05684   hashTableIterInit(&iter, oldTable);
05685 
05686   for (;;) {
05687     ENTITY *newE;
05688     const XML_Char *name;
05689     const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
05690     if (!oldE)
05691       break;
05692     name = poolCopyString(newPool, oldE->name);
05693     if (!name)
05694       return 0;
05695     newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
05696     if (!newE)
05697       return 0;
05698     if (oldE->systemId) {
05699       const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
05700       if (!tem)
05701         return 0;
05702       newE->systemId = tem;
05703       if (oldE->base) {
05704         if (oldE->base == cachedOldBase)
05705           newE->base = cachedNewBase;
05706         else {
05707           cachedOldBase = oldE->base;
05708           tem = poolCopyString(newPool, cachedOldBase);
05709           if (!tem)
05710             return 0;
05711           cachedNewBase = newE->base = tem;
05712         }
05713       }
05714       if (oldE->publicId) {
05715         tem = poolCopyString(newPool, oldE->publicId);
05716         if (!tem)
05717           return 0;
05718         newE->publicId = tem;
05719       }
05720     }
05721     else {
05722       const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
05723                                             oldE->textLen);
05724       if (!tem)
05725         return 0;
05726       newE->textPtr = tem;
05727       newE->textLen = oldE->textLen;
05728     }
05729     if (oldE->notation) {
05730       const XML_Char *tem = poolCopyString(newPool, oldE->notation);
05731       if (!tem)
05732         return 0;
05733       newE->notation = tem;
05734     }
05735     newE->is_param = oldE->is_param;
05736     newE->is_internal = oldE->is_internal;
05737   }
05738   return 1;
05739 }
05740 
05741 #define INIT_POWER 6
05742 
05743 static XML_Bool FASTCALL
05744 keyeq(KEY s1, KEY s2)
05745 {
05746   for (; *s1 == *s2; s1++, s2++)
05747     if (*s1 == 0)
05748       return XML_TRUE;
05749   return XML_FALSE;
05750 }
05751 
05752 static unsigned long FASTCALL
05753 hash(KEY s)
05754 {
05755   unsigned long h = 0;
05756   while (*s)
05757     h = CHAR_HASH(h, *s++);
05758   return h;
05759 }
05760 
05761 static NAMED *
05762 lookup(HASH_TABLE *table, KEY name, size_t createSize)
05763 {
05764   size_t i;
05765   if (table->size == 0) {
05766     size_t tsize;
05767     if (!createSize)
05768       return NULL;
05769     table->power = INIT_POWER;
05770     /* table->size is a power of 2 */
05771     table->size = (size_t)1 << INIT_POWER;
05772     tsize = table->size * sizeof(NAMED *);
05773     table->v = (NAMED **)table->mem->malloc_fcn(tsize);
05774     if (!table->v)
05775       return NULL;
05776     memset(table->v, 0, tsize);
05777     i = hash(name) & ((unsigned long)table->size - 1);
05778   }
05779   else {
05780     unsigned long h = hash(name);
05781     unsigned long mask = (unsigned long)table->size - 1;
05782     unsigned char step = 0;
05783     i = h & mask;
05784     while (table->v[i]) {
05785       if (keyeq(name, table->v[i]->name))
05786         return table->v[i];
05787       if (!step)
05788         step = PROBE_STEP(h, mask, table->power);
05789       i < step ? (i += table->size - step) : (i -= step);
05790     }
05791     if (!createSize)
05792       return NULL;
05793 
05794     /* check for overflow (table is half full) */
05795     if (table->used >> (table->power - 1)) {
05796       unsigned char newPower = table->power + 1;
05797       size_t newSize = (size_t)1 << newPower;
05798       unsigned long newMask = (unsigned long)newSize - 1;
05799       size_t tsize = newSize * sizeof(NAMED *);
05800       NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
05801       if (!newV)
05802         return NULL;
05803       memset(newV, 0, tsize);
05804       for (i = 0; i < table->size; i++)
05805         if (table->v[i]) {
05806           unsigned long newHash = hash(table->v[i]->name);
05807           size_t j = newHash & newMask;
05808           step = 0;
05809           while (newV[j]) {
05810             if (!step)
05811               step = PROBE_STEP(newHash, newMask, newPower);
05812             j < step ? (j += newSize - step) : (j -= step);
05813           }
05814           newV[j] = table->v[i];
05815         }
05816       table->mem->free_fcn(table->v);
05817       table->v = newV;
05818       table->power = newPower;
05819       table->size = newSize;
05820       i = h & newMask;
05821       step = 0;
05822       while (table->v[i]) {
05823         if (!step)
05824           step = PROBE_STEP(h, newMask, newPower);
05825         i < step ? (i += newSize - step) : (i -= step);
05826       }
05827     }
05828   }
05829   table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
05830   if (!table->v[i])
05831     return NULL;
05832   memset(table->v[i], 0, createSize);
05833   table->v[i]->name = name;
05834   (table->used)++;
05835   return table->v[i];
05836 }
05837 
05838 static void FASTCALL
05839 hashTableClear(HASH_TABLE *table)
05840 {
05841   size_t i;
05842   for (i = 0; i < table->size; i++) {
05843     table->mem->free_fcn(table->v[i]);
05844     table->v[i] = NULL;
05845   }
05846   table->used = 0;
05847 }
05848 
05849 static void FASTCALL
05850 hashTableDestroy(HASH_TABLE *table)
05851 {
05852   size_t i;
05853   for (i = 0; i < table->size; i++)
05854     table->mem->free_fcn(table->v[i]);
05855   table->mem->free_fcn(table->v);
05856 }
05857 
05858 static void FASTCALL
05859 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
05860 {
05861   p->power = 0;
05862   p->size = 0;
05863   p->used = 0;
05864   p->v = NULL;
05865   p->mem = ms;
05866 }
05867 
05868 static void FASTCALL
05869 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
05870 {
05871   iter->p = table->v;
05872   iter->end = iter->p + table->size;
05873 }
05874 
05875 static NAMED * FASTCALL
05876 hashTableIterNext(HASH_TABLE_ITER *iter)
05877 {
05878   while (iter->p != iter->end) {
05879     NAMED *tem = *(iter->p)++;
05880     if (tem)
05881       return tem;
05882   }
05883   return NULL;
05884 }
05885 
05886 static void FASTCALL
05887 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
05888 {
05889   pool->blocks = NULL;
05890   pool->freeBlocks = NULL;
05891   pool->start = NULL;
05892   pool->ptr = NULL;
05893   pool->end = NULL;
05894   pool->mem = ms;
05895 }
05896 
05897 static void FASTCALL
05898 poolClear(STRING_POOL *pool)
05899 {
05900   if (!pool->freeBlocks)
05901     pool->freeBlocks = pool->blocks;
05902   else {
05903     BLOCK *p = pool->blocks;
05904     while (p) {
05905       BLOCK *tem = p->next;
05906       p->next = pool->freeBlocks;
05907       pool->freeBlocks = p;
05908       p = tem;
05909     }
05910   }
05911   pool->blocks = NULL;
05912   pool->start = NULL;
05913   pool->ptr = NULL;
05914   pool->end = NULL;
05915 }
05916 
05917 static void FASTCALL
05918 poolDestroy(STRING_POOL *pool)
05919 {
05920   BLOCK *p = pool->blocks;
05921   while (p) {
05922     BLOCK *tem = p->next;
05923     pool->mem->free_fcn(p);
05924     p = tem;
05925   }
05926   p = pool->freeBlocks;
05927   while (p) {
05928     BLOCK *tem = p->next;
05929     pool->mem->free_fcn(p);
05930     p = tem;
05931   }
05932 }
05933 
05934 static XML_Char *
05935 poolAppend(STRING_POOL *pool, const ENCODING *enc,
05936            const char *ptr, const char *end)
05937 {
05938   if (!pool->ptr && !poolGrow(pool))
05939     return NULL;
05940   for (;;) {
05941     XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
05942     if (ptr == end)
05943       break;
05944     if (!poolGrow(pool))
05945       return NULL;
05946   }
05947   return pool->start;
05948 }
05949 
05950 static const XML_Char * FASTCALL
05951 poolCopyString(STRING_POOL *pool, const XML_Char *s)
05952 {
05953   do {
05954     if (!poolAppendChar(pool, *s))
05955       return NULL;
05956   } while (*s++);
05957   s = pool->start;
05958   poolFinish(pool);
05959   return s;
05960 }
05961 
05962 static const XML_Char *
05963 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
05964 {
05965   if (!pool->ptr && !poolGrow(pool))
05966     return NULL;
05967   for (; n > 0; --n, s++) {
05968     if (!poolAppendChar(pool, *s))
05969       return NULL;
05970   }
05971   s = pool->start;
05972   poolFinish(pool);
05973   return s;
05974 }
05975 
05976 static const XML_Char * FASTCALL
05977 poolAppendString(STRING_POOL *pool, const XML_Char *s)
05978 {
05979   while (*s) {
05980     if (!poolAppendChar(pool, *s))
05981       return NULL;
05982     s++;
05983   }
05984   return pool->start;
05985 }
05986 
05987 static XML_Char *
05988 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
05989                 const char *ptr, const char *end)
05990 {
05991   if (!poolAppend(pool, enc, ptr, end))
05992     return NULL;
05993   if (pool->ptr == pool->end && !poolGrow(pool))
05994     return NULL;
05995   *(pool->ptr)++ = 0;
05996   return pool->start;
05997 }
05998 
05999 static XML_Bool FASTCALL
06000 poolGrow(STRING_POOL *pool)
06001 {
06002   if (pool->freeBlocks) {
06003     if (pool->start == 0) {
06004       pool->blocks = pool->freeBlocks;
06005       pool->freeBlocks = pool->freeBlocks->next;
06006       pool->blocks->next = NULL;
06007       pool->start = pool->blocks->s;
06008       pool->end = pool->start + pool->blocks->size;
06009       pool->ptr = pool->start;
06010       return XML_TRUE;
06011     }
06012     if (pool->end - pool->start < pool->freeBlocks->size) {
06013       BLOCK *tem = pool->freeBlocks->next;
06014       pool->freeBlocks->next = pool->blocks;
06015       pool->blocks = pool->freeBlocks;
06016       pool->freeBlocks = tem;
06017       memcpy(pool->blocks->s, pool->start,
06018              (pool->end - pool->start) * sizeof(XML_Char));
06019       pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
06020       pool->start = pool->blocks->s;
06021       pool->end = pool->start + pool->blocks->size;
06022       return XML_TRUE;
06023     }
06024   }
06025   if (pool->blocks && pool->start == pool->blocks->s) {
06026     int blockSize = (pool->end - pool->start)*2;
06027     pool->blocks = (BLOCK *)
06028       pool->mem->realloc_fcn(pool->blocks,
06029                              (offsetof(BLOCK, s)
06030                               + blockSize * sizeof(XML_Char)));
06031     if (pool->blocks == NULL)
06032       return XML_FALSE;
06033     pool->blocks->size = blockSize;
06034     pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
06035     pool->start = pool->blocks->s;
06036     pool->end = pool->start + blockSize;
06037   }
06038   else {
06039     BLOCK *tem;
06040     int blockSize = pool->end - pool->start;
06041     if (blockSize < INIT_BLOCK_SIZE)
06042       blockSize = INIT_BLOCK_SIZE;
06043     else
06044       blockSize *= 2;
06045     tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
06046                                         + blockSize * sizeof(XML_Char));
06047     if (!tem)
06048       return XML_FALSE;
06049     tem->size = blockSize;
06050     tem->next = pool->blocks;
06051     pool->blocks = tem;
06052     if (pool->ptr != pool->start)
06053       memcpy(tem->s, pool->start,
06054              (pool->ptr - pool->start) * sizeof(XML_Char));
06055     pool->ptr = tem->s + (pool->ptr - pool->start);
06056     pool->start = tem->s;
06057     pool->end = tem->s + blockSize;
06058   }
06059   return XML_TRUE;
06060 }
06061 
06062 static int FASTCALL
06063 nextScaffoldPart(XML_Parser parser)
06064 {
06065   DTD * const dtd = _dtd;  /* save one level of indirection */
06066   CONTENT_SCAFFOLD * me;
06067   int next;
06068 
06069   if (!dtd->scaffIndex) {
06070     dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
06071     if (!dtd->scaffIndex)
06072       return -1;
06073     dtd->scaffIndex[0] = 0;
06074   }
06075 
06076   if (dtd->scaffCount >= dtd->scaffSize) {
06077     CONTENT_SCAFFOLD *temp;
06078     if (dtd->scaffold) {
06079       temp = (CONTENT_SCAFFOLD *)
06080         REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
06081       if (temp == NULL)
06082         return -1;
06083       dtd->scaffSize *= 2;
06084     }
06085     else {
06086       temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
06087                                         * sizeof(CONTENT_SCAFFOLD));
06088       if (temp == NULL)
06089         return -1;
06090       dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
06091     }
06092     dtd->scaffold = temp;
06093   }
06094   next = dtd->scaffCount++;
06095   me = &dtd->scaffold[next];
06096   if (dtd->scaffLevel) {
06097     CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
06098     if (parent->lastchild) {
06099       dtd->scaffold[parent->lastchild].nextsib = next;
06100     }
06101     if (!parent->childcnt)
06102       parent->firstchild = next;
06103     parent->lastchild = next;
06104     parent->childcnt++;
06105   }
06106   me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
06107   return next;
06108 }
06109 
06110 static void
06111 build_node(XML_Parser parser,
06112            int src_node,
06113            XML_Content *dest,
06114            XML_Content **contpos,
06115            XML_Char **strpos)
06116 {
06117   DTD * const dtd = _dtd;  /* save one level of indirection */
06118   dest->type = dtd->scaffold[src_node].type;
06119   dest->quant = dtd->scaffold[src_node].quant;
06120   if (dest->type == XML_CTYPE_NAME) {
06121     const XML_Char *src;
06122     dest->name = *strpos;
06123     src = dtd->scaffold[src_node].name;
06124     for (;;) {
06125       *(*strpos)++ = *src;
06126       if (!*src)
06127         break;
06128       src++;
06129     }
06130     dest->numchildren = 0;
06131     dest->children = NULL;
06132   }
06133   else {
06134     unsigned int i;
06135     int cn;
06136     dest->numchildren = dtd->scaffold[src_node].childcnt;
06137     dest->children = *contpos;
06138     *contpos += dest->numchildren;
06139     for (i = 0, cn = dtd->scaffold[src_node].firstchild;
06140          i < dest->numchildren;
06141          i++, cn = dtd->scaffold[cn].nextsib) {
06142       build_node(parser, cn, &(dest->children[i]), contpos, strpos);
06143     }
06144     dest->name = NULL;
06145   }
06146 }
06147 
06148 static XML_Content *
06149 build_model (XML_Parser parser)
06150 {
06151   DTD * const dtd = _dtd;  /* save one level of indirection */
06152   XML_Content *ret;
06153   XML_Content *cpos;
06154   XML_Char * str;
06155   int allocsize = (dtd->scaffCount * sizeof(XML_Content)
06156                    + (dtd->contentStringLen * sizeof(XML_Char)));
06157 
06158   ret = (XML_Content *)MALLOC(allocsize);
06159   if (!ret)
06160     return NULL;
06161 
06162   str =  (XML_Char *) (&ret[dtd->scaffCount]);
06163   cpos = &ret[1];
06164 
06165   build_node(parser, 0, ret, &cpos, &str);
06166   return ret;
06167 }
06168 
06169 static ELEMENT_TYPE *
06170 getElementType(XML_Parser parser,
06171                const ENCODING *enc,
06172                const char *ptr,
06173                const char *end)
06174 {
06175   DTD * const dtd = _dtd;  /* save one level of indirection */
06176   const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
06177   ELEMENT_TYPE *ret;
06178 
06179   if (!name)
06180     return NULL;
06181   ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
06182   if (!ret)
06183     return NULL;
06184   if (ret->name != name)
06185     poolDiscard(&dtd->pool);
06186   else {
06187     poolFinish(&dtd->pool);
06188     if (!setElementTypePrefix(parser, ret))
06189       return NULL;
06190   }
06191   return ret;
06192 }