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