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 */
11 #define getpid GetCurrentProcessId
13 #include <sys/time.h> /* gettimeofday() */
14 #include <sys/types.h> /* getpid() */
15 #include <unistd.h> /* getpid() */
18 #define XML_BUILDING_EXPAT 1
21 #include "winconfig.h"
22 #elif defined(MACOS_CLASSIC)
23 #include "macconfig.h"
24 #elif defined(__amigaos__)
25 #include "amigaconfig.h"
26 #elif defined(__WATCOMC__)
27 #include "watcomconfig.h"
28 #elif defined(HAVE_EXPAT_CONFIG_H)
29 #include <expat_config.h>
30 #endif /* ndef WIN32 */
36 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
37 #define XmlConvert XmlUtf16Convert
38 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
39 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
40 #define XmlEncode XmlUtf16Encode
41 /* Using pointer subtraction to convert to integer type. */
42 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
43 typedef unsigned short ICHAR;
45 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
46 #define XmlConvert XmlUtf8Convert
47 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
48 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
49 #define XmlEncode XmlUtf8Encode
50 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
57 #define XmlInitEncodingNS XmlInitEncoding
58 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
59 #undef XmlGetInternalEncodingNS
60 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
61 #define XmlParseXmlDeclNS XmlParseXmlDecl
67 #ifdef XML_UNICODE_WCHAR_T
68 #define XML_T(x) (const wchar_t)x
69 #define XML_L(x) L ## x
71 #define XML_T(x) (const unsigned short)x
82 /* Round up n to be a multiple of sz, where sz is a power of 2. */
83 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
85 /* Handle the case where memmove() doesn't exist. */
88 #define memmove(d,s,l) bcopy((s),(d),(l))
90 #error memmove does not exist on this platform, nor is a substitute available
91 #endif /* HAVE_BCOPY */
92 #endif /* HAVE_MEMMOVE */
98 typedef const XML_Char *KEY;
109 const XML_Memory_Handling_Suite *mem;
112 /* Basic character hash algorithm, taken from Python's string hash:
113 h = h * 1000003 ^ character, the constant being a prime number.
117 #define CHAR_HASH(h, c) \
118 (((h) * 0xF4243) ^ (unsigned short)(c))
120 #define CHAR_HASH(h, c) \
121 (((h) * 0xF4243) ^ (unsigned char)(c))
124 /* For probing (after a collision) we need a step size relative prime
125 to the hash table size, which is a power of 2. We use double-hashing,
126 since we can calculate a second hash value cheaply by taking those bits
127 of the first hash value that were discarded (masked out) when the table
128 index was calculated: index = hash & mask, where mask = table->size - 1.
129 We limit the maximum step size to table->size / 4 (mask >> 2) and make
130 it odd, since odd numbers are always relative prime to a power of 2.
132 #define SECOND_HASH(hash, mask, power) \
133 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
134 #define PROBE_STEP(hash, mask, power) \
135 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
142 #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
143 #define INIT_DATA_BUF_SIZE 1024
144 #define INIT_ATTS_SIZE 16
145 #define INIT_ATTS_VERSION 0xFFFFFFFF
146 #define INIT_BLOCK_SIZE 1024
147 #define INIT_BUFFER_SIZE 1024
149 #define EXPAND_SPARE 24
151 typedef struct binding {
152 struct prefix *prefix;
153 struct binding *nextTagBinding;
154 struct binding *prevPrefixBinding;
155 const struct attribute_id *attId;
161 typedef struct prefix {
162 const XML_Char *name;
168 const XML_Char *localPart;
169 const XML_Char *prefix;
175 /* TAG represents an open element.
176 The name of the element is stored in both the document and API
177 encodings. The memory buffer 'buf' is a separately-allocated
178 memory area which stores the name. During the XML_Parse()/
179 XMLParseBuffer() when the element is open, the memory for the 'raw'
180 version of the name (in the document encoding) is shared with the
181 document buffer. If the element is open across calls to
182 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
183 contain the 'raw' name as well.
185 A parser re-uses these structures, maintaining a list of allocated
186 TAG objects in a free list.
189 struct tag *parent; /* parent of this element */
190 const char *rawName; /* tagName in the original encoding */
192 TAG_NAME name; /* tagName in the API encoding */
193 char *buf; /* buffer for name components */
194 char *bufEnd; /* end of the buffer */
199 const XML_Char *name;
200 const XML_Char *textPtr;
201 int textLen; /* length in XML_Chars */
202 int processed; /* # of processed bytes - when suspended */
203 const XML_Char *systemId;
204 const XML_Char *base;
205 const XML_Char *publicId;
206 const XML_Char *notation;
209 XML_Bool is_internal; /* true if declared in internal subset outside PE */
213 enum XML_Content_Type type;
214 enum XML_Content_Quant quant;
215 const XML_Char * name;
222 #define INIT_SCAFFOLD_ELEMENTS 32
224 typedef struct block {
236 const XML_Memory_Handling_Suite *mem;
239 /* The XML_Char before the name is used to determine whether
240 an attribute has been specified. */
241 typedef struct attribute_id {
244 XML_Bool maybeTokenized;
249 const ATTRIBUTE_ID *id;
251 const XML_Char *value;
255 unsigned long version;
257 const XML_Char *uriName;
261 const XML_Char *name;
263 const ATTRIBUTE_ID *idAtt;
265 int allocDefaultAtts;
266 DEFAULT_ATTRIBUTE *defaultAtts;
270 HASH_TABLE generalEntities;
271 HASH_TABLE elementTypes;
272 HASH_TABLE attributeIds;
275 STRING_POOL entityValuePool;
276 /* false once a parameter entity reference has been skipped */
277 XML_Bool keepProcessing;
278 /* true once an internal or external PE reference has been encountered;
279 this includes the reference to an external subset */
280 XML_Bool hasParamEntityRefs;
283 /* indicates if external PE has been read */
284 XML_Bool paramEntityRead;
285 HASH_TABLE paramEntities;
287 PREFIX defaultPrefix;
288 /* === scaffolding for building content model === */
290 CONTENT_SCAFFOLD *scaffold;
291 unsigned contentStringLen;
298 typedef struct open_internal_entity {
299 const char *internalEventPtr;
300 const char *internalEventEndPtr;
301 struct open_internal_entity *next;
304 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
305 } OPEN_INTERNAL_ENTITY;
307 typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
310 const char **endPtr);
312 static Processor prologProcessor;
313 static Processor prologInitProcessor;
314 static Processor contentProcessor;
315 static Processor cdataSectionProcessor;
317 static Processor ignoreSectionProcessor;
318 static Processor externalParEntProcessor;
319 static Processor externalParEntInitProcessor;
320 static Processor entityValueProcessor;
321 static Processor entityValueInitProcessor;
323 static Processor epilogProcessor;
324 static Processor errorProcessor;
325 static Processor externalEntityInitProcessor;
326 static Processor externalEntityInitProcessor2;
327 static Processor externalEntityInitProcessor3;
328 static Processor externalEntityContentProcessor;
329 static Processor internalEntityProcessor;
331 static enum XML_Error
332 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
333 static enum XML_Error
334 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
335 const char *s, const char *next);
336 static enum XML_Error
337 initializeEncoding(XML_Parser parser);
338 static enum XML_Error
339 doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
340 const char *end, int tok, const char *next, const char **nextPtr,
342 static enum XML_Error
343 processInternalEntity(XML_Parser parser, ENTITY *entity,
344 XML_Bool betweenDecl);
345 static enum XML_Error
346 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
347 const char *start, const char *end, const char **endPtr,
349 static enum XML_Error
350 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
351 const char *end, const char **nextPtr, XML_Bool haveMore);
353 static enum XML_Error
354 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
355 const char *end, const char **nextPtr, XML_Bool haveMore);
358 static enum XML_Error
359 storeAtts(XML_Parser parser, const ENCODING *, const char *s,
360 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
361 static enum XML_Error
362 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
363 const XML_Char *uri, BINDING **bindingsPtr);
365 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
366 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
367 static enum XML_Error
368 storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
369 const char *, const char *, STRING_POOL *);
370 static enum XML_Error
371 appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
372 const char *, const char *, STRING_POOL *);
373 static ATTRIBUTE_ID *
374 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
377 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
378 static enum XML_Error
379 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
382 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
383 const char *start, const char *end);
385 reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
388 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
391 static const XML_Char * getContext(XML_Parser parser);
393 setContext(XML_Parser parser, const XML_Char *context);
395 static void FASTCALL normalizePublicId(XML_Char *s);
397 static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
398 /* do not call if parentParser != NULL */
399 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
401 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
403 dtdCopy(XML_Parser oldParser,
404 DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
406 copyEntityTable(XML_Parser oldParser,
407 HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
409 lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
411 hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
412 static void FASTCALL hashTableClear(HASH_TABLE *);
413 static void FASTCALL hashTableDestroy(HASH_TABLE *);
415 hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
416 static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
419 poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
420 static void FASTCALL poolClear(STRING_POOL *);
421 static void FASTCALL poolDestroy(STRING_POOL *);
423 poolAppend(STRING_POOL *pool, const ENCODING *enc,
424 const char *ptr, const char *end);
426 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
427 const char *ptr, const char *end);
428 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
429 static const XML_Char * FASTCALL
430 poolCopyString(STRING_POOL *pool, const XML_Char *s);
431 static const XML_Char *
432 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
433 static const XML_Char * FASTCALL
434 poolAppendString(STRING_POOL *pool, const XML_Char *s);
436 static int FASTCALL nextScaffoldPart(XML_Parser parser);
437 static XML_Content * build_model(XML_Parser parser);
438 static ELEMENT_TYPE *
439 getElementType(XML_Parser parser, const ENCODING *enc,
440 const char *ptr, const char *end);
442 static unsigned long generate_hash_secret_salt(XML_Parser parser);
443 static XML_Bool startParsing(XML_Parser parser);
446 parserCreate(const XML_Char *encodingName,
447 const XML_Memory_Handling_Suite *memsuite,
448 const XML_Char *nameSep,
452 parserInit(XML_Parser parser, const XML_Char *encodingName);
454 #define poolStart(pool) ((pool)->start)
455 #define poolEnd(pool) ((pool)->ptr)
456 #define poolLength(pool) ((pool)->ptr - (pool)->start)
457 #define poolChop(pool) ((void)--(pool->ptr))
458 #define poolLastChar(pool) (((pool)->ptr)[-1])
459 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
460 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
461 #define poolAppendChar(pool, c) \
462 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
464 : ((*((pool)->ptr)++ = c), 1))
466 struct XML_ParserStruct {
467 /* The first member must be userData so that the XML_GetUserData
472 const XML_Memory_Handling_Suite m_mem;
473 /* first character to be parsed */
474 const char *m_bufferPtr;
475 /* past last character to be parsed */
477 /* allocated end of buffer */
478 const char *m_bufferLim;
479 XML_Index m_parseEndByteIndex;
480 const char *m_parseEndPtr;
482 XML_Char *m_dataBufEnd;
483 XML_StartElementHandler m_startElementHandler;
484 XML_EndElementHandler m_endElementHandler;
485 XML_CharacterDataHandler m_characterDataHandler;
486 XML_ProcessingInstructionHandler m_processingInstructionHandler;
487 XML_CommentHandler m_commentHandler;
488 XML_StartCdataSectionHandler m_startCdataSectionHandler;
489 XML_EndCdataSectionHandler m_endCdataSectionHandler;
490 XML_DefaultHandler m_defaultHandler;
491 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
492 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
493 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
494 XML_NotationDeclHandler m_notationDeclHandler;
495 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
496 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
497 XML_NotStandaloneHandler m_notStandaloneHandler;
498 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
499 XML_Parser m_externalEntityRefHandlerArg;
500 XML_SkippedEntityHandler m_skippedEntityHandler;
501 XML_UnknownEncodingHandler m_unknownEncodingHandler;
502 XML_ElementDeclHandler m_elementDeclHandler;
503 XML_AttlistDeclHandler m_attlistDeclHandler;
504 XML_EntityDeclHandler m_entityDeclHandler;
505 XML_XmlDeclHandler m_xmlDeclHandler;
506 const ENCODING *m_encoding;
507 INIT_ENCODING m_initEncoding;
508 const ENCODING *m_internalEncoding;
509 const XML_Char *m_protocolEncodingName;
511 XML_Bool m_ns_triplets;
512 void *m_unknownEncodingMem;
513 void *m_unknownEncodingData;
514 void *m_unknownEncodingHandlerData;
515 void (XMLCALL *m_unknownEncodingRelease)(void *);
516 PROLOG_STATE m_prologState;
517 Processor *m_processor;
518 enum XML_Error m_errorCode;
519 const char *m_eventPtr;
520 const char *m_eventEndPtr;
521 const char *m_positionPtr;
522 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
523 OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
524 XML_Bool m_defaultExpandInternalEntities;
526 ENTITY *m_declEntity;
527 const XML_Char *m_doctypeName;
528 const XML_Char *m_doctypeSysid;
529 const XML_Char *m_doctypePubid;
530 const XML_Char *m_declAttributeType;
531 const XML_Char *m_declNotationName;
532 const XML_Char *m_declNotationPublicId;
533 ELEMENT_TYPE *m_declElementType;
534 ATTRIBUTE_ID *m_declAttributeId;
535 XML_Bool m_declAttributeIsCdata;
536 XML_Bool m_declAttributeIsId;
538 const XML_Char *m_curBase;
541 BINDING *m_inheritedBindings;
542 BINDING *m_freeBindingList;
544 int m_nSpecifiedAtts;
548 unsigned long m_nsAttsVersion;
549 unsigned char m_nsAttsPower;
551 XML_AttrInfo *m_attInfo;
554 STRING_POOL m_tempPool;
555 STRING_POOL m_temp2Pool;
556 char *m_groupConnector;
557 unsigned int m_groupSize;
558 XML_Char m_namespaceSeparator;
559 XML_Parser m_parentParser;
560 XML_ParsingStatus m_parsingStatus;
562 XML_Bool m_isParamEntity;
563 XML_Bool m_useForeignDTD;
564 enum XML_ParamEntityParsing m_paramEntityParsing;
566 unsigned long m_hash_secret_salt;
569 #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
570 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
571 #define FREE(p) (parser->m_mem.free_fcn((p)))
573 #define userData (parser->m_userData)
574 #define handlerArg (parser->m_handlerArg)
575 #define startElementHandler (parser->m_startElementHandler)
576 #define endElementHandler (parser->m_endElementHandler)
577 #define characterDataHandler (parser->m_characterDataHandler)
578 #define processingInstructionHandler \
579 (parser->m_processingInstructionHandler)
580 #define commentHandler (parser->m_commentHandler)
581 #define startCdataSectionHandler \
582 (parser->m_startCdataSectionHandler)
583 #define endCdataSectionHandler (parser->m_endCdataSectionHandler)
584 #define defaultHandler (parser->m_defaultHandler)
585 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
586 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
587 #define unparsedEntityDeclHandler \
588 (parser->m_unparsedEntityDeclHandler)
589 #define notationDeclHandler (parser->m_notationDeclHandler)
590 #define startNamespaceDeclHandler \
591 (parser->m_startNamespaceDeclHandler)
592 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
593 #define notStandaloneHandler (parser->m_notStandaloneHandler)
594 #define externalEntityRefHandler \
595 (parser->m_externalEntityRefHandler)
596 #define externalEntityRefHandlerArg \
597 (parser->m_externalEntityRefHandlerArg)
598 #define internalEntityRefHandler \
599 (parser->m_internalEntityRefHandler)
600 #define skippedEntityHandler (parser->m_skippedEntityHandler)
601 #define unknownEncodingHandler (parser->m_unknownEncodingHandler)
602 #define elementDeclHandler (parser->m_elementDeclHandler)
603 #define attlistDeclHandler (parser->m_attlistDeclHandler)
604 #define entityDeclHandler (parser->m_entityDeclHandler)
605 #define xmlDeclHandler (parser->m_xmlDeclHandler)
606 #define encoding (parser->m_encoding)
607 #define initEncoding (parser->m_initEncoding)
608 #define internalEncoding (parser->m_internalEncoding)
609 #define unknownEncodingMem (parser->m_unknownEncodingMem)
610 #define unknownEncodingData (parser->m_unknownEncodingData)
611 #define unknownEncodingHandlerData \
612 (parser->m_unknownEncodingHandlerData)
613 #define unknownEncodingRelease (parser->m_unknownEncodingRelease)
614 #define protocolEncodingName (parser->m_protocolEncodingName)
615 #define ns (parser->m_ns)
616 #define ns_triplets (parser->m_ns_triplets)
617 #define prologState (parser->m_prologState)
618 #define processor (parser->m_processor)
619 #define errorCode (parser->m_errorCode)
620 #define eventPtr (parser->m_eventPtr)
621 #define eventEndPtr (parser->m_eventEndPtr)
622 #define positionPtr (parser->m_positionPtr)
623 #define position (parser->m_position)
624 #define openInternalEntities (parser->m_openInternalEntities)
625 #define freeInternalEntities (parser->m_freeInternalEntities)
626 #define defaultExpandInternalEntities \
627 (parser->m_defaultExpandInternalEntities)
628 #define tagLevel (parser->m_tagLevel)
629 #define buffer (parser->m_buffer)
630 #define bufferPtr (parser->m_bufferPtr)
631 #define bufferEnd (parser->m_bufferEnd)
632 #define parseEndByteIndex (parser->m_parseEndByteIndex)
633 #define parseEndPtr (parser->m_parseEndPtr)
634 #define bufferLim (parser->m_bufferLim)
635 #define dataBuf (parser->m_dataBuf)
636 #define dataBufEnd (parser->m_dataBufEnd)
637 #define _dtd (parser->m_dtd)
638 #define curBase (parser->m_curBase)
639 #define declEntity (parser->m_declEntity)
640 #define doctypeName (parser->m_doctypeName)
641 #define doctypeSysid (parser->m_doctypeSysid)
642 #define doctypePubid (parser->m_doctypePubid)
643 #define declAttributeType (parser->m_declAttributeType)
644 #define declNotationName (parser->m_declNotationName)
645 #define declNotationPublicId (parser->m_declNotationPublicId)
646 #define declElementType (parser->m_declElementType)
647 #define declAttributeId (parser->m_declAttributeId)
648 #define declAttributeIsCdata (parser->m_declAttributeIsCdata)
649 #define declAttributeIsId (parser->m_declAttributeIsId)
650 #define freeTagList (parser->m_freeTagList)
651 #define freeBindingList (parser->m_freeBindingList)
652 #define inheritedBindings (parser->m_inheritedBindings)
653 #define tagStack (parser->m_tagStack)
654 #define atts (parser->m_atts)
655 #define attsSize (parser->m_attsSize)
656 #define nSpecifiedAtts (parser->m_nSpecifiedAtts)
657 #define idAttIndex (parser->m_idAttIndex)
658 #define nsAtts (parser->m_nsAtts)
659 #define nsAttsVersion (parser->m_nsAttsVersion)
660 #define nsAttsPower (parser->m_nsAttsPower)
661 #define attInfo (parser->m_attInfo)
662 #define tempPool (parser->m_tempPool)
663 #define temp2Pool (parser->m_temp2Pool)
664 #define groupConnector (parser->m_groupConnector)
665 #define groupSize (parser->m_groupSize)
666 #define namespaceSeparator (parser->m_namespaceSeparator)
667 #define parentParser (parser->m_parentParser)
668 #define ps_parsing (parser->m_parsingStatus.parsing)
669 #define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
671 #define isParamEntity (parser->m_isParamEntity)
672 #define useForeignDTD (parser->m_useForeignDTD)
673 #define paramEntityParsing (parser->m_paramEntityParsing)
675 #define hash_secret_salt (parser->m_hash_secret_salt)
678 XML_ParserCreate(const XML_Char *encodingName)
680 return XML_ParserCreate_MM(encodingName, NULL, NULL);
684 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
688 return XML_ParserCreate_MM(encodingName, NULL, tmp);
691 static const XML_Char implicitContext[] = {
692 ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
693 ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
694 ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
695 ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
696 ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
697 ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
701 gather_time_entropy(void)
705 GetSystemTimeAsFileTime(&ft); /* never fails */
706 return ft.dwHighDateTime ^ ft.dwLowDateTime;
709 int gettimeofday_res;
711 gettimeofday_res = gettimeofday(&tv, NULL);
712 assert (gettimeofday_res == 0);
714 /* Microseconds time is <20 bits entropy */
720 generate_hash_secret_salt(XML_Parser parser)
722 /* Process ID is 0 bits entropy if attacker has local access
723 * XML_Parser address is few bits of entropy if attacker has local access */
724 const unsigned long entropy =
725 gather_time_entropy() ^ getpid() ^ (unsigned long)parser;
727 /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
728 if (sizeof(unsigned long) == 4) {
729 return entropy * 2147483647;
731 return entropy * (unsigned long)2305843009213693951;
735 static XML_Bool /* only valid for root parser */
736 startParsing(XML_Parser parser)
738 /* hash functions must be initialized before setContext() is called */
739 if (hash_secret_salt == 0)
740 hash_secret_salt = generate_hash_secret_salt(parser);
742 /* implicit context only set for root parser, since child
743 parsers (i.e. external entity parsers) will inherit it
745 return setContext(parser, implicitContext);
751 XML_ParserCreate_MM(const XML_Char *encodingName,
752 const XML_Memory_Handling_Suite *memsuite,
753 const XML_Char *nameSep)
755 return parserCreate(encodingName, memsuite, nameSep, NULL);
759 parserCreate(const XML_Char *encodingName,
760 const XML_Memory_Handling_Suite *memsuite,
761 const XML_Char *nameSep,
767 XML_Memory_Handling_Suite *mtemp;
768 parser = (XML_Parser)
769 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
770 if (parser != NULL) {
771 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
772 mtemp->malloc_fcn = memsuite->malloc_fcn;
773 mtemp->realloc_fcn = memsuite->realloc_fcn;
774 mtemp->free_fcn = memsuite->free_fcn;
778 XML_Memory_Handling_Suite *mtemp;
779 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
780 if (parser != NULL) {
781 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
782 mtemp->malloc_fcn = malloc;
783 mtemp->realloc_fcn = realloc;
784 mtemp->free_fcn = free;
794 attsSize = INIT_ATTS_SIZE;
795 atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
801 attInfo = (XML_AttrInfo*)MALLOC(attsSize * sizeof(XML_AttrInfo));
802 if (attInfo == NULL) {
808 dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
809 if (dataBuf == NULL) {
817 dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
822 _dtd = dtdCreate(&parser->m_mem);
834 freeBindingList = NULL;
836 freeInternalEntities = NULL;
839 groupConnector = NULL;
841 unknownEncodingHandler = NULL;
842 unknownEncodingHandlerData = NULL;
844 namespaceSeparator = ASCII_EXCL;
846 ns_triplets = XML_FALSE;
852 poolInit(&tempPool, &(parser->m_mem));
853 poolInit(&temp2Pool, &(parser->m_mem));
854 parserInit(parser, encodingName);
856 if (encodingName && !protocolEncodingName) {
857 XML_ParserFree(parser);
863 internalEncoding = XmlGetInternalEncodingNS();
864 namespaceSeparator = *nameSep;
867 internalEncoding = XmlGetInternalEncoding();
874 parserInit(XML_Parser parser, const XML_Char *encodingName)
876 processor = prologInitProcessor;
877 XmlPrologStateInit(&prologState);
878 protocolEncodingName = (encodingName != NULL
879 ? poolCopyString(&tempPool, encodingName)
882 XmlInitEncoding(&initEncoding, &encoding, 0);
885 startElementHandler = NULL;
886 endElementHandler = NULL;
887 characterDataHandler = NULL;
888 processingInstructionHandler = NULL;
889 commentHandler = NULL;
890 startCdataSectionHandler = NULL;
891 endCdataSectionHandler = NULL;
892 defaultHandler = NULL;
893 startDoctypeDeclHandler = NULL;
894 endDoctypeDeclHandler = NULL;
895 unparsedEntityDeclHandler = NULL;
896 notationDeclHandler = NULL;
897 startNamespaceDeclHandler = NULL;
898 endNamespaceDeclHandler = NULL;
899 notStandaloneHandler = NULL;
900 externalEntityRefHandler = NULL;
901 externalEntityRefHandlerArg = parser;
902 skippedEntityHandler = NULL;
903 elementDeclHandler = NULL;
904 attlistDeclHandler = NULL;
905 entityDeclHandler = NULL;
906 xmlDeclHandler = NULL;
909 parseEndByteIndex = 0;
911 declElementType = NULL;
912 declAttributeId = NULL;
917 declAttributeType = NULL;
918 declNotationName = NULL;
919 declNotationPublicId = NULL;
920 declAttributeIsCdata = XML_FALSE;
921 declAttributeIsId = XML_FALSE;
922 memset(&position, 0, sizeof(POSITION));
923 errorCode = XML_ERROR_NONE;
927 openInternalEntities = NULL;
928 defaultExpandInternalEntities = XML_TRUE;
931 inheritedBindings = NULL;
933 unknownEncodingMem = NULL;
934 unknownEncodingRelease = NULL;
935 unknownEncodingData = NULL;
937 ps_parsing = XML_INITIALIZED;
939 isParamEntity = XML_FALSE;
940 useForeignDTD = XML_FALSE;
941 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
943 hash_secret_salt = 0;
946 /* moves list of bindings to freeBindingList */
948 moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
951 BINDING *b = bindings;
952 bindings = bindings->nextTagBinding;
953 b->nextTagBinding = freeBindingList;
959 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
962 OPEN_INTERNAL_ENTITY *openEntityList;
965 /* move tagStack to freeTagList */
970 tag->parent = freeTagList;
971 moveToFreeBindingList(parser, tag->bindings);
972 tag->bindings = NULL;
975 /* move openInternalEntities to freeInternalEntities */
976 openEntityList = openInternalEntities;
977 while (openEntityList) {
978 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
979 openEntityList = openEntity->next;
980 openEntity->next = freeInternalEntities;
981 freeInternalEntities = openEntity;
983 moveToFreeBindingList(parser, inheritedBindings);
984 FREE(unknownEncodingMem);
985 if (unknownEncodingRelease)
986 unknownEncodingRelease(unknownEncodingData);
987 poolClear(&tempPool);
988 poolClear(&temp2Pool);
989 parserInit(parser, encodingName);
990 dtdReset(_dtd, &parser->m_mem);
994 enum XML_Status XMLCALL
995 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
997 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
998 XXX There's no way for the caller to determine which of the
999 XXX possible error cases caused the XML_STATUS_ERROR return.
1001 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1002 return XML_STATUS_ERROR;
1003 if (encodingName == NULL)
1004 protocolEncodingName = NULL;
1006 protocolEncodingName = poolCopyString(&tempPool, encodingName);
1007 if (!protocolEncodingName)
1008 return XML_STATUS_ERROR;
1010 return XML_STATUS_OK;
1014 XML_ExternalEntityParserCreate(XML_Parser oldParser,
1015 const XML_Char *context,
1016 const XML_Char *encodingName)
1018 XML_Parser parser = oldParser;
1021 XML_StartElementHandler oldStartElementHandler = startElementHandler;
1022 XML_EndElementHandler oldEndElementHandler = endElementHandler;
1023 XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
1024 XML_ProcessingInstructionHandler oldProcessingInstructionHandler
1025 = processingInstructionHandler;
1026 XML_CommentHandler oldCommentHandler = commentHandler;
1027 XML_StartCdataSectionHandler oldStartCdataSectionHandler
1028 = startCdataSectionHandler;
1029 XML_EndCdataSectionHandler oldEndCdataSectionHandler
1030 = endCdataSectionHandler;
1031 XML_DefaultHandler oldDefaultHandler = defaultHandler;
1032 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
1033 = unparsedEntityDeclHandler;
1034 XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
1035 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
1036 = startNamespaceDeclHandler;
1037 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
1038 = endNamespaceDeclHandler;
1039 XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
1040 XML_ExternalEntityRefHandler oldExternalEntityRefHandler
1041 = externalEntityRefHandler;
1042 XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
1043 XML_UnknownEncodingHandler oldUnknownEncodingHandler
1044 = unknownEncodingHandler;
1045 XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
1046 XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
1047 XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
1048 XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
1049 ELEMENT_TYPE * oldDeclElementType = declElementType;
1051 void *oldUserData = userData;
1052 void *oldHandlerArg = handlerArg;
1053 XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
1054 XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
1056 enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
1057 int oldInEntityValue = prologState.inEntityValue;
1059 XML_Bool oldns_triplets = ns_triplets;
1060 /* Note that the new parser shares the same hash secret as the old
1061 parser, so that dtdCopy and copyEntityTable can lookup values
1062 from hash tables associated with either parser without us having
1063 to worry which hash secrets each table has.
1065 unsigned long oldhash_secret_salt = hash_secret_salt;
1070 #endif /* XML_DTD */
1072 /* Note that the magical uses of the pre-processor to make field
1073 access look more like C++ require that `parser' be overwritten
1074 here. This makes this function more painful to follow than it
1079 *tmp = namespaceSeparator;
1080 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
1083 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1089 startElementHandler = oldStartElementHandler;
1090 endElementHandler = oldEndElementHandler;
1091 characterDataHandler = oldCharacterDataHandler;
1092 processingInstructionHandler = oldProcessingInstructionHandler;
1093 commentHandler = oldCommentHandler;
1094 startCdataSectionHandler = oldStartCdataSectionHandler;
1095 endCdataSectionHandler = oldEndCdataSectionHandler;
1096 defaultHandler = oldDefaultHandler;
1097 unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1098 notationDeclHandler = oldNotationDeclHandler;
1099 startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1100 endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1101 notStandaloneHandler = oldNotStandaloneHandler;
1102 externalEntityRefHandler = oldExternalEntityRefHandler;
1103 skippedEntityHandler = oldSkippedEntityHandler;
1104 unknownEncodingHandler = oldUnknownEncodingHandler;
1105 elementDeclHandler = oldElementDeclHandler;
1106 attlistDeclHandler = oldAttlistDeclHandler;
1107 entityDeclHandler = oldEntityDeclHandler;
1108 xmlDeclHandler = oldXmlDeclHandler;
1109 declElementType = oldDeclElementType;
1110 userData = oldUserData;
1111 if (oldUserData == oldHandlerArg)
1112 handlerArg = userData;
1114 handlerArg = parser;
1115 if (oldExternalEntityRefHandlerArg != oldParser)
1116 externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1117 defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1118 ns_triplets = oldns_triplets;
1119 hash_secret_salt = oldhash_secret_salt;
1120 parentParser = oldParser;
1122 paramEntityParsing = oldParamEntityParsing;
1123 prologState.inEntityValue = oldInEntityValue;
1125 #endif /* XML_DTD */
1126 if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem)
1127 || !setContext(parser, context)) {
1128 XML_ParserFree(parser);
1131 processor = externalEntityInitProcessor;
1135 /* The DTD instance referenced by _dtd is shared between the document's
1136 root parser and external PE parsers, therefore one does not need to
1137 call setContext. In addition, one also *must* not call setContext,
1138 because this would overwrite existing prefix->binding pointers in
1139 _dtd with ones that get destroyed with the external PE parser.
1140 This would leave those prefixes with dangling pointers.
1142 isParamEntity = XML_TRUE;
1143 XmlPrologStateInitExternalEntity(&prologState);
1144 processor = externalParEntInitProcessor;
1146 #endif /* XML_DTD */
1150 static void FASTCALL
1151 destroyBindings(BINDING *bindings, XML_Parser parser)
1154 BINDING *b = bindings;
1157 bindings = b->nextTagBinding;
1164 XML_ParserFree(XML_Parser parser)
1167 OPEN_INTERNAL_ENTITY *entityList;
1170 /* free tagStack and freeTagList */
1174 if (tagList == NULL) {
1175 if (freeTagList == NULL)
1177 tagList = freeTagList;
1181 tagList = tagList->parent;
1183 destroyBindings(p->bindings, parser);
1186 /* free openInternalEntities and freeInternalEntities */
1187 entityList = openInternalEntities;
1189 OPEN_INTERNAL_ENTITY *openEntity;
1190 if (entityList == NULL) {
1191 if (freeInternalEntities == NULL)
1193 entityList = freeInternalEntities;
1194 freeInternalEntities = NULL;
1196 openEntity = entityList;
1197 entityList = entityList->next;
1201 destroyBindings(freeBindingList, parser);
1202 destroyBindings(inheritedBindings, parser);
1203 poolDestroy(&tempPool);
1204 poolDestroy(&temp2Pool);
1206 /* external parameter entity parsers share the DTD structure
1207 parser->m_dtd with the root parser, so we must not destroy it
1209 if (!isParamEntity && _dtd)
1212 #endif /* XML_DTD */
1213 dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
1215 #ifdef XML_ATTR_INFO
1216 FREE((void *)attInfo);
1218 FREE(groupConnector);
1222 FREE(unknownEncodingMem);
1223 if (unknownEncodingRelease)
1224 unknownEncodingRelease(unknownEncodingData);
1229 XML_UseParserAsHandlerArg(XML_Parser parser)
1231 handlerArg = parser;
1234 enum XML_Error XMLCALL
1235 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
1238 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1239 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1240 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
1241 useForeignDTD = useDTD;
1242 return XML_ERROR_NONE;
1244 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1249 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
1251 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1252 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1254 ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
1258 XML_SetUserData(XML_Parser parser, void *p)
1260 if (handlerArg == userData)
1261 handlerArg = userData = p;
1266 enum XML_Status XMLCALL
1267 XML_SetBase(XML_Parser parser, const XML_Char *p)
1270 p = poolCopyString(&_dtd->pool, p);
1272 return XML_STATUS_ERROR;
1277 return XML_STATUS_OK;
1280 const XML_Char * XMLCALL
1281 XML_GetBase(XML_Parser parser)
1287 XML_GetSpecifiedAttributeCount(XML_Parser parser)
1289 return nSpecifiedAtts;
1293 XML_GetIdAttributeIndex(XML_Parser parser)
1298 #ifdef XML_ATTR_INFO
1299 const XML_AttrInfo * XMLCALL
1300 XML_GetAttributeInfo(XML_Parser parser)
1307 XML_SetElementHandler(XML_Parser parser,
1308 XML_StartElementHandler start,
1309 XML_EndElementHandler end)
1311 startElementHandler = start;
1312 endElementHandler = end;
1316 XML_SetStartElementHandler(XML_Parser parser,
1317 XML_StartElementHandler start) {
1318 startElementHandler = start;
1322 XML_SetEndElementHandler(XML_Parser parser,
1323 XML_EndElementHandler end) {
1324 endElementHandler = end;
1328 XML_SetCharacterDataHandler(XML_Parser parser,
1329 XML_CharacterDataHandler handler)
1331 characterDataHandler = handler;
1335 XML_SetProcessingInstructionHandler(XML_Parser parser,
1336 XML_ProcessingInstructionHandler handler)
1338 processingInstructionHandler = handler;
1342 XML_SetCommentHandler(XML_Parser parser,
1343 XML_CommentHandler handler)
1345 commentHandler = handler;
1349 XML_SetCdataSectionHandler(XML_Parser parser,
1350 XML_StartCdataSectionHandler start,
1351 XML_EndCdataSectionHandler end)
1353 startCdataSectionHandler = start;
1354 endCdataSectionHandler = end;
1358 XML_SetStartCdataSectionHandler(XML_Parser parser,
1359 XML_StartCdataSectionHandler start) {
1360 startCdataSectionHandler = start;
1364 XML_SetEndCdataSectionHandler(XML_Parser parser,
1365 XML_EndCdataSectionHandler end) {
1366 endCdataSectionHandler = end;
1370 XML_SetDefaultHandler(XML_Parser parser,
1371 XML_DefaultHandler handler)
1373 defaultHandler = handler;
1374 defaultExpandInternalEntities = XML_FALSE;
1378 XML_SetDefaultHandlerExpand(XML_Parser parser,
1379 XML_DefaultHandler handler)
1381 defaultHandler = handler;
1382 defaultExpandInternalEntities = XML_TRUE;
1386 XML_SetDoctypeDeclHandler(XML_Parser parser,
1387 XML_StartDoctypeDeclHandler start,
1388 XML_EndDoctypeDeclHandler end)
1390 startDoctypeDeclHandler = start;
1391 endDoctypeDeclHandler = end;
1395 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1396 XML_StartDoctypeDeclHandler start) {
1397 startDoctypeDeclHandler = start;
1401 XML_SetEndDoctypeDeclHandler(XML_Parser parser,
1402 XML_EndDoctypeDeclHandler end) {
1403 endDoctypeDeclHandler = end;
1407 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1408 XML_UnparsedEntityDeclHandler handler)
1410 unparsedEntityDeclHandler = handler;
1414 XML_SetNotationDeclHandler(XML_Parser parser,
1415 XML_NotationDeclHandler handler)
1417 notationDeclHandler = handler;
1421 XML_SetNamespaceDeclHandler(XML_Parser parser,
1422 XML_StartNamespaceDeclHandler start,
1423 XML_EndNamespaceDeclHandler end)
1425 startNamespaceDeclHandler = start;
1426 endNamespaceDeclHandler = end;
1430 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1431 XML_StartNamespaceDeclHandler start) {
1432 startNamespaceDeclHandler = start;
1436 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1437 XML_EndNamespaceDeclHandler end) {
1438 endNamespaceDeclHandler = end;
1442 XML_SetNotStandaloneHandler(XML_Parser parser,
1443 XML_NotStandaloneHandler handler)
1445 notStandaloneHandler = handler;
1449 XML_SetExternalEntityRefHandler(XML_Parser parser,
1450 XML_ExternalEntityRefHandler handler)
1452 externalEntityRefHandler = handler;
1456 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
1459 externalEntityRefHandlerArg = (XML_Parser)arg;
1461 externalEntityRefHandlerArg = parser;
1465 XML_SetSkippedEntityHandler(XML_Parser parser,
1466 XML_SkippedEntityHandler handler)
1468 skippedEntityHandler = handler;
1472 XML_SetUnknownEncodingHandler(XML_Parser parser,
1473 XML_UnknownEncodingHandler handler,
1476 unknownEncodingHandler = handler;
1477 unknownEncodingHandlerData = data;
1481 XML_SetElementDeclHandler(XML_Parser parser,
1482 XML_ElementDeclHandler eldecl)
1484 elementDeclHandler = eldecl;
1488 XML_SetAttlistDeclHandler(XML_Parser parser,
1489 XML_AttlistDeclHandler attdecl)
1491 attlistDeclHandler = attdecl;
1495 XML_SetEntityDeclHandler(XML_Parser parser,
1496 XML_EntityDeclHandler handler)
1498 entityDeclHandler = handler;
1502 XML_SetXmlDeclHandler(XML_Parser parser,
1503 XML_XmlDeclHandler handler) {
1504 xmlDeclHandler = handler;
1508 XML_SetParamEntityParsing(XML_Parser parser,
1509 enum XML_ParamEntityParsing peParsing)
1511 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1512 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1515 paramEntityParsing = peParsing;
1518 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1523 XML_SetHashSalt(XML_Parser parser,
1524 unsigned long hash_salt)
1526 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1527 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1529 hash_secret_salt = hash_salt;
1533 enum XML_Status XMLCALL
1534 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
1536 switch (ps_parsing) {
1538 errorCode = XML_ERROR_SUSPENDED;
1539 return XML_STATUS_ERROR;
1541 errorCode = XML_ERROR_FINISHED;
1542 return XML_STATUS_ERROR;
1543 case XML_INITIALIZED:
1544 if (parentParser == NULL && !startParsing(parser)) {
1545 errorCode = XML_ERROR_NO_MEMORY;
1546 return XML_STATUS_ERROR;
1549 ps_parsing = XML_PARSING;
1553 ps_finalBuffer = (XML_Bool)isFinal;
1555 return XML_STATUS_OK;
1556 positionPtr = bufferPtr;
1557 parseEndPtr = bufferEnd;
1559 /* If data are left over from last buffer, and we now know that these
1560 data are the final chunk of input, then we have to check them again
1561 to detect errors based on that fact.
1563 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
1565 if (errorCode == XML_ERROR_NONE) {
1566 switch (ps_parsing) {
1568 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1569 positionPtr = bufferPtr;
1570 return XML_STATUS_SUSPENDED;
1571 case XML_INITIALIZED:
1573 ps_parsing = XML_FINISHED;
1576 return XML_STATUS_OK;
1579 eventEndPtr = eventPtr;
1580 processor = errorProcessor;
1581 return XML_STATUS_ERROR;
1583 #ifndef XML_CONTEXT_BYTES
1584 else if (bufferPtr == bufferEnd) {
1587 enum XML_Status result;
1588 parseEndByteIndex += len;
1590 ps_finalBuffer = (XML_Bool)isFinal;
1592 errorCode = processor(parser, s, parseEndPtr = s + len, &end);
1594 if (errorCode != XML_ERROR_NONE) {
1595 eventEndPtr = eventPtr;
1596 processor = errorProcessor;
1597 return XML_STATUS_ERROR;
1600 switch (ps_parsing) {
1602 result = XML_STATUS_SUSPENDED;
1604 case XML_INITIALIZED:
1607 ps_parsing = XML_FINISHED;
1608 return XML_STATUS_OK;
1612 result = XML_STATUS_OK;
1616 XmlUpdatePosition(encoding, positionPtr, end, &position);
1617 nLeftOver = s + len - end;
1619 if (buffer == NULL || nLeftOver > bufferLim - buffer) {
1620 /* FIXME avoid integer overflow */
1622 temp = (buffer == NULL
1623 ? (char *)MALLOC(len * 2)
1624 : (char *)REALLOC(buffer, len * 2));
1626 errorCode = XML_ERROR_NO_MEMORY;
1627 eventPtr = eventEndPtr = NULL;
1628 processor = errorProcessor;
1629 return XML_STATUS_ERROR;
1632 bufferLim = buffer + len * 2;
1634 memcpy(buffer, end, nLeftOver);
1637 bufferEnd = buffer + nLeftOver;
1638 positionPtr = bufferPtr;
1639 parseEndPtr = bufferEnd;
1640 eventPtr = bufferPtr;
1641 eventEndPtr = bufferPtr;
1644 #endif /* not defined XML_CONTEXT_BYTES */
1646 void *buff = XML_GetBuffer(parser, len);
1648 return XML_STATUS_ERROR;
1650 memcpy(buff, s, len);
1651 return XML_ParseBuffer(parser, len, isFinal);
1656 enum XML_Status XMLCALL
1657 XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
1660 enum XML_Status result = XML_STATUS_OK;
1662 switch (ps_parsing) {
1664 errorCode = XML_ERROR_SUSPENDED;
1665 return XML_STATUS_ERROR;
1667 errorCode = XML_ERROR_FINISHED;
1668 return XML_STATUS_ERROR;
1669 case XML_INITIALIZED:
1670 if (parentParser == NULL && !startParsing(parser)) {
1671 errorCode = XML_ERROR_NO_MEMORY;
1672 return XML_STATUS_ERROR;
1675 ps_parsing = XML_PARSING;
1679 positionPtr = start;
1681 parseEndPtr = bufferEnd;
1682 parseEndByteIndex += len;
1683 ps_finalBuffer = (XML_Bool)isFinal;
1685 errorCode = processor(parser, start, parseEndPtr, &bufferPtr);
1687 if (errorCode != XML_ERROR_NONE) {
1688 eventEndPtr = eventPtr;
1689 processor = errorProcessor;
1690 return XML_STATUS_ERROR;
1693 switch (ps_parsing) {
1695 result = XML_STATUS_SUSPENDED;
1697 case XML_INITIALIZED:
1700 ps_parsing = XML_FINISHED;
1703 default: ; /* should not happen */
1707 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1708 positionPtr = bufferPtr;
1713 XML_GetBuffer(XML_Parser parser, int len)
1716 errorCode = XML_ERROR_NO_MEMORY;
1719 switch (ps_parsing) {
1721 errorCode = XML_ERROR_SUSPENDED;
1724 errorCode = XML_ERROR_FINISHED;
1729 if (len > bufferLim - bufferEnd) {
1730 #ifdef XML_CONTEXT_BYTES
1732 #endif /* defined XML_CONTEXT_BYTES */
1733 /* Do not invoke signed arithmetic overflow: */
1734 int neededSize = (int) ((unsigned)len + (unsigned)(bufferEnd - bufferPtr));
1735 if (neededSize < 0) {
1736 errorCode = XML_ERROR_NO_MEMORY;
1739 #ifdef XML_CONTEXT_BYTES
1740 keep = (int)(bufferPtr - buffer);
1741 if (keep > XML_CONTEXT_BYTES)
1742 keep = XML_CONTEXT_BYTES;
1744 #endif /* defined XML_CONTEXT_BYTES */
1745 if (neededSize <= bufferLim - buffer) {
1746 #ifdef XML_CONTEXT_BYTES
1747 if (keep < bufferPtr - buffer) {
1748 int offset = (int)(bufferPtr - buffer) - keep;
1749 memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
1750 bufferEnd -= offset;
1751 bufferPtr -= offset;
1754 memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
1755 bufferEnd = buffer + (bufferEnd - bufferPtr);
1757 #endif /* not defined XML_CONTEXT_BYTES */
1761 int bufferSize = (int)(bufferLim - bufferPtr);
1762 if (bufferSize == 0)
1763 bufferSize = INIT_BUFFER_SIZE;
1765 /* Do not invoke signed arithmetic overflow: */
1766 bufferSize = (int) (2U * (unsigned) bufferSize);
1767 } while (bufferSize < neededSize && bufferSize > 0);
1768 if (bufferSize <= 0) {
1769 errorCode = XML_ERROR_NO_MEMORY;
1772 newBuf = (char *)MALLOC(bufferSize);
1774 errorCode = XML_ERROR_NO_MEMORY;
1777 bufferLim = newBuf + bufferSize;
1778 #ifdef XML_CONTEXT_BYTES
1780 int keep = (int)(bufferPtr - buffer);
1781 if (keep > XML_CONTEXT_BYTES)
1782 keep = XML_CONTEXT_BYTES;
1783 memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
1786 bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
1787 bufferPtr = buffer + keep;
1790 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1791 bufferPtr = buffer = newBuf;
1795 memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
1798 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1799 bufferPtr = buffer = newBuf;
1800 #endif /* not defined XML_CONTEXT_BYTES */
1802 eventPtr = eventEndPtr = NULL;
1808 enum XML_Status XMLCALL
1809 XML_StopParser(XML_Parser parser, XML_Bool resumable)
1811 switch (ps_parsing) {
1814 errorCode = XML_ERROR_SUSPENDED;
1815 return XML_STATUS_ERROR;
1817 ps_parsing = XML_FINISHED;
1820 errorCode = XML_ERROR_FINISHED;
1821 return XML_STATUS_ERROR;
1825 if (isParamEntity) {
1826 errorCode = XML_ERROR_SUSPEND_PE;
1827 return XML_STATUS_ERROR;
1830 ps_parsing = XML_SUSPENDED;
1833 ps_parsing = XML_FINISHED;
1835 return XML_STATUS_OK;
1838 enum XML_Status XMLCALL
1839 XML_ResumeParser(XML_Parser parser)
1841 enum XML_Status result = XML_STATUS_OK;
1843 if (ps_parsing != XML_SUSPENDED) {
1844 errorCode = XML_ERROR_NOT_SUSPENDED;
1845 return XML_STATUS_ERROR;
1847 ps_parsing = XML_PARSING;
1849 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
1851 if (errorCode != XML_ERROR_NONE) {
1852 eventEndPtr = eventPtr;
1853 processor = errorProcessor;
1854 return XML_STATUS_ERROR;
1857 switch (ps_parsing) {
1859 result = XML_STATUS_SUSPENDED;
1861 case XML_INITIALIZED:
1863 if (ps_finalBuffer) {
1864 ps_parsing = XML_FINISHED;
1871 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1872 positionPtr = bufferPtr;
1877 XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
1879 assert(status != NULL);
1880 *status = parser->m_parsingStatus;
1883 enum XML_Error XMLCALL
1884 XML_GetErrorCode(XML_Parser parser)
1890 XML_GetCurrentByteIndex(XML_Parser parser)
1893 return (XML_Index)(parseEndByteIndex - (parseEndPtr - eventPtr));
1898 XML_GetCurrentByteCount(XML_Parser parser)
1900 if (eventEndPtr && eventPtr)
1901 return (int)(eventEndPtr - eventPtr);
1905 const char * XMLCALL
1906 XML_GetInputContext(XML_Parser parser, int *offset, int *size)
1908 #ifdef XML_CONTEXT_BYTES
1909 if (eventPtr && buffer) {
1910 *offset = (int)(eventPtr - buffer);
1911 *size = (int)(bufferEnd - buffer);
1914 #endif /* defined XML_CONTEXT_BYTES */
1919 XML_GetCurrentLineNumber(XML_Parser parser)
1921 if (eventPtr && eventPtr >= positionPtr) {
1922 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1923 positionPtr = eventPtr;
1925 return position.lineNumber + 1;
1929 XML_GetCurrentColumnNumber(XML_Parser parser)
1931 if (eventPtr && eventPtr >= positionPtr) {
1932 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1933 positionPtr = eventPtr;
1935 return position.columnNumber;
1939 XML_FreeContentModel(XML_Parser parser, XML_Content *model)
1945 XML_MemMalloc(XML_Parser parser, size_t size)
1947 return MALLOC(size);
1951 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
1953 return REALLOC(ptr, size);
1957 XML_MemFree(XML_Parser parser, void *ptr)
1963 XML_DefaultCurrent(XML_Parser parser)
1965 if (defaultHandler) {
1966 if (openInternalEntities)
1967 reportDefault(parser,
1969 openInternalEntities->internalEventPtr,
1970 openInternalEntities->internalEventEndPtr);
1972 reportDefault(parser, encoding, eventPtr, eventEndPtr);
1976 const XML_LChar * XMLCALL
1977 XML_ErrorString(enum XML_Error code)
1979 static const XML_LChar* const message[] = {
1981 XML_L("out of memory"),
1982 XML_L("syntax error"),
1983 XML_L("no element found"),
1984 XML_L("not well-formed (invalid token)"),
1985 XML_L("unclosed token"),
1986 XML_L("partial character"),
1987 XML_L("mismatched tag"),
1988 XML_L("duplicate attribute"),
1989 XML_L("junk after document element"),
1990 XML_L("illegal parameter entity reference"),
1991 XML_L("undefined entity"),
1992 XML_L("recursive entity reference"),
1993 XML_L("asynchronous entity"),
1994 XML_L("reference to invalid character number"),
1995 XML_L("reference to binary entity"),
1996 XML_L("reference to external entity in attribute"),
1997 XML_L("XML or text declaration not at start of entity"),
1998 XML_L("unknown encoding"),
1999 XML_L("encoding specified in XML declaration is incorrect"),
2000 XML_L("unclosed CDATA section"),
2001 XML_L("error in processing external entity reference"),
2002 XML_L("document is not standalone"),
2003 XML_L("unexpected parser state - please send a bug report"),
2004 XML_L("entity declared in parameter entity"),
2005 XML_L("requested feature requires XML_DTD support in Expat"),
2006 XML_L("cannot change setting once parsing has begun"),
2007 XML_L("unbound prefix"),
2008 XML_L("must not undeclare prefix"),
2009 XML_L("incomplete markup in parameter entity"),
2010 XML_L("XML declaration not well-formed"),
2011 XML_L("text declaration not well-formed"),
2012 XML_L("illegal character(s) in public id"),
2013 XML_L("parser suspended"),
2014 XML_L("parser not suspended"),
2015 XML_L("parsing aborted"),
2016 XML_L("parsing finished"),
2017 XML_L("cannot suspend in external parameter entity"),
2018 XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
2019 XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
2020 XML_L("prefix must not be bound to one of the reserved namespace names")
2022 if (code > 0 && code < sizeof(message)/sizeof(message[0]))
2023 return message[code];
2027 const XML_LChar * XMLCALL
2028 XML_ExpatVersion(void) {
2030 /* V1 is used to string-ize the version number. However, it would
2031 string-ize the actual version macro *names* unless we get them
2032 substituted before being passed to V1. CPP is defined to expand
2033 a macro, then rescan for more expansions. Thus, we use V2 to expand
2034 the version macros, then CPP will expand the resulting V1() macro
2035 with the correct numerals. */
2036 /* ### I'm assuming cpp is portable in this respect... */
2038 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
2039 #define V2(a,b,c) XML_L("expat_")V1(a,b,c)
2041 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
2047 XML_Expat_Version XMLCALL
2048 XML_ExpatVersionInfo(void)
2050 XML_Expat_Version version;
2052 version.major = XML_MAJOR_VERSION;
2053 version.minor = XML_MINOR_VERSION;
2054 version.micro = XML_MICRO_VERSION;
2059 const XML_Feature * XMLCALL
2060 XML_GetFeatureList(void)
2062 static const XML_Feature features[] = {
2063 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
2065 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
2068 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
2070 #ifdef XML_UNICODE_WCHAR_T
2071 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
2074 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
2076 #ifdef XML_CONTEXT_BYTES
2077 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
2081 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
2084 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
2086 #ifdef XML_LARGE_SIZE
2087 {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
2089 #ifdef XML_ATTR_INFO
2090 {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
2092 {XML_FEATURE_END, NULL, 0}
2098 /* Initially tag->rawName always points into the parse buffer;
2099 for those TAG instances opened while the current parse buffer was
2100 processed, and not yet closed, we need to store tag->rawName in a more
2101 permanent location, since the parse buffer is about to be discarded.
2104 storeRawNames(XML_Parser parser)
2106 TAG *tag = tagStack;
2109 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
2110 char *rawNameBuf = tag->buf + nameLen;
2111 /* Stop if already stored. Since tagStack is a stack, we can stop
2112 at the first entry that has already been copied; everything
2113 below it in the stack is already been accounted for in a
2114 previous call to this function.
2116 if (tag->rawName == rawNameBuf)
2118 /* For re-use purposes we need to ensure that the
2119 size of tag->buf is a multiple of sizeof(XML_Char).
2121 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
2122 if (bufSize > tag->bufEnd - tag->buf) {
2123 char *temp = (char *)REALLOC(tag->buf, bufSize);
2126 /* if tag->name.str points to tag->buf (only when namespace
2127 processing is off) then we have to update it
2129 if (tag->name.str == (XML_Char *)tag->buf)
2130 tag->name.str = (XML_Char *)temp;
2131 /* if tag->name.localPart is set (when namespace processing is on)
2132 then update it as well, since it will always point into tag->buf
2134 if (tag->name.localPart)
2135 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
2136 (XML_Char *)tag->buf);
2138 tag->bufEnd = temp + bufSize;
2139 rawNameBuf = temp + nameLen;
2141 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2142 tag->rawName = rawNameBuf;
2148 static enum XML_Error PTRCALL
2149 contentProcessor(XML_Parser parser,
2152 const char **endPtr)
2154 enum XML_Error result = doContent(parser, 0, encoding, start, end,
2155 endPtr, (XML_Bool)!ps_finalBuffer);
2156 if (result == XML_ERROR_NONE) {
2157 if (!storeRawNames(parser))
2158 return XML_ERROR_NO_MEMORY;
2163 static enum XML_Error PTRCALL
2164 externalEntityInitProcessor(XML_Parser parser,
2167 const char **endPtr)
2169 enum XML_Error result = initializeEncoding(parser);
2170 if (result != XML_ERROR_NONE)
2172 processor = externalEntityInitProcessor2;
2173 return externalEntityInitProcessor2(parser, start, end, endPtr);
2176 static enum XML_Error PTRCALL
2177 externalEntityInitProcessor2(XML_Parser parser,
2180 const char **endPtr)
2182 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2183 int tok = XmlContentTok(encoding, start, end, &next);
2186 /* If we are at the end of the buffer, this would cause the next stage,
2187 i.e. externalEntityInitProcessor3, to pass control directly to
2188 doContent (by detecting XML_TOK_NONE) without processing any xml text
2189 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2191 if (next == end && !ps_finalBuffer) {
2193 return XML_ERROR_NONE;
2197 case XML_TOK_PARTIAL:
2198 if (!ps_finalBuffer) {
2200 return XML_ERROR_NONE;
2203 return XML_ERROR_UNCLOSED_TOKEN;
2204 case XML_TOK_PARTIAL_CHAR:
2205 if (!ps_finalBuffer) {
2207 return XML_ERROR_NONE;
2210 return XML_ERROR_PARTIAL_CHAR;
2212 processor = externalEntityInitProcessor3;
2213 return externalEntityInitProcessor3(parser, start, end, endPtr);
2216 static enum XML_Error PTRCALL
2217 externalEntityInitProcessor3(XML_Parser parser,
2220 const char **endPtr)
2223 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2225 tok = XmlContentTok(encoding, start, end, &next);
2229 case XML_TOK_XML_DECL:
2231 enum XML_Error result;
2232 result = processXmlDecl(parser, 1, start, next);
2233 if (result != XML_ERROR_NONE)
2235 switch (ps_parsing) {
2238 return XML_ERROR_NONE;
2240 return XML_ERROR_ABORTED;
2246 case XML_TOK_PARTIAL:
2247 if (!ps_finalBuffer) {
2249 return XML_ERROR_NONE;
2251 return XML_ERROR_UNCLOSED_TOKEN;
2252 case XML_TOK_PARTIAL_CHAR:
2253 if (!ps_finalBuffer) {
2255 return XML_ERROR_NONE;
2257 return XML_ERROR_PARTIAL_CHAR;
2259 processor = externalEntityContentProcessor;
2261 return externalEntityContentProcessor(parser, start, end, endPtr);
2264 static enum XML_Error PTRCALL
2265 externalEntityContentProcessor(XML_Parser parser,
2268 const char **endPtr)
2270 enum XML_Error result = doContent(parser, 1, encoding, start, end,
2271 endPtr, (XML_Bool)!ps_finalBuffer);
2272 if (result == XML_ERROR_NONE) {
2273 if (!storeRawNames(parser))
2274 return XML_ERROR_NO_MEMORY;
2279 static enum XML_Error
2280 doContent(XML_Parser parser,
2282 const ENCODING *enc,
2285 const char **nextPtr,
2288 /* save one level of indirection */
2289 DTD * const dtd = _dtd;
2291 const char **eventPP;
2292 const char **eventEndPP;
2293 if (enc == encoding) {
2294 eventPP = &eventPtr;
2295 eventEndPP = &eventEndPtr;
2298 eventPP = &(openInternalEntities->internalEventPtr);
2299 eventEndPP = &(openInternalEntities->internalEventEndPtr);
2304 const char *next = s; /* XmlContentTok doesn't always set the last arg */
2305 int tok = XmlContentTok(enc, s, end, &next);
2308 case XML_TOK_TRAILING_CR:
2311 return XML_ERROR_NONE;
2314 if (characterDataHandler) {
2316 characterDataHandler(handlerArg, &c, 1);
2318 else if (defaultHandler)
2319 reportDefault(parser, enc, s, end);
2320 /* We are at the end of the final buffer, should we check for
2321 XML_SUSPENDED, XML_FINISHED?
2323 if (startTagLevel == 0)
2324 return XML_ERROR_NO_ELEMENTS;
2325 if (tagLevel != startTagLevel)
2326 return XML_ERROR_ASYNC_ENTITY;
2328 return XML_ERROR_NONE;
2332 return XML_ERROR_NONE;
2334 if (startTagLevel > 0) {
2335 if (tagLevel != startTagLevel)
2336 return XML_ERROR_ASYNC_ENTITY;
2338 return XML_ERROR_NONE;
2340 return XML_ERROR_NO_ELEMENTS;
2341 case XML_TOK_INVALID:
2343 return XML_ERROR_INVALID_TOKEN;
2344 case XML_TOK_PARTIAL:
2347 return XML_ERROR_NONE;
2349 return XML_ERROR_UNCLOSED_TOKEN;
2350 case XML_TOK_PARTIAL_CHAR:
2353 return XML_ERROR_NONE;
2355 return XML_ERROR_PARTIAL_CHAR;
2356 case XML_TOK_ENTITY_REF:
2358 const XML_Char *name;
2360 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
2361 s + enc->minBytesPerChar,
2362 next - enc->minBytesPerChar);
2364 if (characterDataHandler)
2365 characterDataHandler(handlerArg, &ch, 1);
2366 else if (defaultHandler)
2367 reportDefault(parser, enc, s, next);
2370 name = poolStoreString(&dtd->pool, enc,
2371 s + enc->minBytesPerChar,
2372 next - enc->minBytesPerChar);
2374 return XML_ERROR_NO_MEMORY;
2375 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
2376 poolDiscard(&dtd->pool);
2377 /* First, determine if a check for an existing declaration is needed;
2378 if yes, check that the entity exists, and that it is internal,
2379 otherwise call the skipped entity or default handler.
2381 if (!dtd->hasParamEntityRefs || dtd->standalone) {
2383 return XML_ERROR_UNDEFINED_ENTITY;
2384 else if (!entity->is_internal)
2385 return XML_ERROR_ENTITY_DECLARED_IN_PE;
2388 if (skippedEntityHandler)
2389 skippedEntityHandler(handlerArg, name, 0);
2390 else if (defaultHandler)
2391 reportDefault(parser, enc, s, next);
2395 return XML_ERROR_RECURSIVE_ENTITY_REF;
2396 if (entity->notation)
2397 return XML_ERROR_BINARY_ENTITY_REF;
2398 if (entity->textPtr) {
2399 enum XML_Error result;
2400 if (!defaultExpandInternalEntities) {
2401 if (skippedEntityHandler)
2402 skippedEntityHandler(handlerArg, entity->name, 0);
2403 else if (defaultHandler)
2404 reportDefault(parser, enc, s, next);
2407 result = processInternalEntity(parser, entity, XML_FALSE);
2408 if (result != XML_ERROR_NONE)
2411 else if (externalEntityRefHandler) {
2412 const XML_Char *context;
2413 entity->open = XML_TRUE;
2414 context = getContext(parser);
2415 entity->open = XML_FALSE;
2417 return XML_ERROR_NO_MEMORY;
2418 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
2423 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2424 poolDiscard(&tempPool);
2426 else if (defaultHandler)
2427 reportDefault(parser, enc, s, next);
2430 case XML_TOK_START_TAG_NO_ATTS:
2432 case XML_TOK_START_TAG_WITH_ATTS:
2435 enum XML_Error result;
2439 freeTagList = freeTagList->parent;
2442 tag = (TAG *)MALLOC(sizeof(TAG));
2444 return XML_ERROR_NO_MEMORY;
2445 tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
2448 return XML_ERROR_NO_MEMORY;
2450 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2452 tag->bindings = NULL;
2453 tag->parent = tagStack;
2455 tag->name.localPart = NULL;
2456 tag->name.prefix = NULL;
2457 tag->rawName = s + enc->minBytesPerChar;
2458 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
2461 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2462 const char *fromPtr = tag->rawName;
2463 toPtr = (XML_Char *)tag->buf;
2467 const enum XML_Convert_Result convert_res = XmlConvert(enc,
2468 &fromPtr, rawNameEnd,
2469 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
2470 convLen = (int)(toPtr - (XML_Char *)tag->buf);
2471 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
2472 tag->name.strLen = convLen;
2475 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2477 char *temp = (char *)REALLOC(tag->buf, bufSize);
2479 return XML_ERROR_NO_MEMORY;
2481 tag->bufEnd = temp + bufSize;
2482 toPtr = (XML_Char *)temp + convLen;
2486 tag->name.str = (XML_Char *)tag->buf;
2487 *toPtr = XML_T('\0');
2488 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2491 if (startElementHandler)
2492 startElementHandler(handlerArg, tag->name.str,
2493 (const XML_Char **)atts);
2494 else if (defaultHandler)
2495 reportDefault(parser, enc, s, next);
2496 poolClear(&tempPool);
2499 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2501 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
2503 const char *rawName = s + enc->minBytesPerChar;
2504 enum XML_Error result;
2505 BINDING *bindings = NULL;
2506 XML_Bool noElmHandlers = XML_TRUE;
2508 name.str = poolStoreString(&tempPool, enc, rawName,
2509 rawName + XmlNameLength(enc, rawName));
2511 return XML_ERROR_NO_MEMORY;
2512 poolFinish(&tempPool);
2513 result = storeAtts(parser, enc, s, &name, &bindings);
2516 poolFinish(&tempPool);
2517 if (startElementHandler) {
2518 startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
2519 noElmHandlers = XML_FALSE;
2521 if (endElementHandler) {
2522 if (startElementHandler)
2523 *eventPP = *eventEndPP;
2524 endElementHandler(handlerArg, name.str);
2525 noElmHandlers = XML_FALSE;
2527 if (noElmHandlers && defaultHandler)
2528 reportDefault(parser, enc, s, next);
2529 poolClear(&tempPool);
2531 BINDING *b = bindings;
2532 if (endNamespaceDeclHandler)
2533 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2534 bindings = bindings->nextTagBinding;
2535 b->nextTagBinding = freeBindingList;
2536 freeBindingList = b;
2537 b->prefix->binding = b->prevPrefixBinding;
2541 return epilogProcessor(parser, next, end, nextPtr);
2543 case XML_TOK_END_TAG:
2544 if (tagLevel == startTagLevel)
2545 return XML_ERROR_ASYNC_ENTITY;
2548 const char *rawName;
2549 TAG *tag = tagStack;
2550 tagStack = tag->parent;
2551 tag->parent = freeTagList;
2553 rawName = s + enc->minBytesPerChar*2;
2554 len = XmlNameLength(enc, rawName);
2555 if (len != tag->rawNameLength
2556 || memcmp(tag->rawName, rawName, len) != 0) {
2558 return XML_ERROR_TAG_MISMATCH;
2561 if (endElementHandler) {
2562 const XML_Char *localPart;
2563 const XML_Char *prefix;
2565 localPart = tag->name.localPart;
2566 if (ns && localPart) {
2567 /* localPart and prefix may have been overwritten in
2568 tag->name.str, since this points to the binding->uri
2569 buffer which gets re-used; so we have to add them again
2571 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2572 /* don't need to check for space - already done in storeAtts() */
2573 while (*localPart) *uri++ = *localPart++;
2574 prefix = (XML_Char *)tag->name.prefix;
2575 if (ns_triplets && prefix) {
2576 *uri++ = namespaceSeparator;
2577 while (*prefix) *uri++ = *prefix++;
2581 endElementHandler(handlerArg, tag->name.str);
2583 else if (defaultHandler)
2584 reportDefault(parser, enc, s, next);
2585 while (tag->bindings) {
2586 BINDING *b = tag->bindings;
2587 if (endNamespaceDeclHandler)
2588 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2589 tag->bindings = tag->bindings->nextTagBinding;
2590 b->nextTagBinding = freeBindingList;
2591 freeBindingList = b;
2592 b->prefix->binding = b->prevPrefixBinding;
2595 return epilogProcessor(parser, next, end, nextPtr);
2598 case XML_TOK_CHAR_REF:
2600 int n = XmlCharRefNumber(enc, s);
2602 return XML_ERROR_BAD_CHAR_REF;
2603 if (characterDataHandler) {
2604 XML_Char buf[XML_ENCODE_MAX];
2605 characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
2607 else if (defaultHandler)
2608 reportDefault(parser, enc, s, next);
2611 case XML_TOK_XML_DECL:
2612 return XML_ERROR_MISPLACED_XML_PI;
2613 case XML_TOK_DATA_NEWLINE:
2614 if (characterDataHandler) {
2616 characterDataHandler(handlerArg, &c, 1);
2618 else if (defaultHandler)
2619 reportDefault(parser, enc, s, next);
2621 case XML_TOK_CDATA_SECT_OPEN:
2623 enum XML_Error result;
2624 if (startCdataSectionHandler)
2625 startCdataSectionHandler(handlerArg);
2627 /* Suppose you doing a transformation on a document that involves
2628 changing only the character data. You set up a defaultHandler
2629 and a characterDataHandler. The defaultHandler simply copies
2630 characters through. The characterDataHandler does the
2631 transformation and writes the characters out escaping them as
2632 necessary. This case will fail to work if we leave out the
2633 following two lines (because & and < inside CDATA sections will
2634 be incorrectly escaped).
2636 However, now we have a start/endCdataSectionHandler, so it seems
2637 easier to let the user deal with this.
2639 else if (characterDataHandler)
2640 characterDataHandler(handlerArg, dataBuf, 0);
2642 else if (defaultHandler)
2643 reportDefault(parser, enc, s, next);
2644 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
2645 if (result != XML_ERROR_NONE)
2648 processor = cdataSectionProcessor;
2653 case XML_TOK_TRAILING_RSQB:
2656 return XML_ERROR_NONE;
2658 if (characterDataHandler) {
2659 if (MUST_CONVERT(enc, s)) {
2660 ICHAR *dataPtr = (ICHAR *)dataBuf;
2661 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
2662 characterDataHandler(handlerArg, dataBuf,
2663 (int)(dataPtr - (ICHAR *)dataBuf));
2666 characterDataHandler(handlerArg,
2668 (int)((XML_Char *)end - (XML_Char *)s));
2670 else if (defaultHandler)
2671 reportDefault(parser, enc, s, end);
2672 /* We are at the end of the final buffer, should we check for
2673 XML_SUSPENDED, XML_FINISHED?
2675 if (startTagLevel == 0) {
2677 return XML_ERROR_NO_ELEMENTS;
2679 if (tagLevel != startTagLevel) {
2681 return XML_ERROR_ASYNC_ENTITY;
2684 return XML_ERROR_NONE;
2685 case XML_TOK_DATA_CHARS:
2687 XML_CharacterDataHandler charDataHandler = characterDataHandler;
2688 if (charDataHandler) {
2689 if (MUST_CONVERT(enc, s)) {
2691 ICHAR *dataPtr = (ICHAR *)dataBuf;
2692 const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
2694 charDataHandler(handlerArg, dataBuf,
2695 (int)(dataPtr - (ICHAR *)dataBuf));
2696 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
2702 charDataHandler(handlerArg,
2704 (int)((XML_Char *)next - (XML_Char *)s));
2706 else if (defaultHandler)
2707 reportDefault(parser, enc, s, next);
2711 if (!reportProcessingInstruction(parser, enc, s, next))
2712 return XML_ERROR_NO_MEMORY;
2714 case XML_TOK_COMMENT:
2715 if (!reportComment(parser, enc, s, next))
2716 return XML_ERROR_NO_MEMORY;
2720 reportDefault(parser, enc, s, next);
2723 *eventPP = s = next;
2724 switch (ps_parsing) {
2727 return XML_ERROR_NONE;
2729 return XML_ERROR_ABORTED;
2736 /* Precondition: all arguments must be non-NULL;
2738 - normalize attributes
2739 - check attributes for well-formedness
2740 - generate namespace aware attribute names (URI, prefix)
2741 - build list of attributes for startElementHandler
2742 - default attributes
2743 - process namespace declarations (check and report them)
2744 - generate namespace aware element name (URI, prefix)
2746 static enum XML_Error
2747 storeAtts(XML_Parser parser, const ENCODING *enc,
2748 const char *attStr, TAG_NAME *tagNamePtr,
2749 BINDING **bindingsPtr)
2751 DTD * const dtd = _dtd; /* save one level of indirection */
2752 ELEMENT_TYPE *elementType;
2754 const XML_Char **appAtts; /* the attribute list for the application */
2762 const XML_Char *localPart;
2764 /* lookup the element type name */
2765 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
2767 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
2769 return XML_ERROR_NO_MEMORY;
2770 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
2771 sizeof(ELEMENT_TYPE));
2773 return XML_ERROR_NO_MEMORY;
2774 if (ns && !setElementTypePrefix(parser, elementType))
2775 return XML_ERROR_NO_MEMORY;
2777 nDefaultAtts = elementType->nDefaultAtts;
2779 /* get the attributes from the tokenizer */
2780 n = XmlGetAttributes(enc, attStr, attsSize, atts);
2781 if (n + nDefaultAtts > attsSize) {
2782 int oldAttsSize = attsSize;
2784 #ifdef XML_ATTR_INFO
2785 XML_AttrInfo *temp2;
2787 attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
2788 temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
2790 return XML_ERROR_NO_MEMORY;
2792 #ifdef XML_ATTR_INFO
2793 temp2 = (XML_AttrInfo *)REALLOC((void *)attInfo, attsSize * sizeof(XML_AttrInfo));
2795 return XML_ERROR_NO_MEMORY;
2798 if (n > oldAttsSize)
2799 XmlGetAttributes(enc, attStr, n, atts);
2802 appAtts = (const XML_Char **)atts;
2803 for (i = 0; i < n; i++) {
2804 ATTRIBUTE *currAtt = &atts[i];
2805 #ifdef XML_ATTR_INFO
2806 XML_AttrInfo *currAttInfo = &attInfo[i];
2808 /* add the name and value to the attribute list */
2809 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
2811 + XmlNameLength(enc, currAtt->name));
2813 return XML_ERROR_NO_MEMORY;
2814 #ifdef XML_ATTR_INFO
2815 currAttInfo->nameStart = parseEndByteIndex - (parseEndPtr - currAtt->name);
2816 currAttInfo->nameEnd = currAttInfo->nameStart +
2817 XmlNameLength(enc, currAtt->name);
2818 currAttInfo->valueStart = parseEndByteIndex -
2819 (parseEndPtr - currAtt->valuePtr);
2820 currAttInfo->valueEnd = parseEndByteIndex - (parseEndPtr - currAtt->valueEnd);
2822 /* Detect duplicate attributes by their QNames. This does not work when
2823 namespace processing is turned on and different prefixes for the same
2824 namespace are used. For this case we have a check further down.
2826 if ((attId->name)[-1]) {
2827 if (enc == encoding)
2828 eventPtr = atts[i].name;
2829 return XML_ERROR_DUPLICATE_ATTRIBUTE;
2831 (attId->name)[-1] = 1;
2832 appAtts[attIndex++] = attId->name;
2833 if (!atts[i].normalized) {
2834 enum XML_Error result;
2835 XML_Bool isCdata = XML_TRUE;
2837 /* figure out whether declared as other than CDATA */
2838 if (attId->maybeTokenized) {
2840 for (j = 0; j < nDefaultAtts; j++) {
2841 if (attId == elementType->defaultAtts[j].id) {
2842 isCdata = elementType->defaultAtts[j].isCdata;
2848 /* normalize the attribute value */
2849 result = storeAttributeValue(parser, enc, isCdata,
2850 atts[i].valuePtr, atts[i].valueEnd,
2854 appAtts[attIndex] = poolStart(&tempPool);
2855 poolFinish(&tempPool);
2858 /* the value did not need normalizing */
2859 appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
2861 if (appAtts[attIndex] == 0)
2862 return XML_ERROR_NO_MEMORY;
2863 poolFinish(&tempPool);
2865 /* handle prefixed attribute names */
2866 if (attId->prefix) {
2868 /* deal with namespace declarations here */
2869 enum XML_Error result = addBinding(parser, attId->prefix, attId,
2870 appAtts[attIndex], bindingsPtr);
2876 /* deal with other prefixed names later */
2879 (attId->name)[-1] = 2;
2886 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
2887 nSpecifiedAtts = attIndex;
2888 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
2889 for (i = 0; i < attIndex; i += 2)
2890 if (appAtts[i] == elementType->idAtt->name) {
2898 /* do attribute defaulting */
2899 for (i = 0; i < nDefaultAtts; i++) {
2900 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
2901 if (!(da->id->name)[-1] && da->value) {
2902 if (da->id->prefix) {
2903 if (da->id->xmlns) {
2904 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
2905 da->value, bindingsPtr);
2910 (da->id->name)[-1] = 2;
2912 appAtts[attIndex++] = da->id->name;
2913 appAtts[attIndex++] = da->value;
2917 (da->id->name)[-1] = 1;
2918 appAtts[attIndex++] = da->id->name;
2919 appAtts[attIndex++] = da->value;
2923 appAtts[attIndex] = 0;
2925 /* expand prefixed attribute names, check for duplicates,
2926 and clear flags that say whether attributes were specified */
2929 int j; /* hash table index */
2930 unsigned long version = nsAttsVersion;
2931 int nsAttsSize = (int)1 << nsAttsPower;
2932 /* size of hash table must be at least 2 * (# of prefixed attributes) */
2933 if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */
2935 /* hash table size must also be a power of 2 and >= 8 */
2936 while (nPrefixes >> nsAttsPower++);
2937 if (nsAttsPower < 3)
2939 nsAttsSize = (int)1 << nsAttsPower;
2940 temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
2942 return XML_ERROR_NO_MEMORY;
2944 version = 0; /* force re-initialization of nsAtts hash table */
2946 /* using a version flag saves us from initializing nsAtts every time */
2947 if (!version) { /* initialize version flags when version wraps around */
2948 version = INIT_ATTS_VERSION;
2949 for (j = nsAttsSize; j != 0; )
2950 nsAtts[--j].version = version;
2952 nsAttsVersion = --version;
2954 /* expand prefixed names and check for duplicates */
2955 for (; i < attIndex; i += 2) {
2956 const XML_Char *s = appAtts[i];
2957 if (s[-1] == 2) { /* prefixed */
2960 unsigned long uriHash = hash_secret_salt;
2961 ((XML_Char *)s)[-1] = 0; /* clear flag */
2962 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
2963 if (!id || !id->prefix)
2964 return XML_ERROR_NO_MEMORY;
2965 b = id->prefix->binding;
2967 return XML_ERROR_UNBOUND_PREFIX;
2969 /* as we expand the name we also calculate its hash value */
2970 for (j = 0; j < b->uriLen; j++) {
2971 const XML_Char c = b->uri[j];
2972 if (!poolAppendChar(&tempPool, c))
2973 return XML_ERROR_NO_MEMORY;
2974 uriHash = CHAR_HASH(uriHash, c);
2976 while (*s++ != XML_T(ASCII_COLON))
2978 do { /* copies null terminator */
2979 const XML_Char c = *s;
2980 if (!poolAppendChar(&tempPool, *s))
2981 return XML_ERROR_NO_MEMORY;
2982 uriHash = CHAR_HASH(uriHash, c);
2985 { /* Check hash table for duplicate of expanded name (uriName).
2986 Derived from code in lookup(parser, HASH_TABLE *table, ...).
2988 unsigned char step = 0;
2989 unsigned long mask = nsAttsSize - 1;
2990 j = uriHash & mask; /* index into hash table */
2991 while (nsAtts[j].version == version) {
2992 /* for speed we compare stored hash values first */
2993 if (uriHash == nsAtts[j].hash) {
2994 const XML_Char *s1 = poolStart(&tempPool);
2995 const XML_Char *s2 = nsAtts[j].uriName;
2996 /* s1 is null terminated, but not s2 */
2997 for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
2999 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3002 step = PROBE_STEP(uriHash, mask, nsAttsPower);
3003 j < step ? (j += nsAttsSize - step) : (j -= step);
3007 if (ns_triplets) { /* append namespace separator and prefix */
3008 tempPool.ptr[-1] = namespaceSeparator;
3009 s = b->prefix->name;
3011 if (!poolAppendChar(&tempPool, *s))
3012 return XML_ERROR_NO_MEMORY;
3016 /* store expanded name in attribute list */
3017 s = poolStart(&tempPool);
3018 poolFinish(&tempPool);
3021 /* fill empty slot with new version, uriName and hash value */
3022 nsAtts[j].version = version;
3023 nsAtts[j].hash = uriHash;
3024 nsAtts[j].uriName = s;
3031 else /* not prefixed */
3032 ((XML_Char *)s)[-1] = 0; /* clear flag */
3035 /* clear flags for the remaining attributes */
3036 for (; i < attIndex; i += 2)
3037 ((XML_Char *)(appAtts[i]))[-1] = 0;
3038 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
3039 binding->attId->name[-1] = 0;
3042 return XML_ERROR_NONE;
3044 /* expand the element type name */
3045 if (elementType->prefix) {
3046 binding = elementType->prefix->binding;
3048 return XML_ERROR_UNBOUND_PREFIX;
3049 localPart = tagNamePtr->str;
3050 while (*localPart++ != XML_T(ASCII_COLON))
3053 else if (dtd->defaultPrefix.binding) {
3054 binding = dtd->defaultPrefix.binding;
3055 localPart = tagNamePtr->str;
3058 return XML_ERROR_NONE;
3060 if (ns_triplets && binding->prefix->name) {
3061 for (; binding->prefix->name[prefixLen++];)
3062 ; /* prefixLen includes null terminator */
3064 tagNamePtr->localPart = localPart;
3065 tagNamePtr->uriLen = binding->uriLen;
3066 tagNamePtr->prefix = binding->prefix->name;
3067 tagNamePtr->prefixLen = prefixLen;
3068 for (i = 0; localPart[i++];)
3069 ; /* i includes null terminator */
3070 n = i + binding->uriLen + prefixLen;
3071 if (n > binding->uriAlloc) {
3073 uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
3075 return XML_ERROR_NO_MEMORY;
3076 binding->uriAlloc = n + EXPAND_SPARE;
3077 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
3078 for (p = tagStack; p; p = p->parent)
3079 if (p->name.str == binding->uri)
3084 /* if namespaceSeparator != '\0' then uri includes it already */
3085 uri = binding->uri + binding->uriLen;
3086 memcpy(uri, localPart, i * sizeof(XML_Char));
3087 /* we always have a namespace separator between localPart and prefix */
3090 *uri = namespaceSeparator; /* replace null terminator */
3091 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
3093 tagNamePtr->str = binding->uri;
3094 return XML_ERROR_NONE;
3097 /* addBinding() overwrites the value of prefix->binding without checking.
3098 Therefore one must keep track of the old value outside of addBinding().
3100 static enum XML_Error
3101 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
3102 const XML_Char *uri, BINDING **bindingsPtr)
3104 static const XML_Char xmlNamespace[] = {
3105 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3106 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
3107 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
3108 ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
3109 ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
3112 static const int xmlLen =
3113 (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
3114 static const XML_Char xmlnsNamespace[] = {
3115 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3116 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
3117 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
3118 ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
3121 static const int xmlnsLen =
3122 (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
3124 XML_Bool mustBeXML = XML_FALSE;
3125 XML_Bool isXML = XML_TRUE;
3126 XML_Bool isXMLNS = XML_TRUE;
3131 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
3132 if (*uri == XML_T('\0') && prefix->name)
3133 return XML_ERROR_UNDECLARING_PREFIX;
3136 && prefix->name[0] == XML_T(ASCII_x)
3137 && prefix->name[1] == XML_T(ASCII_m)
3138 && prefix->name[2] == XML_T(ASCII_l)) {
3140 /* Not allowed to bind xmlns */
3141 if (prefix->name[3] == XML_T(ASCII_n)
3142 && prefix->name[4] == XML_T(ASCII_s)
3143 && prefix->name[5] == XML_T('\0'))
3144 return XML_ERROR_RESERVED_PREFIX_XMLNS;
3146 if (prefix->name[3] == XML_T('\0'))
3147 mustBeXML = XML_TRUE;
3150 for (len = 0; uri[len]; len++) {
3151 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
3154 if (!mustBeXML && isXMLNS
3155 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3156 isXMLNS = XML_FALSE;
3158 isXML = isXML && len == xmlLen;
3159 isXMLNS = isXMLNS && len == xmlnsLen;
3161 if (mustBeXML != isXML)
3162 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3163 : XML_ERROR_RESERVED_NAMESPACE_URI;
3166 return XML_ERROR_RESERVED_NAMESPACE_URI;
3168 if (namespaceSeparator)
3170 if (freeBindingList) {
3171 b = freeBindingList;
3172 if (len > b->uriAlloc) {
3173 XML_Char *temp = (XML_Char *)REALLOC(b->uri,
3174 sizeof(XML_Char) * (len + EXPAND_SPARE));
3176 return XML_ERROR_NO_MEMORY;
3178 b->uriAlloc = len + EXPAND_SPARE;
3180 freeBindingList = b->nextTagBinding;
3183 b = (BINDING *)MALLOC(sizeof(BINDING));
3185 return XML_ERROR_NO_MEMORY;
3186 b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
3189 return XML_ERROR_NO_MEMORY;
3191 b->uriAlloc = len + EXPAND_SPARE;
3194 memcpy(b->uri, uri, len * sizeof(XML_Char));
3195 if (namespaceSeparator)
3196 b->uri[len - 1] = namespaceSeparator;
3199 b->prevPrefixBinding = prefix->binding;
3200 /* NULL binding when default namespace undeclared */
3201 if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
3202 prefix->binding = NULL;
3204 prefix->binding = b;
3205 b->nextTagBinding = *bindingsPtr;
3207 /* if attId == NULL then we are not starting a namespace scope */
3208 if (attId && startNamespaceDeclHandler)
3209 startNamespaceDeclHandler(handlerArg, prefix->name,
3210 prefix->binding ? uri : 0);
3211 return XML_ERROR_NONE;
3214 /* The idea here is to avoid using stack for each CDATA section when
3215 the whole file is parsed with one call.
3217 static enum XML_Error PTRCALL
3218 cdataSectionProcessor(XML_Parser parser,
3221 const char **endPtr)
3223 enum XML_Error result = doCdataSection(parser, encoding, &start, end,
3224 endPtr, (XML_Bool)!ps_finalBuffer);
3225 if (result != XML_ERROR_NONE)
3228 if (parentParser) { /* we are parsing an external entity */
3229 processor = externalEntityContentProcessor;
3230 return externalEntityContentProcessor(parser, start, end, endPtr);
3233 processor = contentProcessor;
3234 return contentProcessor(parser, start, end, endPtr);
3240 /* startPtr gets set to non-null if the section is closed, and to null if
3241 the section is not yet closed.
3243 static enum XML_Error
3244 doCdataSection(XML_Parser parser,
3245 const ENCODING *enc,
3246 const char **startPtr,
3248 const char **nextPtr,
3251 const char *s = *startPtr;
3252 const char **eventPP;
3253 const char **eventEndPP;
3254 if (enc == encoding) {
3255 eventPP = &eventPtr;
3257 eventEndPP = &eventEndPtr;
3260 eventPP = &(openInternalEntities->internalEventPtr);
3261 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3268 int tok = XmlCdataSectionTok(enc, s, end, &next);
3271 case XML_TOK_CDATA_SECT_CLOSE:
3272 if (endCdataSectionHandler)
3273 endCdataSectionHandler(handlerArg);
3275 /* see comment under XML_TOK_CDATA_SECT_OPEN */
3276 else if (characterDataHandler)
3277 characterDataHandler(handlerArg, dataBuf, 0);
3279 else if (defaultHandler)
3280 reportDefault(parser, enc, s, next);
3283 if (ps_parsing == XML_FINISHED)
3284 return XML_ERROR_ABORTED;
3286 return XML_ERROR_NONE;
3287 case XML_TOK_DATA_NEWLINE:
3288 if (characterDataHandler) {
3290 characterDataHandler(handlerArg, &c, 1);
3292 else if (defaultHandler)
3293 reportDefault(parser, enc, s, next);
3295 case XML_TOK_DATA_CHARS:
3297 XML_CharacterDataHandler charDataHandler = characterDataHandler;
3298 if (charDataHandler) {
3299 if (MUST_CONVERT(enc, s)) {
3301 ICHAR *dataPtr = (ICHAR *)dataBuf;
3302 const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
3304 charDataHandler(handlerArg, dataBuf,
3305 (int)(dataPtr - (ICHAR *)dataBuf));
3306 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
3312 charDataHandler(handlerArg,
3314 (int)((XML_Char *)next - (XML_Char *)s));
3316 else if (defaultHandler)
3317 reportDefault(parser, enc, s, next);
3320 case XML_TOK_INVALID:
3322 return XML_ERROR_INVALID_TOKEN;
3323 case XML_TOK_PARTIAL_CHAR:
3326 return XML_ERROR_NONE;
3328 return XML_ERROR_PARTIAL_CHAR;
3329 case XML_TOK_PARTIAL:
3333 return XML_ERROR_NONE;
3335 return XML_ERROR_UNCLOSED_CDATA_SECTION;
3338 return XML_ERROR_UNEXPECTED_STATE;
3341 *eventPP = s = next;
3342 switch (ps_parsing) {
3345 return XML_ERROR_NONE;
3347 return XML_ERROR_ABORTED;
3356 /* The idea here is to avoid using stack for each IGNORE section when
3357 the whole file is parsed with one call.
3359 static enum XML_Error PTRCALL
3360 ignoreSectionProcessor(XML_Parser parser,
3363 const char **endPtr)
3365 enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
3366 endPtr, (XML_Bool)!ps_finalBuffer);
3367 if (result != XML_ERROR_NONE)
3370 processor = prologProcessor;
3371 return prologProcessor(parser, start, end, endPtr);
3376 /* startPtr gets set to non-null is the section is closed, and to null
3377 if the section is not yet closed.
3379 static enum XML_Error
3380 doIgnoreSection(XML_Parser parser,
3381 const ENCODING *enc,
3382 const char **startPtr,
3384 const char **nextPtr,
3389 const char *s = *startPtr;
3390 const char **eventPP;
3391 const char **eventEndPP;
3392 if (enc == encoding) {
3393 eventPP = &eventPtr;
3395 eventEndPP = &eventEndPtr;
3398 eventPP = &(openInternalEntities->internalEventPtr);
3399 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3403 tok = XmlIgnoreSectionTok(enc, s, end, &next);
3406 case XML_TOK_IGNORE_SECT:
3408 reportDefault(parser, enc, s, next);
3411 if (ps_parsing == XML_FINISHED)
3412 return XML_ERROR_ABORTED;
3414 return XML_ERROR_NONE;
3415 case XML_TOK_INVALID:
3417 return XML_ERROR_INVALID_TOKEN;
3418 case XML_TOK_PARTIAL_CHAR:
3421 return XML_ERROR_NONE;
3423 return XML_ERROR_PARTIAL_CHAR;
3424 case XML_TOK_PARTIAL:
3428 return XML_ERROR_NONE;
3430 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3433 return XML_ERROR_UNEXPECTED_STATE;
3438 #endif /* XML_DTD */
3440 static enum XML_Error
3441 initializeEncoding(XML_Parser parser)
3445 char encodingBuf[128];
3446 if (!protocolEncodingName)
3450 for (i = 0; protocolEncodingName[i]; i++) {
3451 if (i == sizeof(encodingBuf) - 1
3452 || (protocolEncodingName[i] & ~0x7f) != 0) {
3453 encodingBuf[0] = '\0';
3456 encodingBuf[i] = (char)protocolEncodingName[i];
3458 encodingBuf[i] = '\0';
3462 s = protocolEncodingName;
3464 if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
3465 return XML_ERROR_NONE;
3466 return handleUnknownEncoding(parser, protocolEncodingName);
3469 static enum XML_Error
3470 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
3471 const char *s, const char *next)
3473 const char *encodingName = NULL;
3474 const XML_Char *storedEncName = NULL;
3475 const ENCODING *newEncoding = NULL;
3476 const char *version = NULL;
3477 const char *versionend;
3478 const XML_Char *storedversion = NULL;
3479 int standalone = -1;
3482 : XmlParseXmlDecl)(isGeneralTextEntity,
3492 if (isGeneralTextEntity)
3493 return XML_ERROR_TEXT_DECL;
3495 return XML_ERROR_XML_DECL;
3497 if (!isGeneralTextEntity && standalone == 1) {
3498 _dtd->standalone = XML_TRUE;
3500 if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
3501 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
3502 #endif /* XML_DTD */
3504 if (xmlDeclHandler) {
3505 if (encodingName != NULL) {
3506 storedEncName = poolStoreString(&temp2Pool,
3510 + XmlNameLength(encoding, encodingName));
3512 return XML_ERROR_NO_MEMORY;
3513 poolFinish(&temp2Pool);
3516 storedversion = poolStoreString(&temp2Pool,
3519 versionend - encoding->minBytesPerChar);
3521 return XML_ERROR_NO_MEMORY;
3523 xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
3525 else if (defaultHandler)
3526 reportDefault(parser, encoding, s, next);
3527 if (protocolEncodingName == NULL) {
3529 if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
3530 eventPtr = encodingName;
3531 return XML_ERROR_INCORRECT_ENCODING;
3533 encoding = newEncoding;
3535 else if (encodingName) {
3536 enum XML_Error result;
3537 if (!storedEncName) {
3538 storedEncName = poolStoreString(
3539 &temp2Pool, encoding, encodingName,
3540 encodingName + XmlNameLength(encoding, encodingName));
3542 return XML_ERROR_NO_MEMORY;
3544 result = handleUnknownEncoding(parser, storedEncName);
3545 poolClear(&temp2Pool);
3546 if (result == XML_ERROR_UNKNOWN_ENCODING)
3547 eventPtr = encodingName;
3552 if (storedEncName || storedversion)
3553 poolClear(&temp2Pool);
3555 return XML_ERROR_NONE;
3558 static enum XML_Error
3559 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
3561 if (unknownEncodingHandler) {
3564 for (i = 0; i < 256; i++)
3566 info.convert = NULL;
3568 info.release = NULL;
3569 if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
3572 unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
3573 if (!unknownEncodingMem) {
3575 info.release(info.data);
3576 return XML_ERROR_NO_MEMORY;
3579 ? XmlInitUnknownEncodingNS
3580 : XmlInitUnknownEncoding)(unknownEncodingMem,
3585 unknownEncodingData = info.data;
3586 unknownEncodingRelease = info.release;
3588 return XML_ERROR_NONE;
3591 if (info.release != NULL)
3592 info.release(info.data);
3594 return XML_ERROR_UNKNOWN_ENCODING;
3597 static enum XML_Error PTRCALL
3598 prologInitProcessor(XML_Parser parser,
3601 const char **nextPtr)
3603 enum XML_Error result = initializeEncoding(parser);
3604 if (result != XML_ERROR_NONE)
3606 processor = prologProcessor;
3607 return prologProcessor(parser, s, end, nextPtr);
3612 static enum XML_Error PTRCALL
3613 externalParEntInitProcessor(XML_Parser parser,
3616 const char **nextPtr)
3618 enum XML_Error result = initializeEncoding(parser);
3619 if (result != XML_ERROR_NONE)
3622 /* we know now that XML_Parse(Buffer) has been called,
3623 so we consider the external parameter entity read */
3624 _dtd->paramEntityRead = XML_TRUE;
3626 if (prologState.inEntityValue) {
3627 processor = entityValueInitProcessor;
3628 return entityValueInitProcessor(parser, s, end, nextPtr);
3631 processor = externalParEntProcessor;
3632 return externalParEntProcessor(parser, s, end, nextPtr);
3636 static enum XML_Error PTRCALL
3637 entityValueInitProcessor(XML_Parser parser,
3640 const char **nextPtr)
3643 const char *start = s;
3644 const char *next = start;
3648 tok = XmlPrologTok(encoding, start, end, &next);
3651 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3653 return XML_ERROR_NONE;
3656 case XML_TOK_INVALID:
3657 return XML_ERROR_INVALID_TOKEN;
3658 case XML_TOK_PARTIAL:
3659 return XML_ERROR_UNCLOSED_TOKEN;
3660 case XML_TOK_PARTIAL_CHAR:
3661 return XML_ERROR_PARTIAL_CHAR;
3662 case XML_TOK_NONE: /* start == end */
3666 /* found end of entity value - can store it now */
3667 return storeEntityValue(parser, encoding, s, end);
3669 else if (tok == XML_TOK_XML_DECL) {
3670 enum XML_Error result;
3671 result = processXmlDecl(parser, 0, start, next);
3672 if (result != XML_ERROR_NONE)
3674 switch (ps_parsing) {
3677 return XML_ERROR_NONE;
3679 return XML_ERROR_ABORTED;
3683 /* stop scanning for text declaration - we found one */
3684 processor = entityValueProcessor;
3685 return entityValueProcessor(parser, next, end, nextPtr);
3687 /* If we are at the end of the buffer, this would cause XmlPrologTok to
3688 return XML_TOK_NONE on the next call, which would then cause the
3689 function to exit with *nextPtr set to s - that is what we want for other
3690 tokens, but not for the BOM - we would rather like to skip it;
3691 then, when this routine is entered the next time, XmlPrologTok will
3692 return XML_TOK_INVALID, since the BOM is still in the buffer
3694 else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
3696 return XML_ERROR_NONE;
3703 static enum XML_Error PTRCALL
3704 externalParEntProcessor(XML_Parser parser,
3707 const char **nextPtr)
3709 const char *next = s;
3712 tok = XmlPrologTok(encoding, s, end, &next);
3714 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3716 return XML_ERROR_NONE;
3719 case XML_TOK_INVALID:
3720 return XML_ERROR_INVALID_TOKEN;
3721 case XML_TOK_PARTIAL:
3722 return XML_ERROR_UNCLOSED_TOKEN;
3723 case XML_TOK_PARTIAL_CHAR:
3724 return XML_ERROR_PARTIAL_CHAR;
3725 case XML_TOK_NONE: /* start == end */
3730 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
3731 However, when parsing an external subset, doProlog will not accept a BOM
3732 as valid, and report a syntax error, so we have to skip the BOM
3734 else if (tok == XML_TOK_BOM) {
3736 tok = XmlPrologTok(encoding, s, end, &next);
3739 processor = prologProcessor;
3740 return doProlog(parser, encoding, s, end, tok, next,
3741 nextPtr, (XML_Bool)!ps_finalBuffer);
3744 static enum XML_Error PTRCALL
3745 entityValueProcessor(XML_Parser parser,
3748 const char **nextPtr)
3750 const char *start = s;
3751 const char *next = s;
3752 const ENCODING *enc = encoding;
3756 tok = XmlPrologTok(enc, start, end, &next);
3758 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3760 return XML_ERROR_NONE;
3763 case XML_TOK_INVALID:
3764 return XML_ERROR_INVALID_TOKEN;
3765 case XML_TOK_PARTIAL:
3766 return XML_ERROR_UNCLOSED_TOKEN;
3767 case XML_TOK_PARTIAL_CHAR:
3768 return XML_ERROR_PARTIAL_CHAR;
3769 case XML_TOK_NONE: /* start == end */
3773 /* found end of entity value - can store it now */
3774 return storeEntityValue(parser, enc, s, end);
3780 #endif /* XML_DTD */
3782 static enum XML_Error PTRCALL
3783 prologProcessor(XML_Parser parser,
3786 const char **nextPtr)
3788 const char *next = s;
3789 int tok = XmlPrologTok(encoding, s, end, &next);
3790 return doProlog(parser, encoding, s, end, tok, next,
3791 nextPtr, (XML_Bool)!ps_finalBuffer);
3794 static enum XML_Error
3795 doProlog(XML_Parser parser,
3796 const ENCODING *enc,
3801 const char **nextPtr,
3805 static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
3806 #endif /* XML_DTD */
3807 static const XML_Char atypeCDATA[] =
3808 { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
3809 static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
3810 static const XML_Char atypeIDREF[] =
3811 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
3812 static const XML_Char atypeIDREFS[] =
3813 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
3814 static const XML_Char atypeENTITY[] =
3815 { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
3816 static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
3817 ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
3818 static const XML_Char atypeNMTOKEN[] = {
3819 ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
3820 static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
3821 ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
3822 static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
3823 ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
3824 static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
3825 static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
3827 /* save one level of indirection */
3828 DTD * const dtd = _dtd;
3830 const char **eventPP;
3831 const char **eventEndPP;
3832 enum XML_Content_Quant quant;
3834 if (enc == encoding) {
3835 eventPP = &eventPtr;
3836 eventEndPP = &eventEndPtr;
3839 eventPP = &(openInternalEntities->internalEventPtr);
3840 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3845 XML_Bool handleDefault = XML_TRUE;
3849 if (haveMore && tok != XML_TOK_INVALID) {
3851 return XML_ERROR_NONE;
3854 case XML_TOK_INVALID:
3856 return XML_ERROR_INVALID_TOKEN;
3857 case XML_TOK_PARTIAL:
3858 return XML_ERROR_UNCLOSED_TOKEN;
3859 case XML_TOK_PARTIAL_CHAR:
3860 return XML_ERROR_PARTIAL_CHAR;
3861 case -XML_TOK_PROLOG_S:
3866 /* for internal PE NOT referenced between declarations */
3867 if (enc != encoding && !openInternalEntities->betweenDecl) {
3869 return XML_ERROR_NONE;
3871 /* WFC: PE Between Declarations - must check that PE contains
3872 complete markup, not only for external PEs, but also for
3873 internal PEs if the reference occurs between declarations.
3875 if (isParamEntity || enc != encoding) {
3876 if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
3878 return XML_ERROR_INCOMPLETE_PE;
3880 return XML_ERROR_NONE;
3882 #endif /* XML_DTD */
3883 return XML_ERROR_NO_ELEMENTS;
3890 role = XmlTokenRole(&prologState, tok, s, next, enc);
3892 case XML_ROLE_XML_DECL:
3894 enum XML_Error result = processXmlDecl(parser, 0, s, next);
3895 if (result != XML_ERROR_NONE)
3898 handleDefault = XML_FALSE;
3901 case XML_ROLE_DOCTYPE_NAME:
3902 if (startDoctypeDeclHandler) {
3903 doctypeName = poolStoreString(&tempPool, enc, s, next);
3905 return XML_ERROR_NO_MEMORY;
3906 poolFinish(&tempPool);
3907 doctypePubid = NULL;
3908 handleDefault = XML_FALSE;
3910 doctypeSysid = NULL; /* always initialize to NULL */
3912 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
3913 if (startDoctypeDeclHandler) {
3914 startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
3917 poolClear(&tempPool);
3918 handleDefault = XML_FALSE;
3922 case XML_ROLE_TEXT_DECL:
3924 enum XML_Error result = processXmlDecl(parser, 1, s, next);
3925 if (result != XML_ERROR_NONE)
3928 handleDefault = XML_FALSE;
3931 #endif /* XML_DTD */
3932 case XML_ROLE_DOCTYPE_PUBLIC_ID:
3934 useForeignDTD = XML_FALSE;
3935 declEntity = (ENTITY *)lookup(parser,
3936 &dtd->paramEntities,
3940 return XML_ERROR_NO_MEMORY;
3941 #endif /* XML_DTD */
3942 dtd->hasParamEntityRefs = XML_TRUE;
3943 if (startDoctypeDeclHandler) {
3945 if (!XmlIsPublicId(enc, s, next, eventPP))
3946 return XML_ERROR_PUBLICID;
3947 pubId = poolStoreString(&tempPool, enc,
3948 s + enc->minBytesPerChar,
3949 next - enc->minBytesPerChar);
3951 return XML_ERROR_NO_MEMORY;
3952 normalizePublicId(pubId);
3953 poolFinish(&tempPool);
3954 doctypePubid = pubId;
3955 handleDefault = XML_FALSE;
3956 goto alreadyChecked;
3959 case XML_ROLE_ENTITY_PUBLIC_ID:
3960 if (!XmlIsPublicId(enc, s, next, eventPP))
3961 return XML_ERROR_PUBLICID;
3963 if (dtd->keepProcessing && declEntity) {
3964 XML_Char *tem = poolStoreString(&dtd->pool,
3966 s + enc->minBytesPerChar,
3967 next - enc->minBytesPerChar);
3969 return XML_ERROR_NO_MEMORY;
3970 normalizePublicId(tem);
3971 declEntity->publicId = tem;
3972 poolFinish(&dtd->pool);
3973 if (entityDeclHandler)
3974 handleDefault = XML_FALSE;
3977 case XML_ROLE_DOCTYPE_CLOSE:
3979 startDoctypeDeclHandler(handlerArg, doctypeName,
3980 doctypeSysid, doctypePubid, 0);
3981 poolClear(&tempPool);
3982 handleDefault = XML_FALSE;
3984 /* doctypeSysid will be non-NULL in the case of a previous
3985 XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
3986 was not set, indicating an external subset
3989 if (doctypeSysid || useForeignDTD) {
3990 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3991 dtd->hasParamEntityRefs = XML_TRUE;
3992 if (paramEntityParsing && externalEntityRefHandler) {
3993 ENTITY *entity = (ENTITY *)lookup(parser,
3994 &dtd->paramEntities,
3998 return XML_ERROR_NO_MEMORY;
4000 entity->base = curBase;
4001 dtd->paramEntityRead = XML_FALSE;
4002 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4007 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4008 if (dtd->paramEntityRead) {
4009 if (!dtd->standalone &&
4010 notStandaloneHandler &&
4011 !notStandaloneHandler(handlerArg))
4012 return XML_ERROR_NOT_STANDALONE;
4014 /* if we didn't read the foreign DTD then this means that there
4015 is no external subset and we must reset dtd->hasParamEntityRefs
4017 else if (!doctypeSysid)
4018 dtd->hasParamEntityRefs = hadParamEntityRefs;
4019 /* end of DTD - no need to update dtd->keepProcessing */
4021 useForeignDTD = XML_FALSE;
4023 #endif /* XML_DTD */
4024 if (endDoctypeDeclHandler) {
4025 endDoctypeDeclHandler(handlerArg);
4026 handleDefault = XML_FALSE;
4029 case XML_ROLE_INSTANCE_START:
4031 /* if there is no DOCTYPE declaration then now is the
4032 last chance to read the foreign DTD
4034 if (useForeignDTD) {
4035 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4036 dtd->hasParamEntityRefs = XML_TRUE;
4037 if (paramEntityParsing && externalEntityRefHandler) {
4038 ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4042 return XML_ERROR_NO_MEMORY;
4043 entity->base = curBase;
4044 dtd->paramEntityRead = XML_FALSE;
4045 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4050 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4051 if (dtd->paramEntityRead) {
4052 if (!dtd->standalone &&
4053 notStandaloneHandler &&
4054 !notStandaloneHandler(handlerArg))
4055 return XML_ERROR_NOT_STANDALONE;
4057 /* if we didn't read the foreign DTD then this means that there
4058 is no external subset and we must reset dtd->hasParamEntityRefs
4061 dtd->hasParamEntityRefs = hadParamEntityRefs;
4062 /* end of DTD - no need to update dtd->keepProcessing */
4065 #endif /* XML_DTD */
4066 processor = contentProcessor;
4067 return contentProcessor(parser, s, end, nextPtr);
4068 case XML_ROLE_ATTLIST_ELEMENT_NAME:
4069 declElementType = getElementType(parser, enc, s, next);
4070 if (!declElementType)
4071 return XML_ERROR_NO_MEMORY;
4072 goto checkAttListDeclHandler;
4073 case XML_ROLE_ATTRIBUTE_NAME:
4074 declAttributeId = getAttributeId(parser, enc, s, next);
4075 if (!declAttributeId)
4076 return XML_ERROR_NO_MEMORY;
4077 declAttributeIsCdata = XML_FALSE;
4078 declAttributeType = NULL;
4079 declAttributeIsId = XML_FALSE;
4080 goto checkAttListDeclHandler;
4081 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
4082 declAttributeIsCdata = XML_TRUE;
4083 declAttributeType = atypeCDATA;
4084 goto checkAttListDeclHandler;
4085 case XML_ROLE_ATTRIBUTE_TYPE_ID:
4086 declAttributeIsId = XML_TRUE;
4087 declAttributeType = atypeID;
4088 goto checkAttListDeclHandler;
4089 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
4090 declAttributeType = atypeIDREF;
4091 goto checkAttListDeclHandler;
4092 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
4093 declAttributeType = atypeIDREFS;
4094 goto checkAttListDeclHandler;
4095 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
4096 declAttributeType = atypeENTITY;
4097 goto checkAttListDeclHandler;
4098 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
4099 declAttributeType = atypeENTITIES;
4100 goto checkAttListDeclHandler;
4101 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
4102 declAttributeType = atypeNMTOKEN;
4103 goto checkAttListDeclHandler;
4104 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
4105 declAttributeType = atypeNMTOKENS;
4106 checkAttListDeclHandler:
4107 if (dtd->keepProcessing && attlistDeclHandler)
4108 handleDefault = XML_FALSE;
4110 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
4111 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
4112 if (dtd->keepProcessing && attlistDeclHandler) {
4113 const XML_Char *prefix;
4114 if (declAttributeType) {
4115 prefix = enumValueSep;
4118 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
4122 if (!poolAppendString(&tempPool, prefix))
4123 return XML_ERROR_NO_MEMORY;
4124 if (!poolAppend(&tempPool, enc, s, next))
4125 return XML_ERROR_NO_MEMORY;
4126 declAttributeType = tempPool.start;
4127 handleDefault = XML_FALSE;
4130 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
4131 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
4132 if (dtd->keepProcessing) {
4133 if (!defineAttribute(declElementType, declAttributeId,
4134 declAttributeIsCdata, declAttributeIsId,
4136 return XML_ERROR_NO_MEMORY;
4137 if (attlistDeclHandler && declAttributeType) {
4138 if (*declAttributeType == XML_T(ASCII_LPAREN)
4139 || (*declAttributeType == XML_T(ASCII_N)
4140 && declAttributeType[1] == XML_T(ASCII_O))) {
4141 /* Enumerated or Notation type */
4142 if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4143 || !poolAppendChar(&tempPool, XML_T('\0')))
4144 return XML_ERROR_NO_MEMORY;
4145 declAttributeType = tempPool.start;
4146 poolFinish(&tempPool);
4149 attlistDeclHandler(handlerArg, declElementType->name,
4150 declAttributeId->name, declAttributeType,
4151 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
4152 poolClear(&tempPool);
4153 handleDefault = XML_FALSE;
4157 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
4158 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
4159 if (dtd->keepProcessing) {
4160 const XML_Char *attVal;
4161 enum XML_Error result =
4162 storeAttributeValue(parser, enc, declAttributeIsCdata,
4163 s + enc->minBytesPerChar,
4164 next - enc->minBytesPerChar,
4168 attVal = poolStart(&dtd->pool);
4169 poolFinish(&dtd->pool);
4170 /* ID attributes aren't allowed to have a default */
4171 if (!defineAttribute(declElementType, declAttributeId,
4172 declAttributeIsCdata, XML_FALSE, attVal, parser))
4173 return XML_ERROR_NO_MEMORY;
4174 if (attlistDeclHandler && declAttributeType) {
4175 if (*declAttributeType == XML_T(ASCII_LPAREN)
4176 || (*declAttributeType == XML_T(ASCII_N)
4177 && declAttributeType[1] == XML_T(ASCII_O))) {
4178 /* Enumerated or Notation type */
4179 if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4180 || !poolAppendChar(&tempPool, XML_T('\0')))
4181 return XML_ERROR_NO_MEMORY;
4182 declAttributeType = tempPool.start;
4183 poolFinish(&tempPool);
4186 attlistDeclHandler(handlerArg, declElementType->name,
4187 declAttributeId->name, declAttributeType,
4189 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
4190 poolClear(&tempPool);
4191 handleDefault = XML_FALSE;
4195 case XML_ROLE_ENTITY_VALUE:
4196 if (dtd->keepProcessing) {
4197 enum XML_Error result = storeEntityValue(parser, enc,
4198 s + enc->minBytesPerChar,
4199 next - enc->minBytesPerChar);
4201 declEntity->textPtr = poolStart(&dtd->entityValuePool);
4202 declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
4203 poolFinish(&dtd->entityValuePool);
4204 if (entityDeclHandler) {
4206 entityDeclHandler(handlerArg,
4208 declEntity->is_param,
4209 declEntity->textPtr,
4210 declEntity->textLen,
4212 handleDefault = XML_FALSE;
4216 poolDiscard(&dtd->entityValuePool);
4217 if (result != XML_ERROR_NONE)
4221 case XML_ROLE_DOCTYPE_SYSTEM_ID:
4223 useForeignDTD = XML_FALSE;
4224 #endif /* XML_DTD */
4225 dtd->hasParamEntityRefs = XML_TRUE;
4226 if (startDoctypeDeclHandler) {
4227 doctypeSysid = poolStoreString(&tempPool, enc,
4228 s + enc->minBytesPerChar,
4229 next - enc->minBytesPerChar);
4230 if (doctypeSysid == NULL)
4231 return XML_ERROR_NO_MEMORY;
4232 poolFinish(&tempPool);
4233 handleDefault = XML_FALSE;
4237 /* use externalSubsetName to make doctypeSysid non-NULL
4238 for the case where no startDoctypeDeclHandler is set */
4239 doctypeSysid = externalSubsetName;
4240 #endif /* XML_DTD */
4241 if (!dtd->standalone
4243 && !paramEntityParsing
4244 #endif /* XML_DTD */
4245 && notStandaloneHandler
4246 && !notStandaloneHandler(handlerArg))
4247 return XML_ERROR_NOT_STANDALONE;
4252 declEntity = (ENTITY *)lookup(parser,
4253 &dtd->paramEntities,
4257 return XML_ERROR_NO_MEMORY;
4258 declEntity->publicId = NULL;
4261 #endif /* XML_DTD */
4262 case XML_ROLE_ENTITY_SYSTEM_ID:
4263 if (dtd->keepProcessing && declEntity) {
4264 declEntity->systemId = poolStoreString(&dtd->pool, enc,
4265 s + enc->minBytesPerChar,
4266 next - enc->minBytesPerChar);
4267 if (!declEntity->systemId)
4268 return XML_ERROR_NO_MEMORY;
4269 declEntity->base = curBase;
4270 poolFinish(&dtd->pool);
4271 if (entityDeclHandler)
4272 handleDefault = XML_FALSE;
4275 case XML_ROLE_ENTITY_COMPLETE:
4276 if (dtd->keepProcessing && declEntity && entityDeclHandler) {
4278 entityDeclHandler(handlerArg,
4280 declEntity->is_param,
4283 declEntity->systemId,
4284 declEntity->publicId,
4286 handleDefault = XML_FALSE;
4289 case XML_ROLE_ENTITY_NOTATION_NAME:
4290 if (dtd->keepProcessing && declEntity) {
4291 declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
4292 if (!declEntity->notation)
4293 return XML_ERROR_NO_MEMORY;
4294 poolFinish(&dtd->pool);
4295 if (unparsedEntityDeclHandler) {
4297 unparsedEntityDeclHandler(handlerArg,
4300 declEntity->systemId,
4301 declEntity->publicId,
4302 declEntity->notation);
4303 handleDefault = XML_FALSE;
4305 else if (entityDeclHandler) {
4307 entityDeclHandler(handlerArg,
4311 declEntity->systemId,
4312 declEntity->publicId,
4313 declEntity->notation);
4314 handleDefault = XML_FALSE;
4318 case XML_ROLE_GENERAL_ENTITY_NAME:
4320 if (XmlPredefinedEntityName(enc, s, next)) {
4324 if (dtd->keepProcessing) {
4325 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4327 return XML_ERROR_NO_MEMORY;
4328 declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
4331 return XML_ERROR_NO_MEMORY;
4332 if (declEntity->name != name) {
4333 poolDiscard(&dtd->pool);
4337 poolFinish(&dtd->pool);
4338 declEntity->publicId = NULL;
4339 declEntity->is_param = XML_FALSE;
4340 /* if we have a parent parser or are reading an internal parameter
4341 entity, then the entity declaration is not considered "internal"
4343 declEntity->is_internal = !(parentParser || openInternalEntities);
4344 if (entityDeclHandler)
4345 handleDefault = XML_FALSE;
4349 poolDiscard(&dtd->pool);
4354 case XML_ROLE_PARAM_ENTITY_NAME:
4356 if (dtd->keepProcessing) {
4357 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4359 return XML_ERROR_NO_MEMORY;
4360 declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4361 name, sizeof(ENTITY));
4363 return XML_ERROR_NO_MEMORY;
4364 if (declEntity->name != name) {
4365 poolDiscard(&dtd->pool);
4369 poolFinish(&dtd->pool);
4370 declEntity->publicId = NULL;
4371 declEntity->is_param = XML_TRUE;
4372 /* if we have a parent parser or are reading an internal parameter
4373 entity, then the entity declaration is not considered "internal"
4375 declEntity->is_internal = !(parentParser || openInternalEntities);
4376 if (entityDeclHandler)
4377 handleDefault = XML_FALSE;
4381 poolDiscard(&dtd->pool);
4384 #else /* not XML_DTD */
4386 #endif /* XML_DTD */
4388 case XML_ROLE_NOTATION_NAME:
4389 declNotationPublicId = NULL;
4390 declNotationName = NULL;
4391 if (notationDeclHandler) {
4392 declNotationName = poolStoreString(&tempPool, enc, s, next);
4393 if (!declNotationName)
4394 return XML_ERROR_NO_MEMORY;
4395 poolFinish(&tempPool);
4396 handleDefault = XML_FALSE;
4399 case XML_ROLE_NOTATION_PUBLIC_ID:
4400 if (!XmlIsPublicId(enc, s, next, eventPP))
4401 return XML_ERROR_PUBLICID;
4402 if (declNotationName) { /* means notationDeclHandler != NULL */
4403 XML_Char *tem = poolStoreString(&tempPool,
4405 s + enc->minBytesPerChar,
4406 next - enc->minBytesPerChar);
4408 return XML_ERROR_NO_MEMORY;
4409 normalizePublicId(tem);
4410 declNotationPublicId = tem;
4411 poolFinish(&tempPool);
4412 handleDefault = XML_FALSE;
4415 case XML_ROLE_NOTATION_SYSTEM_ID:
4416 if (declNotationName && notationDeclHandler) {
4417 const XML_Char *systemId
4418 = poolStoreString(&tempPool, enc,
4419 s + enc->minBytesPerChar,
4420 next - enc->minBytesPerChar);
4422 return XML_ERROR_NO_MEMORY;
4424 notationDeclHandler(handlerArg,
4428 declNotationPublicId);
4429 handleDefault = XML_FALSE;
4431 poolClear(&tempPool);
4433 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
4434 if (declNotationPublicId && notationDeclHandler) {
4436 notationDeclHandler(handlerArg,
4440 declNotationPublicId);
4441 handleDefault = XML_FALSE;
4443 poolClear(&tempPool);
4445 case XML_ROLE_ERROR:
4447 case XML_TOK_PARAM_ENTITY_REF:
4448 /* PE references in internal subset are
4449 not allowed within declarations. */
4450 return XML_ERROR_PARAM_ENTITY_REF;
4451 case XML_TOK_XML_DECL:
4452 return XML_ERROR_MISPLACED_XML_PI;
4454 return XML_ERROR_SYNTAX;
4457 case XML_ROLE_IGNORE_SECT:
4459 enum XML_Error result;
4461 reportDefault(parser, enc, s, next);
4462 handleDefault = XML_FALSE;
4463 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
4464 if (result != XML_ERROR_NONE)
4467 processor = ignoreSectionProcessor;
4472 #endif /* XML_DTD */
4473 case XML_ROLE_GROUP_OPEN:
4474 if (prologState.level >= groupSize) {
4476 char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
4478 return XML_ERROR_NO_MEMORY;
4479 groupConnector = temp;
4480 if (dtd->scaffIndex) {
4481 int *temp = (int *)REALLOC(dtd->scaffIndex,
4482 groupSize * sizeof(int));
4484 return XML_ERROR_NO_MEMORY;
4485 dtd->scaffIndex = temp;
4489 groupConnector = (char *)MALLOC(groupSize = 32);
4490 if (!groupConnector)
4491 return XML_ERROR_NO_MEMORY;
4494 groupConnector[prologState.level] = 0;
4495 if (dtd->in_eldecl) {
4496 int myindex = nextScaffoldPart(parser);
4498 return XML_ERROR_NO_MEMORY;
4499 dtd->scaffIndex[dtd->scaffLevel] = myindex;
4501 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
4502 if (elementDeclHandler)
4503 handleDefault = XML_FALSE;
4506 case XML_ROLE_GROUP_SEQUENCE:
4507 if (groupConnector[prologState.level] == ASCII_PIPE)
4508 return XML_ERROR_SYNTAX;
4509 groupConnector[prologState.level] = ASCII_COMMA;
4510 if (dtd->in_eldecl && elementDeclHandler)
4511 handleDefault = XML_FALSE;
4513 case XML_ROLE_GROUP_CHOICE:
4514 if (groupConnector[prologState.level] == ASCII_COMMA)
4515 return XML_ERROR_SYNTAX;
4517 && !groupConnector[prologState.level]
4518 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4521 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4523 if (elementDeclHandler)
4524 handleDefault = XML_FALSE;
4526 groupConnector[prologState.level] = ASCII_PIPE;
4528 case XML_ROLE_PARAM_ENTITY_REF:
4530 case XML_ROLE_INNER_PARAM_ENTITY_REF:
4531 dtd->hasParamEntityRefs = XML_TRUE;
4532 if (!paramEntityParsing)
4533 dtd->keepProcessing = dtd->standalone;
4535 const XML_Char *name;
4537 name = poolStoreString(&dtd->pool, enc,
4538 s + enc->minBytesPerChar,
4539 next - enc->minBytesPerChar);
4541 return XML_ERROR_NO_MEMORY;
4542 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
4543 poolDiscard(&dtd->pool);
4544 /* first, determine if a check for an existing declaration is needed;
4545 if yes, check that the entity exists, and that it is internal,
4546 otherwise call the skipped entity handler
4548 if (prologState.documentEntity &&
4550 ? !openInternalEntities
4551 : !dtd->hasParamEntityRefs)) {
4553 return XML_ERROR_UNDEFINED_ENTITY;
4554 else if (!entity->is_internal)
4555 return XML_ERROR_ENTITY_DECLARED_IN_PE;
4558 dtd->keepProcessing = dtd->standalone;
4559 /* cannot report skipped entities in declarations */
4560 if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
4561 skippedEntityHandler(handlerArg, name, 1);
4562 handleDefault = XML_FALSE;
4567 return XML_ERROR_RECURSIVE_ENTITY_REF;
4568 if (entity->textPtr) {
4569 enum XML_Error result;
4570 XML_Bool betweenDecl =
4571 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
4572 result = processInternalEntity(parser, entity, betweenDecl);
4573 if (result != XML_ERROR_NONE)
4575 handleDefault = XML_FALSE;
4578 if (externalEntityRefHandler) {
4579 dtd->paramEntityRead = XML_FALSE;
4580 entity->open = XML_TRUE;
4581 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4585 entity->publicId)) {
4586 entity->open = XML_FALSE;
4587 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4589 entity->open = XML_FALSE;
4590 handleDefault = XML_FALSE;
4591 if (!dtd->paramEntityRead) {
4592 dtd->keepProcessing = dtd->standalone;
4597 dtd->keepProcessing = dtd->standalone;
4601 #endif /* XML_DTD */
4602 if (!dtd->standalone &&
4603 notStandaloneHandler &&
4604 !notStandaloneHandler(handlerArg))
4605 return XML_ERROR_NOT_STANDALONE;
4608 /* Element declaration stuff */
4610 case XML_ROLE_ELEMENT_NAME:
4611 if (elementDeclHandler) {
4612 declElementType = getElementType(parser, enc, s, next);
4613 if (!declElementType)
4614 return XML_ERROR_NO_MEMORY;
4615 dtd->scaffLevel = 0;
4616 dtd->scaffCount = 0;
4617 dtd->in_eldecl = XML_TRUE;
4618 handleDefault = XML_FALSE;
4622 case XML_ROLE_CONTENT_ANY:
4623 case XML_ROLE_CONTENT_EMPTY:
4624 if (dtd->in_eldecl) {
4625 if (elementDeclHandler) {
4626 XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
4628 return XML_ERROR_NO_MEMORY;
4629 content->quant = XML_CQUANT_NONE;
4630 content->name = NULL;
4631 content->numchildren = 0;
4632 content->children = NULL;
4633 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
4637 elementDeclHandler(handlerArg, declElementType->name, content);
4638 handleDefault = XML_FALSE;
4640 dtd->in_eldecl = XML_FALSE;
4644 case XML_ROLE_CONTENT_PCDATA:
4645 if (dtd->in_eldecl) {
4646 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4648 if (elementDeclHandler)
4649 handleDefault = XML_FALSE;
4653 case XML_ROLE_CONTENT_ELEMENT:
4654 quant = XML_CQUANT_NONE;
4655 goto elementContent;
4656 case XML_ROLE_CONTENT_ELEMENT_OPT:
4657 quant = XML_CQUANT_OPT;
4658 goto elementContent;
4659 case XML_ROLE_CONTENT_ELEMENT_REP:
4660 quant = XML_CQUANT_REP;
4661 goto elementContent;
4662 case XML_ROLE_CONTENT_ELEMENT_PLUS:
4663 quant = XML_CQUANT_PLUS;
4665 if (dtd->in_eldecl) {
4667 const XML_Char *name;
4669 const char *nxt = (quant == XML_CQUANT_NONE
4671 : next - enc->minBytesPerChar);
4672 int myindex = nextScaffoldPart(parser);
4674 return XML_ERROR_NO_MEMORY;
4675 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
4676 dtd->scaffold[myindex].quant = quant;
4677 el = getElementType(parser, enc, s, nxt);
4679 return XML_ERROR_NO_MEMORY;
4681 dtd->scaffold[myindex].name = name;
4683 for (; name[nameLen++]; );
4684 dtd->contentStringLen += nameLen;
4685 if (elementDeclHandler)
4686 handleDefault = XML_FALSE;
4690 case XML_ROLE_GROUP_CLOSE:
4691 quant = XML_CQUANT_NONE;
4693 case XML_ROLE_GROUP_CLOSE_OPT:
4694 quant = XML_CQUANT_OPT;
4696 case XML_ROLE_GROUP_CLOSE_REP:
4697 quant = XML_CQUANT_REP;
4699 case XML_ROLE_GROUP_CLOSE_PLUS:
4700 quant = XML_CQUANT_PLUS;
4702 if (dtd->in_eldecl) {
4703 if (elementDeclHandler)
4704 handleDefault = XML_FALSE;
4706 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
4707 if (dtd->scaffLevel == 0) {
4708 if (!handleDefault) {
4709 XML_Content *model = build_model(parser);
4711 return XML_ERROR_NO_MEMORY;
4713 elementDeclHandler(handlerArg, declElementType->name, model);
4715 dtd->in_eldecl = XML_FALSE;
4716 dtd->contentStringLen = 0;
4720 /* End element declaration stuff */
4723 if (!reportProcessingInstruction(parser, enc, s, next))
4724 return XML_ERROR_NO_MEMORY;
4725 handleDefault = XML_FALSE;
4727 case XML_ROLE_COMMENT:
4728 if (!reportComment(parser, enc, s, next))
4729 return XML_ERROR_NO_MEMORY;
4730 handleDefault = XML_FALSE;
4735 handleDefault = XML_FALSE;
4739 case XML_ROLE_DOCTYPE_NONE:
4740 if (startDoctypeDeclHandler)
4741 handleDefault = XML_FALSE;
4743 case XML_ROLE_ENTITY_NONE:
4744 if (dtd->keepProcessing && entityDeclHandler)
4745 handleDefault = XML_FALSE;
4747 case XML_ROLE_NOTATION_NONE:
4748 if (notationDeclHandler)
4749 handleDefault = XML_FALSE;
4751 case XML_ROLE_ATTLIST_NONE:
4752 if (dtd->keepProcessing && attlistDeclHandler)
4753 handleDefault = XML_FALSE;
4755 case XML_ROLE_ELEMENT_NONE:
4756 if (elementDeclHandler)
4757 handleDefault = XML_FALSE;
4759 } /* end of big switch */
4761 if (handleDefault && defaultHandler)
4762 reportDefault(parser, enc, s, next);
4764 switch (ps_parsing) {
4767 return XML_ERROR_NONE;
4769 return XML_ERROR_ABORTED;
4772 tok = XmlPrologTok(enc, s, end, &next);
4778 static enum XML_Error PTRCALL
4779 epilogProcessor(XML_Parser parser,
4782 const char **nextPtr)
4784 processor = epilogProcessor;
4787 const char *next = NULL;
4788 int tok = XmlPrologTok(encoding, s, end, &next);
4791 /* report partial linebreak - it might be the last token */
4792 case -XML_TOK_PROLOG_S:
4793 if (defaultHandler) {
4794 reportDefault(parser, encoding, s, next);
4795 if (ps_parsing == XML_FINISHED)
4796 return XML_ERROR_ABORTED;
4799 return XML_ERROR_NONE;
4802 return XML_ERROR_NONE;
4803 case XML_TOK_PROLOG_S:
4805 reportDefault(parser, encoding, s, next);
4808 if (!reportProcessingInstruction(parser, encoding, s, next))
4809 return XML_ERROR_NO_MEMORY;
4811 case XML_TOK_COMMENT:
4812 if (!reportComment(parser, encoding, s, next))
4813 return XML_ERROR_NO_MEMORY;
4815 case XML_TOK_INVALID:
4817 return XML_ERROR_INVALID_TOKEN;
4818 case XML_TOK_PARTIAL:
4819 if (!ps_finalBuffer) {
4821 return XML_ERROR_NONE;
4823 return XML_ERROR_UNCLOSED_TOKEN;
4824 case XML_TOK_PARTIAL_CHAR:
4825 if (!ps_finalBuffer) {
4827 return XML_ERROR_NONE;
4829 return XML_ERROR_PARTIAL_CHAR;
4831 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
4833 eventPtr = s = next;
4834 switch (ps_parsing) {
4837 return XML_ERROR_NONE;
4839 return XML_ERROR_ABORTED;
4845 static enum XML_Error
4846 processInternalEntity(XML_Parser parser, ENTITY *entity,
4847 XML_Bool betweenDecl)
4849 const char *textStart, *textEnd;
4851 enum XML_Error result;
4852 OPEN_INTERNAL_ENTITY *openEntity;
4854 if (freeInternalEntities) {
4855 openEntity = freeInternalEntities;
4856 freeInternalEntities = openEntity->next;
4859 openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
4861 return XML_ERROR_NO_MEMORY;
4863 entity->open = XML_TRUE;
4864 entity->processed = 0;
4865 openEntity->next = openInternalEntities;
4866 openInternalEntities = openEntity;
4867 openEntity->entity = entity;
4868 openEntity->startTagLevel = tagLevel;
4869 openEntity->betweenDecl = betweenDecl;
4870 openEntity->internalEventPtr = NULL;
4871 openEntity->internalEventEndPtr = NULL;
4872 textStart = (char *)entity->textPtr;
4873 textEnd = (char *)(entity->textPtr + entity->textLen);
4876 if (entity->is_param) {
4877 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4878 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4879 next, &next, XML_FALSE);
4882 #endif /* XML_DTD */
4883 result = doContent(parser, tagLevel, internalEncoding, textStart,
4884 textEnd, &next, XML_FALSE);
4886 if (result == XML_ERROR_NONE) {
4887 if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4888 entity->processed = (int)(next - textStart);
4889 processor = internalEntityProcessor;
4892 entity->open = XML_FALSE;
4893 openInternalEntities = openEntity->next;
4894 /* put openEntity back in list of free instances */
4895 openEntity->next = freeInternalEntities;
4896 freeInternalEntities = openEntity;
4902 static enum XML_Error PTRCALL
4903 internalEntityProcessor(XML_Parser parser,
4906 const char **nextPtr)
4909 const char *textStart, *textEnd;
4911 enum XML_Error result;
4912 OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
4914 return XML_ERROR_UNEXPECTED_STATE;
4916 entity = openEntity->entity;
4917 textStart = ((char *)entity->textPtr) + entity->processed;
4918 textEnd = (char *)(entity->textPtr + entity->textLen);
4921 if (entity->is_param) {
4922 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4923 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4924 next, &next, XML_FALSE);
4927 #endif /* XML_DTD */
4928 result = doContent(parser, openEntity->startTagLevel, internalEncoding,
4929 textStart, textEnd, &next, XML_FALSE);
4931 if (result != XML_ERROR_NONE)
4933 else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4934 entity->processed = (int)(next - (char *)entity->textPtr);
4938 entity->open = XML_FALSE;
4939 openInternalEntities = openEntity->next;
4940 /* put openEntity back in list of free instances */
4941 openEntity->next = freeInternalEntities;
4942 freeInternalEntities = openEntity;
4946 if (entity->is_param) {
4948 processor = prologProcessor;
4949 tok = XmlPrologTok(encoding, s, end, &next);
4950 return doProlog(parser, encoding, s, end, tok, next, nextPtr,
4951 (XML_Bool)!ps_finalBuffer);
4954 #endif /* XML_DTD */
4956 processor = contentProcessor;
4957 /* see externalEntityContentProcessor vs contentProcessor */
4958 return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
4959 nextPtr, (XML_Bool)!ps_finalBuffer);
4963 static enum XML_Error PTRCALL
4964 errorProcessor(XML_Parser parser,
4965 const char *UNUSED_P(s),
4966 const char *UNUSED_P(end),
4967 const char **UNUSED_P(nextPtr))
4972 static enum XML_Error
4973 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4974 const char *ptr, const char *end,
4977 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
4981 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
4983 if (!poolAppendChar(pool, XML_T('\0')))
4984 return XML_ERROR_NO_MEMORY;
4985 return XML_ERROR_NONE;
4988 static enum XML_Error
4989 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4990 const char *ptr, const char *end,
4993 DTD * const dtd = _dtd; /* save one level of indirection */
4996 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
4999 return XML_ERROR_NONE;
5000 case XML_TOK_INVALID:
5001 if (enc == encoding)
5003 return XML_ERROR_INVALID_TOKEN;
5004 case XML_TOK_PARTIAL:
5005 if (enc == encoding)
5007 return XML_ERROR_INVALID_TOKEN;
5008 case XML_TOK_CHAR_REF:
5010 XML_Char buf[XML_ENCODE_MAX];
5012 int n = XmlCharRefNumber(enc, ptr);
5014 if (enc == encoding)
5016 return XML_ERROR_BAD_CHAR_REF;
5019 && n == 0x20 /* space */
5020 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5022 n = XmlEncode(n, (ICHAR *)buf);
5024 if (enc == encoding)
5026 return XML_ERROR_BAD_CHAR_REF;
5028 for (i = 0; i < n; i++) {
5029 if (!poolAppendChar(pool, buf[i]))
5030 return XML_ERROR_NO_MEMORY;
5034 case XML_TOK_DATA_CHARS:
5035 if (!poolAppend(pool, enc, ptr, next))
5036 return XML_ERROR_NO_MEMORY;
5038 case XML_TOK_TRAILING_CR:
5039 next = ptr + enc->minBytesPerChar;
5041 case XML_TOK_ATTRIBUTE_VALUE_S:
5042 case XML_TOK_DATA_NEWLINE:
5043 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5045 if (!poolAppendChar(pool, 0x20))
5046 return XML_ERROR_NO_MEMORY;
5048 case XML_TOK_ENTITY_REF:
5050 const XML_Char *name;
5052 char checkEntityDecl;
5053 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
5054 ptr + enc->minBytesPerChar,
5055 next - enc->minBytesPerChar);
5057 if (!poolAppendChar(pool, ch))
5058 return XML_ERROR_NO_MEMORY;
5061 name = poolStoreString(&temp2Pool, enc,
5062 ptr + enc->minBytesPerChar,
5063 next - enc->minBytesPerChar);
5065 return XML_ERROR_NO_MEMORY;
5066 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
5067 poolDiscard(&temp2Pool);
5068 /* First, determine if a check for an existing declaration is needed;
5069 if yes, check that the entity exists, and that it is internal.
5071 if (pool == &dtd->pool) /* are we called from prolog? */
5074 prologState.documentEntity &&
5075 #endif /* XML_DTD */
5077 ? !openInternalEntities
5078 : !dtd->hasParamEntityRefs);
5079 else /* if (pool == &tempPool): we are called from content */
5080 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
5081 if (checkEntityDecl) {
5083 return XML_ERROR_UNDEFINED_ENTITY;
5084 else if (!entity->is_internal)
5085 return XML_ERROR_ENTITY_DECLARED_IN_PE;
5088 /* Cannot report skipped entity here - see comments on
5089 skippedEntityHandler.
5090 if (skippedEntityHandler)
5091 skippedEntityHandler(handlerArg, name, 0);
5093 /* Cannot call the default handler because this would be
5094 out of sync with the call to the startElementHandler.
5095 if ((pool == &tempPool) && defaultHandler)
5096 reportDefault(parser, enc, ptr, next);
5101 if (enc == encoding)
5103 return XML_ERROR_RECURSIVE_ENTITY_REF;
5105 if (entity->notation) {
5106 if (enc == encoding)
5108 return XML_ERROR_BINARY_ENTITY_REF;
5110 if (!entity->textPtr) {
5111 if (enc == encoding)
5113 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
5116 enum XML_Error result;
5117 const XML_Char *textEnd = entity->textPtr + entity->textLen;
5118 entity->open = XML_TRUE;
5119 result = appendAttributeValue(parser, internalEncoding, isCdata,
5120 (char *)entity->textPtr,
5121 (char *)textEnd, pool);
5122 entity->open = XML_FALSE;
5129 if (enc == encoding)
5131 return XML_ERROR_UNEXPECTED_STATE;
5138 static enum XML_Error
5139 storeEntityValue(XML_Parser parser,
5140 const ENCODING *enc,
5141 const char *entityTextPtr,
5142 const char *entityTextEnd)
5144 DTD * const dtd = _dtd; /* save one level of indirection */
5145 STRING_POOL *pool = &(dtd->entityValuePool);
5146 enum XML_Error result = XML_ERROR_NONE;
5148 int oldInEntityValue = prologState.inEntityValue;
5149 prologState.inEntityValue = 1;
5150 #endif /* XML_DTD */
5151 /* never return Null for the value argument in EntityDeclHandler,
5152 since this would indicate an external entity; therefore we
5153 have to make sure that entityValuePool.start is not null */
5154 if (!pool->blocks) {
5155 if (!poolGrow(pool))
5156 return XML_ERROR_NO_MEMORY;
5161 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
5163 case XML_TOK_PARAM_ENTITY_REF:
5165 if (isParamEntity || enc != encoding) {
5166 const XML_Char *name;
5168 name = poolStoreString(&tempPool, enc,
5169 entityTextPtr + enc->minBytesPerChar,
5170 next - enc->minBytesPerChar);
5172 result = XML_ERROR_NO_MEMORY;
5173 goto endEntityValue;
5175 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
5176 poolDiscard(&tempPool);
5178 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5179 /* cannot report skipped entity here - see comments on
5180 skippedEntityHandler
5181 if (skippedEntityHandler)
5182 skippedEntityHandler(handlerArg, name, 0);
5184 dtd->keepProcessing = dtd->standalone;
5185 goto endEntityValue;
5188 if (enc == encoding)
5189 eventPtr = entityTextPtr;
5190 result = XML_ERROR_RECURSIVE_ENTITY_REF;
5191 goto endEntityValue;
5193 if (entity->systemId) {
5194 if (externalEntityRefHandler) {
5195 dtd->paramEntityRead = XML_FALSE;
5196 entity->open = XML_TRUE;
5197 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
5201 entity->publicId)) {
5202 entity->open = XML_FALSE;
5203 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5204 goto endEntityValue;
5206 entity->open = XML_FALSE;
5207 if (!dtd->paramEntityRead)
5208 dtd->keepProcessing = dtd->standalone;
5211 dtd->keepProcessing = dtd->standalone;
5214 entity->open = XML_TRUE;
5215 result = storeEntityValue(parser,
5217 (char *)entity->textPtr,
5218 (char *)(entity->textPtr
5219 + entity->textLen));
5220 entity->open = XML_FALSE;
5222 goto endEntityValue;
5226 #endif /* XML_DTD */
5227 /* In the internal subset, PE references are not legal
5228 within markup declarations, e.g entity values in this case. */
5229 eventPtr = entityTextPtr;
5230 result = XML_ERROR_PARAM_ENTITY_REF;
5231 goto endEntityValue;
5233 result = XML_ERROR_NONE;
5234 goto endEntityValue;
5235 case XML_TOK_ENTITY_REF:
5236 case XML_TOK_DATA_CHARS:
5237 if (!poolAppend(pool, enc, entityTextPtr, next)) {
5238 result = XML_ERROR_NO_MEMORY;
5239 goto endEntityValue;
5242 case XML_TOK_TRAILING_CR:
5243 next = entityTextPtr + enc->minBytesPerChar;
5245 case XML_TOK_DATA_NEWLINE:
5246 if (pool->end == pool->ptr && !poolGrow(pool)) {
5247 result = XML_ERROR_NO_MEMORY;
5248 goto endEntityValue;
5250 *(pool->ptr)++ = 0xA;
5252 case XML_TOK_CHAR_REF:
5254 XML_Char buf[XML_ENCODE_MAX];
5256 int n = XmlCharRefNumber(enc, entityTextPtr);
5258 if (enc == encoding)
5259 eventPtr = entityTextPtr;
5260 result = XML_ERROR_BAD_CHAR_REF;
5261 goto endEntityValue;
5263 n = XmlEncode(n, (ICHAR *)buf);
5265 if (enc == encoding)
5266 eventPtr = entityTextPtr;
5267 result = XML_ERROR_BAD_CHAR_REF;
5268 goto endEntityValue;
5270 for (i = 0; i < n; i++) {
5271 if (pool->end == pool->ptr && !poolGrow(pool)) {
5272 result = XML_ERROR_NO_MEMORY;
5273 goto endEntityValue;
5275 *(pool->ptr)++ = buf[i];
5279 case XML_TOK_PARTIAL:
5280 if (enc == encoding)
5281 eventPtr = entityTextPtr;
5282 result = XML_ERROR_INVALID_TOKEN;
5283 goto endEntityValue;
5284 case XML_TOK_INVALID:
5285 if (enc == encoding)
5287 result = XML_ERROR_INVALID_TOKEN;
5288 goto endEntityValue;
5290 if (enc == encoding)
5291 eventPtr = entityTextPtr;
5292 result = XML_ERROR_UNEXPECTED_STATE;
5293 goto endEntityValue;
5295 entityTextPtr = next;
5299 prologState.inEntityValue = oldInEntityValue;
5300 #endif /* XML_DTD */
5304 static void FASTCALL
5305 normalizeLines(XML_Char *s)
5309 if (*s == XML_T('\0'))
5328 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5329 const char *start, const char *end)
5331 const XML_Char *target;
5334 if (!processingInstructionHandler) {
5336 reportDefault(parser, enc, start, end);
5339 start += enc->minBytesPerChar * 2;
5340 tem = start + XmlNameLength(enc, start);
5341 target = poolStoreString(&tempPool, enc, start, tem);
5344 poolFinish(&tempPool);
5345 data = poolStoreString(&tempPool, enc,
5347 end - enc->minBytesPerChar*2);
5350 normalizeLines(data);
5351 processingInstructionHandler(handlerArg, target, data);
5352 poolClear(&tempPool);
5357 reportComment(XML_Parser parser, const ENCODING *enc,
5358 const char *start, const char *end)
5361 if (!commentHandler) {
5363 reportDefault(parser, enc, start, end);
5366 data = poolStoreString(&tempPool,
5368 start + enc->minBytesPerChar * 4,
5369 end - enc->minBytesPerChar * 3);
5372 normalizeLines(data);
5373 commentHandler(handlerArg, data);
5374 poolClear(&tempPool);
5379 reportDefault(XML_Parser parser, const ENCODING *enc,
5380 const char *s, const char *end)
5382 if (MUST_CONVERT(enc, s)) {
5383 enum XML_Convert_Result convert_res;
5384 const char **eventPP;
5385 const char **eventEndPP;
5386 if (enc == encoding) {
5387 eventPP = &eventPtr;
5388 eventEndPP = &eventEndPtr;
5391 eventPP = &(openInternalEntities->internalEventPtr);
5392 eventEndPP = &(openInternalEntities->internalEventEndPtr);
5395 ICHAR *dataPtr = (ICHAR *)dataBuf;
5396 convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
5398 defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
5400 } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
5403 defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
5408 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
5409 XML_Bool isId, const XML_Char *value, XML_Parser parser)
5411 DEFAULT_ATTRIBUTE *att;
5412 if (value || isId) {
5413 /* The handling of default attributes gets messed up if we have
5414 a default which duplicates a non-default. */
5416 for (i = 0; i < type->nDefaultAtts; i++)
5417 if (attId == type->defaultAtts[i].id)
5419 if (isId && !type->idAtt && !attId->xmlns)
5420 type->idAtt = attId;
5422 if (type->nDefaultAtts == type->allocDefaultAtts) {
5423 if (type->allocDefaultAtts == 0) {
5424 type->allocDefaultAtts = 8;
5425 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
5426 * sizeof(DEFAULT_ATTRIBUTE));
5427 if (!type->defaultAtts)
5431 DEFAULT_ATTRIBUTE *temp;
5432 int count = type->allocDefaultAtts * 2;
5433 temp = (DEFAULT_ATTRIBUTE *)
5434 REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
5437 type->allocDefaultAtts = count;
5438 type->defaultAtts = temp;
5441 att = type->defaultAtts + type->nDefaultAtts;
5444 att->isCdata = isCdata;
5446 attId->maybeTokenized = XML_TRUE;
5447 type->nDefaultAtts += 1;
5452 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
5454 DTD * const dtd = _dtd; /* save one level of indirection */
5455 const XML_Char *name;
5456 for (name = elementType->name; *name; name++) {
5457 if (*name == XML_T(ASCII_COLON)) {
5460 for (s = elementType->name; s != name; s++) {
5461 if (!poolAppendChar(&dtd->pool, *s))
5464 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5466 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
5470 if (prefix->name == poolStart(&dtd->pool))
5471 poolFinish(&dtd->pool);
5473 poolDiscard(&dtd->pool);
5474 elementType->prefix = prefix;
5481 static ATTRIBUTE_ID *
5482 getAttributeId(XML_Parser parser, const ENCODING *enc,
5483 const char *start, const char *end)
5485 DTD * const dtd = _dtd; /* save one level of indirection */
5487 const XML_Char *name;
5488 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5490 name = poolStoreString(&dtd->pool, enc, start, end);
5493 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
5495 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
5498 if (id->name != name)
5499 poolDiscard(&dtd->pool);
5501 poolFinish(&dtd->pool);
5504 else if (name[0] == XML_T(ASCII_x)
5505 && name[1] == XML_T(ASCII_m)
5506 && name[2] == XML_T(ASCII_l)
5507 && name[3] == XML_T(ASCII_n)
5508 && name[4] == XML_T(ASCII_s)
5509 && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
5510 if (name[5] == XML_T('\0'))
5511 id->prefix = &dtd->defaultPrefix;
5513 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
5514 id->xmlns = XML_TRUE;
5518 for (i = 0; name[i]; i++) {
5519 /* attributes without prefix are *not* in the default namespace */
5520 if (name[i] == XML_T(ASCII_COLON)) {
5522 for (j = 0; j < i; j++) {
5523 if (!poolAppendChar(&dtd->pool, name[j]))
5526 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5528 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
5532 if (id->prefix->name == poolStart(&dtd->pool))
5533 poolFinish(&dtd->pool);
5535 poolDiscard(&dtd->pool);
5544 #define CONTEXT_SEP XML_T(ASCII_FF)
5546 static const XML_Char *
5547 getContext(XML_Parser parser)
5549 DTD * const dtd = _dtd; /* save one level of indirection */
5550 HASH_TABLE_ITER iter;
5551 XML_Bool needSep = XML_FALSE;
5553 if (dtd->defaultPrefix.binding) {
5556 if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
5558 len = dtd->defaultPrefix.binding->uriLen;
5559 if (namespaceSeparator)
5561 for (i = 0; i < len; i++)
5562 if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
5567 hashTableIterInit(&iter, &(dtd->prefixes));
5572 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
5575 if (!prefix->binding)
5577 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5579 for (s = prefix->name; *s; s++)
5580 if (!poolAppendChar(&tempPool, *s))
5582 if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
5584 len = prefix->binding->uriLen;
5585 if (namespaceSeparator)
5587 for (i = 0; i < len; i++)
5588 if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
5594 hashTableIterInit(&iter, &(dtd->generalEntities));
5597 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
5602 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5604 for (s = e->name; *s; s++)
5605 if (!poolAppendChar(&tempPool, *s))
5610 if (!poolAppendChar(&tempPool, XML_T('\0')))
5612 return tempPool.start;
5616 setContext(XML_Parser parser, const XML_Char *context)
5618 DTD * const dtd = _dtd; /* save one level of indirection */
5619 const XML_Char *s = context;
5621 while (*context != XML_T('\0')) {
5622 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
5624 if (!poolAppendChar(&tempPool, XML_T('\0')))
5626 e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0);
5629 if (*s != XML_T('\0'))
5632 poolDiscard(&tempPool);
5634 else if (*s == XML_T(ASCII_EQUALS)) {
5636 if (poolLength(&tempPool) == 0)
5637 prefix = &dtd->defaultPrefix;
5639 if (!poolAppendChar(&tempPool, XML_T('\0')))
5641 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool),
5645 if (prefix->name == poolStart(&tempPool)) {
5646 prefix->name = poolCopyString(&dtd->pool, prefix->name);
5650 poolDiscard(&tempPool);
5652 for (context = s + 1;
5653 *context != CONTEXT_SEP && *context != XML_T('\0');
5655 if (!poolAppendChar(&tempPool, *context))
5657 if (!poolAppendChar(&tempPool, XML_T('\0')))
5659 if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
5660 &inheritedBindings) != XML_ERROR_NONE)
5662 poolDiscard(&tempPool);
5663 if (*context != XML_T('\0'))
5668 if (!poolAppendChar(&tempPool, *s))
5676 static void FASTCALL
5677 normalizePublicId(XML_Char *publicId)
5679 XML_Char *p = publicId;
5681 for (s = publicId; *s; s++) {
5686 if (p != publicId && p[-1] != 0x20)
5693 if (p != publicId && p[-1] == 0x20)
5699 dtdCreate(const XML_Memory_Handling_Suite *ms)
5701 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
5704 poolInit(&(p->pool), ms);
5705 poolInit(&(p->entityValuePool), ms);
5706 hashTableInit(&(p->generalEntities), ms);
5707 hashTableInit(&(p->elementTypes), ms);
5708 hashTableInit(&(p->attributeIds), ms);
5709 hashTableInit(&(p->prefixes), ms);
5711 p->paramEntityRead = XML_FALSE;
5712 hashTableInit(&(p->paramEntities), ms);
5713 #endif /* XML_DTD */
5714 p->defaultPrefix.name = NULL;
5715 p->defaultPrefix.binding = NULL;
5717 p->in_eldecl = XML_FALSE;
5718 p->scaffIndex = NULL;
5723 p->contentStringLen = 0;
5725 p->keepProcessing = XML_TRUE;
5726 p->hasParamEntityRefs = XML_FALSE;
5727 p->standalone = XML_FALSE;
5732 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
5734 HASH_TABLE_ITER iter;
5735 hashTableIterInit(&iter, &(p->elementTypes));
5737 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5740 if (e->allocDefaultAtts != 0)
5741 ms->free_fcn(e->defaultAtts);
5743 hashTableClear(&(p->generalEntities));
5745 p->paramEntityRead = XML_FALSE;
5746 hashTableClear(&(p->paramEntities));
5747 #endif /* XML_DTD */
5748 hashTableClear(&(p->elementTypes));
5749 hashTableClear(&(p->attributeIds));
5750 hashTableClear(&(p->prefixes));
5751 poolClear(&(p->pool));
5752 poolClear(&(p->entityValuePool));
5753 p->defaultPrefix.name = NULL;
5754 p->defaultPrefix.binding = NULL;
5756 p->in_eldecl = XML_FALSE;
5758 ms->free_fcn(p->scaffIndex);
5759 p->scaffIndex = NULL;
5760 ms->free_fcn(p->scaffold);
5766 p->contentStringLen = 0;
5768 p->keepProcessing = XML_TRUE;
5769 p->hasParamEntityRefs = XML_FALSE;
5770 p->standalone = XML_FALSE;
5774 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
5776 HASH_TABLE_ITER iter;
5777 hashTableIterInit(&iter, &(p->elementTypes));
5779 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5782 if (e->allocDefaultAtts != 0)
5783 ms->free_fcn(e->defaultAtts);
5785 hashTableDestroy(&(p->generalEntities));
5787 hashTableDestroy(&(p->paramEntities));
5788 #endif /* XML_DTD */
5789 hashTableDestroy(&(p->elementTypes));
5790 hashTableDestroy(&(p->attributeIds));
5791 hashTableDestroy(&(p->prefixes));
5792 poolDestroy(&(p->pool));
5793 poolDestroy(&(p->entityValuePool));
5795 ms->free_fcn(p->scaffIndex);
5796 ms->free_fcn(p->scaffold);
5801 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
5802 The new DTD has already been initialized.
5805 dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
5807 HASH_TABLE_ITER iter;
5809 /* Copy the prefix table. */
5811 hashTableIterInit(&iter, &(oldDtd->prefixes));
5813 const XML_Char *name;
5814 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
5817 name = poolCopyString(&(newDtd->pool), oldP->name);
5820 if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
5824 hashTableIterInit(&iter, &(oldDtd->attributeIds));
5826 /* Copy the attribute id table. */
5830 const XML_Char *name;
5831 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
5835 /* Remember to allocate the scratch byte before the name. */
5836 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
5838 name = poolCopyString(&(newDtd->pool), oldA->name);
5842 newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
5843 sizeof(ATTRIBUTE_ID));
5846 newA->maybeTokenized = oldA->maybeTokenized;
5848 newA->xmlns = oldA->xmlns;
5849 if (oldA->prefix == &oldDtd->defaultPrefix)
5850 newA->prefix = &newDtd->defaultPrefix;
5852 newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
5853 oldA->prefix->name, 0);
5857 /* Copy the element type table. */
5859 hashTableIterInit(&iter, &(oldDtd->elementTypes));
5864 const XML_Char *name;
5865 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5868 name = poolCopyString(&(newDtd->pool), oldE->name);
5871 newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
5872 sizeof(ELEMENT_TYPE));
5875 if (oldE->nDefaultAtts) {
5876 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
5877 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
5878 if (!newE->defaultAtts) {
5884 newE->idAtt = (ATTRIBUTE_ID *)
5885 lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
5886 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
5888 newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
5889 oldE->prefix->name, 0);
5890 for (i = 0; i < newE->nDefaultAtts; i++) {
5891 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
5892 lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
5893 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
5894 if (oldE->defaultAtts[i].value) {
5895 newE->defaultAtts[i].value
5896 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
5897 if (!newE->defaultAtts[i].value)
5901 newE->defaultAtts[i].value = NULL;
5905 /* Copy the entity tables. */
5906 if (!copyEntityTable(oldParser,
5907 &(newDtd->generalEntities),
5909 &(oldDtd->generalEntities)))
5913 if (!copyEntityTable(oldParser,
5914 &(newDtd->paramEntities),
5916 &(oldDtd->paramEntities)))
5918 newDtd->paramEntityRead = oldDtd->paramEntityRead;
5919 #endif /* XML_DTD */
5921 newDtd->keepProcessing = oldDtd->keepProcessing;
5922 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
5923 newDtd->standalone = oldDtd->standalone;
5925 /* Don't want deep copying for scaffolding */
5926 newDtd->in_eldecl = oldDtd->in_eldecl;
5927 newDtd->scaffold = oldDtd->scaffold;
5928 newDtd->contentStringLen = oldDtd->contentStringLen;
5929 newDtd->scaffSize = oldDtd->scaffSize;
5930 newDtd->scaffLevel = oldDtd->scaffLevel;
5931 newDtd->scaffIndex = oldDtd->scaffIndex;
5937 copyEntityTable(XML_Parser oldParser,
5938 HASH_TABLE *newTable,
5939 STRING_POOL *newPool,
5940 const HASH_TABLE *oldTable)
5942 HASH_TABLE_ITER iter;
5943 const XML_Char *cachedOldBase = NULL;
5944 const XML_Char *cachedNewBase = NULL;
5946 hashTableIterInit(&iter, oldTable);
5950 const XML_Char *name;
5951 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
5954 name = poolCopyString(newPool, oldE->name);
5957 newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
5960 if (oldE->systemId) {
5961 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
5964 newE->systemId = tem;
5966 if (oldE->base == cachedOldBase)
5967 newE->base = cachedNewBase;
5969 cachedOldBase = oldE->base;
5970 tem = poolCopyString(newPool, cachedOldBase);
5973 cachedNewBase = newE->base = tem;
5976 if (oldE->publicId) {
5977 tem = poolCopyString(newPool, oldE->publicId);
5980 newE->publicId = tem;
5984 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
5988 newE->textPtr = tem;
5989 newE->textLen = oldE->textLen;
5991 if (oldE->notation) {
5992 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
5995 newE->notation = tem;
5997 newE->is_param = oldE->is_param;
5998 newE->is_internal = oldE->is_internal;
6003 #define INIT_POWER 6
6005 static XML_Bool FASTCALL
6006 keyeq(KEY s1, KEY s2)
6008 for (; *s1 == *s2; s1++, s2++)
6014 static unsigned long FASTCALL
6015 hash(XML_Parser parser, KEY s)
6017 unsigned long h = hash_secret_salt;
6019 h = CHAR_HASH(h, *s++);
6024 lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
6027 if (table->size == 0) {
6031 table->power = INIT_POWER;
6032 /* table->size is a power of 2 */
6033 table->size = (size_t)1 << INIT_POWER;
6034 tsize = table->size * sizeof(NAMED *);
6035 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
6040 memset(table->v, 0, tsize);
6041 i = hash(parser, name) & ((unsigned long)table->size - 1);
6044 unsigned long h = hash(parser, name);
6045 unsigned long mask = (unsigned long)table->size - 1;
6046 unsigned char step = 0;
6048 while (table->v[i]) {
6049 if (keyeq(name, table->v[i]->name))
6052 step = PROBE_STEP(h, mask, table->power);
6053 i < step ? (i += table->size - step) : (i -= step);
6058 /* check for overflow (table is half full) */
6059 if (table->used >> (table->power - 1)) {
6060 unsigned char newPower = table->power + 1;
6061 size_t newSize = (size_t)1 << newPower;
6062 unsigned long newMask = (unsigned long)newSize - 1;
6063 size_t tsize = newSize * sizeof(NAMED *);
6064 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
6067 memset(newV, 0, tsize);
6068 for (i = 0; i < table->size; i++)
6070 unsigned long newHash = hash(parser, table->v[i]->name);
6071 size_t j = newHash & newMask;
6075 step = PROBE_STEP(newHash, newMask, newPower);
6076 j < step ? (j += newSize - step) : (j -= step);
6078 newV[j] = table->v[i];
6080 table->mem->free_fcn(table->v);
6082 table->power = newPower;
6083 table->size = newSize;
6086 while (table->v[i]) {
6088 step = PROBE_STEP(h, newMask, newPower);
6089 i < step ? (i += newSize - step) : (i -= step);
6093 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
6096 memset(table->v[i], 0, createSize);
6097 table->v[i]->name = name;
6102 static void FASTCALL
6103 hashTableClear(HASH_TABLE *table)
6106 for (i = 0; i < table->size; i++) {
6107 table->mem->free_fcn(table->v[i]);
6113 static void FASTCALL
6114 hashTableDestroy(HASH_TABLE *table)
6117 for (i = 0; i < table->size; i++)
6118 table->mem->free_fcn(table->v[i]);
6119 table->mem->free_fcn(table->v);
6122 static void FASTCALL
6123 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
6132 static void FASTCALL
6133 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
6136 iter->end = iter->p + table->size;
6139 static NAMED * FASTCALL
6140 hashTableIterNext(HASH_TABLE_ITER *iter)
6142 while (iter->p != iter->end) {
6143 NAMED *tem = *(iter->p)++;
6150 static void FASTCALL
6151 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
6153 pool->blocks = NULL;
6154 pool->freeBlocks = NULL;
6161 static void FASTCALL
6162 poolClear(STRING_POOL *pool)
6164 if (!pool->freeBlocks)
6165 pool->freeBlocks = pool->blocks;
6167 BLOCK *p = pool->blocks;
6169 BLOCK *tem = p->next;
6170 p->next = pool->freeBlocks;
6171 pool->freeBlocks = p;
6175 pool->blocks = NULL;
6181 static void FASTCALL
6182 poolDestroy(STRING_POOL *pool)
6184 BLOCK *p = pool->blocks;
6186 BLOCK *tem = p->next;
6187 pool->mem->free_fcn(p);
6190 p = pool->freeBlocks;
6192 BLOCK *tem = p->next;
6193 pool->mem->free_fcn(p);
6199 poolAppend(STRING_POOL *pool, const ENCODING *enc,
6200 const char *ptr, const char *end)
6202 if (!pool->ptr && !poolGrow(pool))
6205 const enum XML_Convert_Result convert_res = XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6206 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
6208 if (!poolGrow(pool))
6214 static const XML_Char * FASTCALL
6215 poolCopyString(STRING_POOL *pool, const XML_Char *s)
6218 if (!poolAppendChar(pool, *s))
6226 static const XML_Char *
6227 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
6229 if (!pool->ptr && !poolGrow(pool))
6231 for (; n > 0; --n, s++) {
6232 if (!poolAppendChar(pool, *s))
6240 static const XML_Char * FASTCALL
6241 poolAppendString(STRING_POOL *pool, const XML_Char *s)
6244 if (!poolAppendChar(pool, *s))
6252 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
6253 const char *ptr, const char *end)
6255 if (!poolAppend(pool, enc, ptr, end))
6257 if (pool->ptr == pool->end && !poolGrow(pool))
6263 static XML_Bool FASTCALL
6264 poolGrow(STRING_POOL *pool)
6266 if (pool->freeBlocks) {
6267 if (pool->start == 0) {
6268 pool->blocks = pool->freeBlocks;
6269 pool->freeBlocks = pool->freeBlocks->next;
6270 pool->blocks->next = NULL;
6271 pool->start = pool->blocks->s;
6272 pool->end = pool->start + pool->blocks->size;
6273 pool->ptr = pool->start;
6276 if (pool->end - pool->start < pool->freeBlocks->size) {
6277 BLOCK *tem = pool->freeBlocks->next;
6278 pool->freeBlocks->next = pool->blocks;
6279 pool->blocks = pool->freeBlocks;
6280 pool->freeBlocks = tem;
6281 memcpy(pool->blocks->s, pool->start,
6282 (pool->end - pool->start) * sizeof(XML_Char));
6283 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6284 pool->start = pool->blocks->s;
6285 pool->end = pool->start + pool->blocks->size;
6289 if (pool->blocks && pool->start == pool->blocks->s) {
6291 int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
6297 pool->mem->realloc_fcn(pool->blocks,
6299 + blockSize * sizeof(XML_Char)));
6302 pool->blocks = temp;
6303 pool->blocks->size = blockSize;
6304 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6305 pool->start = pool->blocks->s;
6306 pool->end = pool->start + blockSize;
6310 int blockSize = (int)(pool->end - pool->start);
6315 if (blockSize < INIT_BLOCK_SIZE)
6316 blockSize = INIT_BLOCK_SIZE;
6319 tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
6320 + blockSize * sizeof(XML_Char));
6323 tem->size = blockSize;
6324 tem->next = pool->blocks;
6326 if (pool->ptr != pool->start)
6327 memcpy(tem->s, pool->start,
6328 (pool->ptr - pool->start) * sizeof(XML_Char));
6329 pool->ptr = tem->s + (pool->ptr - pool->start);
6330 pool->start = tem->s;
6331 pool->end = tem->s + blockSize;
6337 nextScaffoldPart(XML_Parser parser)
6339 DTD * const dtd = _dtd; /* save one level of indirection */
6340 CONTENT_SCAFFOLD * me;
6343 if (!dtd->scaffIndex) {
6344 dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
6345 if (!dtd->scaffIndex)
6347 dtd->scaffIndex[0] = 0;
6350 if (dtd->scaffCount >= dtd->scaffSize) {
6351 CONTENT_SCAFFOLD *temp;
6352 if (dtd->scaffold) {
6353 temp = (CONTENT_SCAFFOLD *)
6354 REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
6357 dtd->scaffSize *= 2;
6360 temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
6361 * sizeof(CONTENT_SCAFFOLD));
6364 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
6366 dtd->scaffold = temp;
6368 next = dtd->scaffCount++;
6369 me = &dtd->scaffold[next];
6370 if (dtd->scaffLevel) {
6371 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
6372 if (parent->lastchild) {
6373 dtd->scaffold[parent->lastchild].nextsib = next;
6375 if (!parent->childcnt)
6376 parent->firstchild = next;
6377 parent->lastchild = next;
6380 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
6385 build_node(XML_Parser parser,
6388 XML_Content **contpos,
6391 DTD * const dtd = _dtd; /* save one level of indirection */
6392 dest->type = dtd->scaffold[src_node].type;
6393 dest->quant = dtd->scaffold[src_node].quant;
6394 if (dest->type == XML_CTYPE_NAME) {
6395 const XML_Char *src;
6396 dest->name = *strpos;
6397 src = dtd->scaffold[src_node].name;
6399 *(*strpos)++ = *src;
6404 dest->numchildren = 0;
6405 dest->children = NULL;
6410 dest->numchildren = dtd->scaffold[src_node].childcnt;
6411 dest->children = *contpos;
6412 *contpos += dest->numchildren;
6413 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
6414 i < dest->numchildren;
6415 i++, cn = dtd->scaffold[cn].nextsib) {
6416 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
6422 static XML_Content *
6423 build_model (XML_Parser parser)
6425 DTD * const dtd = _dtd; /* save one level of indirection */
6429 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
6430 + (dtd->contentStringLen * sizeof(XML_Char)));
6432 ret = (XML_Content *)MALLOC(allocsize);
6436 str = (XML_Char *) (&ret[dtd->scaffCount]);
6439 build_node(parser, 0, ret, &cpos, &str);
6443 static ELEMENT_TYPE *
6444 getElementType(XML_Parser parser,
6445 const ENCODING *enc,
6449 DTD * const dtd = _dtd; /* save one level of indirection */
6450 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
6455 ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
6458 if (ret->name != name)
6459 poolDiscard(&dtd->pool);
6461 poolFinish(&dtd->pool);
6462 if (!setElementTypePrefix(parser, ret))