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