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