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