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