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