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