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