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