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