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