parser/expat/lib/xmlparse.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial