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