1 /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
2 See the file COPYING for copying permission.
6 #include <string.h> /* memset(), memcpy() */
8 #include <limits.h> /* UINT_MAX */
9 #include <time.h> /* time() */
11 #define XML_BUILDING_EXPAT 1
13 #ifdef COMPILED_FROM_DSP
14 #include "winconfig.h"
15 #elif defined(MACOS_CLASSIC)
16 #include "macconfig.h"
17 #elif defined(__amigaos__)
18 #include "amigaconfig.h"
19 #elif defined(__WATCOMC__)
20 #include "watcomconfig.h"
21 #elif defined(HAVE_EXPAT_CONFIG_H)
22 #include <expat_config.h>
23 #endif /* ndef COMPILED_FROM_DSP */
29 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
30 #define XmlConvert XmlUtf16Convert
31 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
32 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
33 #define XmlEncode XmlUtf16Encode
34 /* Using pointer subtraction to convert to integer type. */
35 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
36 typedef unsigned short ICHAR;
38 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
39 #define XmlConvert XmlUtf8Convert
40 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
41 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
42 #define XmlEncode XmlUtf8Encode
43 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
50 #define XmlInitEncodingNS XmlInitEncoding
51 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
52 #undef XmlGetInternalEncodingNS
53 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
54 #define XmlParseXmlDeclNS XmlParseXmlDecl
60 #ifdef XML_UNICODE_WCHAR_T
61 #define XML_T(x) (const wchar_t)x
62 #define XML_L(x) L ## x
64 #define XML_T(x) (const unsigned short)x
75 /* Round up n to be a multiple of sz, where sz is a power of 2. */
76 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
78 /* Handle the case where memmove() doesn't exist. */
81 #define memmove(d,s,l) bcopy((s),(d),(l))
83 #error memmove does not exist on this platform, nor is a substitute available
84 #endif /* HAVE_BCOPY */
85 #endif /* HAVE_MEMMOVE */
91 typedef const XML_Char *KEY;
102 const XML_Memory_Handling_Suite *mem;
105 /* Basic character hash algorithm, taken from Python's string hash:
106 h = h * 1000003 ^ character, the constant being a prime number.
110 #define CHAR_HASH(h, c) \
111 (((h) * 0xF4243) ^ (unsigned short)(c))
113 #define CHAR_HASH(h, c) \
114 (((h) * 0xF4243) ^ (unsigned char)(c))
117 /* For probing (after a collision) we need a step size relative prime
118 to the hash table size, which is a power of 2. We use double-hashing,
119 since we can calculate a second hash value cheaply by taking those bits
120 of the first hash value that were discarded (masked out) when the table
121 index was calculated: index = hash & mask, where mask = table->size - 1.
122 We limit the maximum step size to table->size / 4 (mask >> 2) and make
123 it odd, since odd numbers are always relative prime to a power of 2.
125 #define SECOND_HASH(hash, mask, power) \
126 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
127 #define PROBE_STEP(hash, mask, power) \
128 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
135 #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
136 #define INIT_DATA_BUF_SIZE 1024
137 #define INIT_ATTS_SIZE 16
138 #define INIT_ATTS_VERSION 0xFFFFFFFF
139 #define INIT_BLOCK_SIZE 1024
140 #define INIT_BUFFER_SIZE 1024
142 #define EXPAND_SPARE 24
144 typedef struct binding {
145 struct prefix *prefix;
146 struct binding *nextTagBinding;
147 struct binding *prevPrefixBinding;
148 const struct attribute_id *attId;
154 typedef struct prefix {
155 const XML_Char *name;
161 const XML_Char *localPart;
162 const XML_Char *prefix;
168 /* TAG represents an open element.
169 The name of the element is stored in both the document and API
170 encodings. The memory buffer 'buf' is a separately-allocated
171 memory area which stores the name. During the XML_Parse()/
172 XMLParseBuffer() when the element is open, the memory for the 'raw'
173 version of the name (in the document encoding) is shared with the
174 document buffer. If the element is open across calls to
175 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
176 contain the 'raw' name as well.
178 A parser re-uses these structures, maintaining a list of allocated
179 TAG objects in a free list.
182 struct tag *parent; /* parent of this element */
183 const char *rawName; /* tagName in the original encoding */
185 TAG_NAME name; /* tagName in the API encoding */
186 char *buf; /* buffer for name components */
187 char *bufEnd; /* end of the buffer */
192 const XML_Char *name;
193 const XML_Char *textPtr;
194 int textLen; /* length in XML_Chars */
195 int processed; /* # of processed bytes - when suspended */
196 const XML_Char *systemId;
197 const XML_Char *base;
198 const XML_Char *publicId;
199 const XML_Char *notation;
202 XML_Bool is_internal; /* true if declared in internal subset outside PE */
206 enum XML_Content_Type type;
207 enum XML_Content_Quant quant;
208 const XML_Char * name;
215 #define INIT_SCAFFOLD_ELEMENTS 32
217 typedef struct block {
229 const XML_Memory_Handling_Suite *mem;
232 /* The XML_Char before the name is used to determine whether
233 an attribute has been specified. */
234 typedef struct attribute_id {
237 XML_Bool maybeTokenized;
242 const ATTRIBUTE_ID *id;
244 const XML_Char *value;
248 unsigned long version;
250 const XML_Char *uriName;
254 const XML_Char *name;
256 const ATTRIBUTE_ID *idAtt;
258 int allocDefaultAtts;
259 DEFAULT_ATTRIBUTE *defaultAtts;
263 HASH_TABLE generalEntities;
264 HASH_TABLE elementTypes;
265 HASH_TABLE attributeIds;
268 STRING_POOL entityValuePool;
269 /* false once a parameter entity reference has been skipped */
270 XML_Bool keepProcessing;
271 /* true once an internal or external PE reference has been encountered;
272 this includes the reference to an external subset */
273 XML_Bool hasParamEntityRefs;
276 /* indicates if external PE has been read */
277 XML_Bool paramEntityRead;
278 HASH_TABLE paramEntities;
280 PREFIX defaultPrefix;
281 /* === scaffolding for building content model === */
283 CONTENT_SCAFFOLD *scaffold;
284 unsigned contentStringLen;
291 typedef struct open_internal_entity {
292 const char *internalEventPtr;
293 const char *internalEventEndPtr;
294 struct open_internal_entity *next;
297 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
298 } OPEN_INTERNAL_ENTITY;
300 typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
303 const char **endPtr);
305 static Processor prologProcessor;
306 static Processor prologInitProcessor;
307 static Processor contentProcessor;
308 static Processor cdataSectionProcessor;
310 static Processor ignoreSectionProcessor;
311 static Processor externalParEntProcessor;
312 static Processor externalParEntInitProcessor;
313 static Processor entityValueProcessor;
314 static Processor entityValueInitProcessor;
316 static Processor epilogProcessor;
317 static Processor errorProcessor;
318 static Processor externalEntityInitProcessor;
319 static Processor externalEntityInitProcessor2;
320 static Processor externalEntityInitProcessor3;
321 static Processor externalEntityContentProcessor;
322 static Processor internalEntityProcessor;
324 static enum XML_Error
325 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
326 static enum XML_Error
327 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
328 const char *s, const char *next);
329 static enum XML_Error
330 initializeEncoding(XML_Parser parser);
331 static enum XML_Error
332 doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
333 const char *end, int tok, const char *next, const char **nextPtr,
335 static enum XML_Error
336 processInternalEntity(XML_Parser parser, ENTITY *entity,
337 XML_Bool betweenDecl);
338 static enum XML_Error
339 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
340 const char *start, const char *end, const char **endPtr,
342 static enum XML_Error
343 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
344 const char *end, const char **nextPtr, XML_Bool haveMore);
346 static enum XML_Error
347 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
348 const char *end, const char **nextPtr, XML_Bool haveMore);
351 static enum XML_Error
352 storeAtts(XML_Parser parser, const ENCODING *, const char *s,
353 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
354 static enum XML_Error
355 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
356 const XML_Char *uri, BINDING **bindingsPtr);
358 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
359 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
360 static enum XML_Error
361 storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
362 const char *, const char *, STRING_POOL *);
363 static enum XML_Error
364 appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
365 const char *, const char *, STRING_POOL *);
366 static ATTRIBUTE_ID *
367 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
370 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
371 static enum XML_Error
372 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
375 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
376 const char *start, const char *end);
378 reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
381 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
384 static const XML_Char * getContext(XML_Parser parser);
386 setContext(XML_Parser parser, const XML_Char *context);
388 static void FASTCALL normalizePublicId(XML_Char *s);
390 static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
391 /* do not call if parentParser != NULL */
392 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
394 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
396 dtdCopy(XML_Parser oldParser,
397 DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
399 copyEntityTable(XML_Parser oldParser,
400 HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
402 lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
404 hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
405 static void FASTCALL hashTableClear(HASH_TABLE *);
406 static void FASTCALL hashTableDestroy(HASH_TABLE *);
408 hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
409 static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
412 poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
413 static void FASTCALL poolClear(STRING_POOL *);
414 static void FASTCALL poolDestroy(STRING_POOL *);
416 poolAppend(STRING_POOL *pool, const ENCODING *enc,
417 const char *ptr, const char *end);
419 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
420 const char *ptr, const char *end);
421 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
422 static const XML_Char * FASTCALL
423 poolCopyString(STRING_POOL *pool, const XML_Char *s);
424 static const XML_Char *
425 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
426 static const XML_Char * FASTCALL
427 poolAppendString(STRING_POOL *pool, const XML_Char *s);
429 static int FASTCALL nextScaffoldPart(XML_Parser parser);
430 static XML_Content * build_model(XML_Parser parser);
431 static ELEMENT_TYPE *
432 getElementType(XML_Parser parser, const ENCODING *enc,
433 const char *ptr, const char *end);
435 static unsigned long generate_hash_secret_salt(void);
436 static XML_Bool startParsing(XML_Parser parser);
439 parserCreate(const XML_Char *encodingName,
440 const XML_Memory_Handling_Suite *memsuite,
441 const XML_Char *nameSep,
445 parserInit(XML_Parser parser, const XML_Char *encodingName);
447 #define poolStart(pool) ((pool)->start)
448 #define poolEnd(pool) ((pool)->ptr)
449 #define poolLength(pool) ((pool)->ptr - (pool)->start)
450 #define poolChop(pool) ((void)--(pool->ptr))
451 #define poolLastChar(pool) (((pool)->ptr)[-1])
452 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
453 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
454 #define poolAppendChar(pool, c) \
455 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
457 : ((*((pool)->ptr)++ = c), 1))
459 struct XML_ParserStruct {
460 /* The first member must be userData so that the XML_GetUserData
465 const XML_Memory_Handling_Suite m_mem;
466 /* first character to be parsed */
467 const char *m_bufferPtr;
468 /* past last character to be parsed */
470 /* allocated end of buffer */
471 const char *m_bufferLim;
472 XML_Index m_parseEndByteIndex;
473 const char *m_parseEndPtr;
475 XML_Char *m_dataBufEnd;
476 XML_StartElementHandler m_startElementHandler;
477 XML_EndElementHandler m_endElementHandler;
478 XML_CharacterDataHandler m_characterDataHandler;
479 XML_ProcessingInstructionHandler m_processingInstructionHandler;
480 XML_CommentHandler m_commentHandler;
481 XML_StartCdataSectionHandler m_startCdataSectionHandler;
482 XML_EndCdataSectionHandler m_endCdataSectionHandler;
483 XML_DefaultHandler m_defaultHandler;
484 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
485 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
486 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
487 XML_NotationDeclHandler m_notationDeclHandler;
488 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
489 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
490 XML_NotStandaloneHandler m_notStandaloneHandler;
491 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
492 XML_Parser m_externalEntityRefHandlerArg;
493 XML_SkippedEntityHandler m_skippedEntityHandler;
494 XML_UnknownEncodingHandler m_unknownEncodingHandler;
495 XML_ElementDeclHandler m_elementDeclHandler;
496 XML_AttlistDeclHandler m_attlistDeclHandler;
497 XML_EntityDeclHandler m_entityDeclHandler;
498 XML_XmlDeclHandler m_xmlDeclHandler;
499 const ENCODING *m_encoding;
500 INIT_ENCODING m_initEncoding;
501 const ENCODING *m_internalEncoding;
502 const XML_Char *m_protocolEncodingName;
504 XML_Bool m_ns_triplets;
505 void *m_unknownEncodingMem;
506 void *m_unknownEncodingData;
507 void *m_unknownEncodingHandlerData;
508 void (XMLCALL *m_unknownEncodingRelease)(void *);
509 PROLOG_STATE m_prologState;
510 Processor *m_processor;
511 enum XML_Error m_errorCode;
512 const char *m_eventPtr;
513 const char *m_eventEndPtr;
514 const char *m_positionPtr;
515 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
516 OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
517 XML_Bool m_defaultExpandInternalEntities;
519 ENTITY *m_declEntity;
520 const XML_Char *m_doctypeName;
521 const XML_Char *m_doctypeSysid;
522 const XML_Char *m_doctypePubid;
523 const XML_Char *m_declAttributeType;
524 const XML_Char *m_declNotationName;
525 const XML_Char *m_declNotationPublicId;
526 ELEMENT_TYPE *m_declElementType;
527 ATTRIBUTE_ID *m_declAttributeId;
528 XML_Bool m_declAttributeIsCdata;
529 XML_Bool m_declAttributeIsId;
531 const XML_Char *m_curBase;
534 BINDING *m_inheritedBindings;
535 BINDING *m_freeBindingList;
537 int m_nSpecifiedAtts;
541 unsigned long m_nsAttsVersion;
542 unsigned char m_nsAttsPower;
544 XML_AttrInfo *m_attInfo;
547 STRING_POOL m_tempPool;
548 STRING_POOL m_temp2Pool;
549 char *m_groupConnector;
550 unsigned int m_groupSize;
551 XML_Char m_namespaceSeparator;
552 XML_Parser m_parentParser;
553 XML_ParsingStatus m_parsingStatus;
555 XML_Bool m_isParamEntity;
556 XML_Bool m_useForeignDTD;
557 enum XML_ParamEntityParsing m_paramEntityParsing;
559 unsigned long m_hash_secret_salt;
562 #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
563 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
564 #define FREE(p) (parser->m_mem.free_fcn((p)))
566 #define userData (parser->m_userData)
567 #define handlerArg (parser->m_handlerArg)
568 #define startElementHandler (parser->m_startElementHandler)
569 #define endElementHandler (parser->m_endElementHandler)
570 #define characterDataHandler (parser->m_characterDataHandler)
571 #define processingInstructionHandler \
572 (parser->m_processingInstructionHandler)
573 #define commentHandler (parser->m_commentHandler)
574 #define startCdataSectionHandler \
575 (parser->m_startCdataSectionHandler)
576 #define endCdataSectionHandler (parser->m_endCdataSectionHandler)
577 #define defaultHandler (parser->m_defaultHandler)
578 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
579 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
580 #define unparsedEntityDeclHandler \
581 (parser->m_unparsedEntityDeclHandler)
582 #define notationDeclHandler (parser->m_notationDeclHandler)
583 #define startNamespaceDeclHandler \
584 (parser->m_startNamespaceDeclHandler)
585 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
586 #define notStandaloneHandler (parser->m_notStandaloneHandler)
587 #define externalEntityRefHandler \
588 (parser->m_externalEntityRefHandler)
589 #define externalEntityRefHandlerArg \
590 (parser->m_externalEntityRefHandlerArg)
591 #define internalEntityRefHandler \
592 (parser->m_internalEntityRefHandler)
593 #define skippedEntityHandler (parser->m_skippedEntityHandler)
594 #define unknownEncodingHandler (parser->m_unknownEncodingHandler)
595 #define elementDeclHandler (parser->m_elementDeclHandler)
596 #define attlistDeclHandler (parser->m_attlistDeclHandler)
597 #define entityDeclHandler (parser->m_entityDeclHandler)
598 #define xmlDeclHandler (parser->m_xmlDeclHandler)
599 #define encoding (parser->m_encoding)
600 #define initEncoding (parser->m_initEncoding)
601 #define internalEncoding (parser->m_internalEncoding)
602 #define unknownEncodingMem (parser->m_unknownEncodingMem)
603 #define unknownEncodingData (parser->m_unknownEncodingData)
604 #define unknownEncodingHandlerData \
605 (parser->m_unknownEncodingHandlerData)
606 #define unknownEncodingRelease (parser->m_unknownEncodingRelease)
607 #define protocolEncodingName (parser->m_protocolEncodingName)
608 #define ns (parser->m_ns)
609 #define ns_triplets (parser->m_ns_triplets)
610 #define prologState (parser->m_prologState)
611 #define processor (parser->m_processor)
612 #define errorCode (parser->m_errorCode)
613 #define eventPtr (parser->m_eventPtr)
614 #define eventEndPtr (parser->m_eventEndPtr)
615 #define positionPtr (parser->m_positionPtr)
616 #define position (parser->m_position)
617 #define openInternalEntities (parser->m_openInternalEntities)
618 #define freeInternalEntities (parser->m_freeInternalEntities)
619 #define defaultExpandInternalEntities \
620 (parser->m_defaultExpandInternalEntities)
621 #define tagLevel (parser->m_tagLevel)
622 #define buffer (parser->m_buffer)
623 #define bufferPtr (parser->m_bufferPtr)
624 #define bufferEnd (parser->m_bufferEnd)
625 #define parseEndByteIndex (parser->m_parseEndByteIndex)
626 #define parseEndPtr (parser->m_parseEndPtr)
627 #define bufferLim (parser->m_bufferLim)
628 #define dataBuf (parser->m_dataBuf)
629 #define dataBufEnd (parser->m_dataBufEnd)
630 #define _dtd (parser->m_dtd)
631 #define curBase (parser->m_curBase)
632 #define declEntity (parser->m_declEntity)
633 #define doctypeName (parser->m_doctypeName)
634 #define doctypeSysid (parser->m_doctypeSysid)
635 #define doctypePubid (parser->m_doctypePubid)
636 #define declAttributeType (parser->m_declAttributeType)
637 #define declNotationName (parser->m_declNotationName)
638 #define declNotationPublicId (parser->m_declNotationPublicId)
639 #define declElementType (parser->m_declElementType)
640 #define declAttributeId (parser->m_declAttributeId)
641 #define declAttributeIsCdata (parser->m_declAttributeIsCdata)
642 #define declAttributeIsId (parser->m_declAttributeIsId)
643 #define freeTagList (parser->m_freeTagList)
644 #define freeBindingList (parser->m_freeBindingList)
645 #define inheritedBindings (parser->m_inheritedBindings)
646 #define tagStack (parser->m_tagStack)
647 #define atts (parser->m_atts)
648 #define attsSize (parser->m_attsSize)
649 #define nSpecifiedAtts (parser->m_nSpecifiedAtts)
650 #define idAttIndex (parser->m_idAttIndex)
651 #define nsAtts (parser->m_nsAtts)
652 #define nsAttsVersion (parser->m_nsAttsVersion)
653 #define nsAttsPower (parser->m_nsAttsPower)
654 #define attInfo (parser->m_attInfo)
655 #define tempPool (parser->m_tempPool)
656 #define temp2Pool (parser->m_temp2Pool)
657 #define groupConnector (parser->m_groupConnector)
658 #define groupSize (parser->m_groupSize)
659 #define namespaceSeparator (parser->m_namespaceSeparator)
660 #define parentParser (parser->m_parentParser)
661 #define ps_parsing (parser->m_parsingStatus.parsing)
662 #define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
664 #define isParamEntity (parser->m_isParamEntity)
665 #define useForeignDTD (parser->m_useForeignDTD)
666 #define paramEntityParsing (parser->m_paramEntityParsing)
668 #define hash_secret_salt (parser->m_hash_secret_salt)
671 XML_ParserCreate(const XML_Char *encodingName)
673 return XML_ParserCreate_MM(encodingName, NULL, NULL);
677 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
681 return XML_ParserCreate_MM(encodingName, NULL, tmp);
684 static const XML_Char implicitContext[] = {
685 ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
686 ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
687 ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
688 ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
689 ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
690 ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
694 generate_hash_secret_salt(void)
696 unsigned int seed = time(NULL) % UINT_MAX;
701 static XML_Bool /* only valid for root parser */
702 startParsing(XML_Parser parser)
704 /* hash functions must be initialized before setContext() is called */
705 if (hash_secret_salt == 0)
706 hash_secret_salt = generate_hash_secret_salt();
708 /* implicit context only set for root parser, since child
709 parsers (i.e. external entity parsers) will inherit it
711 return setContext(parser, implicitContext);
717 XML_ParserCreate_MM(const XML_Char *encodingName,
718 const XML_Memory_Handling_Suite *memsuite,
719 const XML_Char *nameSep)
721 return parserCreate(encodingName, memsuite, nameSep, NULL);
725 parserCreate(const XML_Char *encodingName,
726 const XML_Memory_Handling_Suite *memsuite,
727 const XML_Char *nameSep,
733 XML_Memory_Handling_Suite *mtemp;
734 parser = (XML_Parser)
735 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
736 if (parser != NULL) {
737 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
738 mtemp->malloc_fcn = memsuite->malloc_fcn;
739 mtemp->realloc_fcn = memsuite->realloc_fcn;
740 mtemp->free_fcn = memsuite->free_fcn;
744 XML_Memory_Handling_Suite *mtemp;
745 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
746 if (parser != NULL) {
747 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
748 mtemp->malloc_fcn = malloc;
749 mtemp->realloc_fcn = realloc;
750 mtemp->free_fcn = free;
760 attsSize = INIT_ATTS_SIZE;
761 atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
767 attInfo = (XML_AttrInfo*)MALLOC(attsSize * sizeof(XML_AttrInfo));
768 if (attInfo == NULL) {
774 dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
775 if (dataBuf == NULL) {
783 dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
788 _dtd = dtdCreate(&parser->m_mem);
800 freeBindingList = NULL;
802 freeInternalEntities = NULL;
805 groupConnector = NULL;
807 unknownEncodingHandler = NULL;
808 unknownEncodingHandlerData = NULL;
810 namespaceSeparator = ASCII_EXCL;
812 ns_triplets = XML_FALSE;
818 poolInit(&tempPool, &(parser->m_mem));
819 poolInit(&temp2Pool, &(parser->m_mem));
820 parserInit(parser, encodingName);
822 if (encodingName && !protocolEncodingName) {
823 XML_ParserFree(parser);
829 internalEncoding = XmlGetInternalEncodingNS();
830 namespaceSeparator = *nameSep;
833 internalEncoding = XmlGetInternalEncoding();
840 parserInit(XML_Parser parser, const XML_Char *encodingName)
842 processor = prologInitProcessor;
843 XmlPrologStateInit(&prologState);
844 protocolEncodingName = (encodingName != NULL
845 ? poolCopyString(&tempPool, encodingName)
848 XmlInitEncoding(&initEncoding, &encoding, 0);
851 startElementHandler = NULL;
852 endElementHandler = NULL;
853 characterDataHandler = NULL;
854 processingInstructionHandler = NULL;
855 commentHandler = NULL;
856 startCdataSectionHandler = NULL;
857 endCdataSectionHandler = NULL;
858 defaultHandler = NULL;
859 startDoctypeDeclHandler = NULL;
860 endDoctypeDeclHandler = NULL;
861 unparsedEntityDeclHandler = NULL;
862 notationDeclHandler = NULL;
863 startNamespaceDeclHandler = NULL;
864 endNamespaceDeclHandler = NULL;
865 notStandaloneHandler = NULL;
866 externalEntityRefHandler = NULL;
867 externalEntityRefHandlerArg = parser;
868 skippedEntityHandler = NULL;
869 elementDeclHandler = NULL;
870 attlistDeclHandler = NULL;
871 entityDeclHandler = NULL;
872 xmlDeclHandler = NULL;
875 parseEndByteIndex = 0;
877 declElementType = NULL;
878 declAttributeId = NULL;
883 declAttributeType = NULL;
884 declNotationName = NULL;
885 declNotationPublicId = NULL;
886 declAttributeIsCdata = XML_FALSE;
887 declAttributeIsId = XML_FALSE;
888 memset(&position, 0, sizeof(POSITION));
889 errorCode = XML_ERROR_NONE;
893 openInternalEntities = NULL;
894 defaultExpandInternalEntities = XML_TRUE;
897 inheritedBindings = NULL;
899 unknownEncodingMem = NULL;
900 unknownEncodingRelease = NULL;
901 unknownEncodingData = NULL;
903 ps_parsing = XML_INITIALIZED;
905 isParamEntity = XML_FALSE;
906 useForeignDTD = XML_FALSE;
907 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
909 hash_secret_salt = 0;
912 /* moves list of bindings to freeBindingList */
914 moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
917 BINDING *b = bindings;
918 bindings = bindings->nextTagBinding;
919 b->nextTagBinding = freeBindingList;
925 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
928 OPEN_INTERNAL_ENTITY *openEntityList;
931 /* move tagStack to freeTagList */
936 tag->parent = freeTagList;
937 moveToFreeBindingList(parser, tag->bindings);
938 tag->bindings = NULL;
941 /* move openInternalEntities to freeInternalEntities */
942 openEntityList = openInternalEntities;
943 while (openEntityList) {
944 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
945 openEntityList = openEntity->next;
946 openEntity->next = freeInternalEntities;
947 freeInternalEntities = openEntity;
949 moveToFreeBindingList(parser, inheritedBindings);
950 FREE(unknownEncodingMem);
951 if (unknownEncodingRelease)
952 unknownEncodingRelease(unknownEncodingData);
953 poolClear(&tempPool);
954 poolClear(&temp2Pool);
955 parserInit(parser, encodingName);
956 dtdReset(_dtd, &parser->m_mem);
960 enum XML_Status XMLCALL
961 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
963 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
964 XXX There's no way for the caller to determine which of the
965 XXX possible error cases caused the XML_STATUS_ERROR return.
967 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
968 return XML_STATUS_ERROR;
969 if (encodingName == NULL)
970 protocolEncodingName = NULL;
972 protocolEncodingName = poolCopyString(&tempPool, encodingName);
973 if (!protocolEncodingName)
974 return XML_STATUS_ERROR;
976 return XML_STATUS_OK;
980 XML_ExternalEntityParserCreate(XML_Parser oldParser,
981 const XML_Char *context,
982 const XML_Char *encodingName)
984 XML_Parser parser = oldParser;
987 XML_StartElementHandler oldStartElementHandler = startElementHandler;
988 XML_EndElementHandler oldEndElementHandler = endElementHandler;
989 XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
990 XML_ProcessingInstructionHandler oldProcessingInstructionHandler
991 = processingInstructionHandler;
992 XML_CommentHandler oldCommentHandler = commentHandler;
993 XML_StartCdataSectionHandler oldStartCdataSectionHandler
994 = startCdataSectionHandler;
995 XML_EndCdataSectionHandler oldEndCdataSectionHandler
996 = endCdataSectionHandler;
997 XML_DefaultHandler oldDefaultHandler = defaultHandler;
998 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
999 = unparsedEntityDeclHandler;
1000 XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
1001 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
1002 = startNamespaceDeclHandler;
1003 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
1004 = endNamespaceDeclHandler;
1005 XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
1006 XML_ExternalEntityRefHandler oldExternalEntityRefHandler
1007 = externalEntityRefHandler;
1008 XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
1009 XML_UnknownEncodingHandler oldUnknownEncodingHandler
1010 = unknownEncodingHandler;
1011 XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
1012 XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
1013 XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
1014 XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
1015 ELEMENT_TYPE * oldDeclElementType = declElementType;
1017 void *oldUserData = userData;
1018 void *oldHandlerArg = handlerArg;
1019 XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
1020 XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
1022 enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
1023 int oldInEntityValue = prologState.inEntityValue;
1025 XML_Bool oldns_triplets = ns_triplets;
1026 /* Note that the new parser shares the same hash secret as the old
1027 parser, so that dtdCopy and copyEntityTable can lookup values
1028 from hash tables associated with either parser without us having
1029 to worry which hash secrets each table has.
1031 unsigned long oldhash_secret_salt = hash_secret_salt;
1036 #endif /* XML_DTD */
1038 /* Note that the magical uses of the pre-processor to make field
1039 access look more like C++ require that `parser' be overwritten
1040 here. This makes this function more painful to follow than it
1045 *tmp = namespaceSeparator;
1046 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
1049 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1055 startElementHandler = oldStartElementHandler;
1056 endElementHandler = oldEndElementHandler;
1057 characterDataHandler = oldCharacterDataHandler;
1058 processingInstructionHandler = oldProcessingInstructionHandler;
1059 commentHandler = oldCommentHandler;
1060 startCdataSectionHandler = oldStartCdataSectionHandler;
1061 endCdataSectionHandler = oldEndCdataSectionHandler;
1062 defaultHandler = oldDefaultHandler;
1063 unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1064 notationDeclHandler = oldNotationDeclHandler;
1065 startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1066 endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1067 notStandaloneHandler = oldNotStandaloneHandler;
1068 externalEntityRefHandler = oldExternalEntityRefHandler;
1069 skippedEntityHandler = oldSkippedEntityHandler;
1070 unknownEncodingHandler = oldUnknownEncodingHandler;
1071 elementDeclHandler = oldElementDeclHandler;
1072 attlistDeclHandler = oldAttlistDeclHandler;
1073 entityDeclHandler = oldEntityDeclHandler;
1074 xmlDeclHandler = oldXmlDeclHandler;
1075 declElementType = oldDeclElementType;
1076 userData = oldUserData;
1077 if (oldUserData == oldHandlerArg)
1078 handlerArg = userData;
1080 handlerArg = parser;
1081 if (oldExternalEntityRefHandlerArg != oldParser)
1082 externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1083 defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1084 ns_triplets = oldns_triplets;
1085 hash_secret_salt = oldhash_secret_salt;
1086 parentParser = oldParser;
1088 paramEntityParsing = oldParamEntityParsing;
1089 prologState.inEntityValue = oldInEntityValue;
1091 #endif /* XML_DTD */
1092 if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem)
1093 || !setContext(parser, context)) {
1094 XML_ParserFree(parser);
1097 processor = externalEntityInitProcessor;
1101 /* The DTD instance referenced by _dtd is shared between the document's
1102 root parser and external PE parsers, therefore one does not need to
1103 call setContext. In addition, one also *must* not call setContext,
1104 because this would overwrite existing prefix->binding pointers in
1105 _dtd with ones that get destroyed with the external PE parser.
1106 This would leave those prefixes with dangling pointers.
1108 isParamEntity = XML_TRUE;
1109 XmlPrologStateInitExternalEntity(&prologState);
1110 processor = externalParEntInitProcessor;
1112 #endif /* XML_DTD */
1116 static void FASTCALL
1117 destroyBindings(BINDING *bindings, XML_Parser parser)
1120 BINDING *b = bindings;
1123 bindings = b->nextTagBinding;
1130 XML_ParserFree(XML_Parser parser)
1133 OPEN_INTERNAL_ENTITY *entityList;
1136 /* free tagStack and freeTagList */
1140 if (tagList == NULL) {
1141 if (freeTagList == NULL)
1143 tagList = freeTagList;
1147 tagList = tagList->parent;
1149 destroyBindings(p->bindings, parser);
1152 /* free openInternalEntities and freeInternalEntities */
1153 entityList = openInternalEntities;
1155 OPEN_INTERNAL_ENTITY *openEntity;
1156 if (entityList == NULL) {
1157 if (freeInternalEntities == NULL)
1159 entityList = freeInternalEntities;
1160 freeInternalEntities = NULL;
1162 openEntity = entityList;
1163 entityList = entityList->next;
1167 destroyBindings(freeBindingList, parser);
1168 destroyBindings(inheritedBindings, parser);
1169 poolDestroy(&tempPool);
1170 poolDestroy(&temp2Pool);
1172 /* external parameter entity parsers share the DTD structure
1173 parser->m_dtd with the root parser, so we must not destroy it
1175 if (!isParamEntity && _dtd)
1178 #endif /* XML_DTD */
1179 dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
1181 #ifdef XML_ATTR_INFO
1182 FREE((void *)attInfo);
1184 FREE(groupConnector);
1188 FREE(unknownEncodingMem);
1189 if (unknownEncodingRelease)
1190 unknownEncodingRelease(unknownEncodingData);
1195 XML_UseParserAsHandlerArg(XML_Parser parser)
1197 handlerArg = parser;
1200 enum XML_Error XMLCALL
1201 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
1204 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1205 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1206 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
1207 useForeignDTD = useDTD;
1208 return XML_ERROR_NONE;
1210 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1215 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
1217 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1218 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1220 ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
1224 XML_SetUserData(XML_Parser parser, void *p)
1226 if (handlerArg == userData)
1227 handlerArg = userData = p;
1232 enum XML_Status XMLCALL
1233 XML_SetBase(XML_Parser parser, const XML_Char *p)
1236 p = poolCopyString(&_dtd->pool, p);
1238 return XML_STATUS_ERROR;
1243 return XML_STATUS_OK;
1246 const XML_Char * XMLCALL
1247 XML_GetBase(XML_Parser parser)
1253 XML_GetSpecifiedAttributeCount(XML_Parser parser)
1255 return nSpecifiedAtts;
1259 XML_GetIdAttributeIndex(XML_Parser parser)
1264 #ifdef XML_ATTR_INFO
1265 const XML_AttrInfo * XMLCALL
1266 XML_GetAttributeInfo(XML_Parser parser)
1273 XML_SetElementHandler(XML_Parser parser,
1274 XML_StartElementHandler start,
1275 XML_EndElementHandler end)
1277 startElementHandler = start;
1278 endElementHandler = end;
1282 XML_SetStartElementHandler(XML_Parser parser,
1283 XML_StartElementHandler start) {
1284 startElementHandler = start;
1288 XML_SetEndElementHandler(XML_Parser parser,
1289 XML_EndElementHandler end) {
1290 endElementHandler = end;
1294 XML_SetCharacterDataHandler(XML_Parser parser,
1295 XML_CharacterDataHandler handler)
1297 characterDataHandler = handler;
1301 XML_SetProcessingInstructionHandler(XML_Parser parser,
1302 XML_ProcessingInstructionHandler handler)
1304 processingInstructionHandler = handler;
1308 XML_SetCommentHandler(XML_Parser parser,
1309 XML_CommentHandler handler)
1311 commentHandler = handler;
1315 XML_SetCdataSectionHandler(XML_Parser parser,
1316 XML_StartCdataSectionHandler start,
1317 XML_EndCdataSectionHandler end)
1319 startCdataSectionHandler = start;
1320 endCdataSectionHandler = end;
1324 XML_SetStartCdataSectionHandler(XML_Parser parser,
1325 XML_StartCdataSectionHandler start) {
1326 startCdataSectionHandler = start;
1330 XML_SetEndCdataSectionHandler(XML_Parser parser,
1331 XML_EndCdataSectionHandler end) {
1332 endCdataSectionHandler = end;
1336 XML_SetDefaultHandler(XML_Parser parser,
1337 XML_DefaultHandler handler)
1339 defaultHandler = handler;
1340 defaultExpandInternalEntities = XML_FALSE;
1344 XML_SetDefaultHandlerExpand(XML_Parser parser,
1345 XML_DefaultHandler handler)
1347 defaultHandler = handler;
1348 defaultExpandInternalEntities = XML_TRUE;
1352 XML_SetDoctypeDeclHandler(XML_Parser parser,
1353 XML_StartDoctypeDeclHandler start,
1354 XML_EndDoctypeDeclHandler end)
1356 startDoctypeDeclHandler = start;
1357 endDoctypeDeclHandler = end;
1361 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1362 XML_StartDoctypeDeclHandler start) {
1363 startDoctypeDeclHandler = start;
1367 XML_SetEndDoctypeDeclHandler(XML_Parser parser,
1368 XML_EndDoctypeDeclHandler end) {
1369 endDoctypeDeclHandler = end;
1373 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1374 XML_UnparsedEntityDeclHandler handler)
1376 unparsedEntityDeclHandler = handler;
1380 XML_SetNotationDeclHandler(XML_Parser parser,
1381 XML_NotationDeclHandler handler)
1383 notationDeclHandler = handler;
1387 XML_SetNamespaceDeclHandler(XML_Parser parser,
1388 XML_StartNamespaceDeclHandler start,
1389 XML_EndNamespaceDeclHandler end)
1391 startNamespaceDeclHandler = start;
1392 endNamespaceDeclHandler = end;
1396 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1397 XML_StartNamespaceDeclHandler start) {
1398 startNamespaceDeclHandler = start;
1402 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1403 XML_EndNamespaceDeclHandler end) {
1404 endNamespaceDeclHandler = end;
1408 XML_SetNotStandaloneHandler(XML_Parser parser,
1409 XML_NotStandaloneHandler handler)
1411 notStandaloneHandler = handler;
1415 XML_SetExternalEntityRefHandler(XML_Parser parser,
1416 XML_ExternalEntityRefHandler handler)
1418 externalEntityRefHandler = handler;
1422 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
1425 externalEntityRefHandlerArg = (XML_Parser)arg;
1427 externalEntityRefHandlerArg = parser;
1431 XML_SetSkippedEntityHandler(XML_Parser parser,
1432 XML_SkippedEntityHandler handler)
1434 skippedEntityHandler = handler;
1438 XML_SetUnknownEncodingHandler(XML_Parser parser,
1439 XML_UnknownEncodingHandler handler,
1442 unknownEncodingHandler = handler;
1443 unknownEncodingHandlerData = data;
1447 XML_SetElementDeclHandler(XML_Parser parser,
1448 XML_ElementDeclHandler eldecl)
1450 elementDeclHandler = eldecl;
1454 XML_SetAttlistDeclHandler(XML_Parser parser,
1455 XML_AttlistDeclHandler attdecl)
1457 attlistDeclHandler = attdecl;
1461 XML_SetEntityDeclHandler(XML_Parser parser,
1462 XML_EntityDeclHandler handler)
1464 entityDeclHandler = handler;
1468 XML_SetXmlDeclHandler(XML_Parser parser,
1469 XML_XmlDeclHandler handler) {
1470 xmlDeclHandler = handler;
1474 XML_SetParamEntityParsing(XML_Parser parser,
1475 enum XML_ParamEntityParsing peParsing)
1477 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1478 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1481 paramEntityParsing = peParsing;
1484 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1489 XML_SetHashSalt(XML_Parser parser,
1490 unsigned long hash_salt)
1492 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1493 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1495 hash_secret_salt = hash_salt;
1499 enum XML_Status XMLCALL
1500 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
1502 switch (ps_parsing) {
1504 errorCode = XML_ERROR_SUSPENDED;
1505 return XML_STATUS_ERROR;
1507 errorCode = XML_ERROR_FINISHED;
1508 return XML_STATUS_ERROR;
1509 case XML_INITIALIZED:
1510 if (parentParser == NULL && !startParsing(parser)) {
1511 errorCode = XML_ERROR_NO_MEMORY;
1512 return XML_STATUS_ERROR;
1515 ps_parsing = XML_PARSING;
1519 ps_finalBuffer = (XML_Bool)isFinal;
1521 return XML_STATUS_OK;
1522 positionPtr = bufferPtr;
1523 parseEndPtr = bufferEnd;
1525 /* If data are left over from last buffer, and we now know that these
1526 data are the final chunk of input, then we have to check them again
1527 to detect errors based on that fact.
1529 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
1531 if (errorCode == XML_ERROR_NONE) {
1532 switch (ps_parsing) {
1534 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1535 positionPtr = bufferPtr;
1536 return XML_STATUS_SUSPENDED;
1537 case XML_INITIALIZED:
1539 ps_parsing = XML_FINISHED;
1542 return XML_STATUS_OK;
1545 eventEndPtr = eventPtr;
1546 processor = errorProcessor;
1547 return XML_STATUS_ERROR;
1549 #ifndef XML_CONTEXT_BYTES
1550 else if (bufferPtr == bufferEnd) {
1553 enum XML_Error result;
1554 parseEndByteIndex += len;
1556 ps_finalBuffer = (XML_Bool)isFinal;
1558 errorCode = processor(parser, s, parseEndPtr = s + len, &end);
1560 if (errorCode != XML_ERROR_NONE) {
1561 eventEndPtr = eventPtr;
1562 processor = errorProcessor;
1563 return XML_STATUS_ERROR;
1566 switch (ps_parsing) {
1568 result = XML_STATUS_SUSPENDED;
1570 case XML_INITIALIZED:
1573 ps_parsing = XML_FINISHED;
1574 return XML_STATUS_OK;
1578 result = XML_STATUS_OK;
1582 XmlUpdatePosition(encoding, positionPtr, end, &position);
1583 nLeftOver = s + len - end;
1585 if (buffer == NULL || nLeftOver > bufferLim - buffer) {
1586 /* FIXME avoid integer overflow */
1588 temp = (buffer == NULL
1589 ? (char *)MALLOC(len * 2)
1590 : (char *)REALLOC(buffer, len * 2));
1592 errorCode = XML_ERROR_NO_MEMORY;
1593 eventPtr = eventEndPtr = NULL;
1594 processor = errorProcessor;
1595 return XML_STATUS_ERROR;
1598 bufferLim = buffer + len * 2;
1600 memcpy(buffer, end, nLeftOver);
1603 bufferEnd = buffer + nLeftOver;
1604 positionPtr = bufferPtr;
1605 parseEndPtr = bufferEnd;
1606 eventPtr = bufferPtr;
1607 eventEndPtr = bufferPtr;
1610 #endif /* not defined XML_CONTEXT_BYTES */
1612 void *buff = XML_GetBuffer(parser, len);
1614 return XML_STATUS_ERROR;
1616 memcpy(buff, s, len);
1617 return XML_ParseBuffer(parser, len, isFinal);
1622 enum XML_Status XMLCALL
1623 XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
1626 enum XML_Status result = XML_STATUS_OK;
1628 switch (ps_parsing) {
1630 errorCode = XML_ERROR_SUSPENDED;
1631 return XML_STATUS_ERROR;
1633 errorCode = XML_ERROR_FINISHED;
1634 return XML_STATUS_ERROR;
1635 case XML_INITIALIZED:
1636 if (parentParser == NULL && !startParsing(parser)) {
1637 errorCode = XML_ERROR_NO_MEMORY;
1638 return XML_STATUS_ERROR;
1641 ps_parsing = XML_PARSING;
1645 positionPtr = start;
1647 parseEndPtr = bufferEnd;
1648 parseEndByteIndex += len;
1649 ps_finalBuffer = (XML_Bool)isFinal;
1651 errorCode = processor(parser, start, parseEndPtr, &bufferPtr);
1653 if (errorCode != XML_ERROR_NONE) {
1654 eventEndPtr = eventPtr;
1655 processor = errorProcessor;
1656 return XML_STATUS_ERROR;
1659 switch (ps_parsing) {
1661 result = XML_STATUS_SUSPENDED;
1663 case XML_INITIALIZED:
1666 ps_parsing = XML_FINISHED;
1669 default: ; /* should not happen */
1673 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1674 positionPtr = bufferPtr;
1679 XML_GetBuffer(XML_Parser parser, int len)
1681 switch (ps_parsing) {
1683 errorCode = XML_ERROR_SUSPENDED;
1686 errorCode = XML_ERROR_FINISHED;
1691 if (len > bufferLim - bufferEnd) {
1692 /* FIXME avoid integer overflow */
1693 int neededSize = len + (int)(bufferEnd - bufferPtr);
1694 #ifdef XML_CONTEXT_BYTES
1695 int keep = (int)(bufferPtr - buffer);
1697 if (keep > XML_CONTEXT_BYTES)
1698 keep = XML_CONTEXT_BYTES;
1700 #endif /* defined XML_CONTEXT_BYTES */
1701 if (neededSize <= bufferLim - buffer) {
1702 #ifdef XML_CONTEXT_BYTES
1703 if (keep < bufferPtr - buffer) {
1704 int offset = (int)(bufferPtr - buffer) - keep;
1705 memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
1706 bufferEnd -= offset;
1707 bufferPtr -= offset;
1710 memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
1711 bufferEnd = buffer + (bufferEnd - bufferPtr);
1713 #endif /* not defined XML_CONTEXT_BYTES */
1717 int bufferSize = (int)(bufferLim - bufferPtr);
1718 if (bufferSize == 0)
1719 bufferSize = INIT_BUFFER_SIZE;
1722 } while (bufferSize < neededSize);
1723 newBuf = (char *)MALLOC(bufferSize);
1725 errorCode = XML_ERROR_NO_MEMORY;
1728 bufferLim = newBuf + bufferSize;
1729 #ifdef XML_CONTEXT_BYTES
1731 int keep = (int)(bufferPtr - buffer);
1732 if (keep > XML_CONTEXT_BYTES)
1733 keep = XML_CONTEXT_BYTES;
1734 memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
1737 bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
1738 bufferPtr = buffer + keep;
1741 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1742 bufferPtr = buffer = newBuf;
1746 memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
1749 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1750 bufferPtr = buffer = newBuf;
1751 #endif /* not defined XML_CONTEXT_BYTES */
1753 eventPtr = eventEndPtr = NULL;
1759 enum XML_Status XMLCALL
1760 XML_StopParser(XML_Parser parser, XML_Bool resumable)
1762 switch (ps_parsing) {
1765 errorCode = XML_ERROR_SUSPENDED;
1766 return XML_STATUS_ERROR;
1768 ps_parsing = XML_FINISHED;
1771 errorCode = XML_ERROR_FINISHED;
1772 return XML_STATUS_ERROR;
1776 if (isParamEntity) {
1777 errorCode = XML_ERROR_SUSPEND_PE;
1778 return XML_STATUS_ERROR;
1781 ps_parsing = XML_SUSPENDED;
1784 ps_parsing = XML_FINISHED;
1786 return XML_STATUS_OK;
1789 enum XML_Status XMLCALL
1790 XML_ResumeParser(XML_Parser parser)
1792 enum XML_Status result = XML_STATUS_OK;
1794 if (ps_parsing != XML_SUSPENDED) {
1795 errorCode = XML_ERROR_NOT_SUSPENDED;
1796 return XML_STATUS_ERROR;
1798 ps_parsing = XML_PARSING;
1800 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
1802 if (errorCode != XML_ERROR_NONE) {
1803 eventEndPtr = eventPtr;
1804 processor = errorProcessor;
1805 return XML_STATUS_ERROR;
1808 switch (ps_parsing) {
1810 result = XML_STATUS_SUSPENDED;
1812 case XML_INITIALIZED:
1814 if (ps_finalBuffer) {
1815 ps_parsing = XML_FINISHED;
1822 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1823 positionPtr = bufferPtr;
1828 XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
1830 assert(status != NULL);
1831 *status = parser->m_parsingStatus;
1834 enum XML_Error XMLCALL
1835 XML_GetErrorCode(XML_Parser parser)
1841 XML_GetCurrentByteIndex(XML_Parser parser)
1844 return parseEndByteIndex - (parseEndPtr - eventPtr);
1849 XML_GetCurrentByteCount(XML_Parser parser)
1851 if (eventEndPtr && eventPtr)
1852 return (int)(eventEndPtr - eventPtr);
1856 const char * XMLCALL
1857 XML_GetInputContext(XML_Parser parser, int *offset, int *size)
1859 #ifdef XML_CONTEXT_BYTES
1860 if (eventPtr && buffer) {
1861 *offset = (int)(eventPtr - buffer);
1862 *size = (int)(bufferEnd - buffer);
1865 #endif /* defined XML_CONTEXT_BYTES */
1870 XML_GetCurrentLineNumber(XML_Parser parser)
1872 if (eventPtr && eventPtr >= positionPtr) {
1873 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1874 positionPtr = eventPtr;
1876 return position.lineNumber + 1;
1880 XML_GetCurrentColumnNumber(XML_Parser parser)
1882 if (eventPtr && eventPtr >= positionPtr) {
1883 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1884 positionPtr = eventPtr;
1886 return position.columnNumber;
1890 XML_FreeContentModel(XML_Parser parser, XML_Content *model)
1896 XML_MemMalloc(XML_Parser parser, size_t size)
1898 return MALLOC(size);
1902 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
1904 return REALLOC(ptr, size);
1908 XML_MemFree(XML_Parser parser, void *ptr)
1914 XML_DefaultCurrent(XML_Parser parser)
1916 if (defaultHandler) {
1917 if (openInternalEntities)
1918 reportDefault(parser,
1920 openInternalEntities->internalEventPtr,
1921 openInternalEntities->internalEventEndPtr);
1923 reportDefault(parser, encoding, eventPtr, eventEndPtr);
1927 const XML_LChar * XMLCALL
1928 XML_ErrorString(enum XML_Error code)
1930 static const XML_LChar* const message[] = {
1932 XML_L("out of memory"),
1933 XML_L("syntax error"),
1934 XML_L("no element found"),
1935 XML_L("not well-formed (invalid token)"),
1936 XML_L("unclosed token"),
1937 XML_L("partial character"),
1938 XML_L("mismatched tag"),
1939 XML_L("duplicate attribute"),
1940 XML_L("junk after document element"),
1941 XML_L("illegal parameter entity reference"),
1942 XML_L("undefined entity"),
1943 XML_L("recursive entity reference"),
1944 XML_L("asynchronous entity"),
1945 XML_L("reference to invalid character number"),
1946 XML_L("reference to binary entity"),
1947 XML_L("reference to external entity in attribute"),
1948 XML_L("XML or text declaration not at start of entity"),
1949 XML_L("unknown encoding"),
1950 XML_L("encoding specified in XML declaration is incorrect"),
1951 XML_L("unclosed CDATA section"),
1952 XML_L("error in processing external entity reference"),
1953 XML_L("document is not standalone"),
1954 XML_L("unexpected parser state - please send a bug report"),
1955 XML_L("entity declared in parameter entity"),
1956 XML_L("requested feature requires XML_DTD support in Expat"),
1957 XML_L("cannot change setting once parsing has begun"),
1958 XML_L("unbound prefix"),
1959 XML_L("must not undeclare prefix"),
1960 XML_L("incomplete markup in parameter entity"),
1961 XML_L("XML declaration not well-formed"),
1962 XML_L("text declaration not well-formed"),
1963 XML_L("illegal character(s) in public id"),
1964 XML_L("parser suspended"),
1965 XML_L("parser not suspended"),
1966 XML_L("parsing aborted"),
1967 XML_L("parsing finished"),
1968 XML_L("cannot suspend in external parameter entity"),
1969 XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
1970 XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
1971 XML_L("prefix must not be bound to one of the reserved namespace names")
1973 if (code > 0 && code < sizeof(message)/sizeof(message[0]))
1974 return message[code];
1978 const XML_LChar * XMLCALL
1979 XML_ExpatVersion(void) {
1981 /* V1 is used to string-ize the version number. However, it would
1982 string-ize the actual version macro *names* unless we get them
1983 substituted before being passed to V1. CPP is defined to expand
1984 a macro, then rescan for more expansions. Thus, we use V2 to expand
1985 the version macros, then CPP will expand the resulting V1() macro
1986 with the correct numerals. */
1987 /* ### I'm assuming cpp is portable in this respect... */
1989 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
1990 #define V2(a,b,c) XML_L("expat_")V1(a,b,c)
1992 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
1998 XML_Expat_Version XMLCALL
1999 XML_ExpatVersionInfo(void)
2001 XML_Expat_Version version;
2003 version.major = XML_MAJOR_VERSION;
2004 version.minor = XML_MINOR_VERSION;
2005 version.micro = XML_MICRO_VERSION;
2010 const XML_Feature * XMLCALL
2011 XML_GetFeatureList(void)
2013 static const XML_Feature features[] = {
2014 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
2016 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
2019 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
2021 #ifdef XML_UNICODE_WCHAR_T
2022 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
2025 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
2027 #ifdef XML_CONTEXT_BYTES
2028 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
2032 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
2035 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
2037 #ifdef XML_LARGE_SIZE
2038 {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
2040 #ifdef XML_ATTR_INFO
2041 {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
2043 {XML_FEATURE_END, NULL, 0}
2049 /* Initially tag->rawName always points into the parse buffer;
2050 for those TAG instances opened while the current parse buffer was
2051 processed, and not yet closed, we need to store tag->rawName in a more
2052 permanent location, since the parse buffer is about to be discarded.
2055 storeRawNames(XML_Parser parser)
2057 TAG *tag = tagStack;
2060 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
2061 char *rawNameBuf = tag->buf + nameLen;
2062 /* Stop if already stored. Since tagStack is a stack, we can stop
2063 at the first entry that has already been copied; everything
2064 below it in the stack is already been accounted for in a
2065 previous call to this function.
2067 if (tag->rawName == rawNameBuf)
2069 /* For re-use purposes we need to ensure that the
2070 size of tag->buf is a multiple of sizeof(XML_Char).
2072 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
2073 if (bufSize > tag->bufEnd - tag->buf) {
2074 char *temp = (char *)REALLOC(tag->buf, bufSize);
2077 /* if tag->name.str points to tag->buf (only when namespace
2078 processing is off) then we have to update it
2080 if (tag->name.str == (XML_Char *)tag->buf)
2081 tag->name.str = (XML_Char *)temp;
2082 /* if tag->name.localPart is set (when namespace processing is on)
2083 then update it as well, since it will always point into tag->buf
2085 if (tag->name.localPart)
2086 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
2087 (XML_Char *)tag->buf);
2089 tag->bufEnd = temp + bufSize;
2090 rawNameBuf = temp + nameLen;
2092 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2093 tag->rawName = rawNameBuf;
2099 static enum XML_Error PTRCALL
2100 contentProcessor(XML_Parser parser,
2103 const char **endPtr)
2105 enum XML_Error result = doContent(parser, 0, encoding, start, end,
2106 endPtr, (XML_Bool)!ps_finalBuffer);
2107 if (result == XML_ERROR_NONE) {
2108 if (!storeRawNames(parser))
2109 return XML_ERROR_NO_MEMORY;
2114 static enum XML_Error PTRCALL
2115 externalEntityInitProcessor(XML_Parser parser,
2118 const char **endPtr)
2120 enum XML_Error result = initializeEncoding(parser);
2121 if (result != XML_ERROR_NONE)
2123 processor = externalEntityInitProcessor2;
2124 return externalEntityInitProcessor2(parser, start, end, endPtr);
2127 static enum XML_Error PTRCALL
2128 externalEntityInitProcessor2(XML_Parser parser,
2131 const char **endPtr)
2133 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2134 int tok = XmlContentTok(encoding, start, end, &next);
2137 /* If we are at the end of the buffer, this would cause the next stage,
2138 i.e. externalEntityInitProcessor3, to pass control directly to
2139 doContent (by detecting XML_TOK_NONE) without processing any xml text
2140 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2142 if (next == end && !ps_finalBuffer) {
2144 return XML_ERROR_NONE;
2148 case XML_TOK_PARTIAL:
2149 if (!ps_finalBuffer) {
2151 return XML_ERROR_NONE;
2154 return XML_ERROR_UNCLOSED_TOKEN;
2155 case XML_TOK_PARTIAL_CHAR:
2156 if (!ps_finalBuffer) {
2158 return XML_ERROR_NONE;
2161 return XML_ERROR_PARTIAL_CHAR;
2163 processor = externalEntityInitProcessor3;
2164 return externalEntityInitProcessor3(parser, start, end, endPtr);
2167 static enum XML_Error PTRCALL
2168 externalEntityInitProcessor3(XML_Parser parser,
2171 const char **endPtr)
2174 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2176 tok = XmlContentTok(encoding, start, end, &next);
2180 case XML_TOK_XML_DECL:
2182 enum XML_Error result;
2183 result = processXmlDecl(parser, 1, start, next);
2184 if (result != XML_ERROR_NONE)
2186 switch (ps_parsing) {
2189 return XML_ERROR_NONE;
2191 return XML_ERROR_ABORTED;
2197 case XML_TOK_PARTIAL:
2198 if (!ps_finalBuffer) {
2200 return XML_ERROR_NONE;
2202 return XML_ERROR_UNCLOSED_TOKEN;
2203 case XML_TOK_PARTIAL_CHAR:
2204 if (!ps_finalBuffer) {
2206 return XML_ERROR_NONE;
2208 return XML_ERROR_PARTIAL_CHAR;
2210 processor = externalEntityContentProcessor;
2212 return externalEntityContentProcessor(parser, start, end, endPtr);
2215 static enum XML_Error PTRCALL
2216 externalEntityContentProcessor(XML_Parser parser,
2219 const char **endPtr)
2221 enum XML_Error result = doContent(parser, 1, encoding, start, end,
2222 endPtr, (XML_Bool)!ps_finalBuffer);
2223 if (result == XML_ERROR_NONE) {
2224 if (!storeRawNames(parser))
2225 return XML_ERROR_NO_MEMORY;
2230 static enum XML_Error
2231 doContent(XML_Parser parser,
2233 const ENCODING *enc,
2236 const char **nextPtr,
2239 /* save one level of indirection */
2240 DTD * const dtd = _dtd;
2242 const char **eventPP;
2243 const char **eventEndPP;
2244 if (enc == encoding) {
2245 eventPP = &eventPtr;
2246 eventEndPP = &eventEndPtr;
2249 eventPP = &(openInternalEntities->internalEventPtr);
2250 eventEndPP = &(openInternalEntities->internalEventEndPtr);
2255 const char *next = s; /* XmlContentTok doesn't always set the last arg */
2256 int tok = XmlContentTok(enc, s, end, &next);
2259 case XML_TOK_TRAILING_CR:
2262 return XML_ERROR_NONE;
2265 if (characterDataHandler) {
2267 characterDataHandler(handlerArg, &c, 1);
2269 else if (defaultHandler)
2270 reportDefault(parser, enc, s, end);
2271 /* We are at the end of the final buffer, should we check for
2272 XML_SUSPENDED, XML_FINISHED?
2274 if (startTagLevel == 0)
2275 return XML_ERROR_NO_ELEMENTS;
2276 if (tagLevel != startTagLevel)
2277 return XML_ERROR_ASYNC_ENTITY;
2279 return XML_ERROR_NONE;
2283 return XML_ERROR_NONE;
2285 if (startTagLevel > 0) {
2286 if (tagLevel != startTagLevel)
2287 return XML_ERROR_ASYNC_ENTITY;
2289 return XML_ERROR_NONE;
2291 return XML_ERROR_NO_ELEMENTS;
2292 case XML_TOK_INVALID:
2294 return XML_ERROR_INVALID_TOKEN;
2295 case XML_TOK_PARTIAL:
2298 return XML_ERROR_NONE;
2300 return XML_ERROR_UNCLOSED_TOKEN;
2301 case XML_TOK_PARTIAL_CHAR:
2304 return XML_ERROR_NONE;
2306 return XML_ERROR_PARTIAL_CHAR;
2307 case XML_TOK_ENTITY_REF:
2309 const XML_Char *name;
2311 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
2312 s + enc->minBytesPerChar,
2313 next - enc->minBytesPerChar);
2315 if (characterDataHandler)
2316 characterDataHandler(handlerArg, &ch, 1);
2317 else if (defaultHandler)
2318 reportDefault(parser, enc, s, next);
2321 name = poolStoreString(&dtd->pool, enc,
2322 s + enc->minBytesPerChar,
2323 next - enc->minBytesPerChar);
2325 return XML_ERROR_NO_MEMORY;
2326 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
2327 poolDiscard(&dtd->pool);
2328 /* First, determine if a check for an existing declaration is needed;
2329 if yes, check that the entity exists, and that it is internal,
2330 otherwise call the skipped entity or default handler.
2332 if (!dtd->hasParamEntityRefs || dtd->standalone) {
2334 return XML_ERROR_UNDEFINED_ENTITY;
2335 else if (!entity->is_internal)
2336 return XML_ERROR_ENTITY_DECLARED_IN_PE;
2339 if (skippedEntityHandler)
2340 skippedEntityHandler(handlerArg, name, 0);
2341 else if (defaultHandler)
2342 reportDefault(parser, enc, s, next);
2346 return XML_ERROR_RECURSIVE_ENTITY_REF;
2347 if (entity->notation)
2348 return XML_ERROR_BINARY_ENTITY_REF;
2349 if (entity->textPtr) {
2350 enum XML_Error result;
2351 if (!defaultExpandInternalEntities) {
2352 if (skippedEntityHandler)
2353 skippedEntityHandler(handlerArg, entity->name, 0);
2354 else if (defaultHandler)
2355 reportDefault(parser, enc, s, next);
2358 result = processInternalEntity(parser, entity, XML_FALSE);
2359 if (result != XML_ERROR_NONE)
2362 else if (externalEntityRefHandler) {
2363 const XML_Char *context;
2364 entity->open = XML_TRUE;
2365 context = getContext(parser);
2366 entity->open = XML_FALSE;
2368 return XML_ERROR_NO_MEMORY;
2369 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
2374 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2375 poolDiscard(&tempPool);
2377 else if (defaultHandler)
2378 reportDefault(parser, enc, s, next);
2381 case XML_TOK_START_TAG_NO_ATTS:
2383 case XML_TOK_START_TAG_WITH_ATTS:
2386 enum XML_Error result;
2390 freeTagList = freeTagList->parent;
2393 tag = (TAG *)MALLOC(sizeof(TAG));
2395 return XML_ERROR_NO_MEMORY;
2396 tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
2399 return XML_ERROR_NO_MEMORY;
2401 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2403 tag->bindings = NULL;
2404 tag->parent = tagStack;
2406 tag->name.localPart = NULL;
2407 tag->name.prefix = NULL;
2408 tag->rawName = s + enc->minBytesPerChar;
2409 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
2412 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2413 const char *fromPtr = tag->rawName;
2414 toPtr = (XML_Char *)tag->buf;
2419 &fromPtr, rawNameEnd,
2420 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
2421 convLen = (int)(toPtr - (XML_Char *)tag->buf);
2422 if (fromPtr == rawNameEnd) {
2423 tag->name.strLen = convLen;
2426 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2428 char *temp = (char *)REALLOC(tag->buf, bufSize);
2430 return XML_ERROR_NO_MEMORY;
2432 tag->bufEnd = temp + bufSize;
2433 toPtr = (XML_Char *)temp + convLen;
2437 tag->name.str = (XML_Char *)tag->buf;
2438 *toPtr = XML_T('\0');
2439 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2442 if (startElementHandler)
2443 startElementHandler(handlerArg, tag->name.str,
2444 (const XML_Char **)atts);
2445 else if (defaultHandler)
2446 reportDefault(parser, enc, s, next);
2447 poolClear(&tempPool);
2450 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2452 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
2454 const char *rawName = s + enc->minBytesPerChar;
2455 enum XML_Error result;
2456 BINDING *bindings = NULL;
2457 XML_Bool noElmHandlers = XML_TRUE;
2459 name.str = poolStoreString(&tempPool, enc, rawName,
2460 rawName + XmlNameLength(enc, rawName));
2462 return XML_ERROR_NO_MEMORY;
2463 poolFinish(&tempPool);
2464 result = storeAtts(parser, enc, s, &name, &bindings);
2467 poolFinish(&tempPool);
2468 if (startElementHandler) {
2469 startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
2470 noElmHandlers = XML_FALSE;
2472 if (endElementHandler) {
2473 if (startElementHandler)
2474 *eventPP = *eventEndPP;
2475 endElementHandler(handlerArg, name.str);
2476 noElmHandlers = XML_FALSE;
2478 if (noElmHandlers && defaultHandler)
2479 reportDefault(parser, enc, s, next);
2480 poolClear(&tempPool);
2482 BINDING *b = bindings;
2483 if (endNamespaceDeclHandler)
2484 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2485 bindings = bindings->nextTagBinding;
2486 b->nextTagBinding = freeBindingList;
2487 freeBindingList = b;
2488 b->prefix->binding = b->prevPrefixBinding;
2492 return epilogProcessor(parser, next, end, nextPtr);
2494 case XML_TOK_END_TAG:
2495 if (tagLevel == startTagLevel)
2496 return XML_ERROR_ASYNC_ENTITY;
2499 const char *rawName;
2500 TAG *tag = tagStack;
2501 tagStack = tag->parent;
2502 tag->parent = freeTagList;
2504 rawName = s + enc->minBytesPerChar*2;
2505 len = XmlNameLength(enc, rawName);
2506 if (len != tag->rawNameLength
2507 || memcmp(tag->rawName, rawName, len) != 0) {
2509 return XML_ERROR_TAG_MISMATCH;
2512 if (endElementHandler) {
2513 const XML_Char *localPart;
2514 const XML_Char *prefix;
2516 localPart = tag->name.localPart;
2517 if (ns && localPart) {
2518 /* localPart and prefix may have been overwritten in
2519 tag->name.str, since this points to the binding->uri
2520 buffer which gets re-used; so we have to add them again
2522 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2523 /* don't need to check for space - already done in storeAtts() */
2524 while (*localPart) *uri++ = *localPart++;
2525 prefix = (XML_Char *)tag->name.prefix;
2526 if (ns_triplets && prefix) {
2527 *uri++ = namespaceSeparator;
2528 while (*prefix) *uri++ = *prefix++;
2532 endElementHandler(handlerArg, tag->name.str);
2534 else if (defaultHandler)
2535 reportDefault(parser, enc, s, next);
2536 while (tag->bindings) {
2537 BINDING *b = tag->bindings;
2538 if (endNamespaceDeclHandler)
2539 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2540 tag->bindings = tag->bindings->nextTagBinding;
2541 b->nextTagBinding = freeBindingList;
2542 freeBindingList = b;
2543 b->prefix->binding = b->prevPrefixBinding;
2546 return epilogProcessor(parser, next, end, nextPtr);
2549 case XML_TOK_CHAR_REF:
2551 int n = XmlCharRefNumber(enc, s);
2553 return XML_ERROR_BAD_CHAR_REF;
2554 if (characterDataHandler) {
2555 XML_Char buf[XML_ENCODE_MAX];
2556 characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
2558 else if (defaultHandler)
2559 reportDefault(parser, enc, s, next);
2562 case XML_TOK_XML_DECL:
2563 return XML_ERROR_MISPLACED_XML_PI;
2564 case XML_TOK_DATA_NEWLINE:
2565 if (characterDataHandler) {
2567 characterDataHandler(handlerArg, &c, 1);
2569 else if (defaultHandler)
2570 reportDefault(parser, enc, s, next);
2572 case XML_TOK_CDATA_SECT_OPEN:
2574 enum XML_Error result;
2575 if (startCdataSectionHandler)
2576 startCdataSectionHandler(handlerArg);
2578 /* Suppose you doing a transformation on a document that involves
2579 changing only the character data. You set up a defaultHandler
2580 and a characterDataHandler. The defaultHandler simply copies
2581 characters through. The characterDataHandler does the
2582 transformation and writes the characters out escaping them as
2583 necessary. This case will fail to work if we leave out the
2584 following two lines (because & and < inside CDATA sections will
2585 be incorrectly escaped).
2587 However, now we have a start/endCdataSectionHandler, so it seems
2588 easier to let the user deal with this.
2590 else if (characterDataHandler)
2591 characterDataHandler(handlerArg, dataBuf, 0);
2593 else if (defaultHandler)
2594 reportDefault(parser, enc, s, next);
2595 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
2596 if (result != XML_ERROR_NONE)
2599 processor = cdataSectionProcessor;
2604 case XML_TOK_TRAILING_RSQB:
2607 return XML_ERROR_NONE;
2609 if (characterDataHandler) {
2610 if (MUST_CONVERT(enc, s)) {
2611 ICHAR *dataPtr = (ICHAR *)dataBuf;
2612 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
2613 characterDataHandler(handlerArg, dataBuf,
2614 (int)(dataPtr - (ICHAR *)dataBuf));
2617 characterDataHandler(handlerArg,
2619 (int)((XML_Char *)end - (XML_Char *)s));
2621 else if (defaultHandler)
2622 reportDefault(parser, enc, s, end);
2623 /* We are at the end of the final buffer, should we check for
2624 XML_SUSPENDED, XML_FINISHED?
2626 if (startTagLevel == 0) {
2628 return XML_ERROR_NO_ELEMENTS;
2630 if (tagLevel != startTagLevel) {
2632 return XML_ERROR_ASYNC_ENTITY;
2635 return XML_ERROR_NONE;
2636 case XML_TOK_DATA_CHARS:
2638 XML_CharacterDataHandler charDataHandler = characterDataHandler;
2639 if (charDataHandler) {
2640 if (MUST_CONVERT(enc, s)) {
2642 ICHAR *dataPtr = (ICHAR *)dataBuf;
2643 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
2645 charDataHandler(handlerArg, dataBuf,
2646 (int)(dataPtr - (ICHAR *)dataBuf));
2653 charDataHandler(handlerArg,
2655 (int)((XML_Char *)next - (XML_Char *)s));
2657 else if (defaultHandler)
2658 reportDefault(parser, enc, s, next);
2662 if (!reportProcessingInstruction(parser, enc, s, next))
2663 return XML_ERROR_NO_MEMORY;
2665 case XML_TOK_COMMENT:
2666 if (!reportComment(parser, enc, s, next))
2667 return XML_ERROR_NO_MEMORY;
2671 reportDefault(parser, enc, s, next);
2674 *eventPP = s = next;
2675 switch (ps_parsing) {
2678 return XML_ERROR_NONE;
2680 return XML_ERROR_ABORTED;
2687 /* Precondition: all arguments must be non-NULL;
2689 - normalize attributes
2690 - check attributes for well-formedness
2691 - generate namespace aware attribute names (URI, prefix)
2692 - build list of attributes for startElementHandler
2693 - default attributes
2694 - process namespace declarations (check and report them)
2695 - generate namespace aware element name (URI, prefix)
2697 static enum XML_Error
2698 storeAtts(XML_Parser parser, const ENCODING *enc,
2699 const char *attStr, TAG_NAME *tagNamePtr,
2700 BINDING **bindingsPtr)
2702 DTD * const dtd = _dtd; /* save one level of indirection */
2703 ELEMENT_TYPE *elementType;
2705 const XML_Char **appAtts; /* the attribute list for the application */
2713 const XML_Char *localPart;
2715 /* lookup the element type name */
2716 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
2718 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
2720 return XML_ERROR_NO_MEMORY;
2721 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
2722 sizeof(ELEMENT_TYPE));
2724 return XML_ERROR_NO_MEMORY;
2725 if (ns && !setElementTypePrefix(parser, elementType))
2726 return XML_ERROR_NO_MEMORY;
2728 nDefaultAtts = elementType->nDefaultAtts;
2730 /* get the attributes from the tokenizer */
2731 n = XmlGetAttributes(enc, attStr, attsSize, atts);
2732 if (n + nDefaultAtts > attsSize) {
2733 int oldAttsSize = attsSize;
2735 #ifdef XML_ATTR_INFO
2736 XML_AttrInfo *temp2;
2738 attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
2739 temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
2741 return XML_ERROR_NO_MEMORY;
2743 #ifdef XML_ATTR_INFO
2744 temp2 = (XML_AttrInfo *)REALLOC((void *)attInfo, attsSize * sizeof(XML_AttrInfo));
2746 return XML_ERROR_NO_MEMORY;
2749 if (n > oldAttsSize)
2750 XmlGetAttributes(enc, attStr, n, atts);
2753 appAtts = (const XML_Char **)atts;
2754 for (i = 0; i < n; i++) {
2755 ATTRIBUTE *currAtt = &atts[i];
2756 #ifdef XML_ATTR_INFO
2757 XML_AttrInfo *currAttInfo = &attInfo[i];
2759 /* add the name and value to the attribute list */
2760 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
2762 + XmlNameLength(enc, currAtt->name));
2764 return XML_ERROR_NO_MEMORY;
2765 #ifdef XML_ATTR_INFO
2766 currAttInfo->nameStart = parseEndByteIndex - (parseEndPtr - currAtt->name);
2767 currAttInfo->nameEnd = currAttInfo->nameStart +
2768 XmlNameLength(enc, currAtt->name);
2769 currAttInfo->valueStart = parseEndByteIndex -
2770 (parseEndPtr - currAtt->valuePtr);
2771 currAttInfo->valueEnd = parseEndByteIndex - (parseEndPtr - currAtt->valueEnd);
2773 /* Detect duplicate attributes by their QNames. This does not work when
2774 namespace processing is turned on and different prefixes for the same
2775 namespace are used. For this case we have a check further down.
2777 if ((attId->name)[-1]) {
2778 if (enc == encoding)
2779 eventPtr = atts[i].name;
2780 return XML_ERROR_DUPLICATE_ATTRIBUTE;
2782 (attId->name)[-1] = 1;
2783 appAtts[attIndex++] = attId->name;
2784 if (!atts[i].normalized) {
2785 enum XML_Error result;
2786 XML_Bool isCdata = XML_TRUE;
2788 /* figure out whether declared as other than CDATA */
2789 if (attId->maybeTokenized) {
2791 for (j = 0; j < nDefaultAtts; j++) {
2792 if (attId == elementType->defaultAtts[j].id) {
2793 isCdata = elementType->defaultAtts[j].isCdata;
2799 /* normalize the attribute value */
2800 result = storeAttributeValue(parser, enc, isCdata,
2801 atts[i].valuePtr, atts[i].valueEnd,
2805 appAtts[attIndex] = poolStart(&tempPool);
2806 poolFinish(&tempPool);
2809 /* the value did not need normalizing */
2810 appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
2812 if (appAtts[attIndex] == 0)
2813 return XML_ERROR_NO_MEMORY;
2814 poolFinish(&tempPool);
2816 /* handle prefixed attribute names */
2817 if (attId->prefix) {
2819 /* deal with namespace declarations here */
2820 enum XML_Error result = addBinding(parser, attId->prefix, attId,
2821 appAtts[attIndex], bindingsPtr);
2827 /* deal with other prefixed names later */
2830 (attId->name)[-1] = 2;
2837 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
2838 nSpecifiedAtts = attIndex;
2839 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
2840 for (i = 0; i < attIndex; i += 2)
2841 if (appAtts[i] == elementType->idAtt->name) {
2849 /* do attribute defaulting */
2850 for (i = 0; i < nDefaultAtts; i++) {
2851 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
2852 if (!(da->id->name)[-1] && da->value) {
2853 if (da->id->prefix) {
2854 if (da->id->xmlns) {
2855 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
2856 da->value, bindingsPtr);
2861 (da->id->name)[-1] = 2;
2863 appAtts[attIndex++] = da->id->name;
2864 appAtts[attIndex++] = da->value;
2868 (da->id->name)[-1] = 1;
2869 appAtts[attIndex++] = da->id->name;
2870 appAtts[attIndex++] = da->value;
2874 appAtts[attIndex] = 0;
2876 /* expand prefixed attribute names, check for duplicates,
2877 and clear flags that say whether attributes were specified */
2880 int j; /* hash table index */
2881 unsigned long version = nsAttsVersion;
2882 int nsAttsSize = (int)1 << nsAttsPower;
2883 /* size of hash table must be at least 2 * (# of prefixed attributes) */
2884 if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */
2886 /* hash table size must also be a power of 2 and >= 8 */
2887 while (nPrefixes >> nsAttsPower++);
2888 if (nsAttsPower < 3)
2890 nsAttsSize = (int)1 << nsAttsPower;
2891 temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
2893 return XML_ERROR_NO_MEMORY;
2895 version = 0; /* force re-initialization of nsAtts hash table */
2897 /* using a version flag saves us from initializing nsAtts every time */
2898 if (!version) { /* initialize version flags when version wraps around */
2899 version = INIT_ATTS_VERSION;
2900 for (j = nsAttsSize; j != 0; )
2901 nsAtts[--j].version = version;
2903 nsAttsVersion = --version;
2905 /* expand prefixed names and check for duplicates */
2906 for (; i < attIndex; i += 2) {
2907 const XML_Char *s = appAtts[i];
2908 if (s[-1] == 2) { /* prefixed */
2911 unsigned long uriHash = hash_secret_salt;
2912 ((XML_Char *)s)[-1] = 0; /* clear flag */
2913 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
2914 b = id->prefix->binding;
2916 return XML_ERROR_UNBOUND_PREFIX;
2918 /* as we expand the name we also calculate its hash value */
2919 for (j = 0; j < b->uriLen; j++) {
2920 const XML_Char c = b->uri[j];
2921 if (!poolAppendChar(&tempPool, c))
2922 return XML_ERROR_NO_MEMORY;
2923 uriHash = CHAR_HASH(uriHash, c);
2925 while (*s++ != XML_T(ASCII_COLON))
2927 do { /* copies null terminator */
2928 const XML_Char c = *s;
2929 if (!poolAppendChar(&tempPool, *s))
2930 return XML_ERROR_NO_MEMORY;
2931 uriHash = CHAR_HASH(uriHash, c);
2934 { /* Check hash table for duplicate of expanded name (uriName).
2935 Derived from code in lookup(parser, HASH_TABLE *table, ...).
2937 unsigned char step = 0;
2938 unsigned long mask = nsAttsSize - 1;
2939 j = uriHash & mask; /* index into hash table */
2940 while (nsAtts[j].version == version) {
2941 /* for speed we compare stored hash values first */
2942 if (uriHash == nsAtts[j].hash) {
2943 const XML_Char *s1 = poolStart(&tempPool);
2944 const XML_Char *s2 = nsAtts[j].uriName;
2945 /* s1 is null terminated, but not s2 */
2946 for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
2948 return XML_ERROR_DUPLICATE_ATTRIBUTE;
2951 step = PROBE_STEP(uriHash, mask, nsAttsPower);
2952 j < step ? (j += nsAttsSize - step) : (j -= step);
2956 if (ns_triplets) { /* append namespace separator and prefix */
2957 tempPool.ptr[-1] = namespaceSeparator;
2958 s = b->prefix->name;
2960 if (!poolAppendChar(&tempPool, *s))
2961 return XML_ERROR_NO_MEMORY;
2965 /* store expanded name in attribute list */
2966 s = poolStart(&tempPool);
2967 poolFinish(&tempPool);
2970 /* fill empty slot with new version, uriName and hash value */
2971 nsAtts[j].version = version;
2972 nsAtts[j].hash = uriHash;
2973 nsAtts[j].uriName = s;
2980 else /* not prefixed */
2981 ((XML_Char *)s)[-1] = 0; /* clear flag */
2984 /* clear flags for the remaining attributes */
2985 for (; i < attIndex; i += 2)
2986 ((XML_Char *)(appAtts[i]))[-1] = 0;
2987 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
2988 binding->attId->name[-1] = 0;
2991 return XML_ERROR_NONE;
2993 /* expand the element type name */
2994 if (elementType->prefix) {
2995 binding = elementType->prefix->binding;
2997 return XML_ERROR_UNBOUND_PREFIX;
2998 localPart = tagNamePtr->str;
2999 while (*localPart++ != XML_T(ASCII_COLON))
3002 else if (dtd->defaultPrefix.binding) {
3003 binding = dtd->defaultPrefix.binding;
3004 localPart = tagNamePtr->str;
3007 return XML_ERROR_NONE;
3009 if (ns_triplets && binding->prefix->name) {
3010 for (; binding->prefix->name[prefixLen++];)
3011 ; /* prefixLen includes null terminator */
3013 tagNamePtr->localPart = localPart;
3014 tagNamePtr->uriLen = binding->uriLen;
3015 tagNamePtr->prefix = binding->prefix->name;
3016 tagNamePtr->prefixLen = prefixLen;
3017 for (i = 0; localPart[i++];)
3018 ; /* i includes null terminator */
3019 n = i + binding->uriLen + prefixLen;
3020 if (n > binding->uriAlloc) {
3022 uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
3024 return XML_ERROR_NO_MEMORY;
3025 binding->uriAlloc = n + EXPAND_SPARE;
3026 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
3027 for (p = tagStack; p; p = p->parent)
3028 if (p->name.str == binding->uri)
3033 /* if namespaceSeparator != '\0' then uri includes it already */
3034 uri = binding->uri + binding->uriLen;
3035 memcpy(uri, localPart, i * sizeof(XML_Char));
3036 /* we always have a namespace separator between localPart and prefix */
3039 *uri = namespaceSeparator; /* replace null terminator */
3040 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
3042 tagNamePtr->str = binding->uri;
3043 return XML_ERROR_NONE;
3046 /* addBinding() overwrites the value of prefix->binding without checking.
3047 Therefore one must keep track of the old value outside of addBinding().
3049 static enum XML_Error
3050 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
3051 const XML_Char *uri, BINDING **bindingsPtr)
3053 static const XML_Char xmlNamespace[] = {
3054 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3055 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
3056 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
3057 ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
3058 ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
3061 static const int xmlLen =
3062 (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
3063 static const XML_Char xmlnsNamespace[] = {
3064 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3065 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
3066 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
3067 ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
3070 static const int xmlnsLen =
3071 (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
3073 XML_Bool mustBeXML = XML_FALSE;
3074 XML_Bool isXML = XML_TRUE;
3075 XML_Bool isXMLNS = XML_TRUE;
3080 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
3081 if (*uri == XML_T('\0') && prefix->name)
3082 return XML_ERROR_UNDECLARING_PREFIX;
3085 && prefix->name[0] == XML_T(ASCII_x)
3086 && prefix->name[1] == XML_T(ASCII_m)
3087 && prefix->name[2] == XML_T(ASCII_l)) {
3089 /* Not allowed to bind xmlns */
3090 if (prefix->name[3] == XML_T(ASCII_n)
3091 && prefix->name[4] == XML_T(ASCII_s)
3092 && prefix->name[5] == XML_T('\0'))
3093 return XML_ERROR_RESERVED_PREFIX_XMLNS;
3095 if (prefix->name[3] == XML_T('\0'))
3096 mustBeXML = XML_TRUE;
3099 for (len = 0; uri[len]; len++) {
3100 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
3103 if (!mustBeXML && isXMLNS
3104 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3105 isXMLNS = XML_FALSE;
3107 isXML = isXML && len == xmlLen;
3108 isXMLNS = isXMLNS && len == xmlnsLen;
3110 if (mustBeXML != isXML)
3111 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3112 : XML_ERROR_RESERVED_NAMESPACE_URI;
3115 return XML_ERROR_RESERVED_NAMESPACE_URI;
3117 if (namespaceSeparator)
3119 if (freeBindingList) {
3120 b = freeBindingList;
3121 if (len > b->uriAlloc) {
3122 XML_Char *temp = (XML_Char *)REALLOC(b->uri,
3123 sizeof(XML_Char) * (len + EXPAND_SPARE));
3125 return XML_ERROR_NO_MEMORY;
3127 b->uriAlloc = len + EXPAND_SPARE;
3129 freeBindingList = b->nextTagBinding;
3132 b = (BINDING *)MALLOC(sizeof(BINDING));
3134 return XML_ERROR_NO_MEMORY;
3135 b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
3138 return XML_ERROR_NO_MEMORY;
3140 b->uriAlloc = len + EXPAND_SPARE;
3143 memcpy(b->uri, uri, len * sizeof(XML_Char));
3144 if (namespaceSeparator)
3145 b->uri[len - 1] = namespaceSeparator;
3148 b->prevPrefixBinding = prefix->binding;
3149 /* NULL binding when default namespace undeclared */
3150 if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
3151 prefix->binding = NULL;
3153 prefix->binding = b;
3154 b->nextTagBinding = *bindingsPtr;
3156 /* if attId == NULL then we are not starting a namespace scope */
3157 if (attId && startNamespaceDeclHandler)
3158 startNamespaceDeclHandler(handlerArg, prefix->name,
3159 prefix->binding ? uri : 0);
3160 return XML_ERROR_NONE;
3163 /* The idea here is to avoid using stack for each CDATA section when
3164 the whole file is parsed with one call.
3166 static enum XML_Error PTRCALL
3167 cdataSectionProcessor(XML_Parser parser,
3170 const char **endPtr)
3172 enum XML_Error result = doCdataSection(parser, encoding, &start, end,
3173 endPtr, (XML_Bool)!ps_finalBuffer);
3174 if (result != XML_ERROR_NONE)
3177 if (parentParser) { /* we are parsing an external entity */
3178 processor = externalEntityContentProcessor;
3179 return externalEntityContentProcessor(parser, start, end, endPtr);
3182 processor = contentProcessor;
3183 return contentProcessor(parser, start, end, endPtr);
3189 /* startPtr gets set to non-null if the section is closed, and to null if
3190 the section is not yet closed.
3192 static enum XML_Error
3193 doCdataSection(XML_Parser parser,
3194 const ENCODING *enc,
3195 const char **startPtr,
3197 const char **nextPtr,
3200 const char *s = *startPtr;
3201 const char **eventPP;
3202 const char **eventEndPP;
3203 if (enc == encoding) {
3204 eventPP = &eventPtr;
3206 eventEndPP = &eventEndPtr;
3209 eventPP = &(openInternalEntities->internalEventPtr);
3210 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3217 int tok = XmlCdataSectionTok(enc, s, end, &next);
3220 case XML_TOK_CDATA_SECT_CLOSE:
3221 if (endCdataSectionHandler)
3222 endCdataSectionHandler(handlerArg);
3224 /* see comment under XML_TOK_CDATA_SECT_OPEN */
3225 else if (characterDataHandler)
3226 characterDataHandler(handlerArg, dataBuf, 0);
3228 else if (defaultHandler)
3229 reportDefault(parser, enc, s, next);
3232 if (ps_parsing == XML_FINISHED)
3233 return XML_ERROR_ABORTED;
3235 return XML_ERROR_NONE;
3236 case XML_TOK_DATA_NEWLINE:
3237 if (characterDataHandler) {
3239 characterDataHandler(handlerArg, &c, 1);
3241 else if (defaultHandler)
3242 reportDefault(parser, enc, s, next);
3244 case XML_TOK_DATA_CHARS:
3246 XML_CharacterDataHandler charDataHandler = characterDataHandler;
3247 if (charDataHandler) {
3248 if (MUST_CONVERT(enc, s)) {
3250 ICHAR *dataPtr = (ICHAR *)dataBuf;
3251 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
3253 charDataHandler(handlerArg, dataBuf,
3254 (int)(dataPtr - (ICHAR *)dataBuf));
3261 charDataHandler(handlerArg,
3263 (int)((XML_Char *)next - (XML_Char *)s));
3265 else if (defaultHandler)
3266 reportDefault(parser, enc, s, next);
3269 case XML_TOK_INVALID:
3271 return XML_ERROR_INVALID_TOKEN;
3272 case XML_TOK_PARTIAL_CHAR:
3275 return XML_ERROR_NONE;
3277 return XML_ERROR_PARTIAL_CHAR;
3278 case XML_TOK_PARTIAL:
3282 return XML_ERROR_NONE;
3284 return XML_ERROR_UNCLOSED_CDATA_SECTION;
3287 return XML_ERROR_UNEXPECTED_STATE;
3290 *eventPP = s = next;
3291 switch (ps_parsing) {
3294 return XML_ERROR_NONE;
3296 return XML_ERROR_ABORTED;
3305 /* The idea here is to avoid using stack for each IGNORE section when
3306 the whole file is parsed with one call.
3308 static enum XML_Error PTRCALL
3309 ignoreSectionProcessor(XML_Parser parser,
3312 const char **endPtr)
3314 enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
3315 endPtr, (XML_Bool)!ps_finalBuffer);
3316 if (result != XML_ERROR_NONE)
3319 processor = prologProcessor;
3320 return prologProcessor(parser, start, end, endPtr);
3325 /* startPtr gets set to non-null is the section is closed, and to null
3326 if the section is not yet closed.
3328 static enum XML_Error
3329 doIgnoreSection(XML_Parser parser,
3330 const ENCODING *enc,
3331 const char **startPtr,
3333 const char **nextPtr,
3338 const char *s = *startPtr;
3339 const char **eventPP;
3340 const char **eventEndPP;
3341 if (enc == encoding) {
3342 eventPP = &eventPtr;
3344 eventEndPP = &eventEndPtr;
3347 eventPP = &(openInternalEntities->internalEventPtr);
3348 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3352 tok = XmlIgnoreSectionTok(enc, s, end, &next);
3355 case XML_TOK_IGNORE_SECT:
3357 reportDefault(parser, enc, s, next);
3360 if (ps_parsing == XML_FINISHED)
3361 return XML_ERROR_ABORTED;
3363 return XML_ERROR_NONE;
3364 case XML_TOK_INVALID:
3366 return XML_ERROR_INVALID_TOKEN;
3367 case XML_TOK_PARTIAL_CHAR:
3370 return XML_ERROR_NONE;
3372 return XML_ERROR_PARTIAL_CHAR;
3373 case XML_TOK_PARTIAL:
3377 return XML_ERROR_NONE;
3379 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3382 return XML_ERROR_UNEXPECTED_STATE;
3387 #endif /* XML_DTD */
3389 static enum XML_Error
3390 initializeEncoding(XML_Parser parser)
3394 char encodingBuf[128];
3395 if (!protocolEncodingName)
3399 for (i = 0; protocolEncodingName[i]; i++) {
3400 if (i == sizeof(encodingBuf) - 1
3401 || (protocolEncodingName[i] & ~0x7f) != 0) {
3402 encodingBuf[0] = '\0';
3405 encodingBuf[i] = (char)protocolEncodingName[i];
3407 encodingBuf[i] = '\0';
3411 s = protocolEncodingName;
3413 if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
3414 return XML_ERROR_NONE;
3415 return handleUnknownEncoding(parser, protocolEncodingName);
3418 static enum XML_Error
3419 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
3420 const char *s, const char *next)
3422 const char *encodingName = NULL;
3423 const XML_Char *storedEncName = NULL;
3424 const ENCODING *newEncoding = NULL;
3425 const char *version = NULL;
3426 const char *versionend;
3427 const XML_Char *storedversion = NULL;
3428 int standalone = -1;
3431 : XmlParseXmlDecl)(isGeneralTextEntity,
3441 if (isGeneralTextEntity)
3442 return XML_ERROR_TEXT_DECL;
3444 return XML_ERROR_XML_DECL;
3446 if (!isGeneralTextEntity && standalone == 1) {
3447 _dtd->standalone = XML_TRUE;
3449 if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
3450 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
3451 #endif /* XML_DTD */
3453 if (xmlDeclHandler) {
3454 if (encodingName != NULL) {
3455 storedEncName = poolStoreString(&temp2Pool,
3459 + XmlNameLength(encoding, encodingName));
3461 return XML_ERROR_NO_MEMORY;
3462 poolFinish(&temp2Pool);
3465 storedversion = poolStoreString(&temp2Pool,
3468 versionend - encoding->minBytesPerChar);
3470 return XML_ERROR_NO_MEMORY;
3472 xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
3474 else if (defaultHandler)
3475 reportDefault(parser, encoding, s, next);
3476 if (protocolEncodingName == NULL) {
3478 if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
3479 eventPtr = encodingName;
3480 return XML_ERROR_INCORRECT_ENCODING;
3482 encoding = newEncoding;
3484 else if (encodingName) {
3485 enum XML_Error result;
3486 if (!storedEncName) {
3487 storedEncName = poolStoreString(
3488 &temp2Pool, encoding, encodingName,
3489 encodingName + XmlNameLength(encoding, encodingName));
3491 return XML_ERROR_NO_MEMORY;
3493 result = handleUnknownEncoding(parser, storedEncName);
3494 poolClear(&temp2Pool);
3495 if (result == XML_ERROR_UNKNOWN_ENCODING)
3496 eventPtr = encodingName;
3501 if (storedEncName || storedversion)
3502 poolClear(&temp2Pool);
3504 return XML_ERROR_NONE;
3507 static enum XML_Error
3508 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
3510 if (unknownEncodingHandler) {
3513 for (i = 0; i < 256; i++)
3515 info.convert = NULL;
3517 info.release = NULL;
3518 if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
3521 unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
3522 if (!unknownEncodingMem) {
3524 info.release(info.data);
3525 return XML_ERROR_NO_MEMORY;
3528 ? XmlInitUnknownEncodingNS
3529 : XmlInitUnknownEncoding)(unknownEncodingMem,
3534 unknownEncodingData = info.data;
3535 unknownEncodingRelease = info.release;
3537 return XML_ERROR_NONE;
3540 if (info.release != NULL)
3541 info.release(info.data);
3543 return XML_ERROR_UNKNOWN_ENCODING;
3546 static enum XML_Error PTRCALL
3547 prologInitProcessor(XML_Parser parser,
3550 const char **nextPtr)
3552 enum XML_Error result = initializeEncoding(parser);
3553 if (result != XML_ERROR_NONE)
3555 processor = prologProcessor;
3556 return prologProcessor(parser, s, end, nextPtr);
3561 static enum XML_Error PTRCALL
3562 externalParEntInitProcessor(XML_Parser parser,
3565 const char **nextPtr)
3567 enum XML_Error result = initializeEncoding(parser);
3568 if (result != XML_ERROR_NONE)
3571 /* we know now that XML_Parse(Buffer) has been called,
3572 so we consider the external parameter entity read */
3573 _dtd->paramEntityRead = XML_TRUE;
3575 if (prologState.inEntityValue) {
3576 processor = entityValueInitProcessor;
3577 return entityValueInitProcessor(parser, s, end, nextPtr);
3580 processor = externalParEntProcessor;
3581 return externalParEntProcessor(parser, s, end, nextPtr);
3585 static enum XML_Error PTRCALL
3586 entityValueInitProcessor(XML_Parser parser,
3589 const char **nextPtr)
3592 const char *start = s;
3593 const char *next = start;
3597 tok = XmlPrologTok(encoding, start, end, &next);
3600 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3602 return XML_ERROR_NONE;
3605 case XML_TOK_INVALID:
3606 return XML_ERROR_INVALID_TOKEN;
3607 case XML_TOK_PARTIAL:
3608 return XML_ERROR_UNCLOSED_TOKEN;
3609 case XML_TOK_PARTIAL_CHAR:
3610 return XML_ERROR_PARTIAL_CHAR;
3611 case XML_TOK_NONE: /* start == end */
3615 /* found end of entity value - can store it now */
3616 return storeEntityValue(parser, encoding, s, end);
3618 else if (tok == XML_TOK_XML_DECL) {
3619 enum XML_Error result;
3620 result = processXmlDecl(parser, 0, start, next);
3621 if (result != XML_ERROR_NONE)
3623 switch (ps_parsing) {
3626 return XML_ERROR_NONE;
3628 return XML_ERROR_ABORTED;
3632 /* stop scanning for text declaration - we found one */
3633 processor = entityValueProcessor;
3634 return entityValueProcessor(parser, next, end, nextPtr);
3636 /* If we are at the end of the buffer, this would cause XmlPrologTok to
3637 return XML_TOK_NONE on the next call, which would then cause the
3638 function to exit with *nextPtr set to s - that is what we want for other
3639 tokens, but not for the BOM - we would rather like to skip it;
3640 then, when this routine is entered the next time, XmlPrologTok will
3641 return XML_TOK_INVALID, since the BOM is still in the buffer
3643 else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
3645 return XML_ERROR_NONE;
3652 static enum XML_Error PTRCALL
3653 externalParEntProcessor(XML_Parser parser,
3656 const char **nextPtr)
3658 const char *next = s;
3661 tok = XmlPrologTok(encoding, s, end, &next);
3663 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3665 return XML_ERROR_NONE;
3668 case XML_TOK_INVALID:
3669 return XML_ERROR_INVALID_TOKEN;
3670 case XML_TOK_PARTIAL:
3671 return XML_ERROR_UNCLOSED_TOKEN;
3672 case XML_TOK_PARTIAL_CHAR:
3673 return XML_ERROR_PARTIAL_CHAR;
3674 case XML_TOK_NONE: /* start == end */
3679 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
3680 However, when parsing an external subset, doProlog will not accept a BOM
3681 as valid, and report a syntax error, so we have to skip the BOM
3683 else if (tok == XML_TOK_BOM) {
3685 tok = XmlPrologTok(encoding, s, end, &next);
3688 processor = prologProcessor;
3689 return doProlog(parser, encoding, s, end, tok, next,
3690 nextPtr, (XML_Bool)!ps_finalBuffer);
3693 static enum XML_Error PTRCALL
3694 entityValueProcessor(XML_Parser parser,
3697 const char **nextPtr)
3699 const char *start = s;
3700 const char *next = s;
3701 const ENCODING *enc = encoding;
3705 tok = XmlPrologTok(enc, start, end, &next);
3707 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3709 return XML_ERROR_NONE;
3712 case XML_TOK_INVALID:
3713 return XML_ERROR_INVALID_TOKEN;
3714 case XML_TOK_PARTIAL:
3715 return XML_ERROR_UNCLOSED_TOKEN;
3716 case XML_TOK_PARTIAL_CHAR:
3717 return XML_ERROR_PARTIAL_CHAR;
3718 case XML_TOK_NONE: /* start == end */
3722 /* found end of entity value - can store it now */
3723 return storeEntityValue(parser, enc, s, end);
3729 #endif /* XML_DTD */
3731 static enum XML_Error PTRCALL
3732 prologProcessor(XML_Parser parser,
3735 const char **nextPtr)
3737 const char *next = s;
3738 int tok = XmlPrologTok(encoding, s, end, &next);
3739 return doProlog(parser, encoding, s, end, tok, next,
3740 nextPtr, (XML_Bool)!ps_finalBuffer);
3743 static enum XML_Error
3744 doProlog(XML_Parser parser,
3745 const ENCODING *enc,
3750 const char **nextPtr,
3754 static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
3755 #endif /* XML_DTD */
3756 static const XML_Char atypeCDATA[] =
3757 { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
3758 static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
3759 static const XML_Char atypeIDREF[] =
3760 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
3761 static const XML_Char atypeIDREFS[] =
3762 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
3763 static const XML_Char atypeENTITY[] =
3764 { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
3765 static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
3766 ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
3767 static const XML_Char atypeNMTOKEN[] = {
3768 ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
3769 static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
3770 ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
3771 static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
3772 ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
3773 static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
3774 static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
3776 /* save one level of indirection */
3777 DTD * const dtd = _dtd;
3779 const char **eventPP;
3780 const char **eventEndPP;
3781 enum XML_Content_Quant quant;
3783 if (enc == encoding) {
3784 eventPP = &eventPtr;
3785 eventEndPP = &eventEndPtr;
3788 eventPP = &(openInternalEntities->internalEventPtr);
3789 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3794 XML_Bool handleDefault = XML_TRUE;
3798 if (haveMore && tok != XML_TOK_INVALID) {
3800 return XML_ERROR_NONE;
3803 case XML_TOK_INVALID:
3805 return XML_ERROR_INVALID_TOKEN;
3806 case XML_TOK_PARTIAL:
3807 return XML_ERROR_UNCLOSED_TOKEN;
3808 case XML_TOK_PARTIAL_CHAR:
3809 return XML_ERROR_PARTIAL_CHAR;
3810 case -XML_TOK_PROLOG_S:
3815 /* for internal PE NOT referenced between declarations */
3816 if (enc != encoding && !openInternalEntities->betweenDecl) {
3818 return XML_ERROR_NONE;
3820 /* WFC: PE Between Declarations - must check that PE contains
3821 complete markup, not only for external PEs, but also for
3822 internal PEs if the reference occurs between declarations.
3824 if (isParamEntity || enc != encoding) {
3825 if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
3827 return XML_ERROR_INCOMPLETE_PE;
3829 return XML_ERROR_NONE;
3831 #endif /* XML_DTD */
3832 return XML_ERROR_NO_ELEMENTS;
3839 role = XmlTokenRole(&prologState, tok, s, next, enc);
3841 case XML_ROLE_XML_DECL:
3843 enum XML_Error result = processXmlDecl(parser, 0, s, next);
3844 if (result != XML_ERROR_NONE)
3847 handleDefault = XML_FALSE;
3850 case XML_ROLE_DOCTYPE_NAME:
3851 if (startDoctypeDeclHandler) {
3852 doctypeName = poolStoreString(&tempPool, enc, s, next);
3854 return XML_ERROR_NO_MEMORY;
3855 poolFinish(&tempPool);
3856 doctypePubid = NULL;
3857 handleDefault = XML_FALSE;
3859 doctypeSysid = NULL; /* always initialize to NULL */
3861 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
3862 if (startDoctypeDeclHandler) {
3863 startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
3866 poolClear(&tempPool);
3867 handleDefault = XML_FALSE;
3871 case XML_ROLE_TEXT_DECL:
3873 enum XML_Error result = processXmlDecl(parser, 1, s, next);
3874 if (result != XML_ERROR_NONE)
3877 handleDefault = XML_FALSE;
3880 #endif /* XML_DTD */
3881 case XML_ROLE_DOCTYPE_PUBLIC_ID:
3883 useForeignDTD = XML_FALSE;
3884 declEntity = (ENTITY *)lookup(parser,
3885 &dtd->paramEntities,
3889 return XML_ERROR_NO_MEMORY;
3890 #endif /* XML_DTD */
3891 dtd->hasParamEntityRefs = XML_TRUE;
3892 if (startDoctypeDeclHandler) {
3894 if (!XmlIsPublicId(enc, s, next, eventPP))
3895 return XML_ERROR_PUBLICID;
3896 pubId = poolStoreString(&tempPool, enc,
3897 s + enc->minBytesPerChar,
3898 next - enc->minBytesPerChar);
3900 return XML_ERROR_NO_MEMORY;
3901 normalizePublicId(pubId);
3902 poolFinish(&tempPool);
3903 doctypePubid = pubId;
3904 handleDefault = XML_FALSE;
3905 goto alreadyChecked;
3908 case XML_ROLE_ENTITY_PUBLIC_ID:
3909 if (!XmlIsPublicId(enc, s, next, eventPP))
3910 return XML_ERROR_PUBLICID;
3912 if (dtd->keepProcessing && declEntity) {
3913 XML_Char *tem = poolStoreString(&dtd->pool,
3915 s + enc->minBytesPerChar,
3916 next - enc->minBytesPerChar);
3918 return XML_ERROR_NO_MEMORY;
3919 normalizePublicId(tem);
3920 declEntity->publicId = tem;
3921 poolFinish(&dtd->pool);
3922 if (entityDeclHandler)
3923 handleDefault = XML_FALSE;
3926 case XML_ROLE_DOCTYPE_CLOSE:
3928 startDoctypeDeclHandler(handlerArg, doctypeName,
3929 doctypeSysid, doctypePubid, 0);
3930 poolClear(&tempPool);
3931 handleDefault = XML_FALSE;
3933 /* doctypeSysid will be non-NULL in the case of a previous
3934 XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
3935 was not set, indicating an external subset
3938 if (doctypeSysid || useForeignDTD) {
3939 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3940 dtd->hasParamEntityRefs = XML_TRUE;
3941 if (paramEntityParsing && externalEntityRefHandler) {
3942 ENTITY *entity = (ENTITY *)lookup(parser,
3943 &dtd->paramEntities,
3947 return XML_ERROR_NO_MEMORY;
3949 entity->base = curBase;
3950 dtd->paramEntityRead = XML_FALSE;
3951 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3956 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3957 if (dtd->paramEntityRead) {
3958 if (!dtd->standalone &&
3959 notStandaloneHandler &&
3960 !notStandaloneHandler(handlerArg))
3961 return XML_ERROR_NOT_STANDALONE;
3963 /* if we didn't read the foreign DTD then this means that there
3964 is no external subset and we must reset dtd->hasParamEntityRefs
3966 else if (!doctypeSysid)
3967 dtd->hasParamEntityRefs = hadParamEntityRefs;
3968 /* end of DTD - no need to update dtd->keepProcessing */
3970 useForeignDTD = XML_FALSE;
3972 #endif /* XML_DTD */
3973 if (endDoctypeDeclHandler) {
3974 endDoctypeDeclHandler(handlerArg);
3975 handleDefault = XML_FALSE;
3978 case XML_ROLE_INSTANCE_START:
3980 /* if there is no DOCTYPE declaration then now is the
3981 last chance to read the foreign DTD
3983 if (useForeignDTD) {
3984 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3985 dtd->hasParamEntityRefs = XML_TRUE;
3986 if (paramEntityParsing && externalEntityRefHandler) {
3987 ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
3991 return XML_ERROR_NO_MEMORY;
3992 entity->base = curBase;
3993 dtd->paramEntityRead = XML_FALSE;
3994 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3999 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4000 if (dtd->paramEntityRead) {
4001 if (!dtd->standalone &&
4002 notStandaloneHandler &&
4003 !notStandaloneHandler(handlerArg))
4004 return XML_ERROR_NOT_STANDALONE;
4006 /* if we didn't read the foreign DTD then this means that there
4007 is no external subset and we must reset dtd->hasParamEntityRefs
4010 dtd->hasParamEntityRefs = hadParamEntityRefs;
4011 /* end of DTD - no need to update dtd->keepProcessing */
4014 #endif /* XML_DTD */
4015 processor = contentProcessor;
4016 return contentProcessor(parser, s, end, nextPtr);
4017 case XML_ROLE_ATTLIST_ELEMENT_NAME:
4018 declElementType = getElementType(parser, enc, s, next);
4019 if (!declElementType)
4020 return XML_ERROR_NO_MEMORY;
4021 goto checkAttListDeclHandler;
4022 case XML_ROLE_ATTRIBUTE_NAME:
4023 declAttributeId = getAttributeId(parser, enc, s, next);
4024 if (!declAttributeId)
4025 return XML_ERROR_NO_MEMORY;
4026 declAttributeIsCdata = XML_FALSE;
4027 declAttributeType = NULL;
4028 declAttributeIsId = XML_FALSE;
4029 goto checkAttListDeclHandler;
4030 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
4031 declAttributeIsCdata = XML_TRUE;
4032 declAttributeType = atypeCDATA;
4033 goto checkAttListDeclHandler;
4034 case XML_ROLE_ATTRIBUTE_TYPE_ID:
4035 declAttributeIsId = XML_TRUE;
4036 declAttributeType = atypeID;
4037 goto checkAttListDeclHandler;
4038 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
4039 declAttributeType = atypeIDREF;
4040 goto checkAttListDeclHandler;
4041 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
4042 declAttributeType = atypeIDREFS;
4043 goto checkAttListDeclHandler;
4044 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
4045 declAttributeType = atypeENTITY;
4046 goto checkAttListDeclHandler;
4047 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
4048 declAttributeType = atypeENTITIES;
4049 goto checkAttListDeclHandler;
4050 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
4051 declAttributeType = atypeNMTOKEN;
4052 goto checkAttListDeclHandler;
4053 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
4054 declAttributeType = atypeNMTOKENS;
4055 checkAttListDeclHandler:
4056 if (dtd->keepProcessing && attlistDeclHandler)
4057 handleDefault = XML_FALSE;
4059 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
4060 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
4061 if (dtd->keepProcessing && attlistDeclHandler) {
4062 const XML_Char *prefix;
4063 if (declAttributeType) {
4064 prefix = enumValueSep;
4067 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
4071 if (!poolAppendString(&tempPool, prefix))
4072 return XML_ERROR_NO_MEMORY;
4073 if (!poolAppend(&tempPool, enc, s, next))
4074 return XML_ERROR_NO_MEMORY;
4075 declAttributeType = tempPool.start;
4076 handleDefault = XML_FALSE;
4079 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
4080 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
4081 if (dtd->keepProcessing) {
4082 if (!defineAttribute(declElementType, declAttributeId,
4083 declAttributeIsCdata, declAttributeIsId,
4085 return XML_ERROR_NO_MEMORY;
4086 if (attlistDeclHandler && declAttributeType) {
4087 if (*declAttributeType == XML_T(ASCII_LPAREN)
4088 || (*declAttributeType == XML_T(ASCII_N)
4089 && declAttributeType[1] == XML_T(ASCII_O))) {
4090 /* Enumerated or Notation type */
4091 if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4092 || !poolAppendChar(&tempPool, XML_T('\0')))
4093 return XML_ERROR_NO_MEMORY;
4094 declAttributeType = tempPool.start;
4095 poolFinish(&tempPool);
4098 attlistDeclHandler(handlerArg, declElementType->name,
4099 declAttributeId->name, declAttributeType,
4100 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
4101 poolClear(&tempPool);
4102 handleDefault = XML_FALSE;
4106 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
4107 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
4108 if (dtd->keepProcessing) {
4109 const XML_Char *attVal;
4110 enum XML_Error result =
4111 storeAttributeValue(parser, enc, declAttributeIsCdata,
4112 s + enc->minBytesPerChar,
4113 next - enc->minBytesPerChar,
4117 attVal = poolStart(&dtd->pool);
4118 poolFinish(&dtd->pool);
4119 /* ID attributes aren't allowed to have a default */
4120 if (!defineAttribute(declElementType, declAttributeId,
4121 declAttributeIsCdata, XML_FALSE, attVal, parser))
4122 return XML_ERROR_NO_MEMORY;
4123 if (attlistDeclHandler && declAttributeType) {
4124 if (*declAttributeType == XML_T(ASCII_LPAREN)
4125 || (*declAttributeType == XML_T(ASCII_N)
4126 && declAttributeType[1] == XML_T(ASCII_O))) {
4127 /* Enumerated or Notation type */
4128 if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4129 || !poolAppendChar(&tempPool, XML_T('\0')))
4130 return XML_ERROR_NO_MEMORY;
4131 declAttributeType = tempPool.start;
4132 poolFinish(&tempPool);
4135 attlistDeclHandler(handlerArg, declElementType->name,
4136 declAttributeId->name, declAttributeType,
4138 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
4139 poolClear(&tempPool);
4140 handleDefault = XML_FALSE;
4144 case XML_ROLE_ENTITY_VALUE:
4145 if (dtd->keepProcessing) {
4146 enum XML_Error result = storeEntityValue(parser, enc,
4147 s + enc->minBytesPerChar,
4148 next - enc->minBytesPerChar);
4150 declEntity->textPtr = poolStart(&dtd->entityValuePool);
4151 declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
4152 poolFinish(&dtd->entityValuePool);
4153 if (entityDeclHandler) {
4155 entityDeclHandler(handlerArg,
4157 declEntity->is_param,
4158 declEntity->textPtr,
4159 declEntity->textLen,
4161 handleDefault = XML_FALSE;
4165 poolDiscard(&dtd->entityValuePool);
4166 if (result != XML_ERROR_NONE)
4170 case XML_ROLE_DOCTYPE_SYSTEM_ID:
4172 useForeignDTD = XML_FALSE;
4173 #endif /* XML_DTD */
4174 dtd->hasParamEntityRefs = XML_TRUE;
4175 if (startDoctypeDeclHandler) {
4176 doctypeSysid = poolStoreString(&tempPool, enc,
4177 s + enc->minBytesPerChar,
4178 next - enc->minBytesPerChar);
4179 if (doctypeSysid == NULL)
4180 return XML_ERROR_NO_MEMORY;
4181 poolFinish(&tempPool);
4182 handleDefault = XML_FALSE;
4186 /* use externalSubsetName to make doctypeSysid non-NULL
4187 for the case where no startDoctypeDeclHandler is set */
4188 doctypeSysid = externalSubsetName;
4189 #endif /* XML_DTD */
4190 if (!dtd->standalone
4192 && !paramEntityParsing
4193 #endif /* XML_DTD */
4194 && notStandaloneHandler
4195 && !notStandaloneHandler(handlerArg))
4196 return XML_ERROR_NOT_STANDALONE;
4201 declEntity = (ENTITY *)lookup(parser,
4202 &dtd->paramEntities,
4206 return XML_ERROR_NO_MEMORY;
4207 declEntity->publicId = NULL;
4210 #endif /* XML_DTD */
4211 case XML_ROLE_ENTITY_SYSTEM_ID:
4212 if (dtd->keepProcessing && declEntity) {
4213 declEntity->systemId = poolStoreString(&dtd->pool, enc,
4214 s + enc->minBytesPerChar,
4215 next - enc->minBytesPerChar);
4216 if (!declEntity->systemId)
4217 return XML_ERROR_NO_MEMORY;
4218 declEntity->base = curBase;
4219 poolFinish(&dtd->pool);
4220 if (entityDeclHandler)
4221 handleDefault = XML_FALSE;
4224 case XML_ROLE_ENTITY_COMPLETE:
4225 if (dtd->keepProcessing && declEntity && entityDeclHandler) {
4227 entityDeclHandler(handlerArg,
4229 declEntity->is_param,
4232 declEntity->systemId,
4233 declEntity->publicId,
4235 handleDefault = XML_FALSE;
4238 case XML_ROLE_ENTITY_NOTATION_NAME:
4239 if (dtd->keepProcessing && declEntity) {
4240 declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
4241 if (!declEntity->notation)
4242 return XML_ERROR_NO_MEMORY;
4243 poolFinish(&dtd->pool);
4244 if (unparsedEntityDeclHandler) {
4246 unparsedEntityDeclHandler(handlerArg,
4249 declEntity->systemId,
4250 declEntity->publicId,
4251 declEntity->notation);
4252 handleDefault = XML_FALSE;
4254 else if (entityDeclHandler) {
4256 entityDeclHandler(handlerArg,
4260 declEntity->systemId,
4261 declEntity->publicId,
4262 declEntity->notation);
4263 handleDefault = XML_FALSE;
4267 case XML_ROLE_GENERAL_ENTITY_NAME:
4269 if (XmlPredefinedEntityName(enc, s, next)) {
4273 if (dtd->keepProcessing) {
4274 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4276 return XML_ERROR_NO_MEMORY;
4277 declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
4280 return XML_ERROR_NO_MEMORY;
4281 if (declEntity->name != name) {
4282 poolDiscard(&dtd->pool);
4286 poolFinish(&dtd->pool);
4287 declEntity->publicId = NULL;
4288 declEntity->is_param = XML_FALSE;
4289 /* if we have a parent parser or are reading an internal parameter
4290 entity, then the entity declaration is not considered "internal"
4292 declEntity->is_internal = !(parentParser || openInternalEntities);
4293 if (entityDeclHandler)
4294 handleDefault = XML_FALSE;
4298 poolDiscard(&dtd->pool);
4303 case XML_ROLE_PARAM_ENTITY_NAME:
4305 if (dtd->keepProcessing) {
4306 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4308 return XML_ERROR_NO_MEMORY;
4309 declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4310 name, sizeof(ENTITY));
4312 return XML_ERROR_NO_MEMORY;
4313 if (declEntity->name != name) {
4314 poolDiscard(&dtd->pool);
4318 poolFinish(&dtd->pool);
4319 declEntity->publicId = NULL;
4320 declEntity->is_param = XML_TRUE;
4321 /* if we have a parent parser or are reading an internal parameter
4322 entity, then the entity declaration is not considered "internal"
4324 declEntity->is_internal = !(parentParser || openInternalEntities);
4325 if (entityDeclHandler)
4326 handleDefault = XML_FALSE;
4330 poolDiscard(&dtd->pool);
4333 #else /* not XML_DTD */
4335 #endif /* XML_DTD */
4337 case XML_ROLE_NOTATION_NAME:
4338 declNotationPublicId = NULL;
4339 declNotationName = NULL;
4340 if (notationDeclHandler) {
4341 declNotationName = poolStoreString(&tempPool, enc, s, next);
4342 if (!declNotationName)
4343 return XML_ERROR_NO_MEMORY;
4344 poolFinish(&tempPool);
4345 handleDefault = XML_FALSE;
4348 case XML_ROLE_NOTATION_PUBLIC_ID:
4349 if (!XmlIsPublicId(enc, s, next, eventPP))
4350 return XML_ERROR_PUBLICID;
4351 if (declNotationName) { /* means notationDeclHandler != NULL */
4352 XML_Char *tem = poolStoreString(&tempPool,
4354 s + enc->minBytesPerChar,
4355 next - enc->minBytesPerChar);
4357 return XML_ERROR_NO_MEMORY;
4358 normalizePublicId(tem);
4359 declNotationPublicId = tem;
4360 poolFinish(&tempPool);
4361 handleDefault = XML_FALSE;
4364 case XML_ROLE_NOTATION_SYSTEM_ID:
4365 if (declNotationName && notationDeclHandler) {
4366 const XML_Char *systemId
4367 = poolStoreString(&tempPool, enc,
4368 s + enc->minBytesPerChar,
4369 next - enc->minBytesPerChar);
4371 return XML_ERROR_NO_MEMORY;
4373 notationDeclHandler(handlerArg,
4377 declNotationPublicId);
4378 handleDefault = XML_FALSE;
4380 poolClear(&tempPool);
4382 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
4383 if (declNotationPublicId && notationDeclHandler) {
4385 notationDeclHandler(handlerArg,
4389 declNotationPublicId);
4390 handleDefault = XML_FALSE;
4392 poolClear(&tempPool);
4394 case XML_ROLE_ERROR:
4396 case XML_TOK_PARAM_ENTITY_REF:
4397 /* PE references in internal subset are
4398 not allowed within declarations. */
4399 return XML_ERROR_PARAM_ENTITY_REF;
4400 case XML_TOK_XML_DECL:
4401 return XML_ERROR_MISPLACED_XML_PI;
4403 return XML_ERROR_SYNTAX;
4406 case XML_ROLE_IGNORE_SECT:
4408 enum XML_Error result;
4410 reportDefault(parser, enc, s, next);
4411 handleDefault = XML_FALSE;
4412 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
4413 if (result != XML_ERROR_NONE)
4416 processor = ignoreSectionProcessor;
4421 #endif /* XML_DTD */
4422 case XML_ROLE_GROUP_OPEN:
4423 if (prologState.level >= groupSize) {
4425 char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
4427 return XML_ERROR_NO_MEMORY;
4428 groupConnector = temp;
4429 if (dtd->scaffIndex) {
4430 int *temp = (int *)REALLOC(dtd->scaffIndex,
4431 groupSize * sizeof(int));
4433 return XML_ERROR_NO_MEMORY;
4434 dtd->scaffIndex = temp;
4438 groupConnector = (char *)MALLOC(groupSize = 32);
4439 if (!groupConnector)
4440 return XML_ERROR_NO_MEMORY;
4443 groupConnector[prologState.level] = 0;
4444 if (dtd->in_eldecl) {
4445 int myindex = nextScaffoldPart(parser);
4447 return XML_ERROR_NO_MEMORY;
4448 dtd->scaffIndex[dtd->scaffLevel] = myindex;
4450 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
4451 if (elementDeclHandler)
4452 handleDefault = XML_FALSE;
4455 case XML_ROLE_GROUP_SEQUENCE:
4456 if (groupConnector[prologState.level] == ASCII_PIPE)
4457 return XML_ERROR_SYNTAX;
4458 groupConnector[prologState.level] = ASCII_COMMA;
4459 if (dtd->in_eldecl && elementDeclHandler)
4460 handleDefault = XML_FALSE;
4462 case XML_ROLE_GROUP_CHOICE:
4463 if (groupConnector[prologState.level] == ASCII_COMMA)
4464 return XML_ERROR_SYNTAX;
4466 && !groupConnector[prologState.level]
4467 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4470 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4472 if (elementDeclHandler)
4473 handleDefault = XML_FALSE;
4475 groupConnector[prologState.level] = ASCII_PIPE;
4477 case XML_ROLE_PARAM_ENTITY_REF:
4479 case XML_ROLE_INNER_PARAM_ENTITY_REF:
4480 dtd->hasParamEntityRefs = XML_TRUE;
4481 if (!paramEntityParsing)
4482 dtd->keepProcessing = dtd->standalone;
4484 const XML_Char *name;
4486 name = poolStoreString(&dtd->pool, enc,
4487 s + enc->minBytesPerChar,
4488 next - enc->minBytesPerChar);
4490 return XML_ERROR_NO_MEMORY;
4491 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
4492 poolDiscard(&dtd->pool);
4493 /* first, determine if a check for an existing declaration is needed;
4494 if yes, check that the entity exists, and that it is internal,
4495 otherwise call the skipped entity handler
4497 if (prologState.documentEntity &&
4499 ? !openInternalEntities
4500 : !dtd->hasParamEntityRefs)) {
4502 return XML_ERROR_UNDEFINED_ENTITY;
4503 else if (!entity->is_internal)
4504 return XML_ERROR_ENTITY_DECLARED_IN_PE;
4507 dtd->keepProcessing = dtd->standalone;
4508 /* cannot report skipped entities in declarations */
4509 if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
4510 skippedEntityHandler(handlerArg, name, 1);
4511 handleDefault = XML_FALSE;
4516 return XML_ERROR_RECURSIVE_ENTITY_REF;
4517 if (entity->textPtr) {
4518 enum XML_Error result;
4519 XML_Bool betweenDecl =
4520 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
4521 result = processInternalEntity(parser, entity, betweenDecl);
4522 if (result != XML_ERROR_NONE)
4524 handleDefault = XML_FALSE;
4527 if (externalEntityRefHandler) {
4528 dtd->paramEntityRead = XML_FALSE;
4529 entity->open = XML_TRUE;
4530 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4534 entity->publicId)) {
4535 entity->open = XML_FALSE;
4536 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4538 entity->open = XML_FALSE;
4539 handleDefault = XML_FALSE;
4540 if (!dtd->paramEntityRead) {
4541 dtd->keepProcessing = dtd->standalone;
4546 dtd->keepProcessing = dtd->standalone;
4550 #endif /* XML_DTD */
4551 if (!dtd->standalone &&
4552 notStandaloneHandler &&
4553 !notStandaloneHandler(handlerArg))
4554 return XML_ERROR_NOT_STANDALONE;
4557 /* Element declaration stuff */
4559 case XML_ROLE_ELEMENT_NAME:
4560 if (elementDeclHandler) {
4561 declElementType = getElementType(parser, enc, s, next);
4562 if (!declElementType)
4563 return XML_ERROR_NO_MEMORY;
4564 dtd->scaffLevel = 0;
4565 dtd->scaffCount = 0;
4566 dtd->in_eldecl = XML_TRUE;
4567 handleDefault = XML_FALSE;
4571 case XML_ROLE_CONTENT_ANY:
4572 case XML_ROLE_CONTENT_EMPTY:
4573 if (dtd->in_eldecl) {
4574 if (elementDeclHandler) {
4575 XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
4577 return XML_ERROR_NO_MEMORY;
4578 content->quant = XML_CQUANT_NONE;
4579 content->name = NULL;
4580 content->numchildren = 0;
4581 content->children = NULL;
4582 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
4586 elementDeclHandler(handlerArg, declElementType->name, content);
4587 handleDefault = XML_FALSE;
4589 dtd->in_eldecl = XML_FALSE;
4593 case XML_ROLE_CONTENT_PCDATA:
4594 if (dtd->in_eldecl) {
4595 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4597 if (elementDeclHandler)
4598 handleDefault = XML_FALSE;
4602 case XML_ROLE_CONTENT_ELEMENT:
4603 quant = XML_CQUANT_NONE;
4604 goto elementContent;
4605 case XML_ROLE_CONTENT_ELEMENT_OPT:
4606 quant = XML_CQUANT_OPT;
4607 goto elementContent;
4608 case XML_ROLE_CONTENT_ELEMENT_REP:
4609 quant = XML_CQUANT_REP;
4610 goto elementContent;
4611 case XML_ROLE_CONTENT_ELEMENT_PLUS:
4612 quant = XML_CQUANT_PLUS;
4614 if (dtd->in_eldecl) {
4616 const XML_Char *name;
4618 const char *nxt = (quant == XML_CQUANT_NONE
4620 : next - enc->minBytesPerChar);
4621 int myindex = nextScaffoldPart(parser);
4623 return XML_ERROR_NO_MEMORY;
4624 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
4625 dtd->scaffold[myindex].quant = quant;
4626 el = getElementType(parser, enc, s, nxt);
4628 return XML_ERROR_NO_MEMORY;
4630 dtd->scaffold[myindex].name = name;
4632 for (; name[nameLen++]; );
4633 dtd->contentStringLen += nameLen;
4634 if (elementDeclHandler)
4635 handleDefault = XML_FALSE;
4639 case XML_ROLE_GROUP_CLOSE:
4640 quant = XML_CQUANT_NONE;
4642 case XML_ROLE_GROUP_CLOSE_OPT:
4643 quant = XML_CQUANT_OPT;
4645 case XML_ROLE_GROUP_CLOSE_REP:
4646 quant = XML_CQUANT_REP;
4648 case XML_ROLE_GROUP_CLOSE_PLUS:
4649 quant = XML_CQUANT_PLUS;
4651 if (dtd->in_eldecl) {
4652 if (elementDeclHandler)
4653 handleDefault = XML_FALSE;
4655 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
4656 if (dtd->scaffLevel == 0) {
4657 if (!handleDefault) {
4658 XML_Content *model = build_model(parser);
4660 return XML_ERROR_NO_MEMORY;
4662 elementDeclHandler(handlerArg, declElementType->name, model);
4664 dtd->in_eldecl = XML_FALSE;
4665 dtd->contentStringLen = 0;
4669 /* End element declaration stuff */
4672 if (!reportProcessingInstruction(parser, enc, s, next))
4673 return XML_ERROR_NO_MEMORY;
4674 handleDefault = XML_FALSE;
4676 case XML_ROLE_COMMENT:
4677 if (!reportComment(parser, enc, s, next))
4678 return XML_ERROR_NO_MEMORY;
4679 handleDefault = XML_FALSE;
4684 handleDefault = XML_FALSE;
4688 case XML_ROLE_DOCTYPE_NONE:
4689 if (startDoctypeDeclHandler)
4690 handleDefault = XML_FALSE;
4692 case XML_ROLE_ENTITY_NONE:
4693 if (dtd->keepProcessing && entityDeclHandler)
4694 handleDefault = XML_FALSE;
4696 case XML_ROLE_NOTATION_NONE:
4697 if (notationDeclHandler)
4698 handleDefault = XML_FALSE;
4700 case XML_ROLE_ATTLIST_NONE:
4701 if (dtd->keepProcessing && attlistDeclHandler)
4702 handleDefault = XML_FALSE;
4704 case XML_ROLE_ELEMENT_NONE:
4705 if (elementDeclHandler)
4706 handleDefault = XML_FALSE;
4708 } /* end of big switch */
4710 if (handleDefault && defaultHandler)
4711 reportDefault(parser, enc, s, next);
4713 switch (ps_parsing) {
4716 return XML_ERROR_NONE;
4718 return XML_ERROR_ABORTED;
4721 tok = XmlPrologTok(enc, s, end, &next);
4727 static enum XML_Error PTRCALL
4728 epilogProcessor(XML_Parser parser,
4731 const char **nextPtr)
4733 processor = epilogProcessor;
4736 const char *next = NULL;
4737 int tok = XmlPrologTok(encoding, s, end, &next);
4740 /* report partial linebreak - it might be the last token */
4741 case -XML_TOK_PROLOG_S:
4742 if (defaultHandler) {
4743 reportDefault(parser, encoding, s, next);
4744 if (ps_parsing == XML_FINISHED)
4745 return XML_ERROR_ABORTED;
4748 return XML_ERROR_NONE;
4751 return XML_ERROR_NONE;
4752 case XML_TOK_PROLOG_S:
4754 reportDefault(parser, encoding, s, next);
4757 if (!reportProcessingInstruction(parser, encoding, s, next))
4758 return XML_ERROR_NO_MEMORY;
4760 case XML_TOK_COMMENT:
4761 if (!reportComment(parser, encoding, s, next))
4762 return XML_ERROR_NO_MEMORY;
4764 case XML_TOK_INVALID:
4766 return XML_ERROR_INVALID_TOKEN;
4767 case XML_TOK_PARTIAL:
4768 if (!ps_finalBuffer) {
4770 return XML_ERROR_NONE;
4772 return XML_ERROR_UNCLOSED_TOKEN;
4773 case XML_TOK_PARTIAL_CHAR:
4774 if (!ps_finalBuffer) {
4776 return XML_ERROR_NONE;
4778 return XML_ERROR_PARTIAL_CHAR;
4780 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
4782 eventPtr = s = next;
4783 switch (ps_parsing) {
4786 return XML_ERROR_NONE;
4788 return XML_ERROR_ABORTED;
4794 static enum XML_Error
4795 processInternalEntity(XML_Parser parser, ENTITY *entity,
4796 XML_Bool betweenDecl)
4798 const char *textStart, *textEnd;
4800 enum XML_Error result;
4801 OPEN_INTERNAL_ENTITY *openEntity;
4803 if (freeInternalEntities) {
4804 openEntity = freeInternalEntities;
4805 freeInternalEntities = openEntity->next;
4808 openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
4810 return XML_ERROR_NO_MEMORY;
4812 entity->open = XML_TRUE;
4813 entity->processed = 0;
4814 openEntity->next = openInternalEntities;
4815 openInternalEntities = openEntity;
4816 openEntity->entity = entity;
4817 openEntity->startTagLevel = tagLevel;
4818 openEntity->betweenDecl = betweenDecl;
4819 openEntity->internalEventPtr = NULL;
4820 openEntity->internalEventEndPtr = NULL;
4821 textStart = (char *)entity->textPtr;
4822 textEnd = (char *)(entity->textPtr + entity->textLen);
4825 if (entity->is_param) {
4826 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4827 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4828 next, &next, XML_FALSE);
4831 #endif /* XML_DTD */
4832 result = doContent(parser, tagLevel, internalEncoding, textStart,
4833 textEnd, &next, XML_FALSE);
4835 if (result == XML_ERROR_NONE) {
4836 if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4837 entity->processed = (int)(next - textStart);
4838 processor = internalEntityProcessor;
4841 entity->open = XML_FALSE;
4842 openInternalEntities = openEntity->next;
4843 /* put openEntity back in list of free instances */
4844 openEntity->next = freeInternalEntities;
4845 freeInternalEntities = openEntity;
4851 static enum XML_Error PTRCALL
4852 internalEntityProcessor(XML_Parser parser,
4855 const char **nextPtr)
4858 const char *textStart, *textEnd;
4860 enum XML_Error result;
4861 OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
4863 return XML_ERROR_UNEXPECTED_STATE;
4865 entity = openEntity->entity;
4866 textStart = ((char *)entity->textPtr) + entity->processed;
4867 textEnd = (char *)(entity->textPtr + entity->textLen);
4870 if (entity->is_param) {
4871 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4872 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4873 next, &next, XML_FALSE);
4876 #endif /* XML_DTD */
4877 result = doContent(parser, openEntity->startTagLevel, internalEncoding,
4878 textStart, textEnd, &next, XML_FALSE);
4880 if (result != XML_ERROR_NONE)
4882 else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4883 entity->processed = (int)(next - (char *)entity->textPtr);
4887 entity->open = XML_FALSE;
4888 openInternalEntities = openEntity->next;
4889 /* put openEntity back in list of free instances */
4890 openEntity->next = freeInternalEntities;
4891 freeInternalEntities = openEntity;
4895 if (entity->is_param) {
4897 processor = prologProcessor;
4898 tok = XmlPrologTok(encoding, s, end, &next);
4899 return doProlog(parser, encoding, s, end, tok, next, nextPtr,
4900 (XML_Bool)!ps_finalBuffer);
4903 #endif /* XML_DTD */
4905 processor = contentProcessor;
4906 /* see externalEntityContentProcessor vs contentProcessor */
4907 return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
4908 nextPtr, (XML_Bool)!ps_finalBuffer);
4912 static enum XML_Error PTRCALL
4913 errorProcessor(XML_Parser parser,
4916 const char **nextPtr)
4921 static enum XML_Error
4922 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4923 const char *ptr, const char *end,
4926 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
4930 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
4932 if (!poolAppendChar(pool, XML_T('\0')))
4933 return XML_ERROR_NO_MEMORY;
4934 return XML_ERROR_NONE;
4937 static enum XML_Error
4938 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4939 const char *ptr, const char *end,
4942 DTD * const dtd = _dtd; /* save one level of indirection */
4945 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
4948 return XML_ERROR_NONE;
4949 case XML_TOK_INVALID:
4950 if (enc == encoding)
4952 return XML_ERROR_INVALID_TOKEN;
4953 case XML_TOK_PARTIAL:
4954 if (enc == encoding)
4956 return XML_ERROR_INVALID_TOKEN;
4957 case XML_TOK_CHAR_REF:
4959 XML_Char buf[XML_ENCODE_MAX];
4961 int n = XmlCharRefNumber(enc, ptr);
4963 if (enc == encoding)
4965 return XML_ERROR_BAD_CHAR_REF;
4968 && n == 0x20 /* space */
4969 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4971 n = XmlEncode(n, (ICHAR *)buf);
4973 if (enc == encoding)
4975 return XML_ERROR_BAD_CHAR_REF;
4977 for (i = 0; i < n; i++) {
4978 if (!poolAppendChar(pool, buf[i]))
4979 return XML_ERROR_NO_MEMORY;
4983 case XML_TOK_DATA_CHARS:
4984 if (!poolAppend(pool, enc, ptr, next))
4985 return XML_ERROR_NO_MEMORY;
4987 case XML_TOK_TRAILING_CR:
4988 next = ptr + enc->minBytesPerChar;
4990 case XML_TOK_ATTRIBUTE_VALUE_S:
4991 case XML_TOK_DATA_NEWLINE:
4992 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4994 if (!poolAppendChar(pool, 0x20))
4995 return XML_ERROR_NO_MEMORY;
4997 case XML_TOK_ENTITY_REF:
4999 const XML_Char *name;
5001 char checkEntityDecl;
5002 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
5003 ptr + enc->minBytesPerChar,
5004 next - enc->minBytesPerChar);
5006 if (!poolAppendChar(pool, ch))
5007 return XML_ERROR_NO_MEMORY;
5010 name = poolStoreString(&temp2Pool, enc,
5011 ptr + enc->minBytesPerChar,
5012 next - enc->minBytesPerChar);
5014 return XML_ERROR_NO_MEMORY;
5015 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
5016 poolDiscard(&temp2Pool);
5017 /* First, determine if a check for an existing declaration is needed;
5018 if yes, check that the entity exists, and that it is internal.
5020 if (pool == &dtd->pool) /* are we called from prolog? */
5023 prologState.documentEntity &&
5024 #endif /* XML_DTD */
5026 ? !openInternalEntities
5027 : !dtd->hasParamEntityRefs);
5028 else /* if (pool == &tempPool): we are called from content */
5029 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
5030 if (checkEntityDecl) {
5032 return XML_ERROR_UNDEFINED_ENTITY;
5033 else if (!entity->is_internal)
5034 return XML_ERROR_ENTITY_DECLARED_IN_PE;
5037 /* Cannot report skipped entity here - see comments on
5038 skippedEntityHandler.
5039 if (skippedEntityHandler)
5040 skippedEntityHandler(handlerArg, name, 0);
5042 /* Cannot call the default handler because this would be
5043 out of sync with the call to the startElementHandler.
5044 if ((pool == &tempPool) && defaultHandler)
5045 reportDefault(parser, enc, ptr, next);
5050 if (enc == encoding)
5052 return XML_ERROR_RECURSIVE_ENTITY_REF;
5054 if (entity->notation) {
5055 if (enc == encoding)
5057 return XML_ERROR_BINARY_ENTITY_REF;
5059 if (!entity->textPtr) {
5060 if (enc == encoding)
5062 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
5065 enum XML_Error result;
5066 const XML_Char *textEnd = entity->textPtr + entity->textLen;
5067 entity->open = XML_TRUE;
5068 result = appendAttributeValue(parser, internalEncoding, isCdata,
5069 (char *)entity->textPtr,
5070 (char *)textEnd, pool);
5071 entity->open = XML_FALSE;
5078 if (enc == encoding)
5080 return XML_ERROR_UNEXPECTED_STATE;
5087 static enum XML_Error
5088 storeEntityValue(XML_Parser parser,
5089 const ENCODING *enc,
5090 const char *entityTextPtr,
5091 const char *entityTextEnd)
5093 DTD * const dtd = _dtd; /* save one level of indirection */
5094 STRING_POOL *pool = &(dtd->entityValuePool);
5095 enum XML_Error result = XML_ERROR_NONE;
5097 int oldInEntityValue = prologState.inEntityValue;
5098 prologState.inEntityValue = 1;
5099 #endif /* XML_DTD */
5100 /* never return Null for the value argument in EntityDeclHandler,
5101 since this would indicate an external entity; therefore we
5102 have to make sure that entityValuePool.start is not null */
5103 if (!pool->blocks) {
5104 if (!poolGrow(pool))
5105 return XML_ERROR_NO_MEMORY;
5110 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
5112 case XML_TOK_PARAM_ENTITY_REF:
5114 if (isParamEntity || enc != encoding) {
5115 const XML_Char *name;
5117 name = poolStoreString(&tempPool, enc,
5118 entityTextPtr + enc->minBytesPerChar,
5119 next - enc->minBytesPerChar);
5121 result = XML_ERROR_NO_MEMORY;
5122 goto endEntityValue;
5124 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
5125 poolDiscard(&tempPool);
5127 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5128 /* cannot report skipped entity here - see comments on
5129 skippedEntityHandler
5130 if (skippedEntityHandler)
5131 skippedEntityHandler(handlerArg, name, 0);
5133 dtd->keepProcessing = dtd->standalone;
5134 goto endEntityValue;
5137 if (enc == encoding)
5138 eventPtr = entityTextPtr;
5139 result = XML_ERROR_RECURSIVE_ENTITY_REF;
5140 goto endEntityValue;
5142 if (entity->systemId) {
5143 if (externalEntityRefHandler) {
5144 dtd->paramEntityRead = XML_FALSE;
5145 entity->open = XML_TRUE;
5146 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
5150 entity->publicId)) {
5151 entity->open = XML_FALSE;
5152 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5153 goto endEntityValue;
5155 entity->open = XML_FALSE;
5156 if (!dtd->paramEntityRead)
5157 dtd->keepProcessing = dtd->standalone;
5160 dtd->keepProcessing = dtd->standalone;
5163 entity->open = XML_TRUE;
5164 result = storeEntityValue(parser,
5166 (char *)entity->textPtr,
5167 (char *)(entity->textPtr
5168 + entity->textLen));
5169 entity->open = XML_FALSE;
5171 goto endEntityValue;
5175 #endif /* XML_DTD */
5176 /* In the internal subset, PE references are not legal
5177 within markup declarations, e.g entity values in this case. */
5178 eventPtr = entityTextPtr;
5179 result = XML_ERROR_PARAM_ENTITY_REF;
5180 goto endEntityValue;
5182 result = XML_ERROR_NONE;
5183 goto endEntityValue;
5184 case XML_TOK_ENTITY_REF:
5185 case XML_TOK_DATA_CHARS:
5186 if (!poolAppend(pool, enc, entityTextPtr, next)) {
5187 result = XML_ERROR_NO_MEMORY;
5188 goto endEntityValue;
5191 case XML_TOK_TRAILING_CR:
5192 next = entityTextPtr + enc->minBytesPerChar;
5194 case XML_TOK_DATA_NEWLINE:
5195 if (pool->end == pool->ptr && !poolGrow(pool)) {
5196 result = XML_ERROR_NO_MEMORY;
5197 goto endEntityValue;
5199 *(pool->ptr)++ = 0xA;
5201 case XML_TOK_CHAR_REF:
5203 XML_Char buf[XML_ENCODE_MAX];
5205 int n = XmlCharRefNumber(enc, entityTextPtr);
5207 if (enc == encoding)
5208 eventPtr = entityTextPtr;
5209 result = XML_ERROR_BAD_CHAR_REF;
5210 goto endEntityValue;
5212 n = XmlEncode(n, (ICHAR *)buf);
5214 if (enc == encoding)
5215 eventPtr = entityTextPtr;
5216 result = XML_ERROR_BAD_CHAR_REF;
5217 goto endEntityValue;
5219 for (i = 0; i < n; i++) {
5220 if (pool->end == pool->ptr && !poolGrow(pool)) {
5221 result = XML_ERROR_NO_MEMORY;
5222 goto endEntityValue;
5224 *(pool->ptr)++ = buf[i];
5228 case XML_TOK_PARTIAL:
5229 if (enc == encoding)
5230 eventPtr = entityTextPtr;
5231 result = XML_ERROR_INVALID_TOKEN;
5232 goto endEntityValue;
5233 case XML_TOK_INVALID:
5234 if (enc == encoding)
5236 result = XML_ERROR_INVALID_TOKEN;
5237 goto endEntityValue;
5239 if (enc == encoding)
5240 eventPtr = entityTextPtr;
5241 result = XML_ERROR_UNEXPECTED_STATE;
5242 goto endEntityValue;
5244 entityTextPtr = next;
5248 prologState.inEntityValue = oldInEntityValue;
5249 #endif /* XML_DTD */
5253 static void FASTCALL
5254 normalizeLines(XML_Char *s)
5258 if (*s == XML_T('\0'))
5277 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5278 const char *start, const char *end)
5280 const XML_Char *target;
5283 if (!processingInstructionHandler) {
5285 reportDefault(parser, enc, start, end);
5288 start += enc->minBytesPerChar * 2;
5289 tem = start + XmlNameLength(enc, start);
5290 target = poolStoreString(&tempPool, enc, start, tem);
5293 poolFinish(&tempPool);
5294 data = poolStoreString(&tempPool, enc,
5296 end - enc->minBytesPerChar*2);
5299 normalizeLines(data);
5300 processingInstructionHandler(handlerArg, target, data);
5301 poolClear(&tempPool);
5306 reportComment(XML_Parser parser, const ENCODING *enc,
5307 const char *start, const char *end)
5310 if (!commentHandler) {
5312 reportDefault(parser, enc, start, end);
5315 data = poolStoreString(&tempPool,
5317 start + enc->minBytesPerChar * 4,
5318 end - enc->minBytesPerChar * 3);
5321 normalizeLines(data);
5322 commentHandler(handlerArg, data);
5323 poolClear(&tempPool);
5328 reportDefault(XML_Parser parser, const ENCODING *enc,
5329 const char *s, const char *end)
5331 if (MUST_CONVERT(enc, s)) {
5332 const char **eventPP;
5333 const char **eventEndPP;
5334 if (enc == encoding) {
5335 eventPP = &eventPtr;
5336 eventEndPP = &eventEndPtr;
5339 eventPP = &(openInternalEntities->internalEventPtr);
5340 eventEndPP = &(openInternalEntities->internalEventEndPtr);
5343 ICHAR *dataPtr = (ICHAR *)dataBuf;
5344 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
5346 defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
5351 defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
5356 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
5357 XML_Bool isId, const XML_Char *value, XML_Parser parser)
5359 DEFAULT_ATTRIBUTE *att;
5360 if (value || isId) {
5361 /* The handling of default attributes gets messed up if we have
5362 a default which duplicates a non-default. */
5364 for (i = 0; i < type->nDefaultAtts; i++)
5365 if (attId == type->defaultAtts[i].id)
5367 if (isId && !type->idAtt && !attId->xmlns)
5368 type->idAtt = attId;
5370 if (type->nDefaultAtts == type->allocDefaultAtts) {
5371 if (type->allocDefaultAtts == 0) {
5372 type->allocDefaultAtts = 8;
5373 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
5374 * sizeof(DEFAULT_ATTRIBUTE));
5375 if (!type->defaultAtts)
5379 DEFAULT_ATTRIBUTE *temp;
5380 int count = type->allocDefaultAtts * 2;
5381 temp = (DEFAULT_ATTRIBUTE *)
5382 REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
5385 type->allocDefaultAtts = count;
5386 type->defaultAtts = temp;
5389 att = type->defaultAtts + type->nDefaultAtts;
5392 att->isCdata = isCdata;
5394 attId->maybeTokenized = XML_TRUE;
5395 type->nDefaultAtts += 1;
5400 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
5402 DTD * const dtd = _dtd; /* save one level of indirection */
5403 const XML_Char *name;
5404 for (name = elementType->name; *name; name++) {
5405 if (*name == XML_T(ASCII_COLON)) {
5408 for (s = elementType->name; s != name; s++) {
5409 if (!poolAppendChar(&dtd->pool, *s))
5412 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5414 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
5418 if (prefix->name == poolStart(&dtd->pool))
5419 poolFinish(&dtd->pool);
5421 poolDiscard(&dtd->pool);
5422 elementType->prefix = prefix;
5429 static ATTRIBUTE_ID *
5430 getAttributeId(XML_Parser parser, const ENCODING *enc,
5431 const char *start, const char *end)
5433 DTD * const dtd = _dtd; /* save one level of indirection */
5435 const XML_Char *name;
5436 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5438 name = poolStoreString(&dtd->pool, enc, start, end);
5441 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
5443 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
5446 if (id->name != name)
5447 poolDiscard(&dtd->pool);
5449 poolFinish(&dtd->pool);
5452 else if (name[0] == XML_T(ASCII_x)
5453 && name[1] == XML_T(ASCII_m)
5454 && name[2] == XML_T(ASCII_l)
5455 && name[3] == XML_T(ASCII_n)
5456 && name[4] == XML_T(ASCII_s)
5457 && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
5458 if (name[5] == XML_T('\0'))
5459 id->prefix = &dtd->defaultPrefix;
5461 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
5462 id->xmlns = XML_TRUE;
5466 for (i = 0; name[i]; i++) {
5467 /* attributes without prefix are *not* in the default namespace */
5468 if (name[i] == XML_T(ASCII_COLON)) {
5470 for (j = 0; j < i; j++) {
5471 if (!poolAppendChar(&dtd->pool, name[j]))
5474 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5476 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
5478 if (id->prefix->name == poolStart(&dtd->pool))
5479 poolFinish(&dtd->pool);
5481 poolDiscard(&dtd->pool);
5490 #define CONTEXT_SEP XML_T(ASCII_FF)
5492 static const XML_Char *
5493 getContext(XML_Parser parser)
5495 DTD * const dtd = _dtd; /* save one level of indirection */
5496 HASH_TABLE_ITER iter;
5497 XML_Bool needSep = XML_FALSE;
5499 if (dtd->defaultPrefix.binding) {
5502 if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
5504 len = dtd->defaultPrefix.binding->uriLen;
5505 if (namespaceSeparator)
5507 for (i = 0; i < len; i++)
5508 if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
5513 hashTableIterInit(&iter, &(dtd->prefixes));
5518 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
5521 if (!prefix->binding)
5523 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5525 for (s = prefix->name; *s; s++)
5526 if (!poolAppendChar(&tempPool, *s))
5528 if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
5530 len = prefix->binding->uriLen;
5531 if (namespaceSeparator)
5533 for (i = 0; i < len; i++)
5534 if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
5540 hashTableIterInit(&iter, &(dtd->generalEntities));
5543 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
5548 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5550 for (s = e->name; *s; s++)
5551 if (!poolAppendChar(&tempPool, *s))
5556 if (!poolAppendChar(&tempPool, XML_T('\0')))
5558 return tempPool.start;
5562 setContext(XML_Parser parser, const XML_Char *context)
5564 DTD * const dtd = _dtd; /* save one level of indirection */
5565 const XML_Char *s = context;
5567 while (*context != XML_T('\0')) {
5568 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
5570 if (!poolAppendChar(&tempPool, XML_T('\0')))
5572 e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0);
5575 if (*s != XML_T('\0'))
5578 poolDiscard(&tempPool);
5580 else if (*s == XML_T(ASCII_EQUALS)) {
5582 if (poolLength(&tempPool) == 0)
5583 prefix = &dtd->defaultPrefix;
5585 if (!poolAppendChar(&tempPool, XML_T('\0')))
5587 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool),
5591 if (prefix->name == poolStart(&tempPool)) {
5592 prefix->name = poolCopyString(&dtd->pool, prefix->name);
5596 poolDiscard(&tempPool);
5598 for (context = s + 1;
5599 *context != CONTEXT_SEP && *context != XML_T('\0');
5601 if (!poolAppendChar(&tempPool, *context))
5603 if (!poolAppendChar(&tempPool, XML_T('\0')))
5605 if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
5606 &inheritedBindings) != XML_ERROR_NONE)
5608 poolDiscard(&tempPool);
5609 if (*context != XML_T('\0'))
5614 if (!poolAppendChar(&tempPool, *s))
5622 static void FASTCALL
5623 normalizePublicId(XML_Char *publicId)
5625 XML_Char *p = publicId;
5627 for (s = publicId; *s; s++) {
5632 if (p != publicId && p[-1] != 0x20)
5639 if (p != publicId && p[-1] == 0x20)
5645 dtdCreate(const XML_Memory_Handling_Suite *ms)
5647 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
5650 poolInit(&(p->pool), ms);
5651 poolInit(&(p->entityValuePool), ms);
5652 hashTableInit(&(p->generalEntities), ms);
5653 hashTableInit(&(p->elementTypes), ms);
5654 hashTableInit(&(p->attributeIds), ms);
5655 hashTableInit(&(p->prefixes), ms);
5657 p->paramEntityRead = XML_FALSE;
5658 hashTableInit(&(p->paramEntities), ms);
5659 #endif /* XML_DTD */
5660 p->defaultPrefix.name = NULL;
5661 p->defaultPrefix.binding = NULL;
5663 p->in_eldecl = XML_FALSE;
5664 p->scaffIndex = NULL;
5669 p->contentStringLen = 0;
5671 p->keepProcessing = XML_TRUE;
5672 p->hasParamEntityRefs = XML_FALSE;
5673 p->standalone = XML_FALSE;
5678 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
5680 HASH_TABLE_ITER iter;
5681 hashTableIterInit(&iter, &(p->elementTypes));
5683 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5686 if (e->allocDefaultAtts != 0)
5687 ms->free_fcn(e->defaultAtts);
5689 hashTableClear(&(p->generalEntities));
5691 p->paramEntityRead = XML_FALSE;
5692 hashTableClear(&(p->paramEntities));
5693 #endif /* XML_DTD */
5694 hashTableClear(&(p->elementTypes));
5695 hashTableClear(&(p->attributeIds));
5696 hashTableClear(&(p->prefixes));
5697 poolClear(&(p->pool));
5698 poolClear(&(p->entityValuePool));
5699 p->defaultPrefix.name = NULL;
5700 p->defaultPrefix.binding = NULL;
5702 p->in_eldecl = XML_FALSE;
5704 ms->free_fcn(p->scaffIndex);
5705 p->scaffIndex = NULL;
5706 ms->free_fcn(p->scaffold);
5712 p->contentStringLen = 0;
5714 p->keepProcessing = XML_TRUE;
5715 p->hasParamEntityRefs = XML_FALSE;
5716 p->standalone = XML_FALSE;
5720 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
5722 HASH_TABLE_ITER iter;
5723 hashTableIterInit(&iter, &(p->elementTypes));
5725 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5728 if (e->allocDefaultAtts != 0)
5729 ms->free_fcn(e->defaultAtts);
5731 hashTableDestroy(&(p->generalEntities));
5733 hashTableDestroy(&(p->paramEntities));
5734 #endif /* XML_DTD */
5735 hashTableDestroy(&(p->elementTypes));
5736 hashTableDestroy(&(p->attributeIds));
5737 hashTableDestroy(&(p->prefixes));
5738 poolDestroy(&(p->pool));
5739 poolDestroy(&(p->entityValuePool));
5741 ms->free_fcn(p->scaffIndex);
5742 ms->free_fcn(p->scaffold);
5747 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
5748 The new DTD has already been initialized.
5751 dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
5753 HASH_TABLE_ITER iter;
5755 /* Copy the prefix table. */
5757 hashTableIterInit(&iter, &(oldDtd->prefixes));
5759 const XML_Char *name;
5760 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
5763 name = poolCopyString(&(newDtd->pool), oldP->name);
5766 if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
5770 hashTableIterInit(&iter, &(oldDtd->attributeIds));
5772 /* Copy the attribute id table. */
5776 const XML_Char *name;
5777 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
5781 /* Remember to allocate the scratch byte before the name. */
5782 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
5784 name = poolCopyString(&(newDtd->pool), oldA->name);
5788 newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
5789 sizeof(ATTRIBUTE_ID));
5792 newA->maybeTokenized = oldA->maybeTokenized;
5794 newA->xmlns = oldA->xmlns;
5795 if (oldA->prefix == &oldDtd->defaultPrefix)
5796 newA->prefix = &newDtd->defaultPrefix;
5798 newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
5799 oldA->prefix->name, 0);
5803 /* Copy the element type table. */
5805 hashTableIterInit(&iter, &(oldDtd->elementTypes));
5810 const XML_Char *name;
5811 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5814 name = poolCopyString(&(newDtd->pool), oldE->name);
5817 newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
5818 sizeof(ELEMENT_TYPE));
5821 if (oldE->nDefaultAtts) {
5822 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
5823 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
5824 if (!newE->defaultAtts) {
5830 newE->idAtt = (ATTRIBUTE_ID *)
5831 lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
5832 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
5834 newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
5835 oldE->prefix->name, 0);
5836 for (i = 0; i < newE->nDefaultAtts; i++) {
5837 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
5838 lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
5839 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
5840 if (oldE->defaultAtts[i].value) {
5841 newE->defaultAtts[i].value
5842 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
5843 if (!newE->defaultAtts[i].value)
5847 newE->defaultAtts[i].value = NULL;
5851 /* Copy the entity tables. */
5852 if (!copyEntityTable(oldParser,
5853 &(newDtd->generalEntities),
5855 &(oldDtd->generalEntities)))
5859 if (!copyEntityTable(oldParser,
5860 &(newDtd->paramEntities),
5862 &(oldDtd->paramEntities)))
5864 newDtd->paramEntityRead = oldDtd->paramEntityRead;
5865 #endif /* XML_DTD */
5867 newDtd->keepProcessing = oldDtd->keepProcessing;
5868 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
5869 newDtd->standalone = oldDtd->standalone;
5871 /* Don't want deep copying for scaffolding */
5872 newDtd->in_eldecl = oldDtd->in_eldecl;
5873 newDtd->scaffold = oldDtd->scaffold;
5874 newDtd->contentStringLen = oldDtd->contentStringLen;
5875 newDtd->scaffSize = oldDtd->scaffSize;
5876 newDtd->scaffLevel = oldDtd->scaffLevel;
5877 newDtd->scaffIndex = oldDtd->scaffIndex;
5883 copyEntityTable(XML_Parser oldParser,
5884 HASH_TABLE *newTable,
5885 STRING_POOL *newPool,
5886 const HASH_TABLE *oldTable)
5888 HASH_TABLE_ITER iter;
5889 const XML_Char *cachedOldBase = NULL;
5890 const XML_Char *cachedNewBase = NULL;
5892 hashTableIterInit(&iter, oldTable);
5896 const XML_Char *name;
5897 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
5900 name = poolCopyString(newPool, oldE->name);
5903 newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
5906 if (oldE->systemId) {
5907 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
5910 newE->systemId = tem;
5912 if (oldE->base == cachedOldBase)
5913 newE->base = cachedNewBase;
5915 cachedOldBase = oldE->base;
5916 tem = poolCopyString(newPool, cachedOldBase);
5919 cachedNewBase = newE->base = tem;
5922 if (oldE->publicId) {
5923 tem = poolCopyString(newPool, oldE->publicId);
5926 newE->publicId = tem;
5930 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
5934 newE->textPtr = tem;
5935 newE->textLen = oldE->textLen;
5937 if (oldE->notation) {
5938 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
5941 newE->notation = tem;
5943 newE->is_param = oldE->is_param;
5944 newE->is_internal = oldE->is_internal;
5949 #define INIT_POWER 6
5951 static XML_Bool FASTCALL
5952 keyeq(KEY s1, KEY s2)
5954 for (; *s1 == *s2; s1++, s2++)
5960 static unsigned long FASTCALL
5961 hash(XML_Parser parser, KEY s)
5963 unsigned long h = hash_secret_salt;
5965 h = CHAR_HASH(h, *s++);
5970 lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
5973 if (table->size == 0) {
5977 table->power = INIT_POWER;
5978 /* table->size is a power of 2 */
5979 table->size = (size_t)1 << INIT_POWER;
5980 tsize = table->size * sizeof(NAMED *);
5981 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
5986 memset(table->v, 0, tsize);
5987 i = hash(parser, name) & ((unsigned long)table->size - 1);
5990 unsigned long h = hash(parser, name);
5991 unsigned long mask = (unsigned long)table->size - 1;
5992 unsigned char step = 0;
5994 while (table->v[i]) {
5995 if (keyeq(name, table->v[i]->name))
5998 step = PROBE_STEP(h, mask, table->power);
5999 i < step ? (i += table->size - step) : (i -= step);
6004 /* check for overflow (table is half full) */
6005 if (table->used >> (table->power - 1)) {
6006 unsigned char newPower = table->power + 1;
6007 size_t newSize = (size_t)1 << newPower;
6008 unsigned long newMask = (unsigned long)newSize - 1;
6009 size_t tsize = newSize * sizeof(NAMED *);
6010 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
6013 memset(newV, 0, tsize);
6014 for (i = 0; i < table->size; i++)
6016 unsigned long newHash = hash(parser, table->v[i]->name);
6017 size_t j = newHash & newMask;
6021 step = PROBE_STEP(newHash, newMask, newPower);
6022 j < step ? (j += newSize - step) : (j -= step);
6024 newV[j] = table->v[i];
6026 table->mem->free_fcn(table->v);
6028 table->power = newPower;
6029 table->size = newSize;
6032 while (table->v[i]) {
6034 step = PROBE_STEP(h, newMask, newPower);
6035 i < step ? (i += newSize - step) : (i -= step);
6039 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
6042 memset(table->v[i], 0, createSize);
6043 table->v[i]->name = name;
6048 static void FASTCALL
6049 hashTableClear(HASH_TABLE *table)
6052 for (i = 0; i < table->size; i++) {
6053 table->mem->free_fcn(table->v[i]);
6059 static void FASTCALL
6060 hashTableDestroy(HASH_TABLE *table)
6063 for (i = 0; i < table->size; i++)
6064 table->mem->free_fcn(table->v[i]);
6065 table->mem->free_fcn(table->v);
6068 static void FASTCALL
6069 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
6078 static void FASTCALL
6079 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
6082 iter->end = iter->p + table->size;
6085 static NAMED * FASTCALL
6086 hashTableIterNext(HASH_TABLE_ITER *iter)
6088 while (iter->p != iter->end) {
6089 NAMED *tem = *(iter->p)++;
6096 static void FASTCALL
6097 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
6099 pool->blocks = NULL;
6100 pool->freeBlocks = NULL;
6107 static void FASTCALL
6108 poolClear(STRING_POOL *pool)
6110 if (!pool->freeBlocks)
6111 pool->freeBlocks = pool->blocks;
6113 BLOCK *p = pool->blocks;
6115 BLOCK *tem = p->next;
6116 p->next = pool->freeBlocks;
6117 pool->freeBlocks = p;
6121 pool->blocks = NULL;
6127 static void FASTCALL
6128 poolDestroy(STRING_POOL *pool)
6130 BLOCK *p = pool->blocks;
6132 BLOCK *tem = p->next;
6133 pool->mem->free_fcn(p);
6136 p = pool->freeBlocks;
6138 BLOCK *tem = p->next;
6139 pool->mem->free_fcn(p);
6145 poolAppend(STRING_POOL *pool, const ENCODING *enc,
6146 const char *ptr, const char *end)
6148 if (!pool->ptr && !poolGrow(pool))
6151 XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6154 if (!poolGrow(pool))
6160 static const XML_Char * FASTCALL
6161 poolCopyString(STRING_POOL *pool, const XML_Char *s)
6164 if (!poolAppendChar(pool, *s))
6172 static const XML_Char *
6173 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
6175 if (!pool->ptr && !poolGrow(pool))
6177 for (; n > 0; --n, s++) {
6178 if (!poolAppendChar(pool, *s))
6186 static const XML_Char * FASTCALL
6187 poolAppendString(STRING_POOL *pool, const XML_Char *s)
6190 if (!poolAppendChar(pool, *s))
6198 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
6199 const char *ptr, const char *end)
6201 if (!poolAppend(pool, enc, ptr, end))
6203 if (pool->ptr == pool->end && !poolGrow(pool))
6209 static XML_Bool FASTCALL
6210 poolGrow(STRING_POOL *pool)
6212 if (pool->freeBlocks) {
6213 if (pool->start == 0) {
6214 pool->blocks = pool->freeBlocks;
6215 pool->freeBlocks = pool->freeBlocks->next;
6216 pool->blocks->next = NULL;
6217 pool->start = pool->blocks->s;
6218 pool->end = pool->start + pool->blocks->size;
6219 pool->ptr = pool->start;
6222 if (pool->end - pool->start < pool->freeBlocks->size) {
6223 BLOCK *tem = pool->freeBlocks->next;
6224 pool->freeBlocks->next = pool->blocks;
6225 pool->blocks = pool->freeBlocks;
6226 pool->freeBlocks = tem;
6227 memcpy(pool->blocks->s, pool->start,
6228 (pool->end - pool->start) * sizeof(XML_Char));
6229 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6230 pool->start = pool->blocks->s;
6231 pool->end = pool->start + pool->blocks->size;
6235 if (pool->blocks && pool->start == pool->blocks->s) {
6236 int blockSize = (int)(pool->end - pool->start)*2;
6237 BLOCK *temp = (BLOCK *)
6238 pool->mem->realloc_fcn(pool->blocks,
6240 + blockSize * sizeof(XML_Char)));
6243 pool->blocks = temp;
6244 pool->blocks->size = blockSize;
6245 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6246 pool->start = pool->blocks->s;
6247 pool->end = pool->start + blockSize;
6251 int blockSize = (int)(pool->end - pool->start);
6252 if (blockSize < INIT_BLOCK_SIZE)
6253 blockSize = INIT_BLOCK_SIZE;
6256 tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
6257 + blockSize * sizeof(XML_Char));
6260 tem->size = blockSize;
6261 tem->next = pool->blocks;
6263 if (pool->ptr != pool->start)
6264 memcpy(tem->s, pool->start,
6265 (pool->ptr - pool->start) * sizeof(XML_Char));
6266 pool->ptr = tem->s + (pool->ptr - pool->start);
6267 pool->start = tem->s;
6268 pool->end = tem->s + blockSize;
6274 nextScaffoldPart(XML_Parser parser)
6276 DTD * const dtd = _dtd; /* save one level of indirection */
6277 CONTENT_SCAFFOLD * me;
6280 if (!dtd->scaffIndex) {
6281 dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
6282 if (!dtd->scaffIndex)
6284 dtd->scaffIndex[0] = 0;
6287 if (dtd->scaffCount >= dtd->scaffSize) {
6288 CONTENT_SCAFFOLD *temp;
6289 if (dtd->scaffold) {
6290 temp = (CONTENT_SCAFFOLD *)
6291 REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
6294 dtd->scaffSize *= 2;
6297 temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
6298 * sizeof(CONTENT_SCAFFOLD));
6301 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
6303 dtd->scaffold = temp;
6305 next = dtd->scaffCount++;
6306 me = &dtd->scaffold[next];
6307 if (dtd->scaffLevel) {
6308 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
6309 if (parent->lastchild) {
6310 dtd->scaffold[parent->lastchild].nextsib = next;
6312 if (!parent->childcnt)
6313 parent->firstchild = next;
6314 parent->lastchild = next;
6317 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
6322 build_node(XML_Parser parser,
6325 XML_Content **contpos,
6328 DTD * const dtd = _dtd; /* save one level of indirection */
6329 dest->type = dtd->scaffold[src_node].type;
6330 dest->quant = dtd->scaffold[src_node].quant;
6331 if (dest->type == XML_CTYPE_NAME) {
6332 const XML_Char *src;
6333 dest->name = *strpos;
6334 src = dtd->scaffold[src_node].name;
6336 *(*strpos)++ = *src;
6341 dest->numchildren = 0;
6342 dest->children = NULL;
6347 dest->numchildren = dtd->scaffold[src_node].childcnt;
6348 dest->children = *contpos;
6349 *contpos += dest->numchildren;
6350 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
6351 i < dest->numchildren;
6352 i++, cn = dtd->scaffold[cn].nextsib) {
6353 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
6359 static XML_Content *
6360 build_model (XML_Parser parser)
6362 DTD * const dtd = _dtd; /* save one level of indirection */
6366 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
6367 + (dtd->contentStringLen * sizeof(XML_Char)));
6369 ret = (XML_Content *)MALLOC(allocsize);
6373 str = (XML_Char *) (&ret[dtd->scaffCount]);
6376 build_node(parser, 0, ret, &cpos, &str);
6380 static ELEMENT_TYPE *
6381 getElementType(XML_Parser parser,
6382 const ENCODING *enc,
6386 DTD * const dtd = _dtd; /* save one level of indirection */
6387 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
6392 ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
6395 if (ret->name != name)
6396 poolDiscard(&dtd->pool);
6398 poolFinish(&dtd->pool);
6399 if (!setElementTypePrefix(parser, ret))