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