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