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