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