source: trunk/third/expat/lib/xmlparse.c @ 18502

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