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        if (characterDataHandler) {
2556          if (MUST_CONVERT(enc, s)) {
2557            for (;;) {
2558              ICHAR *dataPtr = (ICHAR *)dataBuf;
2559              XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
2560              *eventEndPP = s;
2561              characterDataHandler(handlerArg, dataBuf,
2562                              (int)(dataPtr - (ICHAR *)dataBuf));
2563              if (s == next)
2564                break;
2565              *eventPP = s;
2566            }
2567          }
2568          else
2569            characterDataHandler(handlerArg,
2570                            (XML_Char *)s,
2571                            (int)((XML_Char *)next - (XML_Char *)s));
2572        }
2573        else if (defaultHandler)
2574          reportDefault(parser, enc, s, next);
2575      }
2576      break;
2577    case XML_TOK_PI:
2578      if (!reportProcessingInstruction(parser, enc, s, next))
2579        return XML_ERROR_NO_MEMORY;
2580      break;
2581    case XML_TOK_COMMENT:
2582      if (!reportComment(parser, enc, s, next))
2583        return XML_ERROR_NO_MEMORY;
2584      break;
2585    default:
2586      if (defaultHandler)
2587        reportDefault(parser, enc, s, next);
2588      break;
2589    }
2590    *eventPP = s = next;
2591    switch (ps_parsing) {
2592    case XML_SUSPENDED:
2593      *nextPtr = next;
2594      return XML_ERROR_NONE;
2595    case XML_FINISHED:
2596      return XML_ERROR_ABORTED;
2597    default: ;
2598    }
2599  }
2600  /* not reached */
2601}
2602
2603/* Precondition: all arguments must be non-NULL;
2604   Purpose:
2605   - normalize attributes
2606   - check attributes for well-formedness
2607   - generate namespace aware attribute names (URI, prefix)
2608   - build list of attributes for startElementHandler
2609   - default attributes
2610   - process namespace declarations (check and report them)
2611   - generate namespace aware element name (URI, prefix)
2612*/
2613static enum XML_Error
2614storeAtts(XML_Parser parser, const ENCODING *enc,
2615          const char *attStr, TAG_NAME *tagNamePtr,
2616          BINDING **bindingsPtr)
2617{
2618  DTD * const dtd = _dtd;  /* save one level of indirection */
2619  ELEMENT_TYPE *elementType;
2620  int nDefaultAtts;
2621  const XML_Char **appAtts;   /* the attribute list for the application */
2622  int attIndex = 0;
2623  int prefixLen;
2624  int i;
2625  int n;
2626  XML_Char *uri;
2627  int nPrefixes = 0;
2628  BINDING *binding;
2629  const XML_Char *localPart;
2630
2631  /* lookup the element type name */
2632  elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0);
2633  if (!elementType) {
2634    const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
2635    if (!name)
2636      return XML_ERROR_NO_MEMORY;
2637    elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name,
2638                                         sizeof(ELEMENT_TYPE));
2639    if (!elementType)
2640      return XML_ERROR_NO_MEMORY;
2641    if (ns && !setElementTypePrefix(parser, elementType))
2642      return XML_ERROR_NO_MEMORY;
2643  }
2644  nDefaultAtts = elementType->nDefaultAtts;
2645
2646  /* get the attributes from the tokenizer */
2647  n = XmlGetAttributes(enc, attStr, attsSize, atts);
2648  if (n + nDefaultAtts > attsSize) {
2649    int oldAttsSize = attsSize;
2650    ATTRIBUTE *temp;
2651    attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
2652    temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
2653    if (temp == NULL)
2654      return XML_ERROR_NO_MEMORY;
2655    atts = temp;
2656    if (n > oldAttsSize)
2657      XmlGetAttributes(enc, attStr, n, atts);
2658  }
2659
2660  appAtts = (const XML_Char **)atts;
2661  for (i = 0; i < n; i++) {
2662    /* add the name and value to the attribute list */
2663    ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
2664                                         atts[i].name
2665                                         + XmlNameLength(enc, atts[i].name));
2666    if (!attId)
2667      return XML_ERROR_NO_MEMORY;
2668    /* Detect duplicate attributes by their QNames. This does not work when
2669       namespace processing is turned on and different prefixes for the same
2670       namespace are used. For this case we have a check further down.
2671    */
2672    if ((attId->name)[-1]) {
2673      if (enc == encoding)
2674        eventPtr = atts[i].name;
2675      return XML_ERROR_DUPLICATE_ATTRIBUTE;
2676    }
2677    (attId->name)[-1] = 1;
2678    appAtts[attIndex++] = attId->name;
2679    if (!atts[i].normalized) {
2680      enum XML_Error result;
2681      XML_Bool isCdata = XML_TRUE;
2682
2683      /* figure out whether declared as other than CDATA */
2684      if (attId->maybeTokenized) {
2685        int j;
2686        for (j = 0; j < nDefaultAtts; j++) {
2687          if (attId == elementType->defaultAtts[j].id) {
2688            isCdata = elementType->defaultAtts[j].isCdata;
2689            break;
2690          }
2691        }
2692      }
2693
2694      /* normalize the attribute value */
2695      result = storeAttributeValue(parser, enc, isCdata,
2696                                   atts[i].valuePtr, atts[i].valueEnd,
2697                                   &tempPool);
2698      if (result)
2699        return result;
2700      appAtts[attIndex] = poolStart(&tempPool);
2701      poolFinish(&tempPool);
2702    }
2703    else {
2704      /* the value did not need normalizing */
2705      appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
2706                                          atts[i].valueEnd);
2707      if (appAtts[attIndex] == 0)
2708        return XML_ERROR_NO_MEMORY;
2709      poolFinish(&tempPool);
2710    }
2711    /* handle prefixed attribute names */
2712    if (attId->prefix) {
2713      if (attId->xmlns) {
2714        /* deal with namespace declarations here */
2715        enum XML_Error result = addBinding(parser, attId->prefix, attId,
2716                                           appAtts[attIndex], bindingsPtr);
2717        if (result)
2718          return result;
2719        --attIndex;
2720      }
2721      else {
2722        /* deal with other prefixed names later */
2723        attIndex++;
2724        nPrefixes++;
2725        (attId->name)[-1] = 2;
2726      }
2727    }
2728    else
2729      attIndex++;
2730  }
2731
2732  /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
2733  nSpecifiedAtts = attIndex;
2734  if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
2735    for (i = 0; i < attIndex; i += 2)
2736      if (appAtts[i] == elementType->idAtt->name) {
2737        idAttIndex = i;
2738        break;
2739      }
2740  }
2741  else
2742    idAttIndex = -1;
2743
2744  /* do attribute defaulting */
2745  for (i = 0; i < nDefaultAtts; i++) {
2746    const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
2747    if (!(da->id->name)[-1] && da->value) {
2748      if (da->id->prefix) {
2749        if (da->id->xmlns) {
2750          enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
2751                                             da->value, bindingsPtr);
2752          if (result)
2753            return result;
2754        }
2755        else {
2756          (da->id->name)[-1] = 2;
2757          nPrefixes++;
2758          appAtts[attIndex++] = da->id->name;
2759          appAtts[attIndex++] = da->value;
2760        }
2761      }
2762      else {
2763        (da->id->name)[-1] = 1;
2764        appAtts[attIndex++] = da->id->name;
2765        appAtts[attIndex++] = da->value;
2766      }
2767    }
2768  }
2769  appAtts[attIndex] = 0;
2770
2771  /* expand prefixed attribute names, check for duplicates,
2772     and clear flags that say whether attributes were specified */
2773  i = 0;
2774  if (nPrefixes) {
2775    int j;  /* hash table index */
2776    unsigned long version = nsAttsVersion;
2777    int nsAttsSize = (int)1 << nsAttsPower;
2778    /* size of hash table must be at least 2 * (# of prefixed attributes) */
2779    if ((nPrefixes << 1) >> nsAttsPower) {  /* true for nsAttsPower = 0 */
2780      NS_ATT *temp;
2781      /* hash table size must also be a power of 2 and >= 8 */
2782      while (nPrefixes >> nsAttsPower++);
2783      if (nsAttsPower < 3)
2784        nsAttsPower = 3;
2785      nsAttsSize = (int)1 << nsAttsPower;
2786      temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
2787      if (!temp)
2788        return XML_ERROR_NO_MEMORY;
2789      nsAtts = temp;
2790      version = 0;  /* force re-initialization of nsAtts hash table */
2791    }
2792    /* using a version flag saves us from initializing nsAtts every time */
2793    if (!version) {  /* initialize version flags when version wraps around */
2794      version = INIT_ATTS_VERSION;
2795      for (j = nsAttsSize; j != 0; )
2796        nsAtts[--j].version = version;
2797    }
2798    nsAttsVersion = --version;
2799
2800    /* expand prefixed names and check for duplicates */
2801    for (; i < attIndex; i += 2) {
2802      const XML_Char *s = appAtts[i];
2803      if (s[-1] == 2) {  /* prefixed */
2804        ATTRIBUTE_ID *id;
2805        const BINDING *b;
2806        unsigned long uriHash = 0;
2807        ((XML_Char *)s)[-1] = 0;  /* clear flag */
2808        id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);
2809        b = id->prefix->binding;
2810        if (!b)
2811          return XML_ERROR_UNBOUND_PREFIX;
2812
2813        /* as we expand the name we also calculate its hash value */
2814        for (j = 0; j < b->uriLen; j++) {
2815          const XML_Char c = b->uri[j];
2816          if (!poolAppendChar(&tempPool, c))
2817            return XML_ERROR_NO_MEMORY;
2818          uriHash = CHAR_HASH(uriHash, c);
2819        }
2820        while (*s++ != XML_T(ASCII_COLON))
2821          ;
2822        do {  /* copies null terminator */
2823          const XML_Char c = *s;
2824          if (!poolAppendChar(&tempPool, *s))
2825            return XML_ERROR_NO_MEMORY;
2826          uriHash = CHAR_HASH(uriHash, c);
2827        } while (*s++);
2828
2829        { /* Check hash table for duplicate of expanded name (uriName).
2830             Derived from code in lookup(HASH_TABLE *table, ...).
2831          */
2832          unsigned char step = 0;
2833          unsigned long mask = nsAttsSize - 1;
2834          j = uriHash & mask;  /* index into hash table */
2835          while (nsAtts[j].version == version) {
2836            /* for speed we compare stored hash values first */
2837            if (uriHash == nsAtts[j].hash) {
2838              const XML_Char *s1 = poolStart(&tempPool);
2839              const XML_Char *s2 = nsAtts[j].uriName;
2840              /* s1 is null terminated, but not s2 */
2841              for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
2842              if (*s1 == 0)
2843                return XML_ERROR_DUPLICATE_ATTRIBUTE;
2844            }
2845            if (!step)
2846              step = PROBE_STEP(uriHash, mask, nsAttsPower);
2847            j < step ? (j += nsAttsSize - step) : (j -= step);
2848          }
2849        }
2850
2851        if (ns_triplets) {  /* append namespace separator and prefix */
2852          tempPool.ptr[-1] = namespaceSeparator;
2853          s = b->prefix->name;
2854          do {
2855            if (!poolAppendChar(&tempPool, *s))
2856              return XML_ERROR_NO_MEMORY;
2857          } while (*s++);
2858        }
2859
2860        /* store expanded name in attribute list */
2861        s = poolStart(&tempPool);
2862        poolFinish(&tempPool);
2863        appAtts[i] = s;
2864
2865        /* fill empty slot with new version, uriName and hash value */
2866        nsAtts[j].version = version;
2867        nsAtts[j].hash = uriHash;
2868        nsAtts[j].uriName = s;
2869
2870        if (!--nPrefixes) {
2871          i += 2;
2872          break;
2873        }
2874      }
2875      else  /* not prefixed */
2876        ((XML_Char *)s)[-1] = 0;  /* clear flag */
2877    }
2878  }
2879  /* clear flags for the remaining attributes */
2880  for (; i < attIndex; i += 2)
2881    ((XML_Char *)(appAtts[i]))[-1] = 0;
2882  for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
2883    binding->attId->name[-1] = 0;
2884
2885  if (!ns)
2886    return XML_ERROR_NONE;
2887
2888  /* expand the element type name */
2889  if (elementType->prefix) {
2890    binding = elementType->prefix->binding;
2891    if (!binding)
2892      return XML_ERROR_UNBOUND_PREFIX;
2893    localPart = tagNamePtr->str;
2894    while (*localPart++ != XML_T(ASCII_COLON))
2895      ;
2896  }
2897  else if (dtd->defaultPrefix.binding) {
2898    binding = dtd->defaultPrefix.binding;
2899    localPart = tagNamePtr->str;
2900  }
2901  else
2902    return XML_ERROR_NONE;
2903  prefixLen = 0;
2904  if (ns_triplets && binding->prefix->name) {
2905    for (; binding->prefix->name[prefixLen++];)
2906      ;  /* prefixLen includes null terminator */
2907  }
2908  tagNamePtr->localPart = localPart;
2909  tagNamePtr->uriLen = binding->uriLen;
2910  tagNamePtr->prefix = binding->prefix->name;
2911  tagNamePtr->prefixLen = prefixLen;
2912  for (i = 0; localPart[i++];)
2913    ;  /* i includes null terminator */
2914  n = i + binding->uriLen + prefixLen;
2915  if (n > binding->uriAlloc) {
2916    TAG *p;
2917    uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
2918    if (!uri)
2919      return XML_ERROR_NO_MEMORY;
2920    binding->uriAlloc = n + EXPAND_SPARE;
2921    memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
2922    for (p = tagStack; p; p = p->parent)
2923      if (p->name.str == binding->uri)
2924        p->name.str = uri;
2925    FREE(binding->uri);
2926    binding->uri = uri;
2927  }
2928  /* if namespaceSeparator != '\0' then uri includes it already */
2929  uri = binding->uri + binding->uriLen;
2930  memcpy(uri, localPart, i * sizeof(XML_Char));
2931  /* we always have a namespace separator between localPart and prefix */
2932  if (prefixLen) {
2933    uri += i - 1;
2934    *uri = namespaceSeparator;  /* replace null terminator */
2935    memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
2936  }
2937  tagNamePtr->str = binding->uri;
2938  return XML_ERROR_NONE;
2939}
2940
2941/* addBinding() overwrites the value of prefix->binding without checking.
2942   Therefore one must keep track of the old value outside of addBinding().
2943*/
2944static enum XML_Error
2945addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
2946           const XML_Char *uri, BINDING **bindingsPtr)
2947{
2948  static const XML_Char xmlNamespace[] = {
2949    ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
2950    ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
2951    ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
2952    ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
2953    ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
2954    ASCII_e, '\0'
2955  };
2956  static const int xmlLen =
2957    (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
2958  static const XML_Char xmlnsNamespace[] = {
2959    ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
2960    ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
2961    ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
2962    ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
2963    ASCII_SLASH, '\0'
2964  };
2965  static const int xmlnsLen =
2966    (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
2967
2968  XML_Bool mustBeXML = XML_FALSE;
2969  XML_Bool isXML = XML_TRUE;
2970  XML_Bool isXMLNS = XML_TRUE;
2971
2972  BINDING *b;
2973  int len;
2974
2975  /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
2976  if (*uri == XML_T('\0') && prefix->name)
2977    return XML_ERROR_UNDECLARING_PREFIX;
2978
2979  if (prefix->name
2980      && prefix->name[0] == XML_T(ASCII_x)
2981      && prefix->name[1] == XML_T(ASCII_m)
2982      && prefix->name[2] == XML_T(ASCII_l)) {
2983
2984    /* Not allowed to bind xmlns */
2985    if (prefix->name[3] == XML_T(ASCII_n)
2986        && prefix->name[4] == XML_T(ASCII_s)
2987        && prefix->name[5] == XML_T('\0'))
2988      return XML_ERROR_RESERVED_PREFIX_XMLNS;
2989
2990    if (prefix->name[3] == XML_T('\0'))
2991      mustBeXML = XML_TRUE;
2992  }
2993
2994  for (len = 0; uri[len]; len++) {
2995    if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
2996      isXML = XML_FALSE;
2997
2998    if (!mustBeXML && isXMLNS
2999        && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3000      isXMLNS = XML_FALSE;
3001  }
3002  isXML = isXML && len == xmlLen;
3003  isXMLNS = isXMLNS && len == xmlnsLen;
3004
3005  if (mustBeXML != isXML)
3006    return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3007                     : XML_ERROR_RESERVED_NAMESPACE_URI;
3008
3009  if (isXMLNS)
3010    return XML_ERROR_RESERVED_NAMESPACE_URI;
3011
3012  if (namespaceSeparator)
3013    len++;
3014  if (freeBindingList) {
3015    b = freeBindingList;
3016    if (len > b->uriAlloc) {
3017      XML_Char *temp = (XML_Char *)REALLOC(b->uri,
3018                          sizeof(XML_Char) * (len + EXPAND_SPARE));
3019      if (temp == NULL)
3020        return XML_ERROR_NO_MEMORY;
3021      b->uri = temp;
3022      b->uriAlloc = len + EXPAND_SPARE;
3023    }
3024    freeBindingList = b->nextTagBinding;
3025  }
3026  else {
3027    b = (BINDING *)MALLOC(sizeof(BINDING));
3028    if (!b)
3029      return XML_ERROR_NO_MEMORY;
3030    b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
3031    if (!b->uri) {
3032      FREE(b);
3033      return XML_ERROR_NO_MEMORY;
3034    }
3035    b->uriAlloc = len + EXPAND_SPARE;
3036  }
3037  b->uriLen = len;
3038  memcpy(b->uri, uri, len * sizeof(XML_Char));
3039  if (namespaceSeparator)
3040    b->uri[len - 1] = namespaceSeparator;
3041  b->prefix = prefix;
3042  b->attId = attId;
3043  b->prevPrefixBinding = prefix->binding;
3044  /* NULL binding when default namespace undeclared */
3045  if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
3046    prefix->binding = NULL;
3047  else
3048    prefix->binding = b;
3049  b->nextTagBinding = *bindingsPtr;
3050  *bindingsPtr = b;
3051  /* if attId == NULL then we are not starting a namespace scope */
3052  if (attId && startNamespaceDeclHandler)
3053    startNamespaceDeclHandler(handlerArg, prefix->name,
3054                              prefix->binding ? uri : 0);
3055  return XML_ERROR_NONE;
3056}
3057
3058/* The idea here is to avoid using stack for each CDATA section when
3059   the whole file is parsed with one call.
3060*/
3061static enum XML_Error PTRCALL
3062cdataSectionProcessor(XML_Parser parser,
3063                      const char *start,
3064                      const char *end,
3065                      const char **endPtr)
3066{
3067  enum XML_Error result = doCdataSection(parser, encoding, &start, end,
3068                                         endPtr, (XML_Bool)!ps_finalBuffer);
3069  if (result != XML_ERROR_NONE)
3070    return result;
3071  if (start) {
3072    if (parentParser) {  /* we are parsing an external entity */
3073      processor = externalEntityContentProcessor;
3074      return externalEntityContentProcessor(parser, start, end, endPtr);
3075    }
3076    else {
3077      processor = contentProcessor;
3078      return contentProcessor(parser, start, end, endPtr);
3079    }
3080  }
3081  return result;
3082}
3083
3084/* startPtr gets set to non-null if the section is closed, and to null if
3085   the section is not yet closed.
3086*/
3087static enum XML_Error
3088doCdataSection(XML_Parser parser,
3089               const ENCODING *enc,
3090               const char **startPtr,
3091               const char *end,
3092               const char **nextPtr,
3093               XML_Bool haveMore)
3094{
3095  const char *s = *startPtr;
3096  const char **eventPP;
3097  const char **eventEndPP;
3098  if (enc == encoding) {
3099    eventPP = &eventPtr;
3100    *eventPP = s;
3101    eventEndPP = &eventEndPtr;
3102  }
3103  else {
3104    eventPP = &(openInternalEntities->internalEventPtr);
3105    eventEndPP = &(openInternalEntities->internalEventEndPtr);
3106  }
3107  *eventPP = s;
3108  *startPtr = NULL;
3109
3110  for (;;) {
3111    const char *next;
3112    int tok = XmlCdataSectionTok(enc, s, end, &next);
3113    *eventEndPP = next;
3114    switch (tok) {
3115    case XML_TOK_CDATA_SECT_CLOSE:
3116      if (endCdataSectionHandler)
3117        endCdataSectionHandler(handlerArg);
3118#if 0
3119      /* see comment under XML_TOK_CDATA_SECT_OPEN */
3120      else if (characterDataHandler)
3121        characterDataHandler(handlerArg, dataBuf, 0);
3122#endif
3123      else if (defaultHandler)
3124        reportDefault(parser, enc, s, next);
3125      *startPtr = next;
3126      *nextPtr = next;
3127      if (ps_parsing == XML_FINISHED)
3128        return XML_ERROR_ABORTED;
3129      else
3130        return XML_ERROR_NONE;
3131    case XML_TOK_DATA_NEWLINE:
3132      if (characterDataHandler) {
3133        XML_Char c = 0xA;
3134        characterDataHandler(handlerArg, &c, 1);
3135      }
3136      else if (defaultHandler)
3137        reportDefault(parser, enc, s, next);
3138      break;
3139    case XML_TOK_DATA_CHARS:
3140      {
3141        if (characterDataHandler) {
3142          if (MUST_CONVERT(enc, s)) {
3143            for (;;) {
3144              ICHAR *dataPtr = (ICHAR *)dataBuf;
3145              XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
3146              *eventEndPP = next;
3147              characterDataHandler(handlerArg, dataBuf,
3148                              (int)(dataPtr - (ICHAR *)dataBuf));
3149              if (s == next)
3150                break;
3151              *eventPP = s;
3152            }
3153          }
3154          else
3155            characterDataHandler(handlerArg,
3156                            (XML_Char *)s,
3157                            (int)((XML_Char *)next - (XML_Char *)s));
3158        }
3159        else if (defaultHandler)
3160          reportDefault(parser, enc, s, next);
3161      }
3162      break;
3163    case XML_TOK_INVALID:
3164      *eventPP = next;
3165      return XML_ERROR_INVALID_TOKEN;
3166    case XML_TOK_PARTIAL_CHAR:
3167      if (haveMore) {
3168        *nextPtr = s;
3169        return XML_ERROR_NONE;
3170      }
3171      return XML_ERROR_PARTIAL_CHAR;
3172    case XML_TOK_PARTIAL:
3173    case XML_TOK_NONE:
3174      if (haveMore) {
3175        *nextPtr = s;
3176        return XML_ERROR_NONE;
3177      }
3178      return XML_ERROR_UNCLOSED_CDATA_SECTION;
3179    default:
3180      *eventPP = next;
3181      return XML_ERROR_UNEXPECTED_STATE;
3182    }
3183
3184    *eventPP = s = next;
3185    switch (ps_parsing) {
3186    case XML_SUSPENDED:
3187      *nextPtr = next;
3188      return XML_ERROR_NONE;
3189    case XML_FINISHED:
3190      return XML_ERROR_ABORTED;
3191    default: ;
3192    }
3193  }
3194  /* not reached */
3195}
3196
3197#ifdef XML_DTD
3198
3199/* The idea here is to avoid using stack for each IGNORE section when
3200   the whole file is parsed with one call.
3201*/
3202static enum XML_Error PTRCALL
3203ignoreSectionProcessor(XML_Parser parser,
3204                       const char *start,
3205                       const char *end,
3206                       const char **endPtr)
3207{
3208  enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
3209                                          endPtr, (XML_Bool)!ps_finalBuffer);
3210  if (result != XML_ERROR_NONE)
3211    return result;
3212  if (start) {
3213    processor = prologProcessor;
3214    return prologProcessor(parser, start, end, endPtr);
3215  }
3216  return result;
3217}
3218
3219/* startPtr gets set to non-null is the section is closed, and to null
3220   if the section is not yet closed.
3221*/
3222static enum XML_Error
3223doIgnoreSection(XML_Parser parser,
3224                const ENCODING *enc,
3225                const char **startPtr,
3226                const char *end,
3227                const char **nextPtr,
3228                XML_Bool haveMore)
3229{
3230  const char *next;
3231  int tok;
3232  const char *s = *startPtr;
3233  const char **eventPP;
3234  const char **eventEndPP;
3235  if (enc == encoding) {
3236    eventPP = &eventPtr;
3237    *eventPP = s;
3238    eventEndPP = &eventEndPtr;
3239  }
3240  else {
3241    eventPP = &(openInternalEntities->internalEventPtr);
3242    eventEndPP = &(openInternalEntities->internalEventEndPtr);
3243  }
3244  *eventPP = s;
3245  *startPtr = NULL;
3246  tok = XmlIgnoreSectionTok(enc, s, end, &next);
3247  *eventEndPP = next;
3248  switch (tok) {
3249  case XML_TOK_IGNORE_SECT:
3250    if (defaultHandler)
3251      reportDefault(parser, enc, s, next);
3252    *startPtr = next;
3253    *nextPtr = next;
3254    if (ps_parsing == XML_FINISHED)
3255      return XML_ERROR_ABORTED;
3256    else
3257      return XML_ERROR_NONE;
3258  case XML_TOK_INVALID:
3259    *eventPP = next;
3260    return XML_ERROR_INVALID_TOKEN;
3261  case XML_TOK_PARTIAL_CHAR:
3262    if (haveMore) {
3263      *nextPtr = s;
3264      return XML_ERROR_NONE;
3265    }
3266    return XML_ERROR_PARTIAL_CHAR;
3267  case XML_TOK_PARTIAL:
3268  case XML_TOK_NONE:
3269    if (haveMore) {
3270      *nextPtr = s;
3271      return XML_ERROR_NONE;
3272    }
3273    return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3274  default:
3275    *eventPP = next;
3276    return XML_ERROR_UNEXPECTED_STATE;
3277  }
3278  /* not reached */
3279}
3280
3281#endif /* XML_DTD */
3282
3283static enum XML_Error
3284initializeEncoding(XML_Parser parser)
3285{
3286  const char *s;
3287#ifdef XML_UNICODE
3288  char encodingBuf[128];
3289  if (!protocolEncodingName)
3290    s = NULL;
3291  else {
3292    int i;
3293    for (i = 0; protocolEncodingName[i]; i++) {
3294      if (i == sizeof(encodingBuf) - 1
3295          || (protocolEncodingName[i] & ~0x7f) != 0) {
3296        encodingBuf[0] = '\0';
3297        break;
3298      }
3299      encodingBuf[i] = (char)protocolEncodingName[i];
3300    }
3301    encodingBuf[i] = '\0';
3302    s = encodingBuf;
3303  }
3304#else
3305  s = protocolEncodingName;
3306#endif
3307  if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
3308    return XML_ERROR_NONE;
3309  return handleUnknownEncoding(parser, protocolEncodingName);
3310}
3311
3312static enum XML_Error
3313processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
3314               const char *s, const char *next)
3315{
3316  const char *encodingName = NULL;
3317  const XML_Char *storedEncName = NULL;
3318  const ENCODING *newEncoding = NULL;
3319  const char *version = NULL;
3320  const char *versionend;
3321  const XML_Char *storedversion = NULL;
3322  int standalone = -1;
3323  if (!(ns
3324        ? XmlParseXmlDeclNS
3325        : XmlParseXmlDecl)(isGeneralTextEntity,
3326                           encoding,
3327                           s,
3328                           next,
3329                           &eventPtr,
3330                           &version,
3331                           &versionend,
3332                           &encodingName,
3333                           &newEncoding,
3334                           &standalone)) {
3335    if (isGeneralTextEntity)
3336      return XML_ERROR_TEXT_DECL;
3337    else
3338      return XML_ERROR_XML_DECL;
3339  }
3340  if (!isGeneralTextEntity && standalone == 1) {
3341    _dtd->standalone = XML_TRUE;
3342#ifdef XML_DTD
3343    if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
3344      paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
3345#endif /* XML_DTD */
3346  }
3347  if (xmlDeclHandler) {
3348    if (encodingName != NULL) {
3349      storedEncName = poolStoreString(&temp2Pool,
3350                                      encoding,
3351                                      encodingName,
3352                                      encodingName
3353                                      + XmlNameLength(encoding, encodingName));
3354      if (!storedEncName)
3355              return XML_ERROR_NO_MEMORY;
3356      poolFinish(&temp2Pool);
3357    }
3358    if (version) {
3359      storedversion = poolStoreString(&temp2Pool,
3360                                      encoding,
3361                                      version,
3362                                      versionend - encoding->minBytesPerChar);
3363      if (!storedversion)
3364        return XML_ERROR_NO_MEMORY;
3365    }
3366    xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
3367  }
3368  else if (defaultHandler)
3369    reportDefault(parser, encoding, s, next);
3370  if (protocolEncodingName == NULL) {
3371    if (newEncoding) {
3372      if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
3373        eventPtr = encodingName;
3374        return XML_ERROR_INCORRECT_ENCODING;
3375      }
3376      encoding = newEncoding;
3377    }
3378    else if (encodingName) {
3379      enum XML_Error result;
3380      if (!storedEncName) {
3381        storedEncName = poolStoreString(
3382          &temp2Pool, encoding, encodingName,
3383          encodingName + XmlNameLength(encoding, encodingName));
3384        if (!storedEncName)
3385          return XML_ERROR_NO_MEMORY;
3386      }
3387      result = handleUnknownEncoding(parser, storedEncName);
3388      poolClear(&temp2Pool);
3389      if (result == XML_ERROR_UNKNOWN_ENCODING)
3390        eventPtr = encodingName;
3391      return result;
3392    }
3393  }
3394
3395  if (storedEncName || storedversion)
3396    poolClear(&temp2Pool);
3397
3398  return XML_ERROR_NONE;
3399}
3400
3401static enum XML_Error
3402handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
3403{
3404  if (unknownEncodingHandler) {
3405    XML_Encoding info;
3406    int i;
3407    for (i = 0; i < 256; i++)
3408      info.map[i] = -1;
3409    info.convert = NULL;
3410    info.data = NULL;
3411    info.release = NULL;
3412    if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
3413                               &info)) {
3414      ENCODING *enc;
3415      unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
3416      if (!unknownEncodingMem) {
3417        if (info.release)
3418          info.release(info.data);
3419        return XML_ERROR_NO_MEMORY;
3420      }
3421      enc = (ns
3422             ? XmlInitUnknownEncodingNS
3423             : XmlInitUnknownEncoding)(unknownEncodingMem,
3424                                       info.map,
3425                                       info.convert,
3426                                       info.data);
3427      if (enc) {
3428        unknownEncodingData = info.data;
3429        unknownEncodingRelease = info.release;
3430        encoding = enc;
3431        return XML_ERROR_NONE;
3432      }
3433    }
3434    if (info.release != NULL)
3435      info.release(info.data);
3436  }
3437  return XML_ERROR_UNKNOWN_ENCODING;
3438}
3439
3440static enum XML_Error PTRCALL
3441prologInitProcessor(XML_Parser parser,
3442                    const char *s,
3443                    const char *end,
3444                    const char **nextPtr)
3445{
3446  enum XML_Error result = initializeEncoding(parser);
3447  if (result != XML_ERROR_NONE)
3448    return result;
3449  processor = prologProcessor;
3450  return prologProcessor(parser, s, end, nextPtr);
3451}
3452
3453#ifdef XML_DTD
3454
3455static enum XML_Error PTRCALL
3456externalParEntInitProcessor(XML_Parser parser,
3457                            const char *s,
3458                            const char *end,
3459                            const char **nextPtr)
3460{
3461  enum XML_Error result = initializeEncoding(parser);
3462  if (result != XML_ERROR_NONE)
3463    return result;
3464
3465  /* we know now that XML_Parse(Buffer) has been called,
3466     so we consider the external parameter entity read */
3467  _dtd->paramEntityRead = XML_TRUE;
3468
3469  if (prologState.inEntityValue) {
3470    processor = entityValueInitProcessor;
3471    return entityValueInitProcessor(parser, s, end, nextPtr);
3472  }
3473  else {
3474    processor = externalParEntProcessor;
3475    return externalParEntProcessor(parser, s, end, nextPtr);
3476  }
3477}
3478
3479static enum XML_Error PTRCALL
3480entityValueInitProcessor(XML_Parser parser,
3481                         const char *s,
3482                         const char *end,
3483                         const char **nextPtr)
3484{
3485  int tok;
3486  const char *start = s;
3487  const char *next = start;
3488  eventPtr = start;
3489
3490  for (;;) {
3491    tok = XmlPrologTok(encoding, start, end, &next);
3492    eventEndPtr = next;
3493    if (tok <= 0) {
3494      if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3495        *nextPtr = s;
3496        return XML_ERROR_NONE;
3497      }
3498      switch (tok) {
3499      case XML_TOK_INVALID:
3500        return XML_ERROR_INVALID_TOKEN;
3501      case XML_TOK_PARTIAL:
3502        return XML_ERROR_UNCLOSED_TOKEN;
3503      case XML_TOK_PARTIAL_CHAR:
3504        return XML_ERROR_PARTIAL_CHAR;
3505      case XML_TOK_NONE:   /* start == end */
3506      default:
3507        break;
3508      }
3509      /* found end of entity value - can store it now */
3510      return storeEntityValue(parser, encoding, s, end);
3511    }
3512    else if (tok == XML_TOK_XML_DECL) {
3513      enum XML_Error result;
3514      result = processXmlDecl(parser, 0, start, next);
3515      if (result != XML_ERROR_NONE)
3516        return result;
3517      switch (ps_parsing) {
3518      case XML_SUSPENDED:
3519        *nextPtr = next;
3520        return XML_ERROR_NONE;
3521      case XML_FINISHED:
3522        return XML_ERROR_ABORTED;
3523      default:
3524        *nextPtr = next;
3525      }
3526      /* stop scanning for text declaration - we found one */
3527      processor = entityValueProcessor;
3528      return entityValueProcessor(parser, next, end, nextPtr);
3529    }
3530    /* If we are at the end of the buffer, this would cause XmlPrologTok to
3531       return XML_TOK_NONE on the next call, which would then cause the
3532       function to exit with *nextPtr set to s - that is what we want for other
3533       tokens, but not for the BOM - we would rather like to skip it;
3534       then, when this routine is entered the next time, XmlPrologTok will
3535       return XML_TOK_INVALID, since the BOM is still in the buffer
3536    */
3537    else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
3538      *nextPtr = next;
3539      return XML_ERROR_NONE;
3540    }
3541    start = next;
3542    eventPtr = start;
3543  }
3544}
3545
3546static enum XML_Error PTRCALL
3547externalParEntProcessor(XML_Parser parser,
3548                        const char *s,
3549                        const char *end,
3550                        const char **nextPtr)
3551{
3552  const char *next = s;
3553  int tok;
3554
3555  tok = XmlPrologTok(encoding, s, end, &next);
3556  if (tok <= 0) {
3557    if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3558      *nextPtr = s;
3559      return XML_ERROR_NONE;
3560    }
3561    switch (tok) {
3562    case XML_TOK_INVALID:
3563      return XML_ERROR_INVALID_TOKEN;
3564    case XML_TOK_PARTIAL:
3565      return XML_ERROR_UNCLOSED_TOKEN;
3566    case XML_TOK_PARTIAL_CHAR:
3567      return XML_ERROR_PARTIAL_CHAR;
3568    case XML_TOK_NONE:   /* start == end */
3569    default:
3570      break;
3571    }
3572  }
3573  /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
3574     However, when parsing an external subset, doProlog will not accept a BOM
3575     as valid, and report a syntax error, so we have to skip the BOM
3576  */
3577  else if (tok == XML_TOK_BOM) {
3578    s = next;
3579    tok = XmlPrologTok(encoding, s, end, &next);
3580  }
3581
3582  processor = prologProcessor;
3583  return doProlog(parser, encoding, s, end, tok, next,
3584                  nextPtr, (XML_Bool)!ps_finalBuffer);
3585}
3586
3587static enum XML_Error PTRCALL
3588entityValueProcessor(XML_Parser parser,
3589                     const char *s,
3590                     const char *end,
3591                     const char **nextPtr)
3592{
3593  const char *start = s;
3594  const char *next = s;
3595  const ENCODING *enc = encoding;
3596  int tok;
3597
3598  for (;;) {
3599    tok = XmlPrologTok(enc, start, end, &next);
3600    if (tok <= 0) {
3601      if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3602        *nextPtr = s;
3603        return XML_ERROR_NONE;
3604      }
3605      switch (tok) {
3606      case XML_TOK_INVALID:
3607        return XML_ERROR_INVALID_TOKEN;
3608      case XML_TOK_PARTIAL:
3609        return XML_ERROR_UNCLOSED_TOKEN;
3610      case XML_TOK_PARTIAL_CHAR:
3611        return XML_ERROR_PARTIAL_CHAR;
3612      case XML_TOK_NONE:   /* start == end */
3613      default:
3614        break;
3615      }
3616      /* found end of entity value - can store it now */
3617      return storeEntityValue(parser, enc, s, end);
3618    }
3619    start = next;
3620  }
3621}
3622
3623#endif /* XML_DTD */
3624
3625static enum XML_Error PTRCALL
3626prologProcessor(XML_Parser parser,
3627                const char *s,
3628                const char *end,
3629                const char **nextPtr)
3630{
3631  const char *next = s;
3632  int tok = XmlPrologTok(encoding, s, end, &next);
3633  return doProlog(parser, encoding, s, end, tok, next,
3634                  nextPtr, (XML_Bool)!ps_finalBuffer);
3635}
3636
3637static enum XML_Error
3638doProlog(XML_Parser parser,
3639         const ENCODING *enc,
3640         const char *s,
3641         const char *end,
3642         int tok,
3643         const char *next,
3644         const char **nextPtr,
3645         XML_Bool haveMore)
3646{
3647#ifdef XML_DTD
3648  static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
3649#endif /* XML_DTD */
3650  static const XML_Char atypeCDATA[] =
3651      { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
3652  static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
3653  static const XML_Char atypeIDREF[] =
3654      { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
3655  static const XML_Char atypeIDREFS[] =
3656      { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
3657  static const XML_Char atypeENTITY[] =
3658      { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
3659  static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
3660      ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
3661  static const XML_Char atypeNMTOKEN[] = {
3662      ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
3663  static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
3664      ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
3665  static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
3666      ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
3667  static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
3668  static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
3669
3670  /* save one level of indirection */
3671  DTD * const dtd = _dtd;
3672
3673  const char **eventPP;
3674  const char **eventEndPP;
3675  enum XML_Content_Quant quant;
3676
3677  if (enc == encoding) {
3678    eventPP = &eventPtr;
3679    eventEndPP = &eventEndPtr;
3680  }
3681  else {
3682    eventPP = &(openInternalEntities->internalEventPtr);
3683    eventEndPP = &(openInternalEntities->internalEventEndPtr);
3684  }
3685
3686  for (;;) {
3687    int role;
3688    XML_Bool handleDefault = XML_TRUE;
3689    *eventPP = s;
3690    *eventEndPP = next;
3691    if (tok <= 0) {
3692      if (haveMore && tok != XML_TOK_INVALID) {
3693        *nextPtr = s;
3694        return XML_ERROR_NONE;
3695      }
3696      switch (tok) {
3697      case XML_TOK_INVALID:
3698        *eventPP = next;
3699        return XML_ERROR_INVALID_TOKEN;
3700      case XML_TOK_PARTIAL:
3701        return XML_ERROR_UNCLOSED_TOKEN;
3702      case XML_TOK_PARTIAL_CHAR:
3703        return XML_ERROR_PARTIAL_CHAR;
3704      case XML_TOK_NONE:
3705#ifdef XML_DTD
3706        /* for internal PE NOT referenced between declarations */
3707        if (enc != encoding && !openInternalEntities->betweenDecl) {
3708          *nextPtr = s;
3709          return XML_ERROR_NONE;
3710        }
3711        /* WFC: PE Between Declarations - must check that PE contains
3712           complete markup, not only for external PEs, but also for
3713           internal PEs if the reference occurs between declarations.
3714        */
3715        if (isParamEntity || enc != encoding) {
3716          if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
3717              == XML_ROLE_ERROR)
3718            return XML_ERROR_INCOMPLETE_PE;
3719          *nextPtr = s;
3720          return XML_ERROR_NONE;
3721        }
3722#endif /* XML_DTD */
3723        return XML_ERROR_NO_ELEMENTS;
3724      default:
3725        tok = -tok;
3726        next = end;
3727        break;
3728      }
3729    }
3730    role = XmlTokenRole(&prologState, tok, s, next, enc);
3731    switch (role) {
3732    case XML_ROLE_XML_DECL:
3733      {
3734        enum XML_Error result = processXmlDecl(parser, 0, s, next);
3735        if (result != XML_ERROR_NONE)
3736          return result;
3737        enc = encoding;
3738        handleDefault = XML_FALSE;
3739      }
3740      break;
3741    case XML_ROLE_DOCTYPE_NAME:
3742      if (startDoctypeDeclHandler) {
3743        doctypeName = poolStoreString(&tempPool, enc, s, next);
3744        if (!doctypeName)
3745          return XML_ERROR_NO_MEMORY;
3746        poolFinish(&tempPool);
3747        doctypePubid = NULL;
3748        handleDefault = XML_FALSE;
3749      }
3750      doctypeSysid = NULL; /* always initialize to NULL */
3751      break;
3752    case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
3753      if (startDoctypeDeclHandler) {
3754        startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
3755                                doctypePubid, 1);
3756        doctypeName = NULL;
3757        poolClear(&tempPool);
3758        handleDefault = XML_FALSE;
3759      }
3760      break;
3761#ifdef XML_DTD
3762    case XML_ROLE_TEXT_DECL:
3763      {
3764        enum XML_Error result = processXmlDecl(parser, 1, s, next);
3765        if (result != XML_ERROR_NONE)
3766          return result;
3767        enc = encoding;
3768        handleDefault = XML_FALSE;
3769      }
3770      break;
3771#endif /* XML_DTD */
3772    case XML_ROLE_DOCTYPE_PUBLIC_ID:
3773#ifdef XML_DTD
3774      useForeignDTD = XML_FALSE;
3775      declEntity = (ENTITY *)lookup(&dtd->paramEntities,
3776                                    externalSubsetName,
3777                                    sizeof(ENTITY));
3778      if (!declEntity)
3779        return XML_ERROR_NO_MEMORY;
3780#endif /* XML_DTD */
3781      dtd->hasParamEntityRefs = XML_TRUE;
3782      if (startDoctypeDeclHandler) {
3783        if (!XmlIsPublicId(enc, s, next, eventPP))
3784          return XML_ERROR_PUBLICID;
3785        doctypePubid = poolStoreString(&tempPool, enc,
3786                                       s + enc->minBytesPerChar,
3787                                       next - enc->minBytesPerChar);
3788        if (!doctypePubid)
3789          return XML_ERROR_NO_MEMORY;
3790        normalizePublicId((XML_Char *)doctypePubid);
3791        poolFinish(&tempPool);
3792        handleDefault = XML_FALSE;
3793        goto alreadyChecked;
3794      }
3795      /* fall through */
3796    case XML_ROLE_ENTITY_PUBLIC_ID:
3797      if (!XmlIsPublicId(enc, s, next, eventPP))
3798        return XML_ERROR_PUBLICID;
3799    alreadyChecked:
3800      if (dtd->keepProcessing && declEntity) {
3801        XML_Char *tem = poolStoreString(&dtd->pool,
3802                                        enc,
3803                                        s + enc->minBytesPerChar,
3804                                        next - enc->minBytesPerChar);
3805        if (!tem)
3806          return XML_ERROR_NO_MEMORY;
3807        normalizePublicId(tem);
3808        declEntity->publicId = tem;
3809        poolFinish(&dtd->pool);
3810        if (entityDeclHandler)
3811          handleDefault = XML_FALSE;
3812      }
3813      break;
3814    case XML_ROLE_DOCTYPE_CLOSE:
3815      if (doctypeName) {
3816        startDoctypeDeclHandler(handlerArg, doctypeName,
3817                                doctypeSysid, doctypePubid, 0);
3818        poolClear(&tempPool);
3819        handleDefault = XML_FALSE;
3820      }
3821      /* doctypeSysid will be non-NULL in the case of a previous
3822         XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
3823         was not set, indicating an external subset
3824      */
3825#ifdef XML_DTD
3826      if (doctypeSysid || useForeignDTD) {
3827        XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3828        dtd->hasParamEntityRefs = XML_TRUE;
3829        if (paramEntityParsing && externalEntityRefHandler) {
3830          ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
3831                                            externalSubsetName,
3832                                            sizeof(ENTITY));
3833          if (!entity)
3834            return XML_ERROR_NO_MEMORY;
3835          if (useForeignDTD)
3836            entity->base = curBase;
3837          dtd->paramEntityRead = XML_FALSE;
3838          if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3839                                        0,
3840                                        entity->base,
3841                                        entity->systemId,
3842                                        entity->publicId))
3843            return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3844          if (dtd->paramEntityRead) {
3845            if (!dtd->standalone &&
3846                notStandaloneHandler &&
3847                !notStandaloneHandler(handlerArg))
3848              return XML_ERROR_NOT_STANDALONE;
3849          }
3850          /* if we didn't read the foreign DTD then this means that there
3851             is no external subset and we must reset dtd->hasParamEntityRefs
3852          */
3853          else if (!doctypeSysid)
3854            dtd->hasParamEntityRefs = hadParamEntityRefs;
3855          /* end of DTD - no need to update dtd->keepProcessing */
3856        }
3857        useForeignDTD = XML_FALSE;
3858      }
3859#endif /* XML_DTD */
3860      if (endDoctypeDeclHandler) {
3861        endDoctypeDeclHandler(handlerArg);
3862        handleDefault = XML_FALSE;
3863      }
3864      break;
3865    case XML_ROLE_INSTANCE_START:
3866#ifdef XML_DTD
3867      /* if there is no DOCTYPE declaration then now is the
3868         last chance to read the foreign DTD
3869      */
3870      if (useForeignDTD) {
3871        XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3872        dtd->hasParamEntityRefs = XML_TRUE;
3873        if (paramEntityParsing && externalEntityRefHandler) {
3874          ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
3875                                            externalSubsetName,
3876                                            sizeof(ENTITY));
3877          if (!entity)
3878            return XML_ERROR_NO_MEMORY;
3879          entity->base = curBase;
3880          dtd->paramEntityRead = XML_FALSE;
3881          if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3882                                        0,
3883                                        entity->base,
3884                                        entity->systemId,
3885                                        entity->publicId))
3886            return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3887          if (dtd->paramEntityRead) {
3888            if (!dtd->standalone &&
3889                notStandaloneHandler &&
3890                !notStandaloneHandler(handlerArg))
3891              return XML_ERROR_NOT_STANDALONE;
3892          }
3893          /* if we didn't read the foreign DTD then this means that there
3894             is no external subset and we must reset dtd->hasParamEntityRefs
3895          */
3896          else
3897            dtd->hasParamEntityRefs = hadParamEntityRefs;
3898          /* end of DTD - no need to update dtd->keepProcessing */
3899        }
3900      }
3901#endif /* XML_DTD */
3902      processor = contentProcessor;
3903      return contentProcessor(parser, s, end, nextPtr);
3904    case XML_ROLE_ATTLIST_ELEMENT_NAME:
3905      declElementType = getElementType(parser, enc, s, next);
3906      if (!declElementType)
3907        return XML_ERROR_NO_MEMORY;
3908      goto checkAttListDeclHandler;
3909    case XML_ROLE_ATTRIBUTE_NAME:
3910      declAttributeId = getAttributeId(parser, enc, s, next);
3911      if (!declAttributeId)
3912        return XML_ERROR_NO_MEMORY;
3913      declAttributeIsCdata = XML_FALSE;
3914      declAttributeType = NULL;
3915      declAttributeIsId = XML_FALSE;
3916      goto checkAttListDeclHandler;
3917    case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
3918      declAttributeIsCdata = XML_TRUE;
3919      declAttributeType = atypeCDATA;
3920      goto checkAttListDeclHandler;
3921    case XML_ROLE_ATTRIBUTE_TYPE_ID:
3922      declAttributeIsId = XML_TRUE;
3923      declAttributeType = atypeID;
3924      goto checkAttListDeclHandler;
3925    case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
3926      declAttributeType = atypeIDREF;
3927      goto checkAttListDeclHandler;
3928    case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
3929      declAttributeType = atypeIDREFS;
3930      goto checkAttListDeclHandler;
3931    case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
3932      declAttributeType = atypeENTITY;
3933      goto checkAttListDeclHandler;
3934    case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
3935      declAttributeType = atypeENTITIES;
3936      goto checkAttListDeclHandler;
3937    case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
3938      declAttributeType = atypeNMTOKEN;
3939      goto checkAttListDeclHandler;
3940    case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
3941      declAttributeType = atypeNMTOKENS;
3942    checkAttListDeclHandler:
3943      if (dtd->keepProcessing && attlistDeclHandler)
3944        handleDefault = XML_FALSE;
3945      break;
3946    case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
3947    case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
3948      if (dtd->keepProcessing && attlistDeclHandler) {
3949        const XML_Char *prefix;
3950        if (declAttributeType) {
3951          prefix = enumValueSep;
3952        }
3953        else {
3954          prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
3955                    ? notationPrefix
3956                    : enumValueStart);
3957        }
3958        if (!poolAppendString(&tempPool, prefix))
3959          return XML_ERROR_NO_MEMORY;
3960        if (!poolAppend(&tempPool, enc, s, next))
3961          return XML_ERROR_NO_MEMORY;
3962        declAttributeType = tempPool.start;
3963        handleDefault = XML_FALSE;
3964      }
3965      break;
3966    case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
3967    case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
3968      if (dtd->keepProcessing) {
3969        if (!defineAttribute(declElementType, declAttributeId,
3970                             declAttributeIsCdata, declAttributeIsId,
3971                             0, parser))
3972          return XML_ERROR_NO_MEMORY;
3973        if (attlistDeclHandler && declAttributeType) {
3974          if (*declAttributeType == XML_T(ASCII_LPAREN)
3975              || (*declAttributeType == XML_T(ASCII_N)
3976                  && declAttributeType[1] == XML_T(ASCII_O))) {
3977            /* Enumerated or Notation type */
3978            if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
3979                || !poolAppendChar(&tempPool, XML_T('\0')))
3980              return XML_ERROR_NO_MEMORY;
3981            declAttributeType = tempPool.start;
3982            poolFinish(&tempPool);
3983          }
3984          *eventEndPP = s;
3985          attlistDeclHandler(handlerArg, declElementType->name,
3986                             declAttributeId->name, declAttributeType,
3987                             0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
3988          poolClear(&tempPool);
3989          handleDefault = XML_FALSE;
3990        }
3991      }
3992      break;
3993    case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
3994    case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
3995      if (dtd->keepProcessing) {
3996        const XML_Char *attVal;
3997        enum XML_Error result =
3998          storeAttributeValue(parser, enc, declAttributeIsCdata,
3999                              s + enc->minBytesPerChar,
4000                              next - enc->minBytesPerChar,
4001                              &dtd->pool);
4002        if (result)
4003          return result;
4004        attVal = poolStart(&dtd->pool);
4005        poolFinish(&dtd->pool);
4006        /* ID attributes aren't allowed to have a default */
4007        if (!defineAttribute(declElementType, declAttributeId,
4008                             declAttributeIsCdata, XML_FALSE, attVal, parser))
4009          return XML_ERROR_NO_MEMORY;
4010        if (attlistDeclHandler && declAttributeType) {
4011          if (*declAttributeType == XML_T(ASCII_LPAREN)
4012              || (*declAttributeType == XML_T(ASCII_N)
4013                  && declAttributeType[1] == XML_T(ASCII_O))) {
4014            /* Enumerated or Notation type */
4015            if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4016                || !poolAppendChar(&tempPool, XML_T('\0')))
4017              return XML_ERROR_NO_MEMORY;
4018            declAttributeType = tempPool.start;
4019            poolFinish(&tempPool);
4020          }
4021          *eventEndPP = s;
4022          attlistDeclHandler(handlerArg, declElementType->name,
4023                             declAttributeId->name, declAttributeType,
4024                             attVal,
4025                             role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
4026          poolClear(&tempPool);
4027          handleDefault = XML_FALSE;
4028        }
4029      }
4030      break;
4031    case XML_ROLE_ENTITY_VALUE:
4032      if (dtd->keepProcessing) {
4033        enum XML_Error result = storeEntityValue(parser, enc,
4034                                            s + enc->minBytesPerChar,
4035                                            next - enc->minBytesPerChar);
4036        if (declEntity) {
4037          declEntity->textPtr = poolStart(&dtd->entityValuePool);
4038          declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
4039          poolFinish(&dtd->entityValuePool);
4040          if (entityDeclHandler) {
4041            *eventEndPP = s;
4042            entityDeclHandler(handlerArg,
4043                              declEntity->name,
4044                              declEntity->is_param,
4045                              declEntity->textPtr,
4046                              declEntity->textLen,
4047                              curBase, 0, 0, 0);
4048            handleDefault = XML_FALSE;
4049          }
4050        }
4051        else
4052          poolDiscard(&dtd->entityValuePool);
4053        if (result != XML_ERROR_NONE)
4054          return result;
4055      }
4056      break;
4057    case XML_ROLE_DOCTYPE_SYSTEM_ID:
4058#ifdef XML_DTD
4059      useForeignDTD = XML_FALSE;
4060#endif /* XML_DTD */
4061      dtd->hasParamEntityRefs = XML_TRUE;
4062      if (startDoctypeDeclHandler) {
4063        doctypeSysid = poolStoreString(&tempPool, enc,
4064                                       s + enc->minBytesPerChar,
4065                                       next - enc->minBytesPerChar);
4066        if (doctypeSysid == NULL)
4067          return XML_ERROR_NO_MEMORY;
4068        poolFinish(&tempPool);
4069        handleDefault = XML_FALSE;
4070      }
4071#ifdef XML_DTD
4072      else
4073        /* use externalSubsetName to make doctypeSysid non-NULL
4074           for the case where no startDoctypeDeclHandler is set */
4075        doctypeSysid = externalSubsetName;
4076#endif /* XML_DTD */
4077      if (!dtd->standalone
4078#ifdef XML_DTD
4079          && !paramEntityParsing
4080#endif /* XML_DTD */
4081          && notStandaloneHandler
4082          && !notStandaloneHandler(handlerArg))
4083        return XML_ERROR_NOT_STANDALONE;
4084#ifndef XML_DTD
4085      break;
4086#else /* XML_DTD */
4087      if (!declEntity) {
4088        declEntity = (ENTITY *)lookup(&dtd->paramEntities,
4089                                      externalSubsetName,
4090                                      sizeof(ENTITY));
4091        if (!declEntity)
4092          return XML_ERROR_NO_MEMORY;
4093        declEntity->publicId = NULL;
4094      }
4095      /* fall through */
4096#endif /* XML_DTD */
4097    case XML_ROLE_ENTITY_SYSTEM_ID:
4098      if (dtd->keepProcessing && declEntity) {
4099        declEntity->systemId = poolStoreString(&dtd->pool, enc,
4100                                               s + enc->minBytesPerChar,
4101                                               next - enc->minBytesPerChar);
4102        if (!declEntity->systemId)
4103          return XML_ERROR_NO_MEMORY;
4104        declEntity->base = curBase;
4105        poolFinish(&dtd->pool);
4106        if (entityDeclHandler)
4107          handleDefault = XML_FALSE;
4108      }
4109      break;
4110    case XML_ROLE_ENTITY_COMPLETE:
4111      if (dtd->keepProcessing && declEntity && entityDeclHandler) {
4112        *eventEndPP = s;
4113        entityDeclHandler(handlerArg,
4114                          declEntity->name,
4115                          declEntity->is_param,
4116                          0,0,
4117                          declEntity->base,
4118                          declEntity->systemId,
4119                          declEntity->publicId,
4120                          0);
4121        handleDefault = XML_FALSE;
4122      }
4123      break;
4124    case XML_ROLE_ENTITY_NOTATION_NAME:
4125      if (dtd->keepProcessing && declEntity) {
4126        declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
4127        if (!declEntity->notation)
4128          return XML_ERROR_NO_MEMORY;
4129        poolFinish(&dtd->pool);
4130        if (unparsedEntityDeclHandler) {
4131          *eventEndPP = s;
4132          unparsedEntityDeclHandler(handlerArg,
4133                                    declEntity->name,
4134                                    declEntity->base,
4135                                    declEntity->systemId,
4136                                    declEntity->publicId,
4137                                    declEntity->notation);
4138          handleDefault = XML_FALSE;
4139        }
4140        else if (entityDeclHandler) {
4141          *eventEndPP = s;
4142          entityDeclHandler(handlerArg,
4143                            declEntity->name,
4144                            0,0,0,
4145                            declEntity->base,
4146                            declEntity->systemId,
4147                            declEntity->publicId,
4148                            declEntity->notation);
4149          handleDefault = XML_FALSE;
4150        }
4151      }
4152      break;
4153    case XML_ROLE_GENERAL_ENTITY_NAME:
4154      {
4155        if (XmlPredefinedEntityName(enc, s, next)) {
4156          declEntity = NULL;
4157          break;
4158        }
4159        if (dtd->keepProcessing) {
4160          const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4161          if (!name)
4162            return XML_ERROR_NO_MEMORY;
4163          declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
4164                                        sizeof(ENTITY));
4165          if (!declEntity)
4166            return XML_ERROR_NO_MEMORY;
4167          if (declEntity->name != name) {
4168            poolDiscard(&dtd->pool);
4169            declEntity = NULL;
4170          }
4171          else {
4172            poolFinish(&dtd->pool);
4173            declEntity->publicId = NULL;
4174            declEntity->is_param = XML_FALSE;
4175            /* if we have a parent parser or are reading an internal parameter
4176               entity, then the entity declaration is not considered "internal"
4177            */
4178            declEntity->is_internal = !(parentParser || openInternalEntities);
4179            if (entityDeclHandler)
4180              handleDefault = XML_FALSE;
4181          }
4182        }
4183        else {
4184          poolDiscard(&dtd->pool);
4185          declEntity = NULL;
4186        }
4187      }
4188      break;
4189    case XML_ROLE_PARAM_ENTITY_NAME:
4190#ifdef XML_DTD
4191      if (dtd->keepProcessing) {
4192        const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4193        if (!name)
4194          return XML_ERROR_NO_MEMORY;
4195        declEntity = (ENTITY *)lookup(&dtd->paramEntities,
4196                                           name, sizeof(ENTITY));
4197        if (!declEntity)
4198          return XML_ERROR_NO_MEMORY;
4199        if (declEntity->name != name) {
4200          poolDiscard(&dtd->pool);
4201          declEntity = NULL;
4202        }
4203        else {
4204          poolFinish(&dtd->pool);
4205          declEntity->publicId = NULL;
4206          declEntity->is_param = XML_TRUE;
4207          /* if we have a parent parser or are reading an internal parameter
4208             entity, then the entity declaration is not considered "internal"
4209          */
4210          declEntity->is_internal = !(parentParser || openInternalEntities);
4211          if (entityDeclHandler)
4212            handleDefault = XML_FALSE;
4213        }
4214      }
4215      else {
4216        poolDiscard(&dtd->pool);
4217        declEntity = NULL;
4218      }
4219#else /* not XML_DTD */
4220      declEntity = NULL;
4221#endif /* XML_DTD */
4222      break;
4223    case XML_ROLE_NOTATION_NAME:
4224      declNotationPublicId = NULL;
4225      declNotationName = NULL;
4226      if (notationDeclHandler) {
4227        declNotationName = poolStoreString(&tempPool, enc, s, next);
4228        if (!declNotationName)
4229          return XML_ERROR_NO_MEMORY;
4230        poolFinish(&tempPool);
4231        handleDefault = XML_FALSE;
4232      }
4233      break;
4234    case XML_ROLE_NOTATION_PUBLIC_ID:
4235      if (!XmlIsPublicId(enc, s, next, eventPP))
4236        return XML_ERROR_PUBLICID;
4237      if (declNotationName) {  /* means notationDeclHandler != NULL */
4238        XML_Char *tem = poolStoreString(&tempPool,
4239                                        enc,
4240                                        s + enc->minBytesPerChar,
4241                                        next - enc->minBytesPerChar);
4242        if (!tem)
4243          return XML_ERROR_NO_MEMORY;
4244        normalizePublicId(tem);
4245        declNotationPublicId = tem;
4246        poolFinish(&tempPool);
4247        handleDefault = XML_FALSE;
4248      }
4249      break;
4250    case XML_ROLE_NOTATION_SYSTEM_ID:
4251      if (declNotationName && notationDeclHandler) {
4252        const XML_Char *systemId
4253          = poolStoreString(&tempPool, enc,
4254                            s + enc->minBytesPerChar,
4255                            next - enc->minBytesPerChar);
4256        if (!systemId)
4257          return XML_ERROR_NO_MEMORY;
4258        *eventEndPP = s;
4259        notationDeclHandler(handlerArg,
4260                            declNotationName,
4261                            curBase,
4262                            systemId,
4263                            declNotationPublicId);
4264        handleDefault = XML_FALSE;
4265      }
4266      poolClear(&tempPool);
4267      break;
4268    case XML_ROLE_NOTATION_NO_SYSTEM_ID:
4269      if (declNotationPublicId && notationDeclHandler) {
4270        *eventEndPP = s;
4271        notationDeclHandler(handlerArg,
4272                            declNotationName,
4273                            curBase,
4274                            0,
4275                            declNotationPublicId);
4276        handleDefault = XML_FALSE;
4277      }
4278      poolClear(&tempPool);
4279      break;
4280    case XML_ROLE_ERROR:
4281      switch (tok) {
4282      case XML_TOK_PARAM_ENTITY_REF:
4283        /* PE references in internal subset are
4284           not allowed within declarations. */
4285        return XML_ERROR_PARAM_ENTITY_REF;
4286      case XML_TOK_XML_DECL:
4287        return XML_ERROR_MISPLACED_XML_PI;
4288      default:
4289        return XML_ERROR_SYNTAX;
4290      }
4291#ifdef XML_DTD
4292    case XML_ROLE_IGNORE_SECT:
4293      {
4294        enum XML_Error result;
4295        if (defaultHandler)
4296          reportDefault(parser, enc, s, next);
4297        handleDefault = XML_FALSE;
4298        result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
4299        if (result != XML_ERROR_NONE)
4300          return result;
4301        else if (!next) {
4302          processor = ignoreSectionProcessor;
4303          return result;
4304        }
4305      }
4306      break;
4307#endif /* XML_DTD */
4308    case XML_ROLE_GROUP_OPEN:
4309      if (prologState.level >= groupSize) {
4310        if (groupSize) {
4311          char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
4312          if (temp == NULL)
4313            return XML_ERROR_NO_MEMORY;
4314          groupConnector = temp;
4315          if (dtd->scaffIndex) {
4316            int *temp = (int *)REALLOC(dtd->scaffIndex,
4317                          groupSize * sizeof(int));
4318            if (temp == NULL)
4319              return XML_ERROR_NO_MEMORY;
4320            dtd->scaffIndex = temp;
4321          }
4322        }
4323        else {
4324          groupConnector = (char *)MALLOC(groupSize = 32);
4325          if (!groupConnector)
4326            return XML_ERROR_NO_MEMORY;
4327        }
4328      }
4329      groupConnector[prologState.level] = 0;
4330      if (dtd->in_eldecl) {
4331        int myindex = nextScaffoldPart(parser);
4332        if (myindex < 0)
4333          return XML_ERROR_NO_MEMORY;
4334        dtd->scaffIndex[dtd->scaffLevel] = myindex;
4335        dtd->scaffLevel++;
4336        dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
4337        if (elementDeclHandler)
4338          handleDefault = XML_FALSE;
4339      }
4340      break;
4341    case XML_ROLE_GROUP_SEQUENCE:
4342      if (groupConnector[prologState.level] == ASCII_PIPE)
4343        return XML_ERROR_SYNTAX;
4344      groupConnector[prologState.level] = ASCII_COMMA;
4345      if (dtd->in_eldecl && elementDeclHandler)
4346        handleDefault = XML_FALSE;
4347      break;
4348    case XML_ROLE_GROUP_CHOICE:
4349      if (groupConnector[prologState.level] == ASCII_COMMA)
4350        return XML_ERROR_SYNTAX;
4351      if (dtd->in_eldecl
4352          && !groupConnector[prologState.level]
4353          && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4354              != XML_CTYPE_MIXED)
4355          ) {
4356        dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4357            = XML_CTYPE_CHOICE;
4358        if (elementDeclHandler)
4359          handleDefault = XML_FALSE;
4360      }
4361      groupConnector[prologState.level] = ASCII_PIPE;
4362      break;
4363    case XML_ROLE_PARAM_ENTITY_REF:
4364#ifdef XML_DTD
4365    case XML_ROLE_INNER_PARAM_ENTITY_REF:
4366      dtd->hasParamEntityRefs = XML_TRUE;
4367      if (!paramEntityParsing)
4368        dtd->keepProcessing = dtd->standalone;
4369      else {
4370        const XML_Char *name;
4371        ENTITY *entity;
4372        name = poolStoreString(&dtd->pool, enc,
4373                                s + enc->minBytesPerChar,
4374                                next - enc->minBytesPerChar);
4375        if (!name)
4376          return XML_ERROR_NO_MEMORY;
4377        entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
4378        poolDiscard(&dtd->pool);
4379        /* first, determine if a check for an existing declaration is needed;
4380           if yes, check that the entity exists, and that it is internal,
4381           otherwise call the skipped entity handler
4382        */
4383        if (prologState.documentEntity &&
4384            (dtd->standalone
4385             ? !openInternalEntities
4386             : !dtd->hasParamEntityRefs)) {
4387          if (!entity)
4388            return XML_ERROR_UNDEFINED_ENTITY;
4389          else if (!entity->is_internal)
4390            return XML_ERROR_ENTITY_DECLARED_IN_PE;
4391        }
4392        else if (!entity) {
4393          dtd->keepProcessing = dtd->standalone;
4394          /* cannot report skipped entities in declarations */
4395          if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
4396            skippedEntityHandler(handlerArg, name, 1);
4397            handleDefault = XML_FALSE;
4398          }
4399          break;
4400        }
4401        if (entity->open)
4402          return XML_ERROR_RECURSIVE_ENTITY_REF;
4403        if (entity->textPtr) {
4404          enum XML_Error result;
4405          XML_Bool betweenDecl =
4406            (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
4407          result = processInternalEntity(parser, entity, betweenDecl);
4408          if (result != XML_ERROR_NONE)
4409            return result;
4410          handleDefault = XML_FALSE;
4411          break;
4412        }
4413        if (externalEntityRefHandler) {
4414          dtd->paramEntityRead = XML_FALSE;
4415          entity->open = XML_TRUE;
4416          if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4417                                        0,
4418                                        entity->base,
4419                                        entity->systemId,
4420                                        entity->publicId)) {
4421            entity->open = XML_FALSE;
4422            return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4423          }
4424          entity->open = XML_FALSE;
4425          handleDefault = XML_FALSE;
4426          if (!dtd->paramEntityRead) {
4427            dtd->keepProcessing = dtd->standalone;
4428            break;
4429          }
4430        }
4431        else {
4432          dtd->keepProcessing = dtd->standalone;
4433          break;
4434        }
4435      }
4436#endif /* XML_DTD */
4437      if (!dtd->standalone &&
4438          notStandaloneHandler &&
4439          !notStandaloneHandler(handlerArg))
4440        return XML_ERROR_NOT_STANDALONE;
4441      break;
4442
4443    /* Element declaration stuff */
4444
4445    case XML_ROLE_ELEMENT_NAME:
4446      if (elementDeclHandler) {
4447        declElementType = getElementType(parser, enc, s, next);
4448        if (!declElementType)
4449          return XML_ERROR_NO_MEMORY;
4450        dtd->scaffLevel = 0;
4451        dtd->scaffCount = 0;
4452        dtd->in_eldecl = XML_TRUE;
4453        handleDefault = XML_FALSE;
4454      }
4455      break;
4456
4457    case XML_ROLE_CONTENT_ANY:
4458    case XML_ROLE_CONTENT_EMPTY:
4459      if (dtd->in_eldecl) {
4460        if (elementDeclHandler) {
4461          XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
4462          if (!content)
4463            return XML_ERROR_NO_MEMORY;
4464          content->quant = XML_CQUANT_NONE;
4465          content->name = NULL;
4466          content->numchildren = 0;
4467          content->children = NULL;
4468          content->type = ((role == XML_ROLE_CONTENT_ANY) ?
4469                           XML_CTYPE_ANY :
4470                           XML_CTYPE_EMPTY);
4471          *eventEndPP = s;
4472          elementDeclHandler(handlerArg, declElementType->name, content);
4473          handleDefault = XML_FALSE;
4474        }
4475        dtd->in_eldecl = XML_FALSE;
4476      }
4477      break;
4478
4479    case XML_ROLE_CONTENT_PCDATA:
4480      if (dtd->in_eldecl) {
4481        dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4482            = XML_CTYPE_MIXED;
4483        if (elementDeclHandler)
4484          handleDefault = XML_FALSE;
4485      }
4486      break;
4487
4488    case XML_ROLE_CONTENT_ELEMENT:
4489      quant = XML_CQUANT_NONE;
4490      goto elementContent;
4491    case XML_ROLE_CONTENT_ELEMENT_OPT:
4492      quant = XML_CQUANT_OPT;
4493      goto elementContent;
4494    case XML_ROLE_CONTENT_ELEMENT_REP:
4495      quant = XML_CQUANT_REP;
4496      goto elementContent;
4497    case XML_ROLE_CONTENT_ELEMENT_PLUS:
4498      quant = XML_CQUANT_PLUS;
4499    elementContent:
4500      if (dtd->in_eldecl) {
4501        ELEMENT_TYPE *el;
4502        const XML_Char *name;
4503        int nameLen;
4504        const char *nxt = (quant == XML_CQUANT_NONE
4505                           ? next
4506                           : next - enc->minBytesPerChar);
4507        int myindex = nextScaffoldPart(parser);
4508        if (myindex < 0)
4509          return XML_ERROR_NO_MEMORY;
4510        dtd->scaffold[myindex].type = XML_CTYPE_NAME;
4511        dtd->scaffold[myindex].quant = quant;
4512        el = getElementType(parser, enc, s, nxt);
4513        if (!el)
4514          return XML_ERROR_NO_MEMORY;
4515        name = el->name;
4516        dtd->scaffold[myindex].name = name;
4517        nameLen = 0;
4518        for (; name[nameLen++]; );
4519        dtd->contentStringLen +=  nameLen;
4520        if (elementDeclHandler)
4521          handleDefault = XML_FALSE;
4522      }
4523      break;
4524
4525    case XML_ROLE_GROUP_CLOSE:
4526      quant = XML_CQUANT_NONE;
4527      goto closeGroup;
4528    case XML_ROLE_GROUP_CLOSE_OPT:
4529      quant = XML_CQUANT_OPT;
4530      goto closeGroup;
4531    case XML_ROLE_GROUP_CLOSE_REP:
4532      quant = XML_CQUANT_REP;
4533      goto closeGroup;
4534    case XML_ROLE_GROUP_CLOSE_PLUS:
4535      quant = XML_CQUANT_PLUS;
4536    closeGroup:
4537      if (dtd->in_eldecl) {
4538        if (elementDeclHandler)
4539          handleDefault = XML_FALSE;
4540        dtd->scaffLevel--;
4541        dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
4542        if (dtd->scaffLevel == 0) {
4543          if (!handleDefault) {
4544            XML_Content *model = build_model(parser);
4545            if (!model)
4546              return XML_ERROR_NO_MEMORY;
4547            *eventEndPP = s;
4548            elementDeclHandler(handlerArg, declElementType->name, model);
4549          }
4550          dtd->in_eldecl = XML_FALSE;
4551          dtd->contentStringLen = 0;
4552        }
4553      }
4554      break;
4555      /* End element declaration stuff */
4556
4557    case XML_ROLE_PI:
4558      if (!reportProcessingInstruction(parser, enc, s, next))
4559        return XML_ERROR_NO_MEMORY;
4560      handleDefault = XML_FALSE;
4561      break;
4562    case XML_ROLE_COMMENT:
4563      if (!reportComment(parser, enc, s, next))
4564        return XML_ERROR_NO_MEMORY;
4565      handleDefault = XML_FALSE;
4566      break;
4567    case XML_ROLE_NONE:
4568      switch (tok) {
4569      case XML_TOK_BOM:
4570        handleDefault = XML_FALSE;
4571        break;
4572      }
4573      break;
4574    case XML_ROLE_DOCTYPE_NONE:
4575      if (startDoctypeDeclHandler)
4576        handleDefault = XML_FALSE;
4577      break;
4578    case XML_ROLE_ENTITY_NONE:
4579      if (dtd->keepProcessing && entityDeclHandler)
4580        handleDefault = XML_FALSE;
4581      break;
4582    case XML_ROLE_NOTATION_NONE:
4583      if (notationDeclHandler)
4584        handleDefault = XML_FALSE;
4585      break;
4586    case XML_ROLE_ATTLIST_NONE:
4587      if (dtd->keepProcessing && attlistDeclHandler)
4588        handleDefault = XML_FALSE;
4589      break;
4590    case XML_ROLE_ELEMENT_NONE:
4591      if (elementDeclHandler)
4592        handleDefault = XML_FALSE;
4593      break;
4594    } /* end of big switch */
4595
4596    if (handleDefault && defaultHandler)
4597      reportDefault(parser, enc, s, next);
4598
4599    switch (ps_parsing) {
4600    case XML_SUSPENDED:
4601      *nextPtr = next;
4602      return XML_ERROR_NONE;
4603    case XML_FINISHED:
4604      return XML_ERROR_ABORTED;
4605    default:
4606      s = next;
4607      tok = XmlPrologTok(enc, s, end, &next);
4608    }
4609  }
4610  /* not reached */
4611}
4612
4613static enum XML_Error PTRCALL
4614epilogProcessor(XML_Parser parser,
4615                const char *s,
4616                const char *end,
4617                const char **nextPtr)
4618{
4619  processor = epilogProcessor;
4620  eventPtr = s;
4621  for (;;) {
4622    const char *next = NULL;
4623    int tok = XmlPrologTok(encoding, s, end, &next);
4624    eventEndPtr = next;
4625    switch (tok) {
4626    /* report partial linebreak - it might be the last token */
4627    case -XML_TOK_PROLOG_S:
4628      if (defaultHandler) {
4629        reportDefault(parser, encoding, s, next);
4630        if (ps_parsing == XML_FINISHED)
4631          return XML_ERROR_ABORTED;
4632      }
4633      *nextPtr = next;
4634      return XML_ERROR_NONE;
4635    case XML_TOK_NONE:
4636      *nextPtr = s;
4637      return XML_ERROR_NONE;
4638    case XML_TOK_PROLOG_S:
4639      if (defaultHandler)
4640        reportDefault(parser, encoding, s, next);
4641      break;
4642    case XML_TOK_PI:
4643      if (!reportProcessingInstruction(parser, encoding, s, next))
4644        return XML_ERROR_NO_MEMORY;
4645      break;
4646    case XML_TOK_COMMENT:
4647      if (!reportComment(parser, encoding, s, next))
4648        return XML_ERROR_NO_MEMORY;
4649      break;
4650    case XML_TOK_INVALID:
4651      eventPtr = next;
4652      return XML_ERROR_INVALID_TOKEN;
4653    case XML_TOK_PARTIAL:
4654      if (!ps_finalBuffer) {
4655        *nextPtr = s;
4656        return XML_ERROR_NONE;
4657      }
4658      return XML_ERROR_UNCLOSED_TOKEN;
4659    case XML_TOK_PARTIAL_CHAR:
4660      if (!ps_finalBuffer) {
4661        *nextPtr = s;
4662        return XML_ERROR_NONE;
4663      }
4664      return XML_ERROR_PARTIAL_CHAR;
4665    default:
4666      return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
4667    }
4668    eventPtr = s = next;
4669    switch (ps_parsing) {
4670    case XML_SUSPENDED:
4671      *nextPtr = next;
4672      return XML_ERROR_NONE;
4673    case XML_FINISHED:
4674      return XML_ERROR_ABORTED;
4675    default: ;
4676    }
4677  }
4678}
4679
4680static enum XML_Error
4681processInternalEntity(XML_Parser parser, ENTITY *entity,
4682                      XML_Bool betweenDecl)
4683{
4684  const char *textStart, *textEnd;
4685  const char *next;
4686  enum XML_Error result;
4687  OPEN_INTERNAL_ENTITY *openEntity;
4688
4689  if (freeInternalEntities) {
4690    openEntity = freeInternalEntities;
4691    freeInternalEntities = openEntity->next;
4692  }
4693  else {
4694    openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
4695    if (!openEntity)
4696      return XML_ERROR_NO_MEMORY;
4697  }
4698  entity->open = XML_TRUE;
4699  entity->processed = 0;
4700  openEntity->next = openInternalEntities;
4701  openInternalEntities = openEntity;
4702  openEntity->entity = entity;
4703  openEntity->startTagLevel = tagLevel;
4704  openEntity->betweenDecl = betweenDecl;
4705  openEntity->internalEventPtr = NULL;
4706  openEntity->internalEventEndPtr = NULL;
4707  textStart = (char *)entity->textPtr;
4708  textEnd = (char *)(entity->textPtr + entity->textLen);
4709
4710#ifdef XML_DTD
4711  if (entity->is_param) {
4712    int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4713    result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4714                      next, &next, XML_FALSE);
4715  }
4716  else
4717#endif /* XML_DTD */
4718    result = doContent(parser, tagLevel, internalEncoding, textStart,
4719                       textEnd, &next, XML_FALSE);
4720
4721  if (result == XML_ERROR_NONE) {
4722    if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4723      entity->processed = (int)(next - textStart);
4724      processor = internalEntityProcessor;
4725    }
4726    else {
4727      entity->open = XML_FALSE;
4728      openInternalEntities = openEntity->next;
4729      /* put openEntity back in list of free instances */
4730      openEntity->next = freeInternalEntities;
4731      freeInternalEntities = openEntity;
4732    }
4733  }
4734  return result;
4735}
4736
4737static enum XML_Error PTRCALL
4738internalEntityProcessor(XML_Parser parser,
4739                        const char *s,
4740                        const char *end,
4741                        const char **nextPtr)
4742{
4743  ENTITY *entity;
4744  const char *textStart, *textEnd;
4745  const char *next;
4746  enum XML_Error result;
4747  OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
4748  if (!openEntity)
4749    return XML_ERROR_UNEXPECTED_STATE;
4750
4751  entity = openEntity->entity;
4752  textStart = ((char *)entity->textPtr) + entity->processed;
4753  textEnd = (char *)(entity->textPtr + entity->textLen);
4754
4755#ifdef XML_DTD
4756  if (entity->is_param) {
4757    int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4758    result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4759                      next, &next, XML_FALSE);
4760  }
4761  else
4762#endif /* XML_DTD */
4763    result = doContent(parser, openEntity->startTagLevel, internalEncoding,
4764                       textStart, textEnd, &next, XML_FALSE);
4765
4766  if (result != XML_ERROR_NONE)
4767    return result;
4768  else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4769    entity->processed = (int)(next - (char *)entity->textPtr);
4770    return result;
4771  }
4772  else {
4773    entity->open = XML_FALSE;
4774    openInternalEntities = openEntity->next;
4775    /* put openEntity back in list of free instances */
4776    openEntity->next = freeInternalEntities;
4777    freeInternalEntities = openEntity;
4778  }
4779
4780#ifdef XML_DTD
4781  if (entity->is_param) {
4782    int tok;
4783    processor = prologProcessor;
4784    tok = XmlPrologTok(encoding, s, end, &next);
4785    return doProlog(parser, encoding, s, end, tok, next, nextPtr,
4786                    (XML_Bool)!ps_finalBuffer);
4787  }
4788  else
4789#endif /* XML_DTD */
4790  {
4791    processor = contentProcessor;
4792    /* see externalEntityContentProcessor vs contentProcessor */
4793    return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
4794                     nextPtr, (XML_Bool)!ps_finalBuffer);
4795  }
4796}
4797
4798static enum XML_Error PTRCALL
4799errorProcessor(XML_Parser parser,
4800               const char *s,
4801               const char *end,
4802               const char **nextPtr)
4803{
4804  return errorCode;
4805}
4806
4807static enum XML_Error
4808storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4809                    const char *ptr, const char *end,
4810                    STRING_POOL *pool)
4811{
4812  enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
4813                                               end, pool);
4814  if (result)
4815    return result;
4816  if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
4817    poolChop(pool);
4818  if (!poolAppendChar(pool, XML_T('\0')))
4819    return XML_ERROR_NO_MEMORY;
4820  return XML_ERROR_NONE;
4821}
4822
4823static enum XML_Error
4824appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4825                     const char *ptr, const char *end,
4826                     STRING_POOL *pool)
4827{
4828  DTD * const dtd = _dtd;  /* save one level of indirection */
4829  for (;;) {
4830    const char *next;
4831    int tok = XmlAttributeValueTok(enc, ptr, end, &next);
4832    switch (tok) {
4833    case XML_TOK_NONE:
4834      return XML_ERROR_NONE;
4835    case XML_TOK_INVALID:
4836      if (enc == encoding)
4837        eventPtr = next;
4838      return XML_ERROR_INVALID_TOKEN;
4839    case XML_TOK_PARTIAL:
4840      if (enc == encoding)
4841        eventPtr = ptr;
4842      return XML_ERROR_INVALID_TOKEN;
4843    case XML_TOK_CHAR_REF:
4844      {
4845        XML_Char buf[XML_ENCODE_MAX];
4846        int i;
4847        int n = XmlCharRefNumber(enc, ptr);
4848        if (n < 0) {
4849          if (enc == encoding)
4850            eventPtr = ptr;
4851          return XML_ERROR_BAD_CHAR_REF;
4852        }
4853        if (!isCdata
4854            && n == 0x20 /* space */
4855            && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4856          break;
4857        n = XmlEncode(n, (ICHAR *)buf);
4858        if (!n) {
4859          if (enc == encoding)
4860            eventPtr = ptr;
4861          return XML_ERROR_BAD_CHAR_REF;
4862        }
4863        for (i = 0; i < n; i++) {
4864          if (!poolAppendChar(pool, buf[i]))
4865            return XML_ERROR_NO_MEMORY;
4866        }
4867      }
4868      break;
4869    case XML_TOK_DATA_CHARS:
4870      if (!poolAppend(pool, enc, ptr, next))
4871        return XML_ERROR_NO_MEMORY;
4872      break;
4873    case XML_TOK_TRAILING_CR:
4874      next = ptr + enc->minBytesPerChar;
4875      /* fall through */
4876    case XML_TOK_ATTRIBUTE_VALUE_S:
4877    case XML_TOK_DATA_NEWLINE:
4878      if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4879        break;
4880      if (!poolAppendChar(pool, 0x20))
4881        return XML_ERROR_NO_MEMORY;
4882      break;
4883    case XML_TOK_ENTITY_REF:
4884      {
4885        const XML_Char *name;
4886        ENTITY *entity;
4887        char checkEntityDecl;
4888        XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
4889                                              ptr + enc->minBytesPerChar,
4890                                              next - enc->minBytesPerChar);
4891        if (ch) {
4892          if (!poolAppendChar(pool, ch))
4893                return XML_ERROR_NO_MEMORY;
4894          break;
4895        }
4896        name = poolStoreString(&temp2Pool, enc,
4897                               ptr + enc->minBytesPerChar,
4898                               next - enc->minBytesPerChar);
4899        if (!name)
4900          return XML_ERROR_NO_MEMORY;
4901        entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
4902        poolDiscard(&temp2Pool);
4903        /* First, determine if a check for an existing declaration is needed;
4904           if yes, check that the entity exists, and that it is internal.
4905        */
4906        if (pool == &dtd->pool)  /* are we called from prolog? */
4907          checkEntityDecl =
4908#ifdef XML_DTD
4909              prologState.documentEntity &&
4910#endif /* XML_DTD */
4911              (dtd->standalone
4912               ? !openInternalEntities
4913               : !dtd->hasParamEntityRefs);
4914        else /* if (pool == &tempPool): we are called from content */
4915          checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
4916        if (checkEntityDecl) {
4917          if (!entity)
4918            return XML_ERROR_UNDEFINED_ENTITY;
4919          else if (!entity->is_internal)
4920            return XML_ERROR_ENTITY_DECLARED_IN_PE;
4921        }
4922        else if (!entity) {
4923          /* Cannot report skipped entity here - see comments on
4924             skippedEntityHandler.
4925          if (skippedEntityHandler)
4926            skippedEntityHandler(handlerArg, name, 0);
4927          */
4928          /* Cannot call the default handler because this would be
4929             out of sync with the call to the startElementHandler.
4930          if ((pool == &tempPool) && defaultHandler)
4931            reportDefault(parser, enc, ptr, next);
4932          */
4933          break;
4934        }
4935        if (entity->open) {
4936          if (enc == encoding)
4937            eventPtr = ptr;
4938          return XML_ERROR_RECURSIVE_ENTITY_REF;
4939        }
4940        if (entity->notation) {
4941          if (enc == encoding)
4942            eventPtr = ptr;
4943          return XML_ERROR_BINARY_ENTITY_REF;
4944        }
4945        if (!entity->textPtr) {
4946          if (enc == encoding)
4947            eventPtr = ptr;
4948              return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
4949        }
4950        else {
4951          enum XML_Error result;
4952          const XML_Char *textEnd = entity->textPtr + entity->textLen;
4953          entity->open = XML_TRUE;
4954          result = appendAttributeValue(parser, internalEncoding, isCdata,
4955                                        (char *)entity->textPtr,
4956                                        (char *)textEnd, pool);
4957          entity->open = XML_FALSE;
4958          if (result)
4959            return result;
4960        }
4961      }
4962      break;
4963    default:
4964      if (enc == encoding)
4965        eventPtr = ptr;
4966      return XML_ERROR_UNEXPECTED_STATE;
4967    }
4968    ptr = next;
4969  }
4970  /* not reached */
4971}
4972
4973static enum XML_Error
4974storeEntityValue(XML_Parser parser,
4975                 const ENCODING *enc,
4976                 const char *entityTextPtr,
4977                 const char *entityTextEnd)
4978{
4979  DTD * const dtd = _dtd;  /* save one level of indirection */
4980  STRING_POOL *pool = &(dtd->entityValuePool);
4981  enum XML_Error result = XML_ERROR_NONE;
4982#ifdef XML_DTD
4983  int oldInEntityValue = prologState.inEntityValue;
4984  prologState.inEntityValue = 1;
4985#endif /* XML_DTD */
4986  /* never return Null for the value argument in EntityDeclHandler,
4987     since this would indicate an external entity; therefore we
4988     have to make sure that entityValuePool.start is not null */
4989  if (!pool->blocks) {
4990    if (!poolGrow(pool))
4991      return XML_ERROR_NO_MEMORY;
4992  }
4993
4994  for (;;) {
4995    const char *next;
4996    int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
4997    switch (tok) {
4998    case XML_TOK_PARAM_ENTITY_REF:
4999#ifdef XML_DTD
5000      if (isParamEntity || enc != encoding) {
5001        const XML_Char *name;
5002        ENTITY *entity;
5003        name = poolStoreString(&tempPool, enc,
5004                               entityTextPtr + enc->minBytesPerChar,
5005                               next - enc->minBytesPerChar);
5006        if (!name) {
5007          result = XML_ERROR_NO_MEMORY;
5008          goto endEntityValue;
5009        }
5010        entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
5011        poolDiscard(&tempPool);
5012        if (!entity) {
5013          /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5014          /* cannot report skipped entity here - see comments on
5015             skippedEntityHandler
5016          if (skippedEntityHandler)
5017            skippedEntityHandler(handlerArg, name, 0);
5018          */
5019          dtd->keepProcessing = dtd->standalone;
5020          goto endEntityValue;
5021        }
5022        if (entity->open) {
5023          if (enc == encoding)
5024            eventPtr = entityTextPtr;
5025          result = XML_ERROR_RECURSIVE_ENTITY_REF;
5026          goto endEntityValue;
5027        }
5028        if (entity->systemId) {
5029          if (externalEntityRefHandler) {
5030            dtd->paramEntityRead = XML_FALSE;
5031            entity->open = XML_TRUE;
5032            if (!externalEntityRefHandler(externalEntityRefHandlerArg,
5033                                          0,
5034                                          entity->base,
5035                                          entity->systemId,
5036                                          entity->publicId)) {
5037              entity->open = XML_FALSE;
5038              result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5039              goto endEntityValue;
5040            }
5041            entity->open = XML_FALSE;
5042            if (!dtd->paramEntityRead)
5043              dtd->keepProcessing = dtd->standalone;
5044          }
5045          else
5046            dtd->keepProcessing = dtd->standalone;
5047        }
5048        else {
5049          entity->open = XML_TRUE;
5050          result = storeEntityValue(parser,
5051                                    internalEncoding,
5052                                    (char *)entity->textPtr,
5053                                    (char *)(entity->textPtr
5054                                             + entity->textLen));
5055          entity->open = XML_FALSE;
5056          if (result)
5057            goto endEntityValue;
5058        }
5059        break;
5060      }
5061#endif /* XML_DTD */
5062      /* In the internal subset, PE references are not legal
5063         within markup declarations, e.g entity values in this case. */
5064      eventPtr = entityTextPtr;
5065      result = XML_ERROR_PARAM_ENTITY_REF;
5066      goto endEntityValue;
5067    case XML_TOK_NONE:
5068      result = XML_ERROR_NONE;
5069      goto endEntityValue;
5070    case XML_TOK_ENTITY_REF:
5071    case XML_TOK_DATA_CHARS:
5072      if (!poolAppend(pool, enc, entityTextPtr, next)) {
5073        result = XML_ERROR_NO_MEMORY;
5074        goto endEntityValue;
5075      }
5076      break;
5077    case XML_TOK_TRAILING_CR:
5078      next = entityTextPtr + enc->minBytesPerChar;
5079      /* fall through */
5080    case XML_TOK_DATA_NEWLINE:
5081      if (pool->end == pool->ptr && !poolGrow(pool)) {
5082              result = XML_ERROR_NO_MEMORY;
5083        goto endEntityValue;
5084      }
5085      *(pool->ptr)++ = 0xA;
5086      break;
5087    case XML_TOK_CHAR_REF:
5088      {
5089        XML_Char buf[XML_ENCODE_MAX];
5090        int i;
5091        int n = XmlCharRefNumber(enc, entityTextPtr);
5092        if (n < 0) {
5093          if (enc == encoding)
5094            eventPtr = entityTextPtr;
5095          result = XML_ERROR_BAD_CHAR_REF;
5096          goto endEntityValue;
5097        }
5098        n = XmlEncode(n, (ICHAR *)buf);
5099        if (!n) {
5100          if (enc == encoding)
5101            eventPtr = entityTextPtr;
5102          result = XML_ERROR_BAD_CHAR_REF;
5103          goto endEntityValue;
5104        }
5105        for (i = 0; i < n; i++) {
5106          if (pool->end == pool->ptr && !poolGrow(pool)) {
5107            result = XML_ERROR_NO_MEMORY;
5108            goto endEntityValue;
5109          }
5110          *(pool->ptr)++ = buf[i];
5111        }
5112      }
5113      break;
5114    case XML_TOK_PARTIAL:
5115      if (enc == encoding)
5116        eventPtr = entityTextPtr;
5117      result = XML_ERROR_INVALID_TOKEN;
5118      goto endEntityValue;
5119    case XML_TOK_INVALID:
5120      if (enc == encoding)
5121        eventPtr = next;
5122      result = XML_ERROR_INVALID_TOKEN;
5123      goto endEntityValue;
5124    default:
5125      if (enc == encoding)
5126        eventPtr = entityTextPtr;
5127      result = XML_ERROR_UNEXPECTED_STATE;
5128      goto endEntityValue;
5129    }
5130    entityTextPtr = next;
5131  }
5132endEntityValue:
5133#ifdef XML_DTD
5134  prologState.inEntityValue = oldInEntityValue;
5135#endif /* XML_DTD */
5136  return result;
5137}
5138
5139static void FASTCALL
5140normalizeLines(XML_Char *s)
5141{
5142  XML_Char *p;
5143  for (;; s++) {
5144    if (*s == XML_T('\0'))
5145      return;
5146    if (*s == 0xD)
5147      break;
5148  }
5149  p = s;
5150  do {
5151    if (*s == 0xD) {
5152      *p++ = 0xA;
5153      if (*++s == 0xA)
5154        s++;
5155    }
5156    else
5157      *p++ = *s++;
5158  } while (*s);
5159  *p = XML_T('\0');
5160}
5161
5162static int
5163reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5164                            const char *start, const char *end)
5165{
5166  const XML_Char *target;
5167  XML_Char *data;
5168  const char *tem;
5169  if (!processingInstructionHandler) {
5170    if (defaultHandler)
5171      reportDefault(parser, enc, start, end);
5172    return 1;
5173  }
5174  start += enc->minBytesPerChar * 2;
5175  tem = start + XmlNameLength(enc, start);
5176  target = poolStoreString(&tempPool, enc, start, tem);
5177  if (!target)
5178    return 0;
5179  poolFinish(&tempPool);
5180  data = poolStoreString(&tempPool, enc,
5181                        XmlSkipS(enc, tem),
5182                        end - enc->minBytesPerChar*2);
5183  if (!data)
5184    return 0;
5185  normalizeLines(data);
5186  processingInstructionHandler(handlerArg, target, data);
5187  poolClear(&tempPool);
5188  return 1;
5189}
5190
5191static int
5192reportComment(XML_Parser parser, const ENCODING *enc,
5193              const char *start, const char *end)
5194{
5195  XML_Char *data;
5196  if (!commentHandler) {
5197    if (defaultHandler)
5198      reportDefault(parser, enc, start, end);
5199    return 1;
5200  }
5201  data = poolStoreString(&tempPool,
5202                         enc,
5203                         start + enc->minBytesPerChar * 4,
5204                         end - enc->minBytesPerChar * 3);
5205  if (!data)
5206    return 0;
5207  normalizeLines(data);
5208  commentHandler(handlerArg, data);
5209  poolClear(&tempPool);
5210  return 1;
5211}
5212
5213static void
5214reportDefault(XML_Parser parser, const ENCODING *enc,
5215              const char *s, const char *end)
5216{
5217  if (MUST_CONVERT(enc, s)) {
5218    const char **eventPP;
5219    const char **eventEndPP;
5220    if (enc == encoding) {
5221      eventPP = &eventPtr;
5222      eventEndPP = &eventEndPtr;
5223    }
5224    else {
5225      eventPP = &(openInternalEntities->internalEventPtr);
5226      eventEndPP = &(openInternalEntities->internalEventEndPtr);
5227    }
5228    do {
5229      ICHAR *dataPtr = (ICHAR *)dataBuf;
5230      XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
5231      *eventEndPP = s;
5232      defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
5233      *eventPP = s;
5234    } while (s != end);
5235  }
5236  else
5237    defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
5238}
5239
5240
5241static int
5242defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
5243                XML_Bool isId, const XML_Char *value, XML_Parser parser)
5244{
5245  DEFAULT_ATTRIBUTE *att;
5246  if (value || isId) {
5247    /* The handling of default attributes gets messed up if we have
5248       a default which duplicates a non-default. */
5249    int i;
5250    for (i = 0; i < type->nDefaultAtts; i++)
5251      if (attId == type->defaultAtts[i].id)
5252        return 1;
5253    if (isId && !type->idAtt && !attId->xmlns)
5254      type->idAtt = attId;
5255  }
5256  if (type->nDefaultAtts == type->allocDefaultAtts) {
5257    if (type->allocDefaultAtts == 0) {
5258      type->allocDefaultAtts = 8;
5259      type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
5260                            * sizeof(DEFAULT_ATTRIBUTE));
5261      if (!type->defaultAtts)
5262        return 0;
5263    }
5264    else {
5265      DEFAULT_ATTRIBUTE *temp;
5266      int count = type->allocDefaultAtts * 2;
5267      temp = (DEFAULT_ATTRIBUTE *)
5268        REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
5269      if (temp == NULL)
5270        return 0;
5271      type->allocDefaultAtts = count;
5272      type->defaultAtts = temp;
5273    }
5274  }
5275  att = type->defaultAtts + type->nDefaultAtts;
5276  att->id = attId;
5277  att->value = value;
5278  att->isCdata = isCdata;
5279  if (!isCdata)
5280    attId->maybeTokenized = XML_TRUE;
5281  type->nDefaultAtts += 1;
5282  return 1;
5283}
5284
5285static int
5286setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
5287{
5288  DTD * const dtd = _dtd;  /* save one level of indirection */
5289  const XML_Char *name;
5290  for (name = elementType->name; *name; name++) {
5291    if (*name == XML_T(ASCII_COLON)) {
5292      PREFIX *prefix;
5293      const XML_Char *s;
5294      for (s = elementType->name; s != name; s++) {
5295        if (!poolAppendChar(&dtd->pool, *s))
5296          return 0;
5297      }
5298      if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5299        return 0;
5300      prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
5301                                sizeof(PREFIX));
5302      if (!prefix)
5303        return 0;
5304      if (prefix->name == poolStart(&dtd->pool))
5305        poolFinish(&dtd->pool);
5306      else
5307        poolDiscard(&dtd->pool);
5308      elementType->prefix = prefix;
5309
5310    }
5311  }
5312  return 1;
5313}
5314
5315static ATTRIBUTE_ID *
5316getAttributeId(XML_Parser parser, const ENCODING *enc,
5317               const char *start, const char *end)
5318{
5319  DTD * const dtd = _dtd;  /* save one level of indirection */
5320  ATTRIBUTE_ID *id;
5321  const XML_Char *name;
5322  if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5323    return NULL;
5324  name = poolStoreString(&dtd->pool, enc, start, end);
5325  if (!name)
5326    return NULL;
5327  /* skip quotation mark - its storage will be re-used (like in name[-1]) */
5328  ++name;
5329  id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
5330  if (!id)
5331    return NULL;
5332  if (id->name != name)
5333    poolDiscard(&dtd->pool);
5334  else {
5335    poolFinish(&dtd->pool);
5336    if (!ns)
5337      ;
5338    else if (name[0] == XML_T(ASCII_x)
5339        && name[1] == XML_T(ASCII_m)
5340        && name[2] == XML_T(ASCII_l)
5341        && name[3] == XML_T(ASCII_n)
5342        && name[4] == XML_T(ASCII_s)
5343        && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
5344      if (name[5] == XML_T('\0'))
5345        id->prefix = &dtd->defaultPrefix;
5346      else
5347        id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
5348      id->xmlns = XML_TRUE;
5349    }
5350    else {
5351      int i;
5352      for (i = 0; name[i]; i++) {
5353        /* attributes without prefix are *not* in the default namespace */
5354        if (name[i] == XML_T(ASCII_COLON)) {
5355          int j;
5356          for (j = 0; j < i; j++) {
5357            if (!poolAppendChar(&dtd->pool, name[j]))
5358              return NULL;
5359          }
5360          if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5361            return NULL;
5362          id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
5363                                        sizeof(PREFIX));
5364          if (id->prefix->name == poolStart(&dtd->pool))
5365            poolFinish(&dtd->pool);
5366          else
5367            poolDiscard(&dtd->pool);
5368          break;
5369        }
5370      }
5371    }
5372  }
5373  return id;
5374}
5375
5376#define CONTEXT_SEP XML_T(ASCII_FF)
5377
5378static const XML_Char *
5379getContext(XML_Parser parser)
5380{
5381  DTD * const dtd = _dtd;  /* save one level of indirection */
5382  HASH_TABLE_ITER iter;
5383  XML_Bool needSep = XML_FALSE;
5384
5385  if (dtd->defaultPrefix.binding) {
5386    int i;
5387    int len;
5388    if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
5389      return NULL;
5390    len = dtd->defaultPrefix.binding->uriLen;
5391    if (namespaceSeparator)
5392      len--;
5393    for (i = 0; i < len; i++)
5394      if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
5395        return NULL;
5396    needSep = XML_TRUE;
5397  }
5398
5399  hashTableIterInit(&iter, &(dtd->prefixes));
5400  for (;;) {
5401    int i;
5402    int len;
5403    const XML_Char *s;
5404    PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
5405    if (!prefix)
5406      break;
5407    if (!prefix->binding)
5408      continue;
5409    if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5410      return NULL;
5411    for (s = prefix->name; *s; s++)
5412      if (!poolAppendChar(&tempPool, *s))
5413        return NULL;
5414    if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
5415      return NULL;
5416    len = prefix->binding->uriLen;
5417    if (namespaceSeparator)
5418      len--;
5419    for (i = 0; i < len; i++)
5420      if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
5421        return NULL;
5422    needSep = XML_TRUE;
5423  }
5424
5425
5426  hashTableIterInit(&iter, &(dtd->generalEntities));
5427  for (;;) {
5428    const XML_Char *s;
5429    ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
5430    if (!e)
5431      break;
5432    if (!e->open)
5433      continue;
5434    if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5435      return NULL;
5436    for (s = e->name; *s; s++)
5437      if (!poolAppendChar(&tempPool, *s))
5438        return 0;
5439    needSep = XML_TRUE;
5440  }
5441
5442  if (!poolAppendChar(&tempPool, XML_T('\0')))
5443    return NULL;
5444  return tempPool.start;
5445}
5446
5447static XML_Bool
5448setContext(XML_Parser parser, const XML_Char *context)
5449{
5450  DTD * const dtd = _dtd;  /* save one level of indirection */
5451  const XML_Char *s = context;
5452
5453  while (*context != XML_T('\0')) {
5454    if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
5455      ENTITY *e;
5456      if (!poolAppendChar(&tempPool, XML_T('\0')))
5457        return XML_FALSE;
5458      e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
5459      if (e)
5460        e->open = XML_TRUE;
5461      if (*s != XML_T('\0'))
5462        s++;
5463      context = s;
5464      poolDiscard(&tempPool);
5465    }
5466    else if (*s == XML_T(ASCII_EQUALS)) {
5467      PREFIX *prefix;
5468      if (poolLength(&tempPool) == 0)
5469        prefix = &dtd->defaultPrefix;
5470      else {
5471        if (!poolAppendChar(&tempPool, XML_T('\0')))
5472          return XML_FALSE;
5473        prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
5474                                  sizeof(PREFIX));
5475        if (!prefix)
5476          return XML_FALSE;
5477        if (prefix->name == poolStart(&tempPool)) {
5478          prefix->name = poolCopyString(&dtd->pool, prefix->name);
5479          if (!prefix->name)
5480            return XML_FALSE;
5481        }
5482        poolDiscard(&tempPool);
5483      }
5484      for (context = s + 1;
5485           *context != CONTEXT_SEP && *context != XML_T('\0');
5486           context++)
5487        if (!poolAppendChar(&tempPool, *context))
5488          return XML_FALSE;
5489      if (!poolAppendChar(&tempPool, XML_T('\0')))
5490        return XML_FALSE;
5491      if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
5492                     &inheritedBindings) != XML_ERROR_NONE)
5493        return XML_FALSE;
5494      poolDiscard(&tempPool);
5495      if (*context != XML_T('\0'))
5496        ++context;
5497      s = context;
5498    }
5499    else {
5500      if (!poolAppendChar(&tempPool, *s))
5501        return XML_FALSE;
5502      s++;
5503    }
5504  }
5505  return XML_TRUE;
5506}
5507
5508static void FASTCALL
5509normalizePublicId(XML_Char *publicId)
5510{
5511  XML_Char *p = publicId;
5512  XML_Char *s;
5513  for (s = publicId; *s; s++) {
5514    switch (*s) {
5515    case 0x20:
5516    case 0xD:
5517    case 0xA:
5518      if (p != publicId && p[-1] != 0x20)
5519        *p++ = 0x20;
5520      break;
5521    default:
5522      *p++ = *s;
5523    }
5524  }
5525  if (p != publicId && p[-1] == 0x20)
5526    --p;
5527  *p = XML_T('\0');
5528}
5529
5530static DTD *
5531dtdCreate(const XML_Memory_Handling_Suite *ms)
5532{
5533  DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
5534  if (p == NULL)
5535    return p;
5536  poolInit(&(p->pool), ms);
5537  poolInit(&(p->entityValuePool), ms);
5538  hashTableInit(&(p->generalEntities), ms);
5539  hashTableInit(&(p->elementTypes), ms);
5540  hashTableInit(&(p->attributeIds), ms);
5541  hashTableInit(&(p->prefixes), ms);
5542#ifdef XML_DTD
5543  p->paramEntityRead = XML_FALSE;
5544  hashTableInit(&(p->paramEntities), ms);
5545#endif /* XML_DTD */
5546  p->defaultPrefix.name = NULL;
5547  p->defaultPrefix.binding = NULL;
5548
5549  p->in_eldecl = XML_FALSE;
5550  p->scaffIndex = NULL;
5551  p->scaffold = NULL;
5552  p->scaffLevel = 0;
5553  p->scaffSize = 0;
5554  p->scaffCount = 0;
5555  p->contentStringLen = 0;
5556
5557  p->keepProcessing = XML_TRUE;
5558  p->hasParamEntityRefs = XML_FALSE;
5559  p->standalone = XML_FALSE;
5560  return p;
5561}
5562
5563static void
5564dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
5565{
5566  HASH_TABLE_ITER iter;
5567  hashTableIterInit(&iter, &(p->elementTypes));
5568  for (;;) {
5569    ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5570    if (!e)
5571      break;
5572    if (e->allocDefaultAtts != 0)
5573      ms->free_fcn(e->defaultAtts);
5574  }
5575  hashTableClear(&(p->generalEntities));
5576#ifdef XML_DTD
5577  p->paramEntityRead = XML_FALSE;
5578  hashTableClear(&(p->paramEntities));
5579#endif /* XML_DTD */
5580  hashTableClear(&(p->elementTypes));
5581  hashTableClear(&(p->attributeIds));
5582  hashTableClear(&(p->prefixes));
5583  poolClear(&(p->pool));
5584  poolClear(&(p->entityValuePool));
5585  p->defaultPrefix.name = NULL;
5586  p->defaultPrefix.binding = NULL;
5587
5588  p->in_eldecl = XML_FALSE;
5589
5590  ms->free_fcn(p->scaffIndex);
5591  p->scaffIndex = NULL;
5592  ms->free_fcn(p->scaffold);
5593  p->scaffold = NULL;
5594
5595  p->scaffLevel = 0;
5596  p->scaffSize = 0;
5597  p->scaffCount = 0;
5598  p->contentStringLen = 0;
5599
5600  p->keepProcessing = XML_TRUE;
5601  p->hasParamEntityRefs = XML_FALSE;
5602  p->standalone = XML_FALSE;
5603}
5604
5605static void
5606dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
5607{
5608  HASH_TABLE_ITER iter;
5609  hashTableIterInit(&iter, &(p->elementTypes));
5610  for (;;) {
5611    ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5612    if (!e)
5613      break;
5614    if (e->allocDefaultAtts != 0)
5615      ms->free_fcn(e->defaultAtts);
5616  }
5617  hashTableDestroy(&(p->generalEntities));
5618#ifdef XML_DTD
5619  hashTableDestroy(&(p->paramEntities));
5620#endif /* XML_DTD */
5621  hashTableDestroy(&(p->elementTypes));
5622  hashTableDestroy(&(p->attributeIds));
5623  hashTableDestroy(&(p->prefixes));
5624  poolDestroy(&(p->pool));
5625  poolDestroy(&(p->entityValuePool));
5626  if (isDocEntity) {
5627    ms->free_fcn(p->scaffIndex);
5628    ms->free_fcn(p->scaffold);
5629  }
5630  ms->free_fcn(p);
5631}
5632
5633/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
5634   The new DTD has already been initialized.
5635*/
5636static int
5637dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
5638{
5639  HASH_TABLE_ITER iter;
5640
5641  /* Copy the prefix table. */
5642
5643  hashTableIterInit(&iter, &(oldDtd->prefixes));
5644  for (;;) {
5645    const XML_Char *name;
5646    const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
5647    if (!oldP)
5648      break;
5649    name = poolCopyString(&(newDtd->pool), oldP->name);
5650    if (!name)
5651      return 0;
5652    if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
5653      return 0;
5654  }
5655
5656  hashTableIterInit(&iter, &(oldDtd->attributeIds));
5657
5658  /* Copy the attribute id table. */
5659
5660  for (;;) {
5661    ATTRIBUTE_ID *newA;
5662    const XML_Char *name;
5663    const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
5664
5665    if (!oldA)
5666      break;
5667    /* Remember to allocate the scratch byte before the name. */
5668    if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
5669      return 0;
5670    name = poolCopyString(&(newDtd->pool), oldA->name);
5671    if (!name)
5672      return 0;
5673    ++name;
5674    newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
5675                                  sizeof(ATTRIBUTE_ID));
5676    if (!newA)
5677      return 0;
5678    newA->maybeTokenized = oldA->maybeTokenized;
5679    if (oldA->prefix) {
5680      newA->xmlns = oldA->xmlns;
5681      if (oldA->prefix == &oldDtd->defaultPrefix)
5682        newA->prefix = &newDtd->defaultPrefix;
5683      else
5684        newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
5685                                        oldA->prefix->name, 0);
5686    }
5687  }
5688
5689  /* Copy the element type table. */
5690
5691  hashTableIterInit(&iter, &(oldDtd->elementTypes));
5692
5693  for (;;) {
5694    int i;
5695    ELEMENT_TYPE *newE;
5696    const XML_Char *name;
5697    const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5698    if (!oldE)
5699      break;
5700    name = poolCopyString(&(newDtd->pool), oldE->name);
5701    if (!name)
5702      return 0;
5703    newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
5704                                  sizeof(ELEMENT_TYPE));
5705    if (!newE)
5706      return 0;
5707    if (oldE->nDefaultAtts) {
5708      newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
5709          ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
5710      if (!newE->defaultAtts) {
5711        ms->free_fcn(newE);
5712        return 0;
5713      }
5714    }
5715    if (oldE->idAtt)
5716      newE->idAtt = (ATTRIBUTE_ID *)
5717          lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
5718    newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
5719    if (oldE->prefix)
5720      newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
5721                                      oldE->prefix->name, 0);
5722    for (i = 0; i < newE->nDefaultAtts; i++) {
5723      newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
5724          lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
5725      newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
5726      if (oldE->defaultAtts[i].value) {
5727        newE->defaultAtts[i].value
5728            = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
5729        if (!newE->defaultAtts[i].value)
5730          return 0;
5731      }
5732      else
5733        newE->defaultAtts[i].value = NULL;
5734    }
5735  }
5736
5737  /* Copy the entity tables. */
5738  if (!copyEntityTable(&(newDtd->generalEntities),
5739                       &(newDtd->pool),
5740                       &(oldDtd->generalEntities)))
5741      return 0;
5742
5743#ifdef XML_DTD
5744  if (!copyEntityTable(&(newDtd->paramEntities),
5745                       &(newDtd->pool),
5746                       &(oldDtd->paramEntities)))
5747      return 0;
5748  newDtd->paramEntityRead = oldDtd->paramEntityRead;
5749#endif /* XML_DTD */
5750
5751  newDtd->keepProcessing = oldDtd->keepProcessing;
5752  newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
5753  newDtd->standalone = oldDtd->standalone;
5754
5755  /* Don't want deep copying for scaffolding */
5756  newDtd->in_eldecl = oldDtd->in_eldecl;
5757  newDtd->scaffold = oldDtd->scaffold;
5758  newDtd->contentStringLen = oldDtd->contentStringLen;
5759  newDtd->scaffSize = oldDtd->scaffSize;
5760  newDtd->scaffLevel = oldDtd->scaffLevel;
5761  newDtd->scaffIndex = oldDtd->scaffIndex;
5762
5763  return 1;
5764}  /* End dtdCopy */
5765
5766static int
5767copyEntityTable(HASH_TABLE *newTable,
5768                STRING_POOL *newPool,
5769                const HASH_TABLE *oldTable)
5770{
5771  HASH_TABLE_ITER iter;
5772  const XML_Char *cachedOldBase = NULL;
5773  const XML_Char *cachedNewBase = NULL;
5774
5775  hashTableIterInit(&iter, oldTable);
5776
5777  for (;;) {
5778    ENTITY *newE;
5779    const XML_Char *name;
5780    const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
5781    if (!oldE)
5782      break;
5783    name = poolCopyString(newPool, oldE->name);
5784    if (!name)
5785      return 0;
5786    newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
5787    if (!newE)
5788      return 0;
5789    if (oldE->systemId) {
5790      const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
5791      if (!tem)
5792        return 0;
5793      newE->systemId = tem;
5794      if (oldE->base) {
5795        if (oldE->base == cachedOldBase)
5796          newE->base = cachedNewBase;
5797        else {
5798          cachedOldBase = oldE->base;
5799          tem = poolCopyString(newPool, cachedOldBase);
5800          if (!tem)
5801            return 0;
5802          cachedNewBase = newE->base = tem;
5803        }
5804      }
5805      if (oldE->publicId) {
5806        tem = poolCopyString(newPool, oldE->publicId);
5807        if (!tem)
5808          return 0;
5809        newE->publicId = tem;
5810      }
5811    }
5812    else {
5813      const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
5814                                            oldE->textLen);
5815      if (!tem)
5816        return 0;
5817      newE->textPtr = tem;
5818      newE->textLen = oldE->textLen;
5819    }
5820    if (oldE->notation) {
5821      const XML_Char *tem = poolCopyString(newPool, oldE->notation);
5822      if (!tem)
5823        return 0;
5824      newE->notation = tem;
5825    }
5826    newE->is_param = oldE->is_param;
5827    newE->is_internal = oldE->is_internal;
5828  }
5829  return 1;
5830}
5831
5832#define INIT_POWER 6
5833
5834static XML_Bool FASTCALL
5835keyeq(KEY s1, KEY s2)
5836{
5837  for (; *s1 == *s2; s1++, s2++)
5838    if (*s1 == 0)
5839      return XML_TRUE;
5840  return XML_FALSE;
5841}
5842
5843static unsigned long FASTCALL
5844hash(KEY s)
5845{
5846  unsigned long h = 0;
5847  while (*s)
5848    h = CHAR_HASH(h, *s++);
5849  return h;
5850}
5851
5852static NAMED *
5853lookup(HASH_TABLE *table, KEY name, size_t createSize)
5854{
5855  size_t i;
5856  if (table->size == 0) {
5857    size_t tsize;
5858    if (!createSize)
5859      return NULL;
5860    table->power = INIT_POWER;
5861    /* table->size is a power of 2 */
5862    table->size = (size_t)1 << INIT_POWER;
5863    tsize = table->size * sizeof(NAMED *);
5864    table->v = (NAMED **)table->mem->malloc_fcn(tsize);
5865    if (!table->v) {
5866      table->size = 0;
5867      return NULL;
5868    }
5869    memset(table->v, 0, tsize);
5870    i = hash(name) & ((unsigned long)table->size - 1);
5871  }
5872  else {
5873    unsigned long h = hash(name);
5874    unsigned long mask = (unsigned long)table->size - 1;
5875    unsigned char step = 0;
5876    i = h & mask;
5877    while (table->v[i]) {
5878      if (keyeq(name, table->v[i]->name))
5879        return table->v[i];
5880      if (!step)
5881        step = PROBE_STEP(h, mask, table->power);
5882      i < step ? (i += table->size - step) : (i -= step);
5883    }
5884    if (!createSize)
5885      return NULL;
5886
5887    /* check for overflow (table is half full) */
5888    if (table->used >> (table->power - 1)) {
5889      unsigned char newPower = table->power + 1;
5890      size_t newSize = (size_t)1 << newPower;
5891      unsigned long newMask = (unsigned long)newSize - 1;
5892      size_t tsize = newSize * sizeof(NAMED *);
5893      NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
5894      if (!newV)
5895        return NULL;
5896      memset(newV, 0, tsize);
5897      for (i = 0; i < table->size; i++)
5898        if (table->v[i]) {
5899          unsigned long newHash = hash(table->v[i]->name);
5900          size_t j = newHash & newMask;
5901          step = 0;
5902          while (newV[j]) {
5903            if (!step)
5904              step = PROBE_STEP(newHash, newMask, newPower);
5905            j < step ? (j += newSize - step) : (j -= step);
5906          }
5907          newV[j] = table->v[i];
5908        }
5909      table->mem->free_fcn(table->v);
5910      table->v = newV;
5911      table->power = newPower;
5912      table->size = newSize;
5913      i = h & newMask;
5914      step = 0;
5915      while (table->v[i]) {
5916        if (!step)
5917          step = PROBE_STEP(h, newMask, newPower);
5918        i < step ? (i += newSize - step) : (i -= step);
5919      }
5920    }
5921  }
5922  table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
5923  if (!table->v[i])
5924    return NULL;
5925  memset(table->v[i], 0, createSize);
5926  table->v[i]->name = name;
5927  (table->used)++;
5928  return table->v[i];
5929}
5930
5931static void FASTCALL
5932hashTableClear(HASH_TABLE *table)
5933{
5934  size_t i;
5935  for (i = 0; i < table->size; i++) {
5936    table->mem->free_fcn(table->v[i]);
5937    table->v[i] = NULL;
5938  }
5939  table->used = 0;
5940}
5941
5942static void FASTCALL
5943hashTableDestroy(HASH_TABLE *table)
5944{
5945  size_t i;
5946  for (i = 0; i < table->size; i++)
5947    table->mem->free_fcn(table->v[i]);
5948  table->mem->free_fcn(table->v);
5949}
5950
5951static void FASTCALL
5952hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
5953{
5954  p->power = 0;
5955  p->size = 0;
5956  p->used = 0;
5957  p->v = NULL;
5958  p->mem = ms;
5959}
5960
5961static void FASTCALL
5962hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
5963{
5964  iter->p = table->v;
5965  iter->end = iter->p + table->size;
5966}
5967
5968static NAMED * FASTCALL
5969hashTableIterNext(HASH_TABLE_ITER *iter)
5970{
5971  while (iter->p != iter->end) {
5972    NAMED *tem = *(iter->p)++;
5973    if (tem)
5974      return tem;
5975  }
5976  return NULL;
5977}
5978
5979static void FASTCALL
5980poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
5981{
5982  pool->blocks = NULL;
5983  pool->freeBlocks = NULL;
5984  pool->start = NULL;
5985  pool->ptr = NULL;
5986  pool->end = NULL;
5987  pool->mem = ms;
5988}
5989
5990static void FASTCALL
5991poolClear(STRING_POOL *pool)
5992{
5993  if (!pool->freeBlocks)
5994    pool->freeBlocks = pool->blocks;
5995  else {
5996    BLOCK *p = pool->blocks;
5997    while (p) {
5998      BLOCK *tem = p->next;
5999      p->next = pool->freeBlocks;
6000      pool->freeBlocks = p;
6001      p = tem;
6002    }
6003  }
6004  pool->blocks = NULL;
6005  pool->start = NULL;
6006  pool->ptr = NULL;
6007  pool->end = NULL;
6008}
6009
6010static void FASTCALL
6011poolDestroy(STRING_POOL *pool)
6012{
6013  BLOCK *p = pool->blocks;
6014  while (p) {
6015    BLOCK *tem = p->next;
6016    pool->mem->free_fcn(p);
6017    p = tem;
6018  }
6019  p = pool->freeBlocks;
6020  while (p) {
6021    BLOCK *tem = p->next;
6022    pool->mem->free_fcn(p);
6023    p = tem;
6024  }
6025}
6026
6027static XML_Char *
6028poolAppend(STRING_POOL *pool, const ENCODING *enc,
6029           const char *ptr, const char *end)
6030{
6031  if (!pool->ptr && !poolGrow(pool))
6032    return NULL;
6033  for (;;) {
6034    XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6035    if (ptr == end)
6036      break;
6037    if (!poolGrow(pool))
6038      return NULL;
6039  }
6040  return pool->start;
6041}
6042
6043static const XML_Char * FASTCALL
6044poolCopyString(STRING_POOL *pool, const XML_Char *s)
6045{
6046  do {
6047    if (!poolAppendChar(pool, *s))
6048      return NULL;
6049  } while (*s++);
6050  s = pool->start;
6051  poolFinish(pool);
6052  return s;
6053}
6054
6055static const XML_Char *
6056poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
6057{
6058  if (!pool->ptr && !poolGrow(pool))
6059    return NULL;
6060  for (; n > 0; --n, s++) {
6061    if (!poolAppendChar(pool, *s))
6062      return NULL;
6063  }
6064  s = pool->start;
6065  poolFinish(pool);
6066  return s;
6067}
6068
6069static const XML_Char * FASTCALL
6070poolAppendString(STRING_POOL *pool, const XML_Char *s)
6071{
6072  while (*s) {
6073    if (!poolAppendChar(pool, *s))
6074      return NULL;
6075    s++;
6076  }
6077  return pool->start;
6078}
6079
6080static XML_Char *
6081poolStoreString(STRING_POOL *pool, const ENCODING *enc,
6082                const char *ptr, const char *end)
6083{
6084  if (!poolAppend(pool, enc, ptr, end))
6085    return NULL;
6086  if (pool->ptr == pool->end && !poolGrow(pool))
6087    return NULL;
6088  *(pool->ptr)++ = 0;
6089  return pool->start;
6090}
6091
6092static XML_Bool FASTCALL
6093poolGrow(STRING_POOL *pool)
6094{
6095  if (pool->freeBlocks) {
6096    if (pool->start == 0) {
6097      pool->blocks = pool->freeBlocks;
6098      pool->freeBlocks = pool->freeBlocks->next;
6099      pool->blocks->next = NULL;
6100      pool->start = pool->blocks->s;
6101      pool->end = pool->start + pool->blocks->size;
6102      pool->ptr = pool->start;
6103      return XML_TRUE;
6104    }
6105    if (pool->end - pool->start < pool->freeBlocks->size) {
6106      BLOCK *tem = pool->freeBlocks->next;
6107      pool->freeBlocks->next = pool->blocks;
6108      pool->blocks = pool->freeBlocks;
6109      pool->freeBlocks = tem;
6110      memcpy(pool->blocks->s, pool->start,
6111             (pool->end - pool->start) * sizeof(XML_Char));
6112      pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6113      pool->start = pool->blocks->s;
6114      pool->end = pool->start + pool->blocks->size;
6115      return XML_TRUE;
6116    }
6117  }
6118  if (pool->blocks && pool->start == pool->blocks->s) {
6119    int blockSize = (int)(pool->end - pool->start)*2;
6120    pool->blocks = (BLOCK *)
6121      pool->mem->realloc_fcn(pool->blocks,
6122                             (offsetof(BLOCK, s)
6123                              + blockSize * sizeof(XML_Char)));
6124    if (pool->blocks == NULL)
6125      return XML_FALSE;
6126    pool->blocks->size = blockSize;
6127    pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6128    pool->start = pool->blocks->s;
6129    pool->end = pool->start + blockSize;
6130  }
6131  else {
6132    BLOCK *tem;
6133    int blockSize = (int)(pool->end - pool->start);
6134    if (blockSize < INIT_BLOCK_SIZE)
6135      blockSize = INIT_BLOCK_SIZE;
6136    else
6137      blockSize *= 2;
6138    tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
6139                                        + blockSize * sizeof(XML_Char));
6140    if (!tem)
6141      return XML_FALSE;
6142    tem->size = blockSize;
6143    tem->next = pool->blocks;
6144    pool->blocks = tem;
6145    if (pool->ptr != pool->start)
6146      memcpy(tem->s, pool->start,
6147             (pool->ptr - pool->start) * sizeof(XML_Char));
6148    pool->ptr = tem->s + (pool->ptr - pool->start);
6149    pool->start = tem->s;
6150    pool->end = tem->s + blockSize;
6151  }
6152  return XML_TRUE;
6153}
6154
6155static int FASTCALL
6156nextScaffoldPart(XML_Parser parser)
6157{
6158  DTD * const dtd = _dtd;  /* save one level of indirection */
6159  CONTENT_SCAFFOLD * me;
6160  int next;
6161
6162  if (!dtd->scaffIndex) {
6163    dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
6164    if (!dtd->scaffIndex)
6165      return -1;
6166    dtd->scaffIndex[0] = 0;
6167  }
6168
6169  if (dtd->scaffCount >= dtd->scaffSize) {
6170    CONTENT_SCAFFOLD *temp;
6171    if (dtd->scaffold) {
6172      temp = (CONTENT_SCAFFOLD *)
6173        REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
6174      if (temp == NULL)
6175        return -1;
6176      dtd->scaffSize *= 2;
6177    }
6178    else {
6179      temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
6180                                        * sizeof(CONTENT_SCAFFOLD));
6181      if (temp == NULL)
6182        return -1;
6183      dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
6184    }
6185    dtd->scaffold = temp;
6186  }
6187  next = dtd->scaffCount++;
6188  me = &dtd->scaffold[next];
6189  if (dtd->scaffLevel) {
6190    CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
6191    if (parent->lastchild) {
6192      dtd->scaffold[parent->lastchild].nextsib = next;
6193    }
6194    if (!parent->childcnt)
6195      parent->firstchild = next;
6196    parent->lastchild = next;
6197    parent->childcnt++;
6198  }
6199  me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
6200  return next;
6201}
6202
6203static void
6204build_node(XML_Parser parser,
6205           int src_node,
6206           XML_Content *dest,
6207           XML_Content **contpos,
6208           XML_Char **strpos)
6209{
6210  DTD * const dtd = _dtd;  /* save one level of indirection */
6211  dest->type = dtd->scaffold[src_node].type;
6212  dest->quant = dtd->scaffold[src_node].quant;
6213  if (dest->type == XML_CTYPE_NAME) {
6214    const XML_Char *src;
6215    dest->name = *strpos;
6216    src = dtd->scaffold[src_node].name;
6217    for (;;) {
6218      *(*strpos)++ = *src;
6219      if (!*src)
6220        break;
6221      src++;
6222    }
6223    dest->numchildren = 0;
6224    dest->children = NULL;
6225  }
6226  else {
6227    unsigned int i;
6228    int cn;
6229    dest->numchildren = dtd->scaffold[src_node].childcnt;
6230    dest->children = *contpos;
6231    *contpos += dest->numchildren;
6232    for (i = 0, cn = dtd->scaffold[src_node].firstchild;
6233         i < dest->numchildren;
6234         i++, cn = dtd->scaffold[cn].nextsib) {
6235      build_node(parser, cn, &(dest->children[i]), contpos, strpos);
6236    }
6237    dest->name = NULL;
6238  }
6239}
6240
6241static XML_Content *
6242build_model (XML_Parser parser)
6243{
6244  DTD * const dtd = _dtd;  /* save one level of indirection */
6245  XML_Content *ret;
6246  XML_Content *cpos;
6247  XML_Char * str;
6248  int allocsize = (dtd->scaffCount * sizeof(XML_Content)
6249                   + (dtd->contentStringLen * sizeof(XML_Char)));
6250
6251  ret = (XML_Content *)MALLOC(allocsize);
6252  if (!ret)
6253    return NULL;
6254
6255  str =  (XML_Char *) (&ret[dtd->scaffCount]);
6256  cpos = &ret[1];
6257
6258  build_node(parser, 0, ret, &cpos, &str);
6259  return ret;
6260}
6261
6262static ELEMENT_TYPE *
6263getElementType(XML_Parser parser,
6264               const ENCODING *enc,
6265               const char *ptr,
6266               const char *end)
6267{
6268  DTD * const dtd = _dtd;  /* save one level of indirection */
6269  const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
6270  ELEMENT_TYPE *ret;
6271
6272  if (!name)
6273    return NULL;
6274  ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
6275  if (!ret)
6276    return NULL;
6277  if (ret->name != name)
6278    poolDiscard(&dtd->pool);
6279  else {
6280    poolFinish(&dtd->pool);
6281    if (!setElementTypePrefix(parser, ret))
6282      return NULL;
6283  }
6284  return ret;
6285}
6286