source: trunk/poppler/expat-1.95.8/lib/xmlparse.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

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