xref: /freebsd/contrib/expat/lib/xmlparse.c (revision 9005607c8fa7317a759f1fc16cae4738f9a2fbb3)
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_NONE:
3707 #ifdef XML_DTD
3708         /* for internal PE NOT referenced between declarations */
3709         if (enc != encoding && !openInternalEntities->betweenDecl) {
3710           *nextPtr = s;
3711           return XML_ERROR_NONE;
3712         }
3713         /* WFC: PE Between Declarations - must check that PE contains
3714            complete markup, not only for external PEs, but also for
3715            internal PEs if the reference occurs between declarations.
3716         */
3717         if (isParamEntity || enc != encoding) {
3718           if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
3719               == XML_ROLE_ERROR)
3720             return XML_ERROR_INCOMPLETE_PE;
3721           *nextPtr = s;
3722           return XML_ERROR_NONE;
3723         }
3724 #endif /* XML_DTD */
3725         return XML_ERROR_NO_ELEMENTS;
3726       default:
3727         tok = -tok;
3728         break;
3729       }
3730     }
3731     role = XmlTokenRole(&prologState, tok, s, next, enc);
3732     switch (role) {
3733     case XML_ROLE_XML_DECL:
3734       {
3735         enum XML_Error result = processXmlDecl(parser, 0, s, next);
3736         if (result != XML_ERROR_NONE)
3737           return result;
3738         enc = encoding;
3739         handleDefault = XML_FALSE;
3740       }
3741       break;
3742     case XML_ROLE_DOCTYPE_NAME:
3743       if (startDoctypeDeclHandler) {
3744         doctypeName = poolStoreString(&tempPool, enc, s, next);
3745         if (!doctypeName)
3746           return XML_ERROR_NO_MEMORY;
3747         poolFinish(&tempPool);
3748         doctypePubid = NULL;
3749         handleDefault = XML_FALSE;
3750       }
3751       doctypeSysid = NULL; /* always initialize to NULL */
3752       break;
3753     case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
3754       if (startDoctypeDeclHandler) {
3755         startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
3756                                 doctypePubid, 1);
3757         doctypeName = NULL;
3758         poolClear(&tempPool);
3759         handleDefault = XML_FALSE;
3760       }
3761       break;
3762 #ifdef XML_DTD
3763     case XML_ROLE_TEXT_DECL:
3764       {
3765         enum XML_Error result = processXmlDecl(parser, 1, s, next);
3766         if (result != XML_ERROR_NONE)
3767           return result;
3768         enc = encoding;
3769         handleDefault = XML_FALSE;
3770       }
3771       break;
3772 #endif /* XML_DTD */
3773     case XML_ROLE_DOCTYPE_PUBLIC_ID:
3774 #ifdef XML_DTD
3775       useForeignDTD = XML_FALSE;
3776       declEntity = (ENTITY *)lookup(&dtd->paramEntities,
3777                                     externalSubsetName,
3778                                     sizeof(ENTITY));
3779       if (!declEntity)
3780         return XML_ERROR_NO_MEMORY;
3781 #endif /* XML_DTD */
3782       dtd->hasParamEntityRefs = XML_TRUE;
3783       if (startDoctypeDeclHandler) {
3784         if (!XmlIsPublicId(enc, s, next, eventPP))
3785           return XML_ERROR_PUBLICID;
3786         doctypePubid = poolStoreString(&tempPool, enc,
3787                                        s + enc->minBytesPerChar,
3788                                        next - enc->minBytesPerChar);
3789         if (!doctypePubid)
3790           return XML_ERROR_NO_MEMORY;
3791         normalizePublicId((XML_Char *)doctypePubid);
3792         poolFinish(&tempPool);
3793         handleDefault = XML_FALSE;
3794         goto alreadyChecked;
3795       }
3796       /* fall through */
3797     case XML_ROLE_ENTITY_PUBLIC_ID:
3798       if (!XmlIsPublicId(enc, s, next, eventPP))
3799         return XML_ERROR_PUBLICID;
3800     alreadyChecked:
3801       if (dtd->keepProcessing && declEntity) {
3802         XML_Char *tem = poolStoreString(&dtd->pool,
3803                                         enc,
3804                                         s + enc->minBytesPerChar,
3805                                         next - enc->minBytesPerChar);
3806         if (!tem)
3807           return XML_ERROR_NO_MEMORY;
3808         normalizePublicId(tem);
3809         declEntity->publicId = tem;
3810         poolFinish(&dtd->pool);
3811         if (entityDeclHandler)
3812           handleDefault = XML_FALSE;
3813       }
3814       break;
3815     case XML_ROLE_DOCTYPE_CLOSE:
3816       if (doctypeName) {
3817         startDoctypeDeclHandler(handlerArg, doctypeName,
3818                                 doctypeSysid, doctypePubid, 0);
3819         poolClear(&tempPool);
3820         handleDefault = XML_FALSE;
3821       }
3822       /* doctypeSysid will be non-NULL in the case of a previous
3823          XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
3824          was not set, indicating an external subset
3825       */
3826 #ifdef XML_DTD
3827       if (doctypeSysid || useForeignDTD) {
3828         XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3829         dtd->hasParamEntityRefs = XML_TRUE;
3830         if (paramEntityParsing && externalEntityRefHandler) {
3831           ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
3832                                             externalSubsetName,
3833                                             sizeof(ENTITY));
3834           if (!entity)
3835             return XML_ERROR_NO_MEMORY;
3836           if (useForeignDTD)
3837             entity->base = curBase;
3838           dtd->paramEntityRead = XML_FALSE;
3839           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3840                                         0,
3841                                         entity->base,
3842                                         entity->systemId,
3843                                         entity->publicId))
3844             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3845           if (dtd->paramEntityRead) {
3846             if (!dtd->standalone &&
3847                 notStandaloneHandler &&
3848                 !notStandaloneHandler(handlerArg))
3849               return XML_ERROR_NOT_STANDALONE;
3850           }
3851           /* if we didn't read the foreign DTD then this means that there
3852              is no external subset and we must reset dtd->hasParamEntityRefs
3853           */
3854           else if (!doctypeSysid)
3855             dtd->hasParamEntityRefs = hadParamEntityRefs;
3856           /* end of DTD - no need to update dtd->keepProcessing */
3857         }
3858         useForeignDTD = XML_FALSE;
3859       }
3860 #endif /* XML_DTD */
3861       if (endDoctypeDeclHandler) {
3862         endDoctypeDeclHandler(handlerArg);
3863         handleDefault = XML_FALSE;
3864       }
3865       break;
3866     case XML_ROLE_INSTANCE_START:
3867 #ifdef XML_DTD
3868       /* if there is no DOCTYPE declaration then now is the
3869          last chance to read the foreign DTD
3870       */
3871       if (useForeignDTD) {
3872         XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3873         dtd->hasParamEntityRefs = XML_TRUE;
3874         if (paramEntityParsing && externalEntityRefHandler) {
3875           ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
3876                                             externalSubsetName,
3877                                             sizeof(ENTITY));
3878           if (!entity)
3879             return XML_ERROR_NO_MEMORY;
3880           entity->base = curBase;
3881           dtd->paramEntityRead = XML_FALSE;
3882           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3883                                         0,
3884                                         entity->base,
3885                                         entity->systemId,
3886                                         entity->publicId))
3887             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3888           if (dtd->paramEntityRead) {
3889             if (!dtd->standalone &&
3890                 notStandaloneHandler &&
3891                 !notStandaloneHandler(handlerArg))
3892               return XML_ERROR_NOT_STANDALONE;
3893           }
3894           /* if we didn't read the foreign DTD then this means that there
3895              is no external subset and we must reset dtd->hasParamEntityRefs
3896           */
3897           else
3898             dtd->hasParamEntityRefs = hadParamEntityRefs;
3899           /* end of DTD - no need to update dtd->keepProcessing */
3900         }
3901       }
3902 #endif /* XML_DTD */
3903       processor = contentProcessor;
3904       return contentProcessor(parser, s, end, nextPtr);
3905     case XML_ROLE_ATTLIST_ELEMENT_NAME:
3906       declElementType = getElementType(parser, enc, s, next);
3907       if (!declElementType)
3908         return XML_ERROR_NO_MEMORY;
3909       goto checkAttListDeclHandler;
3910     case XML_ROLE_ATTRIBUTE_NAME:
3911       declAttributeId = getAttributeId(parser, enc, s, next);
3912       if (!declAttributeId)
3913         return XML_ERROR_NO_MEMORY;
3914       declAttributeIsCdata = XML_FALSE;
3915       declAttributeType = NULL;
3916       declAttributeIsId = XML_FALSE;
3917       goto checkAttListDeclHandler;
3918     case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
3919       declAttributeIsCdata = XML_TRUE;
3920       declAttributeType = atypeCDATA;
3921       goto checkAttListDeclHandler;
3922     case XML_ROLE_ATTRIBUTE_TYPE_ID:
3923       declAttributeIsId = XML_TRUE;
3924       declAttributeType = atypeID;
3925       goto checkAttListDeclHandler;
3926     case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
3927       declAttributeType = atypeIDREF;
3928       goto checkAttListDeclHandler;
3929     case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
3930       declAttributeType = atypeIDREFS;
3931       goto checkAttListDeclHandler;
3932     case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
3933       declAttributeType = atypeENTITY;
3934       goto checkAttListDeclHandler;
3935     case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
3936       declAttributeType = atypeENTITIES;
3937       goto checkAttListDeclHandler;
3938     case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
3939       declAttributeType = atypeNMTOKEN;
3940       goto checkAttListDeclHandler;
3941     case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
3942       declAttributeType = atypeNMTOKENS;
3943     checkAttListDeclHandler:
3944       if (dtd->keepProcessing && attlistDeclHandler)
3945         handleDefault = XML_FALSE;
3946       break;
3947     case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
3948     case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
3949       if (dtd->keepProcessing && attlistDeclHandler) {
3950         const XML_Char *prefix;
3951         if (declAttributeType) {
3952           prefix = enumValueSep;
3953         }
3954         else {
3955           prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
3956                     ? notationPrefix
3957                     : enumValueStart);
3958         }
3959         if (!poolAppendString(&tempPool, prefix))
3960           return XML_ERROR_NO_MEMORY;
3961         if (!poolAppend(&tempPool, enc, s, next))
3962           return XML_ERROR_NO_MEMORY;
3963         declAttributeType = tempPool.start;
3964         handleDefault = XML_FALSE;
3965       }
3966       break;
3967     case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
3968     case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
3969       if (dtd->keepProcessing) {
3970         if (!defineAttribute(declElementType, declAttributeId,
3971                              declAttributeIsCdata, declAttributeIsId,
3972                              0, parser))
3973           return XML_ERROR_NO_MEMORY;
3974         if (attlistDeclHandler && declAttributeType) {
3975           if (*declAttributeType == XML_T(ASCII_LPAREN)
3976               || (*declAttributeType == XML_T(ASCII_N)
3977                   && declAttributeType[1] == XML_T(ASCII_O))) {
3978             /* Enumerated or Notation type */
3979             if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
3980                 || !poolAppendChar(&tempPool, XML_T('\0')))
3981               return XML_ERROR_NO_MEMORY;
3982             declAttributeType = tempPool.start;
3983             poolFinish(&tempPool);
3984           }
3985           *eventEndPP = s;
3986           attlistDeclHandler(handlerArg, declElementType->name,
3987                              declAttributeId->name, declAttributeType,
3988                              0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
3989           poolClear(&tempPool);
3990           handleDefault = XML_FALSE;
3991         }
3992       }
3993       break;
3994     case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
3995     case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
3996       if (dtd->keepProcessing) {
3997         const XML_Char *attVal;
3998         enum XML_Error result =
3999           storeAttributeValue(parser, enc, declAttributeIsCdata,
4000                               s + enc->minBytesPerChar,
4001                               next - enc->minBytesPerChar,
4002                               &dtd->pool);
4003         if (result)
4004           return result;
4005         attVal = poolStart(&dtd->pool);
4006         poolFinish(&dtd->pool);
4007         /* ID attributes aren't allowed to have a default */
4008         if (!defineAttribute(declElementType, declAttributeId,
4009                              declAttributeIsCdata, XML_FALSE, attVal, parser))
4010           return XML_ERROR_NO_MEMORY;
4011         if (attlistDeclHandler && declAttributeType) {
4012           if (*declAttributeType == XML_T(ASCII_LPAREN)
4013               || (*declAttributeType == XML_T(ASCII_N)
4014                   && declAttributeType[1] == XML_T(ASCII_O))) {
4015             /* Enumerated or Notation type */
4016             if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4017                 || !poolAppendChar(&tempPool, XML_T('\0')))
4018               return XML_ERROR_NO_MEMORY;
4019             declAttributeType = tempPool.start;
4020             poolFinish(&tempPool);
4021           }
4022           *eventEndPP = s;
4023           attlistDeclHandler(handlerArg, declElementType->name,
4024                              declAttributeId->name, declAttributeType,
4025                              attVal,
4026                              role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
4027           poolClear(&tempPool);
4028           handleDefault = XML_FALSE;
4029         }
4030       }
4031       break;
4032     case XML_ROLE_ENTITY_VALUE:
4033       if (dtd->keepProcessing) {
4034         enum XML_Error result = storeEntityValue(parser, enc,
4035                                             s + enc->minBytesPerChar,
4036                                             next - enc->minBytesPerChar);
4037         if (declEntity) {
4038           declEntity->textPtr = poolStart(&dtd->entityValuePool);
4039           declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
4040           poolFinish(&dtd->entityValuePool);
4041           if (entityDeclHandler) {
4042             *eventEndPP = s;
4043             entityDeclHandler(handlerArg,
4044                               declEntity->name,
4045                               declEntity->is_param,
4046                               declEntity->textPtr,
4047                               declEntity->textLen,
4048                               curBase, 0, 0, 0);
4049             handleDefault = XML_FALSE;
4050           }
4051         }
4052         else
4053           poolDiscard(&dtd->entityValuePool);
4054         if (result != XML_ERROR_NONE)
4055           return result;
4056       }
4057       break;
4058     case XML_ROLE_DOCTYPE_SYSTEM_ID:
4059 #ifdef XML_DTD
4060       useForeignDTD = XML_FALSE;
4061 #endif /* XML_DTD */
4062       dtd->hasParamEntityRefs = XML_TRUE;
4063       if (startDoctypeDeclHandler) {
4064         doctypeSysid = poolStoreString(&tempPool, enc,
4065                                        s + enc->minBytesPerChar,
4066                                        next - enc->minBytesPerChar);
4067         if (doctypeSysid == NULL)
4068           return XML_ERROR_NO_MEMORY;
4069         poolFinish(&tempPool);
4070         handleDefault = XML_FALSE;
4071       }
4072 #ifdef XML_DTD
4073       else
4074         /* use externalSubsetName to make doctypeSysid non-NULL
4075            for the case where no startDoctypeDeclHandler is set */
4076         doctypeSysid = externalSubsetName;
4077 #endif /* XML_DTD */
4078       if (!dtd->standalone
4079 #ifdef XML_DTD
4080           && !paramEntityParsing
4081 #endif /* XML_DTD */
4082           && notStandaloneHandler
4083           && !notStandaloneHandler(handlerArg))
4084         return XML_ERROR_NOT_STANDALONE;
4085 #ifndef XML_DTD
4086       break;
4087 #else /* XML_DTD */
4088       if (!declEntity) {
4089         declEntity = (ENTITY *)lookup(&dtd->paramEntities,
4090                                       externalSubsetName,
4091                                       sizeof(ENTITY));
4092         if (!declEntity)
4093           return XML_ERROR_NO_MEMORY;
4094         declEntity->publicId = NULL;
4095       }
4096       /* fall through */
4097 #endif /* XML_DTD */
4098     case XML_ROLE_ENTITY_SYSTEM_ID:
4099       if (dtd->keepProcessing && declEntity) {
4100         declEntity->systemId = poolStoreString(&dtd->pool, enc,
4101                                                s + enc->minBytesPerChar,
4102                                                next - enc->minBytesPerChar);
4103         if (!declEntity->systemId)
4104           return XML_ERROR_NO_MEMORY;
4105         declEntity->base = curBase;
4106         poolFinish(&dtd->pool);
4107         if (entityDeclHandler)
4108           handleDefault = XML_FALSE;
4109       }
4110       break;
4111     case XML_ROLE_ENTITY_COMPLETE:
4112       if (dtd->keepProcessing && declEntity && entityDeclHandler) {
4113         *eventEndPP = s;
4114         entityDeclHandler(handlerArg,
4115                           declEntity->name,
4116                           declEntity->is_param,
4117                           0,0,
4118                           declEntity->base,
4119                           declEntity->systemId,
4120                           declEntity->publicId,
4121                           0);
4122         handleDefault = XML_FALSE;
4123       }
4124       break;
4125     case XML_ROLE_ENTITY_NOTATION_NAME:
4126       if (dtd->keepProcessing && declEntity) {
4127         declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
4128         if (!declEntity->notation)
4129           return XML_ERROR_NO_MEMORY;
4130         poolFinish(&dtd->pool);
4131         if (unparsedEntityDeclHandler) {
4132           *eventEndPP = s;
4133           unparsedEntityDeclHandler(handlerArg,
4134                                     declEntity->name,
4135                                     declEntity->base,
4136                                     declEntity->systemId,
4137                                     declEntity->publicId,
4138                                     declEntity->notation);
4139           handleDefault = XML_FALSE;
4140         }
4141         else if (entityDeclHandler) {
4142           *eventEndPP = s;
4143           entityDeclHandler(handlerArg,
4144                             declEntity->name,
4145                             0,0,0,
4146                             declEntity->base,
4147                             declEntity->systemId,
4148                             declEntity->publicId,
4149                             declEntity->notation);
4150           handleDefault = XML_FALSE;
4151         }
4152       }
4153       break;
4154     case XML_ROLE_GENERAL_ENTITY_NAME:
4155       {
4156         if (XmlPredefinedEntityName(enc, s, next)) {
4157           declEntity = NULL;
4158           break;
4159         }
4160         if (dtd->keepProcessing) {
4161           const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4162           if (!name)
4163             return XML_ERROR_NO_MEMORY;
4164           declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
4165                                         sizeof(ENTITY));
4166           if (!declEntity)
4167             return XML_ERROR_NO_MEMORY;
4168           if (declEntity->name != name) {
4169             poolDiscard(&dtd->pool);
4170             declEntity = NULL;
4171           }
4172           else {
4173             poolFinish(&dtd->pool);
4174             declEntity->publicId = NULL;
4175             declEntity->is_param = XML_FALSE;
4176             /* if we have a parent parser or are reading an internal parameter
4177                entity, then the entity declaration is not considered "internal"
4178             */
4179             declEntity->is_internal = !(parentParser || openInternalEntities);
4180             if (entityDeclHandler)
4181               handleDefault = XML_FALSE;
4182           }
4183         }
4184         else {
4185           poolDiscard(&dtd->pool);
4186           declEntity = NULL;
4187         }
4188       }
4189       break;
4190     case XML_ROLE_PARAM_ENTITY_NAME:
4191 #ifdef XML_DTD
4192       if (dtd->keepProcessing) {
4193         const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4194         if (!name)
4195           return XML_ERROR_NO_MEMORY;
4196         declEntity = (ENTITY *)lookup(&dtd->paramEntities,
4197                                            name, sizeof(ENTITY));
4198         if (!declEntity)
4199           return XML_ERROR_NO_MEMORY;
4200         if (declEntity->name != name) {
4201           poolDiscard(&dtd->pool);
4202           declEntity = NULL;
4203         }
4204         else {
4205           poolFinish(&dtd->pool);
4206           declEntity->publicId = NULL;
4207           declEntity->is_param = XML_TRUE;
4208           /* if we have a parent parser or are reading an internal parameter
4209              entity, then the entity declaration is not considered "internal"
4210           */
4211           declEntity->is_internal = !(parentParser || openInternalEntities);
4212           if (entityDeclHandler)
4213             handleDefault = XML_FALSE;
4214         }
4215       }
4216       else {
4217         poolDiscard(&dtd->pool);
4218         declEntity = NULL;
4219       }
4220 #else /* not XML_DTD */
4221       declEntity = NULL;
4222 #endif /* XML_DTD */
4223       break;
4224     case XML_ROLE_NOTATION_NAME:
4225       declNotationPublicId = NULL;
4226       declNotationName = NULL;
4227       if (notationDeclHandler) {
4228         declNotationName = poolStoreString(&tempPool, enc, s, next);
4229         if (!declNotationName)
4230           return XML_ERROR_NO_MEMORY;
4231         poolFinish(&tempPool);
4232         handleDefault = XML_FALSE;
4233       }
4234       break;
4235     case XML_ROLE_NOTATION_PUBLIC_ID:
4236       if (!XmlIsPublicId(enc, s, next, eventPP))
4237         return XML_ERROR_PUBLICID;
4238       if (declNotationName) {  /* means notationDeclHandler != NULL */
4239         XML_Char *tem = poolStoreString(&tempPool,
4240                                         enc,
4241                                         s + enc->minBytesPerChar,
4242                                         next - enc->minBytesPerChar);
4243         if (!tem)
4244           return XML_ERROR_NO_MEMORY;
4245         normalizePublicId(tem);
4246         declNotationPublicId = tem;
4247         poolFinish(&tempPool);
4248         handleDefault = XML_FALSE;
4249       }
4250       break;
4251     case XML_ROLE_NOTATION_SYSTEM_ID:
4252       if (declNotationName && notationDeclHandler) {
4253         const XML_Char *systemId
4254           = poolStoreString(&tempPool, enc,
4255                             s + enc->minBytesPerChar,
4256                             next - enc->minBytesPerChar);
4257         if (!systemId)
4258           return XML_ERROR_NO_MEMORY;
4259         *eventEndPP = s;
4260         notationDeclHandler(handlerArg,
4261                             declNotationName,
4262                             curBase,
4263                             systemId,
4264                             declNotationPublicId);
4265         handleDefault = XML_FALSE;
4266       }
4267       poolClear(&tempPool);
4268       break;
4269     case XML_ROLE_NOTATION_NO_SYSTEM_ID:
4270       if (declNotationPublicId && notationDeclHandler) {
4271         *eventEndPP = s;
4272         notationDeclHandler(handlerArg,
4273                             declNotationName,
4274                             curBase,
4275                             0,
4276                             declNotationPublicId);
4277         handleDefault = XML_FALSE;
4278       }
4279       poolClear(&tempPool);
4280       break;
4281     case XML_ROLE_ERROR:
4282       switch (tok) {
4283       case XML_TOK_PARAM_ENTITY_REF:
4284         /* PE references in internal subset are
4285            not allowed within declarations. */
4286         return XML_ERROR_PARAM_ENTITY_REF;
4287       case XML_TOK_XML_DECL:
4288         return XML_ERROR_MISPLACED_XML_PI;
4289       default:
4290         return XML_ERROR_SYNTAX;
4291       }
4292 #ifdef XML_DTD
4293     case XML_ROLE_IGNORE_SECT:
4294       {
4295         enum XML_Error result;
4296         if (defaultHandler)
4297           reportDefault(parser, enc, s, next);
4298         handleDefault = XML_FALSE;
4299         result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
4300         if (result != XML_ERROR_NONE)
4301           return result;
4302         else if (!next) {
4303           processor = ignoreSectionProcessor;
4304           return result;
4305         }
4306       }
4307       break;
4308 #endif /* XML_DTD */
4309     case XML_ROLE_GROUP_OPEN:
4310       if (prologState.level >= groupSize) {
4311         if (groupSize) {
4312           char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
4313           if (temp == NULL)
4314             return XML_ERROR_NO_MEMORY;
4315           groupConnector = temp;
4316           if (dtd->scaffIndex) {
4317             int *temp = (int *)REALLOC(dtd->scaffIndex,
4318                           groupSize * sizeof(int));
4319             if (temp == NULL)
4320               return XML_ERROR_NO_MEMORY;
4321             dtd->scaffIndex = temp;
4322           }
4323         }
4324         else {
4325           groupConnector = (char *)MALLOC(groupSize = 32);
4326           if (!groupConnector)
4327             return XML_ERROR_NO_MEMORY;
4328         }
4329       }
4330       groupConnector[prologState.level] = 0;
4331       if (dtd->in_eldecl) {
4332         int myindex = nextScaffoldPart(parser);
4333         if (myindex < 0)
4334           return XML_ERROR_NO_MEMORY;
4335         dtd->scaffIndex[dtd->scaffLevel] = myindex;
4336         dtd->scaffLevel++;
4337         dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
4338         if (elementDeclHandler)
4339           handleDefault = XML_FALSE;
4340       }
4341       break;
4342     case XML_ROLE_GROUP_SEQUENCE:
4343       if (groupConnector[prologState.level] == ASCII_PIPE)
4344         return XML_ERROR_SYNTAX;
4345       groupConnector[prologState.level] = ASCII_COMMA;
4346       if (dtd->in_eldecl && elementDeclHandler)
4347         handleDefault = XML_FALSE;
4348       break;
4349     case XML_ROLE_GROUP_CHOICE:
4350       if (groupConnector[prologState.level] == ASCII_COMMA)
4351         return XML_ERROR_SYNTAX;
4352       if (dtd->in_eldecl
4353           && !groupConnector[prologState.level]
4354           && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4355               != XML_CTYPE_MIXED)
4356           ) {
4357         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4358             = XML_CTYPE_CHOICE;
4359         if (elementDeclHandler)
4360           handleDefault = XML_FALSE;
4361       }
4362       groupConnector[prologState.level] = ASCII_PIPE;
4363       break;
4364     case XML_ROLE_PARAM_ENTITY_REF:
4365 #ifdef XML_DTD
4366     case XML_ROLE_INNER_PARAM_ENTITY_REF:
4367       dtd->hasParamEntityRefs = XML_TRUE;
4368       if (!paramEntityParsing)
4369         dtd->keepProcessing = dtd->standalone;
4370       else {
4371         const XML_Char *name;
4372         ENTITY *entity;
4373         name = poolStoreString(&dtd->pool, enc,
4374                                 s + enc->minBytesPerChar,
4375                                 next - enc->minBytesPerChar);
4376         if (!name)
4377           return XML_ERROR_NO_MEMORY;
4378         entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
4379         poolDiscard(&dtd->pool);
4380         /* first, determine if a check for an existing declaration is needed;
4381            if yes, check that the entity exists, and that it is internal,
4382            otherwise call the skipped entity handler
4383         */
4384         if (prologState.documentEntity &&
4385             (dtd->standalone
4386              ? !openInternalEntities
4387              : !dtd->hasParamEntityRefs)) {
4388           if (!entity)
4389             return XML_ERROR_UNDEFINED_ENTITY;
4390           else if (!entity->is_internal)
4391             return XML_ERROR_ENTITY_DECLARED_IN_PE;
4392         }
4393         else if (!entity) {
4394           dtd->keepProcessing = dtd->standalone;
4395           /* cannot report skipped entities in declarations */
4396           if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
4397             skippedEntityHandler(handlerArg, name, 1);
4398             handleDefault = XML_FALSE;
4399           }
4400           break;
4401         }
4402         if (entity->open)
4403           return XML_ERROR_RECURSIVE_ENTITY_REF;
4404         if (entity->textPtr) {
4405           enum XML_Error result;
4406           XML_Bool betweenDecl =
4407             (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
4408           result = processInternalEntity(parser, entity, betweenDecl);
4409           if (result != XML_ERROR_NONE)
4410             return result;
4411           handleDefault = XML_FALSE;
4412           break;
4413         }
4414         if (externalEntityRefHandler) {
4415           dtd->paramEntityRead = XML_FALSE;
4416           entity->open = XML_TRUE;
4417           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4418                                         0,
4419                                         entity->base,
4420                                         entity->systemId,
4421                                         entity->publicId)) {
4422             entity->open = XML_FALSE;
4423             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4424           }
4425           entity->open = XML_FALSE;
4426           handleDefault = XML_FALSE;
4427           if (!dtd->paramEntityRead) {
4428             dtd->keepProcessing = dtd->standalone;
4429             break;
4430           }
4431         }
4432         else {
4433           dtd->keepProcessing = dtd->standalone;
4434           break;
4435         }
4436       }
4437 #endif /* XML_DTD */
4438       if (!dtd->standalone &&
4439           notStandaloneHandler &&
4440           !notStandaloneHandler(handlerArg))
4441         return XML_ERROR_NOT_STANDALONE;
4442       break;
4443 
4444     /* Element declaration stuff */
4445 
4446     case XML_ROLE_ELEMENT_NAME:
4447       if (elementDeclHandler) {
4448         declElementType = getElementType(parser, enc, s, next);
4449         if (!declElementType)
4450           return XML_ERROR_NO_MEMORY;
4451         dtd->scaffLevel = 0;
4452         dtd->scaffCount = 0;
4453         dtd->in_eldecl = XML_TRUE;
4454         handleDefault = XML_FALSE;
4455       }
4456       break;
4457 
4458     case XML_ROLE_CONTENT_ANY:
4459     case XML_ROLE_CONTENT_EMPTY:
4460       if (dtd->in_eldecl) {
4461         if (elementDeclHandler) {
4462           XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
4463           if (!content)
4464             return XML_ERROR_NO_MEMORY;
4465           content->quant = XML_CQUANT_NONE;
4466           content->name = NULL;
4467           content->numchildren = 0;
4468           content->children = NULL;
4469           content->type = ((role == XML_ROLE_CONTENT_ANY) ?
4470                            XML_CTYPE_ANY :
4471                            XML_CTYPE_EMPTY);
4472           *eventEndPP = s;
4473           elementDeclHandler(handlerArg, declElementType->name, content);
4474           handleDefault = XML_FALSE;
4475         }
4476         dtd->in_eldecl = XML_FALSE;
4477       }
4478       break;
4479 
4480     case XML_ROLE_CONTENT_PCDATA:
4481       if (dtd->in_eldecl) {
4482         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4483             = XML_CTYPE_MIXED;
4484         if (elementDeclHandler)
4485           handleDefault = XML_FALSE;
4486       }
4487       break;
4488 
4489     case XML_ROLE_CONTENT_ELEMENT:
4490       quant = XML_CQUANT_NONE;
4491       goto elementContent;
4492     case XML_ROLE_CONTENT_ELEMENT_OPT:
4493       quant = XML_CQUANT_OPT;
4494       goto elementContent;
4495     case XML_ROLE_CONTENT_ELEMENT_REP:
4496       quant = XML_CQUANT_REP;
4497       goto elementContent;
4498     case XML_ROLE_CONTENT_ELEMENT_PLUS:
4499       quant = XML_CQUANT_PLUS;
4500     elementContent:
4501       if (dtd->in_eldecl) {
4502         ELEMENT_TYPE *el;
4503         const XML_Char *name;
4504         int nameLen;
4505         const char *nxt = (quant == XML_CQUANT_NONE
4506                            ? next
4507                            : next - enc->minBytesPerChar);
4508         int myindex = nextScaffoldPart(parser);
4509         if (myindex < 0)
4510           return XML_ERROR_NO_MEMORY;
4511         dtd->scaffold[myindex].type = XML_CTYPE_NAME;
4512         dtd->scaffold[myindex].quant = quant;
4513         el = getElementType(parser, enc, s, nxt);
4514         if (!el)
4515           return XML_ERROR_NO_MEMORY;
4516         name = el->name;
4517         dtd->scaffold[myindex].name = name;
4518         nameLen = 0;
4519         for (; name[nameLen++]; );
4520         dtd->contentStringLen +=  nameLen;
4521         if (elementDeclHandler)
4522           handleDefault = XML_FALSE;
4523       }
4524       break;
4525 
4526     case XML_ROLE_GROUP_CLOSE:
4527       quant = XML_CQUANT_NONE;
4528       goto closeGroup;
4529     case XML_ROLE_GROUP_CLOSE_OPT:
4530       quant = XML_CQUANT_OPT;
4531       goto closeGroup;
4532     case XML_ROLE_GROUP_CLOSE_REP:
4533       quant = XML_CQUANT_REP;
4534       goto closeGroup;
4535     case XML_ROLE_GROUP_CLOSE_PLUS:
4536       quant = XML_CQUANT_PLUS;
4537     closeGroup:
4538       if (dtd->in_eldecl) {
4539         if (elementDeclHandler)
4540           handleDefault = XML_FALSE;
4541         dtd->scaffLevel--;
4542         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
4543         if (dtd->scaffLevel == 0) {
4544           if (!handleDefault) {
4545             XML_Content *model = build_model(parser);
4546             if (!model)
4547               return XML_ERROR_NO_MEMORY;
4548             *eventEndPP = s;
4549             elementDeclHandler(handlerArg, declElementType->name, model);
4550           }
4551           dtd->in_eldecl = XML_FALSE;
4552           dtd->contentStringLen = 0;
4553         }
4554       }
4555       break;
4556       /* End element declaration stuff */
4557 
4558     case XML_ROLE_PI:
4559       if (!reportProcessingInstruction(parser, enc, s, next))
4560         return XML_ERROR_NO_MEMORY;
4561       handleDefault = XML_FALSE;
4562       break;
4563     case XML_ROLE_COMMENT:
4564       if (!reportComment(parser, enc, s, next))
4565         return XML_ERROR_NO_MEMORY;
4566       handleDefault = XML_FALSE;
4567       break;
4568     case XML_ROLE_NONE:
4569       switch (tok) {
4570       case XML_TOK_BOM:
4571         handleDefault = XML_FALSE;
4572         break;
4573       }
4574       break;
4575     case XML_ROLE_DOCTYPE_NONE:
4576       if (startDoctypeDeclHandler)
4577         handleDefault = XML_FALSE;
4578       break;
4579     case XML_ROLE_ENTITY_NONE:
4580       if (dtd->keepProcessing && entityDeclHandler)
4581         handleDefault = XML_FALSE;
4582       break;
4583     case XML_ROLE_NOTATION_NONE:
4584       if (notationDeclHandler)
4585         handleDefault = XML_FALSE;
4586       break;
4587     case XML_ROLE_ATTLIST_NONE:
4588       if (dtd->keepProcessing && attlistDeclHandler)
4589         handleDefault = XML_FALSE;
4590       break;
4591     case XML_ROLE_ELEMENT_NONE:
4592       if (elementDeclHandler)
4593         handleDefault = XML_FALSE;
4594       break;
4595     } /* end of big switch */
4596 
4597     if (handleDefault && defaultHandler)
4598       reportDefault(parser, enc, s, next);
4599 
4600     switch (ps_parsing) {
4601     case XML_SUSPENDED:
4602       *nextPtr = next;
4603       return XML_ERROR_NONE;
4604     case XML_FINISHED:
4605       return XML_ERROR_ABORTED;
4606     default:
4607       s = next;
4608       tok = XmlPrologTok(enc, s, end, &next);
4609     }
4610   }
4611   /* not reached */
4612 }
4613 
4614 static enum XML_Error PTRCALL
4615 epilogProcessor(XML_Parser parser,
4616                 const char *s,
4617                 const char *end,
4618                 const char **nextPtr)
4619 {
4620   processor = epilogProcessor;
4621   eventPtr = s;
4622   for (;;) {
4623     const char *next = NULL;
4624     int tok = XmlPrologTok(encoding, s, end, &next);
4625     eventEndPtr = next;
4626     switch (tok) {
4627     /* report partial linebreak - it might be the last token */
4628     case -XML_TOK_PROLOG_S:
4629       if (defaultHandler) {
4630         reportDefault(parser, encoding, s, next);
4631         if (ps_parsing == XML_FINISHED)
4632           return XML_ERROR_ABORTED;
4633       }
4634       *nextPtr = next;
4635       return XML_ERROR_NONE;
4636     case XML_TOK_NONE:
4637       *nextPtr = s;
4638       return XML_ERROR_NONE;
4639     case XML_TOK_PROLOG_S:
4640       if (defaultHandler)
4641         reportDefault(parser, encoding, s, next);
4642       break;
4643     case XML_TOK_PI:
4644       if (!reportProcessingInstruction(parser, encoding, s, next))
4645         return XML_ERROR_NO_MEMORY;
4646       break;
4647     case XML_TOK_COMMENT:
4648       if (!reportComment(parser, encoding, s, next))
4649         return XML_ERROR_NO_MEMORY;
4650       break;
4651     case XML_TOK_INVALID:
4652       eventPtr = next;
4653       return XML_ERROR_INVALID_TOKEN;
4654     case XML_TOK_PARTIAL:
4655       if (!ps_finalBuffer) {
4656         *nextPtr = s;
4657         return XML_ERROR_NONE;
4658       }
4659       return XML_ERROR_UNCLOSED_TOKEN;
4660     case XML_TOK_PARTIAL_CHAR:
4661       if (!ps_finalBuffer) {
4662         *nextPtr = s;
4663         return XML_ERROR_NONE;
4664       }
4665       return XML_ERROR_PARTIAL_CHAR;
4666     default:
4667       return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
4668     }
4669     eventPtr = s = next;
4670     switch (ps_parsing) {
4671     case XML_SUSPENDED:
4672       *nextPtr = next;
4673       return XML_ERROR_NONE;
4674     case XML_FINISHED:
4675       return XML_ERROR_ABORTED;
4676     default: ;
4677     }
4678   }
4679 }
4680 
4681 static enum XML_Error
4682 processInternalEntity(XML_Parser parser, ENTITY *entity,
4683                       XML_Bool betweenDecl)
4684 {
4685   const char *textStart, *textEnd;
4686   const char *next;
4687   enum XML_Error result;
4688   OPEN_INTERNAL_ENTITY *openEntity;
4689 
4690   if (freeInternalEntities) {
4691     openEntity = freeInternalEntities;
4692     freeInternalEntities = openEntity->next;
4693   }
4694   else {
4695     openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
4696     if (!openEntity)
4697       return XML_ERROR_NO_MEMORY;
4698   }
4699   entity->open = XML_TRUE;
4700   entity->processed = 0;
4701   openEntity->next = openInternalEntities;
4702   openInternalEntities = openEntity;
4703   openEntity->entity = entity;
4704   openEntity->startTagLevel = tagLevel;
4705   openEntity->betweenDecl = betweenDecl;
4706   openEntity->internalEventPtr = NULL;
4707   openEntity->internalEventEndPtr = NULL;
4708   textStart = (char *)entity->textPtr;
4709   textEnd = (char *)(entity->textPtr + entity->textLen);
4710 
4711 #ifdef XML_DTD
4712   if (entity->is_param) {
4713     int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4714     result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4715                       next, &next, XML_FALSE);
4716   }
4717   else
4718 #endif /* XML_DTD */
4719     result = doContent(parser, tagLevel, internalEncoding, textStart,
4720                        textEnd, &next, XML_FALSE);
4721 
4722   if (result == XML_ERROR_NONE) {
4723     if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4724       entity->processed = (int)(next - textStart);
4725       processor = internalEntityProcessor;
4726     }
4727     else {
4728       entity->open = XML_FALSE;
4729       openInternalEntities = openEntity->next;
4730       /* put openEntity back in list of free instances */
4731       openEntity->next = freeInternalEntities;
4732       freeInternalEntities = openEntity;
4733     }
4734   }
4735   return result;
4736 }
4737 
4738 static enum XML_Error PTRCALL
4739 internalEntityProcessor(XML_Parser parser,
4740                         const char *s,
4741                         const char *end,
4742                         const char **nextPtr)
4743 {
4744   ENTITY *entity;
4745   const char *textStart, *textEnd;
4746   const char *next;
4747   enum XML_Error result;
4748   OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
4749   if (!openEntity)
4750     return XML_ERROR_UNEXPECTED_STATE;
4751 
4752   entity = openEntity->entity;
4753   textStart = ((char *)entity->textPtr) + entity->processed;
4754   textEnd = (char *)(entity->textPtr + entity->textLen);
4755 
4756 #ifdef XML_DTD
4757   if (entity->is_param) {
4758     int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4759     result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4760                       next, &next, XML_FALSE);
4761   }
4762   else
4763 #endif /* XML_DTD */
4764     result = doContent(parser, openEntity->startTagLevel, internalEncoding,
4765                        textStart, textEnd, &next, XML_FALSE);
4766 
4767   if (result != XML_ERROR_NONE)
4768     return result;
4769   else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4770     entity->processed = (int)(next - (char *)entity->textPtr);
4771     return result;
4772   }
4773   else {
4774     entity->open = XML_FALSE;
4775     openInternalEntities = openEntity->next;
4776     /* put openEntity back in list of free instances */
4777     openEntity->next = freeInternalEntities;
4778     freeInternalEntities = openEntity;
4779   }
4780 
4781 #ifdef XML_DTD
4782   if (entity->is_param) {
4783     int tok;
4784     processor = prologProcessor;
4785     tok = XmlPrologTok(encoding, s, end, &next);
4786     return doProlog(parser, encoding, s, end, tok, next, nextPtr,
4787                     (XML_Bool)!ps_finalBuffer);
4788   }
4789   else
4790 #endif /* XML_DTD */
4791   {
4792     processor = contentProcessor;
4793     /* see externalEntityContentProcessor vs contentProcessor */
4794     return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
4795                      nextPtr, (XML_Bool)!ps_finalBuffer);
4796   }
4797 }
4798 
4799 static enum XML_Error PTRCALL
4800 errorProcessor(XML_Parser parser,
4801                const char *s,
4802                const char *end,
4803                const char **nextPtr)
4804 {
4805   return errorCode;
4806 }
4807 
4808 static enum XML_Error
4809 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4810                     const char *ptr, const char *end,
4811                     STRING_POOL *pool)
4812 {
4813   enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
4814                                                end, pool);
4815   if (result)
4816     return result;
4817   if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
4818     poolChop(pool);
4819   if (!poolAppendChar(pool, XML_T('\0')))
4820     return XML_ERROR_NO_MEMORY;
4821   return XML_ERROR_NONE;
4822 }
4823 
4824 static enum XML_Error
4825 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4826                      const char *ptr, const char *end,
4827                      STRING_POOL *pool)
4828 {
4829   DTD * const dtd = _dtd;  /* save one level of indirection */
4830   for (;;) {
4831     const char *next;
4832     int tok = XmlAttributeValueTok(enc, ptr, end, &next);
4833     switch (tok) {
4834     case XML_TOK_NONE:
4835       return XML_ERROR_NONE;
4836     case XML_TOK_INVALID:
4837       if (enc == encoding)
4838         eventPtr = next;
4839       return XML_ERROR_INVALID_TOKEN;
4840     case XML_TOK_PARTIAL:
4841       if (enc == encoding)
4842         eventPtr = ptr;
4843       return XML_ERROR_INVALID_TOKEN;
4844     case XML_TOK_CHAR_REF:
4845       {
4846         XML_Char buf[XML_ENCODE_MAX];
4847         int i;
4848         int n = XmlCharRefNumber(enc, ptr);
4849         if (n < 0) {
4850           if (enc == encoding)
4851             eventPtr = ptr;
4852           return XML_ERROR_BAD_CHAR_REF;
4853         }
4854         if (!isCdata
4855             && n == 0x20 /* space */
4856             && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4857           break;
4858         n = XmlEncode(n, (ICHAR *)buf);
4859         if (!n) {
4860           if (enc == encoding)
4861             eventPtr = ptr;
4862           return XML_ERROR_BAD_CHAR_REF;
4863         }
4864         for (i = 0; i < n; i++) {
4865           if (!poolAppendChar(pool, buf[i]))
4866             return XML_ERROR_NO_MEMORY;
4867         }
4868       }
4869       break;
4870     case XML_TOK_DATA_CHARS:
4871       if (!poolAppend(pool, enc, ptr, next))
4872         return XML_ERROR_NO_MEMORY;
4873       break;
4874     case XML_TOK_TRAILING_CR:
4875       next = ptr + enc->minBytesPerChar;
4876       /* fall through */
4877     case XML_TOK_ATTRIBUTE_VALUE_S:
4878     case XML_TOK_DATA_NEWLINE:
4879       if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4880         break;
4881       if (!poolAppendChar(pool, 0x20))
4882         return XML_ERROR_NO_MEMORY;
4883       break;
4884     case XML_TOK_ENTITY_REF:
4885       {
4886         const XML_Char *name;
4887         ENTITY *entity;
4888         char checkEntityDecl;
4889         XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
4890                                               ptr + enc->minBytesPerChar,
4891                                               next - enc->minBytesPerChar);
4892         if (ch) {
4893           if (!poolAppendChar(pool, ch))
4894                 return XML_ERROR_NO_MEMORY;
4895           break;
4896         }
4897         name = poolStoreString(&temp2Pool, enc,
4898                                ptr + enc->minBytesPerChar,
4899                                next - enc->minBytesPerChar);
4900         if (!name)
4901           return XML_ERROR_NO_MEMORY;
4902         entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
4903         poolDiscard(&temp2Pool);
4904         /* First, determine if a check for an existing declaration is needed;
4905            if yes, check that the entity exists, and that it is internal.
4906         */
4907         if (pool == &dtd->pool)  /* are we called from prolog? */
4908           checkEntityDecl =
4909 #ifdef XML_DTD
4910               prologState.documentEntity &&
4911 #endif /* XML_DTD */
4912               (dtd->standalone
4913                ? !openInternalEntities
4914                : !dtd->hasParamEntityRefs);
4915         else /* if (pool == &tempPool): we are called from content */
4916           checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
4917         if (checkEntityDecl) {
4918           if (!entity)
4919             return XML_ERROR_UNDEFINED_ENTITY;
4920           else if (!entity->is_internal)
4921             return XML_ERROR_ENTITY_DECLARED_IN_PE;
4922         }
4923         else if (!entity) {
4924           /* Cannot report skipped entity here - see comments on
4925              skippedEntityHandler.
4926           if (skippedEntityHandler)
4927             skippedEntityHandler(handlerArg, name, 0);
4928           */
4929           /* Cannot call the default handler because this would be
4930              out of sync with the call to the startElementHandler.
4931           if ((pool == &tempPool) && defaultHandler)
4932             reportDefault(parser, enc, ptr, next);
4933           */
4934           break;
4935         }
4936         if (entity->open) {
4937           if (enc == encoding)
4938             eventPtr = ptr;
4939           return XML_ERROR_RECURSIVE_ENTITY_REF;
4940         }
4941         if (entity->notation) {
4942           if (enc == encoding)
4943             eventPtr = ptr;
4944           return XML_ERROR_BINARY_ENTITY_REF;
4945         }
4946         if (!entity->textPtr) {
4947           if (enc == encoding)
4948             eventPtr = ptr;
4949               return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
4950         }
4951         else {
4952           enum XML_Error result;
4953           const XML_Char *textEnd = entity->textPtr + entity->textLen;
4954           entity->open = XML_TRUE;
4955           result = appendAttributeValue(parser, internalEncoding, isCdata,
4956                                         (char *)entity->textPtr,
4957                                         (char *)textEnd, pool);
4958           entity->open = XML_FALSE;
4959           if (result)
4960             return result;
4961         }
4962       }
4963       break;
4964     default:
4965       if (enc == encoding)
4966         eventPtr = ptr;
4967       return XML_ERROR_UNEXPECTED_STATE;
4968     }
4969     ptr = next;
4970   }
4971   /* not reached */
4972 }
4973 
4974 static enum XML_Error
4975 storeEntityValue(XML_Parser parser,
4976                  const ENCODING *enc,
4977                  const char *entityTextPtr,
4978                  const char *entityTextEnd)
4979 {
4980   DTD * const dtd = _dtd;  /* save one level of indirection */
4981   STRING_POOL *pool = &(dtd->entityValuePool);
4982   enum XML_Error result = XML_ERROR_NONE;
4983 #ifdef XML_DTD
4984   int oldInEntityValue = prologState.inEntityValue;
4985   prologState.inEntityValue = 1;
4986 #endif /* XML_DTD */
4987   /* never return Null for the value argument in EntityDeclHandler,
4988      since this would indicate an external entity; therefore we
4989      have to make sure that entityValuePool.start is not null */
4990   if (!pool->blocks) {
4991     if (!poolGrow(pool))
4992       return XML_ERROR_NO_MEMORY;
4993   }
4994 
4995   for (;;) {
4996     const char *next;
4997     int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
4998     switch (tok) {
4999     case XML_TOK_PARAM_ENTITY_REF:
5000 #ifdef XML_DTD
5001       if (isParamEntity || enc != encoding) {
5002         const XML_Char *name;
5003         ENTITY *entity;
5004         name = poolStoreString(&tempPool, enc,
5005                                entityTextPtr + enc->minBytesPerChar,
5006                                next - enc->minBytesPerChar);
5007         if (!name) {
5008           result = XML_ERROR_NO_MEMORY;
5009           goto endEntityValue;
5010         }
5011         entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
5012         poolDiscard(&tempPool);
5013         if (!entity) {
5014           /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5015           /* cannot report skipped entity here - see comments on
5016              skippedEntityHandler
5017           if (skippedEntityHandler)
5018             skippedEntityHandler(handlerArg, name, 0);
5019           */
5020           dtd->keepProcessing = dtd->standalone;
5021           goto endEntityValue;
5022         }
5023         if (entity->open) {
5024           if (enc == encoding)
5025             eventPtr = entityTextPtr;
5026           result = XML_ERROR_RECURSIVE_ENTITY_REF;
5027           goto endEntityValue;
5028         }
5029         if (entity->systemId) {
5030           if (externalEntityRefHandler) {
5031             dtd->paramEntityRead = XML_FALSE;
5032             entity->open = XML_TRUE;
5033             if (!externalEntityRefHandler(externalEntityRefHandlerArg,
5034                                           0,
5035                                           entity->base,
5036                                           entity->systemId,
5037                                           entity->publicId)) {
5038               entity->open = XML_FALSE;
5039               result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5040               goto endEntityValue;
5041             }
5042             entity->open = XML_FALSE;
5043             if (!dtd->paramEntityRead)
5044               dtd->keepProcessing = dtd->standalone;
5045           }
5046           else
5047             dtd->keepProcessing = dtd->standalone;
5048         }
5049         else {
5050           entity->open = XML_TRUE;
5051           result = storeEntityValue(parser,
5052                                     internalEncoding,
5053                                     (char *)entity->textPtr,
5054                                     (char *)(entity->textPtr
5055                                              + entity->textLen));
5056           entity->open = XML_FALSE;
5057           if (result)
5058             goto endEntityValue;
5059         }
5060         break;
5061       }
5062 #endif /* XML_DTD */
5063       /* In the internal subset, PE references are not legal
5064          within markup declarations, e.g entity values in this case. */
5065       eventPtr = entityTextPtr;
5066       result = XML_ERROR_PARAM_ENTITY_REF;
5067       goto endEntityValue;
5068     case XML_TOK_NONE:
5069       result = XML_ERROR_NONE;
5070       goto endEntityValue;
5071     case XML_TOK_ENTITY_REF:
5072     case XML_TOK_DATA_CHARS:
5073       if (!poolAppend(pool, enc, entityTextPtr, next)) {
5074         result = XML_ERROR_NO_MEMORY;
5075         goto endEntityValue;
5076       }
5077       break;
5078     case XML_TOK_TRAILING_CR:
5079       next = entityTextPtr + enc->minBytesPerChar;
5080       /* fall through */
5081     case XML_TOK_DATA_NEWLINE:
5082       if (pool->end == pool->ptr && !poolGrow(pool)) {
5083               result = XML_ERROR_NO_MEMORY;
5084         goto endEntityValue;
5085       }
5086       *(pool->ptr)++ = 0xA;
5087       break;
5088     case XML_TOK_CHAR_REF:
5089       {
5090         XML_Char buf[XML_ENCODE_MAX];
5091         int i;
5092         int n = XmlCharRefNumber(enc, entityTextPtr);
5093         if (n < 0) {
5094           if (enc == encoding)
5095             eventPtr = entityTextPtr;
5096           result = XML_ERROR_BAD_CHAR_REF;
5097           goto endEntityValue;
5098         }
5099         n = XmlEncode(n, (ICHAR *)buf);
5100         if (!n) {
5101           if (enc == encoding)
5102             eventPtr = entityTextPtr;
5103           result = XML_ERROR_BAD_CHAR_REF;
5104           goto endEntityValue;
5105         }
5106         for (i = 0; i < n; i++) {
5107           if (pool->end == pool->ptr && !poolGrow(pool)) {
5108             result = XML_ERROR_NO_MEMORY;
5109             goto endEntityValue;
5110           }
5111           *(pool->ptr)++ = buf[i];
5112         }
5113       }
5114       break;
5115     case XML_TOK_PARTIAL:
5116       if (enc == encoding)
5117         eventPtr = entityTextPtr;
5118       result = XML_ERROR_INVALID_TOKEN;
5119       goto endEntityValue;
5120     case XML_TOK_INVALID:
5121       if (enc == encoding)
5122         eventPtr = next;
5123       result = XML_ERROR_INVALID_TOKEN;
5124       goto endEntityValue;
5125     default:
5126       if (enc == encoding)
5127         eventPtr = entityTextPtr;
5128       result = XML_ERROR_UNEXPECTED_STATE;
5129       goto endEntityValue;
5130     }
5131     entityTextPtr = next;
5132   }
5133 endEntityValue:
5134 #ifdef XML_DTD
5135   prologState.inEntityValue = oldInEntityValue;
5136 #endif /* XML_DTD */
5137   return result;
5138 }
5139 
5140 static void FASTCALL
5141 normalizeLines(XML_Char *s)
5142 {
5143   XML_Char *p;
5144   for (;; s++) {
5145     if (*s == XML_T('\0'))
5146       return;
5147     if (*s == 0xD)
5148       break;
5149   }
5150   p = s;
5151   do {
5152     if (*s == 0xD) {
5153       *p++ = 0xA;
5154       if (*++s == 0xA)
5155         s++;
5156     }
5157     else
5158       *p++ = *s++;
5159   } while (*s);
5160   *p = XML_T('\0');
5161 }
5162 
5163 static int
5164 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5165                             const char *start, const char *end)
5166 {
5167   const XML_Char *target;
5168   XML_Char *data;
5169   const char *tem;
5170   if (!processingInstructionHandler) {
5171     if (defaultHandler)
5172       reportDefault(parser, enc, start, end);
5173     return 1;
5174   }
5175   start += enc->minBytesPerChar * 2;
5176   tem = start + XmlNameLength(enc, start);
5177   target = poolStoreString(&tempPool, enc, start, tem);
5178   if (!target)
5179     return 0;
5180   poolFinish(&tempPool);
5181   data = poolStoreString(&tempPool, enc,
5182                         XmlSkipS(enc, tem),
5183                         end - enc->minBytesPerChar*2);
5184   if (!data)
5185     return 0;
5186   normalizeLines(data);
5187   processingInstructionHandler(handlerArg, target, data);
5188   poolClear(&tempPool);
5189   return 1;
5190 }
5191 
5192 static int
5193 reportComment(XML_Parser parser, const ENCODING *enc,
5194               const char *start, const char *end)
5195 {
5196   XML_Char *data;
5197   if (!commentHandler) {
5198     if (defaultHandler)
5199       reportDefault(parser, enc, start, end);
5200     return 1;
5201   }
5202   data = poolStoreString(&tempPool,
5203                          enc,
5204                          start + enc->minBytesPerChar * 4,
5205                          end - enc->minBytesPerChar * 3);
5206   if (!data)
5207     return 0;
5208   normalizeLines(data);
5209   commentHandler(handlerArg, data);
5210   poolClear(&tempPool);
5211   return 1;
5212 }
5213 
5214 static void
5215 reportDefault(XML_Parser parser, const ENCODING *enc,
5216               const char *s, const char *end)
5217 {
5218   if (MUST_CONVERT(enc, s)) {
5219     const char **eventPP;
5220     const char **eventEndPP;
5221     if (enc == encoding) {
5222       eventPP = &eventPtr;
5223       eventEndPP = &eventEndPtr;
5224     }
5225     else {
5226       eventPP = &(openInternalEntities->internalEventPtr);
5227       eventEndPP = &(openInternalEntities->internalEventEndPtr);
5228     }
5229     do {
5230       ICHAR *dataPtr = (ICHAR *)dataBuf;
5231       XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
5232       *eventEndPP = s;
5233       defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
5234       *eventPP = s;
5235     } while (s != end);
5236   }
5237   else
5238     defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
5239 }
5240 
5241 
5242 static int
5243 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
5244                 XML_Bool isId, const XML_Char *value, XML_Parser parser)
5245 {
5246   DEFAULT_ATTRIBUTE *att;
5247   if (value || isId) {
5248     /* The handling of default attributes gets messed up if we have
5249        a default which duplicates a non-default. */
5250     int i;
5251     for (i = 0; i < type->nDefaultAtts; i++)
5252       if (attId == type->defaultAtts[i].id)
5253         return 1;
5254     if (isId && !type->idAtt && !attId->xmlns)
5255       type->idAtt = attId;
5256   }
5257   if (type->nDefaultAtts == type->allocDefaultAtts) {
5258     if (type->allocDefaultAtts == 0) {
5259       type->allocDefaultAtts = 8;
5260       type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
5261                             * sizeof(DEFAULT_ATTRIBUTE));
5262       if (!type->defaultAtts)
5263         return 0;
5264     }
5265     else {
5266       DEFAULT_ATTRIBUTE *temp;
5267       int count = type->allocDefaultAtts * 2;
5268       temp = (DEFAULT_ATTRIBUTE *)
5269         REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
5270       if (temp == NULL)
5271         return 0;
5272       type->allocDefaultAtts = count;
5273       type->defaultAtts = temp;
5274     }
5275   }
5276   att = type->defaultAtts + type->nDefaultAtts;
5277   att->id = attId;
5278   att->value = value;
5279   att->isCdata = isCdata;
5280   if (!isCdata)
5281     attId->maybeTokenized = XML_TRUE;
5282   type->nDefaultAtts += 1;
5283   return 1;
5284 }
5285 
5286 static int
5287 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
5288 {
5289   DTD * const dtd = _dtd;  /* save one level of indirection */
5290   const XML_Char *name;
5291   for (name = elementType->name; *name; name++) {
5292     if (*name == XML_T(ASCII_COLON)) {
5293       PREFIX *prefix;
5294       const XML_Char *s;
5295       for (s = elementType->name; s != name; s++) {
5296         if (!poolAppendChar(&dtd->pool, *s))
5297           return 0;
5298       }
5299       if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5300         return 0;
5301       prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
5302                                 sizeof(PREFIX));
5303       if (!prefix)
5304         return 0;
5305       if (prefix->name == poolStart(&dtd->pool))
5306         poolFinish(&dtd->pool);
5307       else
5308         poolDiscard(&dtd->pool);
5309       elementType->prefix = prefix;
5310 
5311     }
5312   }
5313   return 1;
5314 }
5315 
5316 static ATTRIBUTE_ID *
5317 getAttributeId(XML_Parser parser, const ENCODING *enc,
5318                const char *start, const char *end)
5319 {
5320   DTD * const dtd = _dtd;  /* save one level of indirection */
5321   ATTRIBUTE_ID *id;
5322   const XML_Char *name;
5323   if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5324     return NULL;
5325   name = poolStoreString(&dtd->pool, enc, start, end);
5326   if (!name)
5327     return NULL;
5328   /* skip quotation mark - its storage will be re-used (like in name[-1]) */
5329   ++name;
5330   id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
5331   if (!id)
5332     return NULL;
5333   if (id->name != name)
5334     poolDiscard(&dtd->pool);
5335   else {
5336     poolFinish(&dtd->pool);
5337     if (!ns)
5338       ;
5339     else if (name[0] == XML_T(ASCII_x)
5340         && name[1] == XML_T(ASCII_m)
5341         && name[2] == XML_T(ASCII_l)
5342         && name[3] == XML_T(ASCII_n)
5343         && name[4] == XML_T(ASCII_s)
5344         && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
5345       if (name[5] == XML_T('\0'))
5346         id->prefix = &dtd->defaultPrefix;
5347       else
5348         id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
5349       id->xmlns = XML_TRUE;
5350     }
5351     else {
5352       int i;
5353       for (i = 0; name[i]; i++) {
5354         /* attributes without prefix are *not* in the default namespace */
5355         if (name[i] == XML_T(ASCII_COLON)) {
5356           int j;
5357           for (j = 0; j < i; j++) {
5358             if (!poolAppendChar(&dtd->pool, name[j]))
5359               return NULL;
5360           }
5361           if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5362             return NULL;
5363           id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
5364                                         sizeof(PREFIX));
5365           if (id->prefix->name == poolStart(&dtd->pool))
5366             poolFinish(&dtd->pool);
5367           else
5368             poolDiscard(&dtd->pool);
5369           break;
5370         }
5371       }
5372     }
5373   }
5374   return id;
5375 }
5376 
5377 #define CONTEXT_SEP XML_T(ASCII_FF)
5378 
5379 static const XML_Char *
5380 getContext(XML_Parser parser)
5381 {
5382   DTD * const dtd = _dtd;  /* save one level of indirection */
5383   HASH_TABLE_ITER iter;
5384   XML_Bool needSep = XML_FALSE;
5385 
5386   if (dtd->defaultPrefix.binding) {
5387     int i;
5388     int len;
5389     if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
5390       return NULL;
5391     len = dtd->defaultPrefix.binding->uriLen;
5392     if (namespaceSeparator)
5393       len--;
5394     for (i = 0; i < len; i++)
5395       if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
5396         return NULL;
5397     needSep = XML_TRUE;
5398   }
5399 
5400   hashTableIterInit(&iter, &(dtd->prefixes));
5401   for (;;) {
5402     int i;
5403     int len;
5404     const XML_Char *s;
5405     PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
5406     if (!prefix)
5407       break;
5408     if (!prefix->binding)
5409       continue;
5410     if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5411       return NULL;
5412     for (s = prefix->name; *s; s++)
5413       if (!poolAppendChar(&tempPool, *s))
5414         return NULL;
5415     if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
5416       return NULL;
5417     len = prefix->binding->uriLen;
5418     if (namespaceSeparator)
5419       len--;
5420     for (i = 0; i < len; i++)
5421       if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
5422         return NULL;
5423     needSep = XML_TRUE;
5424   }
5425 
5426 
5427   hashTableIterInit(&iter, &(dtd->generalEntities));
5428   for (;;) {
5429     const XML_Char *s;
5430     ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
5431     if (!e)
5432       break;
5433     if (!e->open)
5434       continue;
5435     if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5436       return NULL;
5437     for (s = e->name; *s; s++)
5438       if (!poolAppendChar(&tempPool, *s))
5439         return 0;
5440     needSep = XML_TRUE;
5441   }
5442 
5443   if (!poolAppendChar(&tempPool, XML_T('\0')))
5444     return NULL;
5445   return tempPool.start;
5446 }
5447 
5448 static XML_Bool
5449 setContext(XML_Parser parser, const XML_Char *context)
5450 {
5451   DTD * const dtd = _dtd;  /* save one level of indirection */
5452   const XML_Char *s = context;
5453 
5454   while (*context != XML_T('\0')) {
5455     if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
5456       ENTITY *e;
5457       if (!poolAppendChar(&tempPool, XML_T('\0')))
5458         return XML_FALSE;
5459       e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
5460       if (e)
5461         e->open = XML_TRUE;
5462       if (*s != XML_T('\0'))
5463         s++;
5464       context = s;
5465       poolDiscard(&tempPool);
5466     }
5467     else if (*s == XML_T(ASCII_EQUALS)) {
5468       PREFIX *prefix;
5469       if (poolLength(&tempPool) == 0)
5470         prefix = &dtd->defaultPrefix;
5471       else {
5472         if (!poolAppendChar(&tempPool, XML_T('\0')))
5473           return XML_FALSE;
5474         prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
5475                                   sizeof(PREFIX));
5476         if (!prefix)
5477           return XML_FALSE;
5478         if (prefix->name == poolStart(&tempPool)) {
5479           prefix->name = poolCopyString(&dtd->pool, prefix->name);
5480           if (!prefix->name)
5481             return XML_FALSE;
5482         }
5483         poolDiscard(&tempPool);
5484       }
5485       for (context = s + 1;
5486            *context != CONTEXT_SEP && *context != XML_T('\0');
5487            context++)
5488         if (!poolAppendChar(&tempPool, *context))
5489           return XML_FALSE;
5490       if (!poolAppendChar(&tempPool, XML_T('\0')))
5491         return XML_FALSE;
5492       if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
5493                      &inheritedBindings) != XML_ERROR_NONE)
5494         return XML_FALSE;
5495       poolDiscard(&tempPool);
5496       if (*context != XML_T('\0'))
5497         ++context;
5498       s = context;
5499     }
5500     else {
5501       if (!poolAppendChar(&tempPool, *s))
5502         return XML_FALSE;
5503       s++;
5504     }
5505   }
5506   return XML_TRUE;
5507 }
5508 
5509 static void FASTCALL
5510 normalizePublicId(XML_Char *publicId)
5511 {
5512   XML_Char *p = publicId;
5513   XML_Char *s;
5514   for (s = publicId; *s; s++) {
5515     switch (*s) {
5516     case 0x20:
5517     case 0xD:
5518     case 0xA:
5519       if (p != publicId && p[-1] != 0x20)
5520         *p++ = 0x20;
5521       break;
5522     default:
5523       *p++ = *s;
5524     }
5525   }
5526   if (p != publicId && p[-1] == 0x20)
5527     --p;
5528   *p = XML_T('\0');
5529 }
5530 
5531 static DTD *
5532 dtdCreate(const XML_Memory_Handling_Suite *ms)
5533 {
5534   DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
5535   if (p == NULL)
5536     return p;
5537   poolInit(&(p->pool), ms);
5538   poolInit(&(p->entityValuePool), ms);
5539   hashTableInit(&(p->generalEntities), ms);
5540   hashTableInit(&(p->elementTypes), ms);
5541   hashTableInit(&(p->attributeIds), ms);
5542   hashTableInit(&(p->prefixes), ms);
5543 #ifdef XML_DTD
5544   p->paramEntityRead = XML_FALSE;
5545   hashTableInit(&(p->paramEntities), ms);
5546 #endif /* XML_DTD */
5547   p->defaultPrefix.name = NULL;
5548   p->defaultPrefix.binding = NULL;
5549 
5550   p->in_eldecl = XML_FALSE;
5551   p->scaffIndex = NULL;
5552   p->scaffold = NULL;
5553   p->scaffLevel = 0;
5554   p->scaffSize = 0;
5555   p->scaffCount = 0;
5556   p->contentStringLen = 0;
5557 
5558   p->keepProcessing = XML_TRUE;
5559   p->hasParamEntityRefs = XML_FALSE;
5560   p->standalone = XML_FALSE;
5561   return p;
5562 }
5563 
5564 static void
5565 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
5566 {
5567   HASH_TABLE_ITER iter;
5568   hashTableIterInit(&iter, &(p->elementTypes));
5569   for (;;) {
5570     ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5571     if (!e)
5572       break;
5573     if (e->allocDefaultAtts != 0)
5574       ms->free_fcn(e->defaultAtts);
5575   }
5576   hashTableClear(&(p->generalEntities));
5577 #ifdef XML_DTD
5578   p->paramEntityRead = XML_FALSE;
5579   hashTableClear(&(p->paramEntities));
5580 #endif /* XML_DTD */
5581   hashTableClear(&(p->elementTypes));
5582   hashTableClear(&(p->attributeIds));
5583   hashTableClear(&(p->prefixes));
5584   poolClear(&(p->pool));
5585   poolClear(&(p->entityValuePool));
5586   p->defaultPrefix.name = NULL;
5587   p->defaultPrefix.binding = NULL;
5588 
5589   p->in_eldecl = XML_FALSE;
5590 
5591   ms->free_fcn(p->scaffIndex);
5592   p->scaffIndex = NULL;
5593   ms->free_fcn(p->scaffold);
5594   p->scaffold = NULL;
5595 
5596   p->scaffLevel = 0;
5597   p->scaffSize = 0;
5598   p->scaffCount = 0;
5599   p->contentStringLen = 0;
5600 
5601   p->keepProcessing = XML_TRUE;
5602   p->hasParamEntityRefs = XML_FALSE;
5603   p->standalone = XML_FALSE;
5604 }
5605 
5606 static void
5607 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
5608 {
5609   HASH_TABLE_ITER iter;
5610   hashTableIterInit(&iter, &(p->elementTypes));
5611   for (;;) {
5612     ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5613     if (!e)
5614       break;
5615     if (e->allocDefaultAtts != 0)
5616       ms->free_fcn(e->defaultAtts);
5617   }
5618   hashTableDestroy(&(p->generalEntities));
5619 #ifdef XML_DTD
5620   hashTableDestroy(&(p->paramEntities));
5621 #endif /* XML_DTD */
5622   hashTableDestroy(&(p->elementTypes));
5623   hashTableDestroy(&(p->attributeIds));
5624   hashTableDestroy(&(p->prefixes));
5625   poolDestroy(&(p->pool));
5626   poolDestroy(&(p->entityValuePool));
5627   if (isDocEntity) {
5628     ms->free_fcn(p->scaffIndex);
5629     ms->free_fcn(p->scaffold);
5630   }
5631   ms->free_fcn(p);
5632 }
5633 
5634 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
5635    The new DTD has already been initialized.
5636 */
5637 static int
5638 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
5639 {
5640   HASH_TABLE_ITER iter;
5641 
5642   /* Copy the prefix table. */
5643 
5644   hashTableIterInit(&iter, &(oldDtd->prefixes));
5645   for (;;) {
5646     const XML_Char *name;
5647     const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
5648     if (!oldP)
5649       break;
5650     name = poolCopyString(&(newDtd->pool), oldP->name);
5651     if (!name)
5652       return 0;
5653     if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
5654       return 0;
5655   }
5656 
5657   hashTableIterInit(&iter, &(oldDtd->attributeIds));
5658 
5659   /* Copy the attribute id table. */
5660 
5661   for (;;) {
5662     ATTRIBUTE_ID *newA;
5663     const XML_Char *name;
5664     const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
5665 
5666     if (!oldA)
5667       break;
5668     /* Remember to allocate the scratch byte before the name. */
5669     if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
5670       return 0;
5671     name = poolCopyString(&(newDtd->pool), oldA->name);
5672     if (!name)
5673       return 0;
5674     ++name;
5675     newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
5676                                   sizeof(ATTRIBUTE_ID));
5677     if (!newA)
5678       return 0;
5679     newA->maybeTokenized = oldA->maybeTokenized;
5680     if (oldA->prefix) {
5681       newA->xmlns = oldA->xmlns;
5682       if (oldA->prefix == &oldDtd->defaultPrefix)
5683         newA->prefix = &newDtd->defaultPrefix;
5684       else
5685         newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
5686                                         oldA->prefix->name, 0);
5687     }
5688   }
5689 
5690   /* Copy the element type table. */
5691 
5692   hashTableIterInit(&iter, &(oldDtd->elementTypes));
5693 
5694   for (;;) {
5695     int i;
5696     ELEMENT_TYPE *newE;
5697     const XML_Char *name;
5698     const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5699     if (!oldE)
5700       break;
5701     name = poolCopyString(&(newDtd->pool), oldE->name);
5702     if (!name)
5703       return 0;
5704     newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
5705                                   sizeof(ELEMENT_TYPE));
5706     if (!newE)
5707       return 0;
5708     if (oldE->nDefaultAtts) {
5709       newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
5710           ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
5711       if (!newE->defaultAtts) {
5712         ms->free_fcn(newE);
5713         return 0;
5714       }
5715     }
5716     if (oldE->idAtt)
5717       newE->idAtt = (ATTRIBUTE_ID *)
5718           lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
5719     newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
5720     if (oldE->prefix)
5721       newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
5722                                       oldE->prefix->name, 0);
5723     for (i = 0; i < newE->nDefaultAtts; i++) {
5724       newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
5725           lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
5726       newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
5727       if (oldE->defaultAtts[i].value) {
5728         newE->defaultAtts[i].value
5729             = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
5730         if (!newE->defaultAtts[i].value)
5731           return 0;
5732       }
5733       else
5734         newE->defaultAtts[i].value = NULL;
5735     }
5736   }
5737 
5738   /* Copy the entity tables. */
5739   if (!copyEntityTable(&(newDtd->generalEntities),
5740                        &(newDtd->pool),
5741                        &(oldDtd->generalEntities)))
5742       return 0;
5743 
5744 #ifdef XML_DTD
5745   if (!copyEntityTable(&(newDtd->paramEntities),
5746                        &(newDtd->pool),
5747                        &(oldDtd->paramEntities)))
5748       return 0;
5749   newDtd->paramEntityRead = oldDtd->paramEntityRead;
5750 #endif /* XML_DTD */
5751 
5752   newDtd->keepProcessing = oldDtd->keepProcessing;
5753   newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
5754   newDtd->standalone = oldDtd->standalone;
5755 
5756   /* Don't want deep copying for scaffolding */
5757   newDtd->in_eldecl = oldDtd->in_eldecl;
5758   newDtd->scaffold = oldDtd->scaffold;
5759   newDtd->contentStringLen = oldDtd->contentStringLen;
5760   newDtd->scaffSize = oldDtd->scaffSize;
5761   newDtd->scaffLevel = oldDtd->scaffLevel;
5762   newDtd->scaffIndex = oldDtd->scaffIndex;
5763 
5764   return 1;
5765 }  /* End dtdCopy */
5766 
5767 static int
5768 copyEntityTable(HASH_TABLE *newTable,
5769                 STRING_POOL *newPool,
5770                 const HASH_TABLE *oldTable)
5771 {
5772   HASH_TABLE_ITER iter;
5773   const XML_Char *cachedOldBase = NULL;
5774   const XML_Char *cachedNewBase = NULL;
5775 
5776   hashTableIterInit(&iter, oldTable);
5777 
5778   for (;;) {
5779     ENTITY *newE;
5780     const XML_Char *name;
5781     const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
5782     if (!oldE)
5783       break;
5784     name = poolCopyString(newPool, oldE->name);
5785     if (!name)
5786       return 0;
5787     newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
5788     if (!newE)
5789       return 0;
5790     if (oldE->systemId) {
5791       const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
5792       if (!tem)
5793         return 0;
5794       newE->systemId = tem;
5795       if (oldE->base) {
5796         if (oldE->base == cachedOldBase)
5797           newE->base = cachedNewBase;
5798         else {
5799           cachedOldBase = oldE->base;
5800           tem = poolCopyString(newPool, cachedOldBase);
5801           if (!tem)
5802             return 0;
5803           cachedNewBase = newE->base = tem;
5804         }
5805       }
5806       if (oldE->publicId) {
5807         tem = poolCopyString(newPool, oldE->publicId);
5808         if (!tem)
5809           return 0;
5810         newE->publicId = tem;
5811       }
5812     }
5813     else {
5814       const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
5815                                             oldE->textLen);
5816       if (!tem)
5817         return 0;
5818       newE->textPtr = tem;
5819       newE->textLen = oldE->textLen;
5820     }
5821     if (oldE->notation) {
5822       const XML_Char *tem = poolCopyString(newPool, oldE->notation);
5823       if (!tem)
5824         return 0;
5825       newE->notation = tem;
5826     }
5827     newE->is_param = oldE->is_param;
5828     newE->is_internal = oldE->is_internal;
5829   }
5830   return 1;
5831 }
5832 
5833 #define INIT_POWER 6
5834 
5835 static XML_Bool FASTCALL
5836 keyeq(KEY s1, KEY s2)
5837 {
5838   for (; *s1 == *s2; s1++, s2++)
5839     if (*s1 == 0)
5840       return XML_TRUE;
5841   return XML_FALSE;
5842 }
5843 
5844 static unsigned long FASTCALL
5845 hash(KEY s)
5846 {
5847   unsigned long h = 0;
5848   while (*s)
5849     h = CHAR_HASH(h, *s++);
5850   return h;
5851 }
5852 
5853 static NAMED *
5854 lookup(HASH_TABLE *table, KEY name, size_t createSize)
5855 {
5856   size_t i;
5857   if (table->size == 0) {
5858     size_t tsize;
5859     if (!createSize)
5860       return NULL;
5861     table->power = INIT_POWER;
5862     /* table->size is a power of 2 */
5863     table->size = (size_t)1 << INIT_POWER;
5864     tsize = table->size * sizeof(NAMED *);
5865     table->v = (NAMED **)table->mem->malloc_fcn(tsize);
5866     if (!table->v) {
5867       table->size = 0;
5868       return NULL;
5869     }
5870     memset(table->v, 0, tsize);
5871     i = hash(name) & ((unsigned long)table->size - 1);
5872   }
5873   else {
5874     unsigned long h = hash(name);
5875     unsigned long mask = (unsigned long)table->size - 1;
5876     unsigned char step = 0;
5877     i = h & mask;
5878     while (table->v[i]) {
5879       if (keyeq(name, table->v[i]->name))
5880         return table->v[i];
5881       if (!step)
5882         step = PROBE_STEP(h, mask, table->power);
5883       i < step ? (i += table->size - step) : (i -= step);
5884     }
5885     if (!createSize)
5886       return NULL;
5887 
5888     /* check for overflow (table is half full) */
5889     if (table->used >> (table->power - 1)) {
5890       unsigned char newPower = table->power + 1;
5891       size_t newSize = (size_t)1 << newPower;
5892       unsigned long newMask = (unsigned long)newSize - 1;
5893       size_t tsize = newSize * sizeof(NAMED *);
5894       NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
5895       if (!newV)
5896         return NULL;
5897       memset(newV, 0, tsize);
5898       for (i = 0; i < table->size; i++)
5899         if (table->v[i]) {
5900           unsigned long newHash = hash(table->v[i]->name);
5901           size_t j = newHash & newMask;
5902           step = 0;
5903           while (newV[j]) {
5904             if (!step)
5905               step = PROBE_STEP(newHash, newMask, newPower);
5906             j < step ? (j += newSize - step) : (j -= step);
5907           }
5908           newV[j] = table->v[i];
5909         }
5910       table->mem->free_fcn(table->v);
5911       table->v = newV;
5912       table->power = newPower;
5913       table->size = newSize;
5914       i = h & newMask;
5915       step = 0;
5916       while (table->v[i]) {
5917         if (!step)
5918           step = PROBE_STEP(h, newMask, newPower);
5919         i < step ? (i += newSize - step) : (i -= step);
5920       }
5921     }
5922   }
5923   table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
5924   if (!table->v[i])
5925     return NULL;
5926   memset(table->v[i], 0, createSize);
5927   table->v[i]->name = name;
5928   (table->used)++;
5929   return table->v[i];
5930 }
5931 
5932 static void FASTCALL
5933 hashTableClear(HASH_TABLE *table)
5934 {
5935   size_t i;
5936   for (i = 0; i < table->size; i++) {
5937     table->mem->free_fcn(table->v[i]);
5938     table->v[i] = NULL;
5939   }
5940   table->used = 0;
5941 }
5942 
5943 static void FASTCALL
5944 hashTableDestroy(HASH_TABLE *table)
5945 {
5946   size_t i;
5947   for (i = 0; i < table->size; i++)
5948     table->mem->free_fcn(table->v[i]);
5949   table->mem->free_fcn(table->v);
5950 }
5951 
5952 static void FASTCALL
5953 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
5954 {
5955   p->power = 0;
5956   p->size = 0;
5957   p->used = 0;
5958   p->v = NULL;
5959   p->mem = ms;
5960 }
5961 
5962 static void FASTCALL
5963 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
5964 {
5965   iter->p = table->v;
5966   iter->end = iter->p + table->size;
5967 }
5968 
5969 static NAMED * FASTCALL
5970 hashTableIterNext(HASH_TABLE_ITER *iter)
5971 {
5972   while (iter->p != iter->end) {
5973     NAMED *tem = *(iter->p)++;
5974     if (tem)
5975       return tem;
5976   }
5977   return NULL;
5978 }
5979 
5980 static void FASTCALL
5981 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
5982 {
5983   pool->blocks = NULL;
5984   pool->freeBlocks = NULL;
5985   pool->start = NULL;
5986   pool->ptr = NULL;
5987   pool->end = NULL;
5988   pool->mem = ms;
5989 }
5990 
5991 static void FASTCALL
5992 poolClear(STRING_POOL *pool)
5993 {
5994   if (!pool->freeBlocks)
5995     pool->freeBlocks = pool->blocks;
5996   else {
5997     BLOCK *p = pool->blocks;
5998     while (p) {
5999       BLOCK *tem = p->next;
6000       p->next = pool->freeBlocks;
6001       pool->freeBlocks = p;
6002       p = tem;
6003     }
6004   }
6005   pool->blocks = NULL;
6006   pool->start = NULL;
6007   pool->ptr = NULL;
6008   pool->end = NULL;
6009 }
6010 
6011 static void FASTCALL
6012 poolDestroy(STRING_POOL *pool)
6013 {
6014   BLOCK *p = pool->blocks;
6015   while (p) {
6016     BLOCK *tem = p->next;
6017     pool->mem->free_fcn(p);
6018     p = tem;
6019   }
6020   p = pool->freeBlocks;
6021   while (p) {
6022     BLOCK *tem = p->next;
6023     pool->mem->free_fcn(p);
6024     p = tem;
6025   }
6026 }
6027 
6028 static XML_Char *
6029 poolAppend(STRING_POOL *pool, const ENCODING *enc,
6030            const char *ptr, const char *end)
6031 {
6032   if (!pool->ptr && !poolGrow(pool))
6033     return NULL;
6034   for (;;) {
6035     XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6036     if (ptr == end)
6037       break;
6038     if (!poolGrow(pool))
6039       return NULL;
6040   }
6041   return pool->start;
6042 }
6043 
6044 static const XML_Char * FASTCALL
6045 poolCopyString(STRING_POOL *pool, const XML_Char *s)
6046 {
6047   do {
6048     if (!poolAppendChar(pool, *s))
6049       return NULL;
6050   } while (*s++);
6051   s = pool->start;
6052   poolFinish(pool);
6053   return s;
6054 }
6055 
6056 static const XML_Char *
6057 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
6058 {
6059   if (!pool->ptr && !poolGrow(pool))
6060     return NULL;
6061   for (; n > 0; --n, s++) {
6062     if (!poolAppendChar(pool, *s))
6063       return NULL;
6064   }
6065   s = pool->start;
6066   poolFinish(pool);
6067   return s;
6068 }
6069 
6070 static const XML_Char * FASTCALL
6071 poolAppendString(STRING_POOL *pool, const XML_Char *s)
6072 {
6073   while (*s) {
6074     if (!poolAppendChar(pool, *s))
6075       return NULL;
6076     s++;
6077   }
6078   return pool->start;
6079 }
6080 
6081 static XML_Char *
6082 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
6083                 const char *ptr, const char *end)
6084 {
6085   if (!poolAppend(pool, enc, ptr, end))
6086     return NULL;
6087   if (pool->ptr == pool->end && !poolGrow(pool))
6088     return NULL;
6089   *(pool->ptr)++ = 0;
6090   return pool->start;
6091 }
6092 
6093 static XML_Bool FASTCALL
6094 poolGrow(STRING_POOL *pool)
6095 {
6096   if (pool->freeBlocks) {
6097     if (pool->start == 0) {
6098       pool->blocks = pool->freeBlocks;
6099       pool->freeBlocks = pool->freeBlocks->next;
6100       pool->blocks->next = NULL;
6101       pool->start = pool->blocks->s;
6102       pool->end = pool->start + pool->blocks->size;
6103       pool->ptr = pool->start;
6104       return XML_TRUE;
6105     }
6106     if (pool->end - pool->start < pool->freeBlocks->size) {
6107       BLOCK *tem = pool->freeBlocks->next;
6108       pool->freeBlocks->next = pool->blocks;
6109       pool->blocks = pool->freeBlocks;
6110       pool->freeBlocks = tem;
6111       memcpy(pool->blocks->s, pool->start,
6112              (pool->end - pool->start) * sizeof(XML_Char));
6113       pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6114       pool->start = pool->blocks->s;
6115       pool->end = pool->start + pool->blocks->size;
6116       return XML_TRUE;
6117     }
6118   }
6119   if (pool->blocks && pool->start == pool->blocks->s) {
6120     int blockSize = (int)(pool->end - pool->start)*2;
6121     pool->blocks = (BLOCK *)
6122       pool->mem->realloc_fcn(pool->blocks,
6123                              (offsetof(BLOCK, s)
6124                               + blockSize * sizeof(XML_Char)));
6125     if (pool->blocks == NULL)
6126       return XML_FALSE;
6127     pool->blocks->size = blockSize;
6128     pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6129     pool->start = pool->blocks->s;
6130     pool->end = pool->start + blockSize;
6131   }
6132   else {
6133     BLOCK *tem;
6134     int blockSize = (int)(pool->end - pool->start);
6135     if (blockSize < INIT_BLOCK_SIZE)
6136       blockSize = INIT_BLOCK_SIZE;
6137     else
6138       blockSize *= 2;
6139     tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
6140                                         + blockSize * sizeof(XML_Char));
6141     if (!tem)
6142       return XML_FALSE;
6143     tem->size = blockSize;
6144     tem->next = pool->blocks;
6145     pool->blocks = tem;
6146     if (pool->ptr != pool->start)
6147       memcpy(tem->s, pool->start,
6148              (pool->ptr - pool->start) * sizeof(XML_Char));
6149     pool->ptr = tem->s + (pool->ptr - pool->start);
6150     pool->start = tem->s;
6151     pool->end = tem->s + blockSize;
6152   }
6153   return XML_TRUE;
6154 }
6155 
6156 static int FASTCALL
6157 nextScaffoldPart(XML_Parser parser)
6158 {
6159   DTD * const dtd = _dtd;  /* save one level of indirection */
6160   CONTENT_SCAFFOLD * me;
6161   int next;
6162 
6163   if (!dtd->scaffIndex) {
6164     dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
6165     if (!dtd->scaffIndex)
6166       return -1;
6167     dtd->scaffIndex[0] = 0;
6168   }
6169 
6170   if (dtd->scaffCount >= dtd->scaffSize) {
6171     CONTENT_SCAFFOLD *temp;
6172     if (dtd->scaffold) {
6173       temp = (CONTENT_SCAFFOLD *)
6174         REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
6175       if (temp == NULL)
6176         return -1;
6177       dtd->scaffSize *= 2;
6178     }
6179     else {
6180       temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
6181                                         * sizeof(CONTENT_SCAFFOLD));
6182       if (temp == NULL)
6183         return -1;
6184       dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
6185     }
6186     dtd->scaffold = temp;
6187   }
6188   next = dtd->scaffCount++;
6189   me = &dtd->scaffold[next];
6190   if (dtd->scaffLevel) {
6191     CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
6192     if (parent->lastchild) {
6193       dtd->scaffold[parent->lastchild].nextsib = next;
6194     }
6195     if (!parent->childcnt)
6196       parent->firstchild = next;
6197     parent->lastchild = next;
6198     parent->childcnt++;
6199   }
6200   me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
6201   return next;
6202 }
6203 
6204 static void
6205 build_node(XML_Parser parser,
6206            int src_node,
6207            XML_Content *dest,
6208            XML_Content **contpos,
6209            XML_Char **strpos)
6210 {
6211   DTD * const dtd = _dtd;  /* save one level of indirection */
6212   dest->type = dtd->scaffold[src_node].type;
6213   dest->quant = dtd->scaffold[src_node].quant;
6214   if (dest->type == XML_CTYPE_NAME) {
6215     const XML_Char *src;
6216     dest->name = *strpos;
6217     src = dtd->scaffold[src_node].name;
6218     for (;;) {
6219       *(*strpos)++ = *src;
6220       if (!*src)
6221         break;
6222       src++;
6223     }
6224     dest->numchildren = 0;
6225     dest->children = NULL;
6226   }
6227   else {
6228     unsigned int i;
6229     int cn;
6230     dest->numchildren = dtd->scaffold[src_node].childcnt;
6231     dest->children = *contpos;
6232     *contpos += dest->numchildren;
6233     for (i = 0, cn = dtd->scaffold[src_node].firstchild;
6234          i < dest->numchildren;
6235          i++, cn = dtd->scaffold[cn].nextsib) {
6236       build_node(parser, cn, &(dest->children[i]), contpos, strpos);
6237     }
6238     dest->name = NULL;
6239   }
6240 }
6241 
6242 static XML_Content *
6243 build_model (XML_Parser parser)
6244 {
6245   DTD * const dtd = _dtd;  /* save one level of indirection */
6246   XML_Content *ret;
6247   XML_Content *cpos;
6248   XML_Char * str;
6249   int allocsize = (dtd->scaffCount * sizeof(XML_Content)
6250                    + (dtd->contentStringLen * sizeof(XML_Char)));
6251 
6252   ret = (XML_Content *)MALLOC(allocsize);
6253   if (!ret)
6254     return NULL;
6255 
6256   str =  (XML_Char *) (&ret[dtd->scaffCount]);
6257   cpos = &ret[1];
6258 
6259   build_node(parser, 0, ret, &cpos, &str);
6260   return ret;
6261 }
6262 
6263 static ELEMENT_TYPE *
6264 getElementType(XML_Parser parser,
6265                const ENCODING *enc,
6266                const char *ptr,
6267                const char *end)
6268 {
6269   DTD * const dtd = _dtd;  /* save one level of indirection */
6270   const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
6271   ELEMENT_TYPE *ret;
6272 
6273   if (!name)
6274     return NULL;
6275   ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
6276   if (!ret)
6277     return NULL;
6278   if (ret->name != name)
6279     poolDiscard(&dtd->pool);
6280   else {
6281     poolFinish(&dtd->pool);
6282     if (!setElementTypePrefix(parser, ret))
6283       return NULL;
6284   }
6285   return ret;
6286 }
6287