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