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