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