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() */
9 #define XML_BUILDING_EXPAT 1
11 #ifdef COMPILED_FROM_DSP
12 #include "winconfig.h"
13 #elif defined(MACOS_CLASSIC)
14 #include "macconfig.h"
15 #elif defined(__amigaos4__)
16 #include "amigaconfig.h"
17 #elif defined(HAVE_EXPAT_CONFIG_H)
18 #include <expat_config.h>
19 #endif /* ndef COMPILED_FROM_DSP */
24 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
25 #define XmlConvert XmlUtf16Convert
26 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
27 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
28 #define XmlEncode XmlUtf16Encode
29 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
30 typedef unsigned short ICHAR
;
32 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
33 #define XmlConvert XmlUtf8Convert
34 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
35 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
36 #define XmlEncode XmlUtf8Encode
37 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
44 #define XmlInitEncodingNS XmlInitEncoding
45 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
46 #undef XmlGetInternalEncodingNS
47 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
48 #define XmlParseXmlDeclNS XmlParseXmlDecl
52 /* BEGIN MOZILLA CHANGE (typedef XML_Char to PRUnichar) */
57 #ifdef XML_UNICODE_WCHAR_T
58 #define XML_T(x) (const wchar_t)x
59 #define XML_L(x) L ## x
61 #define XML_T(x) (const unsigned short)x
73 /* END MOZILLA CHANGE */
75 /* Round up n to be a multiple of sz, where sz is a power of 2. */
76 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
78 /* Handle the case where memmove() doesn't exist. */
81 #define memmove(d,s,l) bcopy((s),(d),(l))
83 #error memmove does not exist on this platform, nor is a substitute available
84 #endif /* HAVE_BCOPY */
85 #endif /* HAVE_MEMMOVE */
91 typedef const XML_Char
*KEY
;
102 const XML_Memory_Handling_Suite
*mem
;
105 /* Basic character hash algorithm, taken from Python's string hash:
106 h = h * 1000003 ^ character, the constant being a prime number.
110 #define CHAR_HASH(h, c) \
111 (((h) * 0xF4243) ^ (unsigned short)(c))
113 #define CHAR_HASH(h, c) \
114 (((h) * 0xF4243) ^ (unsigned char)(c))
117 /* For probing (after a collision) we need a step size relative prime
118 to the hash table size, which is a power of 2. We use double-hashing,
119 since we can calculate a second hash value cheaply by taking those bits
120 of the first hash value that were discarded (masked out) when the table
121 index was calculated: index = hash & mask, where mask = table->size - 1.
122 We limit the maximum step size to table->size / 4 (mask >> 2) and make
123 it odd, since odd numbers are always relative prime to a power of 2.
125 #define SECOND_HASH(hash, mask, power) \
126 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
127 #define PROBE_STEP(hash, mask, power) \
128 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
135 #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
136 #define INIT_DATA_BUF_SIZE 1024
137 #define INIT_ATTS_SIZE 16
138 #define INIT_ATTS_VERSION 0xFFFFFFFF
139 #define INIT_BLOCK_SIZE 1024
140 #define INIT_BUFFER_SIZE 1024
142 #define EXPAND_SPARE 24
144 typedef struct binding
{
145 struct prefix
*prefix
;
146 struct binding
*nextTagBinding
;
147 struct binding
*prevPrefixBinding
;
148 const struct attribute_id
*attId
;
154 typedef struct prefix
{
155 const XML_Char
*name
;
161 const XML_Char
*localPart
;
162 const XML_Char
*prefix
;
168 /* TAG represents an open element.
169 The name of the element is stored in both the document and API
170 encodings. The memory buffer 'buf' is a separately-allocated
171 memory area which stores the name. During the XML_Parse()/
172 XMLParseBuffer() when the element is open, the memory for the 'raw'
173 version of the name (in the document encoding) is shared with the
174 document buffer. If the element is open across calls to
175 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
176 contain the 'raw' name as well.
178 A parser re-uses these structures, maintaining a list of allocated
179 TAG objects in a free list.
182 struct tag
*parent
; /* parent of this element */
183 const char *rawName
; /* tagName in the original encoding */
185 TAG_NAME name
; /* tagName in the API encoding */
186 char *buf
; /* buffer for name components */
187 char *bufEnd
; /* end of the buffer */
192 const XML_Char
*name
;
193 const XML_Char
*textPtr
;
194 int textLen
; /* length in XML_Chars */
195 int processed
; /* # of processed bytes - when suspended */
196 const XML_Char
*systemId
;
197 const XML_Char
*base
;
198 const XML_Char
*publicId
;
199 const XML_Char
*notation
;
202 XML_Bool is_internal
; /* true if declared in internal subset outside PE */
206 enum XML_Content_Type type
;
207 enum XML_Content_Quant quant
;
208 const XML_Char
* name
;
215 #define INIT_SCAFFOLD_ELEMENTS 32
217 typedef struct block
{
229 const XML_Memory_Handling_Suite
*mem
;
232 /* The XML_Char before the name is used to determine whether
233 an attribute has been specified. */
234 typedef struct attribute_id
{
237 XML_Bool maybeTokenized
;
242 const ATTRIBUTE_ID
*id
;
244 const XML_Char
*value
;
248 unsigned long version
;
250 const XML_Char
*uriName
;
254 const XML_Char
*name
;
256 const ATTRIBUTE_ID
*idAtt
;
258 int allocDefaultAtts
;
259 DEFAULT_ATTRIBUTE
*defaultAtts
;
263 HASH_TABLE generalEntities
;
264 HASH_TABLE elementTypes
;
265 HASH_TABLE attributeIds
;
268 STRING_POOL entityValuePool
;
269 /* false once a parameter entity reference has been skipped */
270 XML_Bool keepProcessing
;
271 /* true once an internal or external PE reference has been encountered;
272 this includes the reference to an external subset */
273 XML_Bool hasParamEntityRefs
;
276 /* indicates if external PE has been read */
277 XML_Bool paramEntityRead
;
278 HASH_TABLE paramEntities
;
280 PREFIX defaultPrefix
;
281 /* === scaffolding for building content model === */
283 CONTENT_SCAFFOLD
*scaffold
;
284 unsigned contentStringLen
;
291 typedef struct open_internal_entity
{
292 const char *internalEventPtr
;
293 const char *internalEventEndPtr
;
294 struct open_internal_entity
*next
;
297 XML_Bool betweenDecl
; /* WFC: PE Between Declarations */
298 } OPEN_INTERNAL_ENTITY
;
300 typedef enum XML_Error PTRCALL
Processor(XML_Parser parser
,
303 const char **endPtr
);
305 static Processor prologProcessor
;
306 static Processor prologInitProcessor
;
307 static Processor contentProcessor
;
308 static Processor cdataSectionProcessor
;
310 static Processor ignoreSectionProcessor
;
311 static Processor externalParEntProcessor
;
312 static Processor externalParEntInitProcessor
;
313 static Processor entityValueProcessor
;
314 static Processor entityValueInitProcessor
;
316 static Processor epilogProcessor
;
317 static Processor errorProcessor
;
318 static Processor externalEntityInitProcessor
;
319 static Processor externalEntityInitProcessor2
;
320 static Processor externalEntityInitProcessor3
;
321 static Processor externalEntityContentProcessor
;
322 static Processor internalEntityProcessor
;
324 static enum XML_Error
325 handleUnknownEncoding(XML_Parser parser
, const XML_Char
*encodingName
);
326 static enum XML_Error
327 processXmlDecl(XML_Parser parser
, int isGeneralTextEntity
,
328 const char *s
, const char *next
);
329 static enum XML_Error
330 initializeEncoding(XML_Parser parser
);
331 static enum XML_Error
332 doProlog(XML_Parser parser
, const ENCODING
*enc
, const char *s
,
333 const char *end
, int tok
, const char *next
, const char **nextPtr
,
335 static enum XML_Error
336 processInternalEntity(XML_Parser parser
, ENTITY
*entity
,
337 XML_Bool betweenDecl
);
338 static enum XML_Error
339 doContent(XML_Parser parser
, int startTagLevel
, const ENCODING
*enc
,
340 const char *start
, const char *end
, const char **endPtr
,
342 static enum XML_Error
343 doCdataSection(XML_Parser parser
, const ENCODING
*, const char **startPtr
,
344 const char *end
, const char **nextPtr
, XML_Bool haveMore
);
346 static enum XML_Error
347 doIgnoreSection(XML_Parser parser
, const ENCODING
*, const char **startPtr
,
348 const char *end
, const char **nextPtr
, XML_Bool haveMore
);
351 static enum XML_Error
352 storeAtts(XML_Parser parser
, const ENCODING
*, const char *s
,
353 TAG_NAME
*tagNamePtr
, BINDING
**bindingsPtr
);
354 static enum XML_Error
355 addBinding(XML_Parser parser
, PREFIX
*prefix
, const ATTRIBUTE_ID
*attId
,
356 const XML_Char
*uri
, BINDING
**bindingsPtr
);
358 defineAttribute(ELEMENT_TYPE
*type
, ATTRIBUTE_ID
*, XML_Bool isCdata
,
359 XML_Bool isId
, const XML_Char
*dfltValue
, XML_Parser parser
);
360 static enum XML_Error
361 storeAttributeValue(XML_Parser parser
, const ENCODING
*, XML_Bool isCdata
,
362 const char *, const char *, STRING_POOL
*);
363 static enum XML_Error
364 appendAttributeValue(XML_Parser parser
, const ENCODING
*, XML_Bool isCdata
,
365 const char *, const char *, STRING_POOL
*);
366 static ATTRIBUTE_ID
*
367 getAttributeId(XML_Parser parser
, const ENCODING
*enc
, const char *start
,
370 setElementTypePrefix(XML_Parser parser
, ELEMENT_TYPE
*);
371 static enum XML_Error
372 storeEntityValue(XML_Parser parser
, const ENCODING
*enc
, const char *start
,
375 reportProcessingInstruction(XML_Parser parser
, const ENCODING
*enc
,
376 const char *start
, const char *end
);
378 reportComment(XML_Parser parser
, const ENCODING
*enc
, const char *start
,
381 reportDefault(XML_Parser parser
, const ENCODING
*enc
, const char *start
,
384 static const XML_Char
* getContext(XML_Parser parser
);
386 setContext(XML_Parser parser
, const XML_Char
*context
);
388 static void FASTCALL
normalizePublicId(XML_Char
*s
);
390 static DTD
* dtdCreate(const XML_Memory_Handling_Suite
*ms
);
391 /* do not call if parentParser != NULL */
392 static void dtdReset(DTD
*p
, const XML_Memory_Handling_Suite
*ms
);
394 dtdDestroy(DTD
*p
, XML_Bool isDocEntity
, const XML_Memory_Handling_Suite
*ms
);
396 dtdCopy(DTD
*newDtd
, const DTD
*oldDtd
, const XML_Memory_Handling_Suite
*ms
);
398 copyEntityTable(HASH_TABLE
*, STRING_POOL
*, const HASH_TABLE
*);
401 lookup(HASH_TABLE
*table
, KEY name
, size_t createSize
);
403 hashTableInit(HASH_TABLE
*, const XML_Memory_Handling_Suite
*ms
);
404 static void FASTCALL
hashTableClear(HASH_TABLE
*);
405 static void FASTCALL
hashTableDestroy(HASH_TABLE
*);
407 hashTableIterInit(HASH_TABLE_ITER
*, const HASH_TABLE
*);
408 static NAMED
* FASTCALL
hashTableIterNext(HASH_TABLE_ITER
*);
411 poolInit(STRING_POOL
*, const XML_Memory_Handling_Suite
*ms
);
412 static void FASTCALL
poolClear(STRING_POOL
*);
413 static void FASTCALL
poolDestroy(STRING_POOL
*);
415 poolAppend(STRING_POOL
*pool
, const ENCODING
*enc
,
416 const char *ptr
, const char *end
);
418 poolStoreString(STRING_POOL
*pool
, const ENCODING
*enc
,
419 const char *ptr
, const char *end
);
420 static XML_Bool FASTCALL
poolGrow(STRING_POOL
*pool
);
421 static const XML_Char
* FASTCALL
422 poolCopyString(STRING_POOL
*pool
, const XML_Char
*s
);
423 static const XML_Char
*
424 poolCopyStringN(STRING_POOL
*pool
, const XML_Char
*s
, int n
);
425 static const XML_Char
* FASTCALL
426 poolAppendString(STRING_POOL
*pool
, const XML_Char
*s
);
428 static int FASTCALL
nextScaffoldPart(XML_Parser parser
);
429 static XML_Content
* build_model(XML_Parser parser
);
430 static ELEMENT_TYPE
*
431 getElementType(XML_Parser parser
, const ENCODING
*enc
,
432 const char *ptr
, const char *end
);
435 parserCreate(const XML_Char
*encodingName
,
436 const XML_Memory_Handling_Suite
*memsuite
,
437 const XML_Char
*nameSep
,
440 parserInit(XML_Parser parser
, const XML_Char
*encodingName
);
442 #define poolStart(pool) ((pool)->start)
443 #define poolEnd(pool) ((pool)->ptr)
444 #define poolLength(pool) ((pool)->ptr - (pool)->start)
445 #define poolChop(pool) ((void)--(pool->ptr))
446 #define poolLastChar(pool) (((pool)->ptr)[-1])
447 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
448 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
449 #define poolAppendChar(pool, c) \
450 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
452 : ((*((pool)->ptr)++ = c), 1))
454 struct XML_ParserStruct
{
455 /* The first member must be userData so that the XML_GetUserData
460 const XML_Memory_Handling_Suite m_mem
;
461 /* first character to be parsed */
462 const char *m_bufferPtr
;
463 /* past last character to be parsed */
465 /* allocated end of buffer */
466 const char *m_bufferLim
;
467 XML_Index m_parseEndByteIndex
;
468 const char *m_parseEndPtr
;
470 XML_Char
*m_dataBufEnd
;
471 XML_StartElementHandler m_startElementHandler
;
472 XML_EndElementHandler m_endElementHandler
;
473 XML_CharacterDataHandler m_characterDataHandler
;
474 XML_ProcessingInstructionHandler m_processingInstructionHandler
;
475 XML_CommentHandler m_commentHandler
;
476 XML_StartCdataSectionHandler m_startCdataSectionHandler
;
477 XML_EndCdataSectionHandler m_endCdataSectionHandler
;
478 XML_DefaultHandler m_defaultHandler
;
479 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler
;
480 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler
;
481 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler
;
482 XML_NotationDeclHandler m_notationDeclHandler
;
483 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler
;
484 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler
;
485 XML_NotStandaloneHandler m_notStandaloneHandler
;
486 XML_ExternalEntityRefHandler m_externalEntityRefHandler
;
487 XML_Parser m_externalEntityRefHandlerArg
;
488 XML_SkippedEntityHandler m_skippedEntityHandler
;
489 XML_UnknownEncodingHandler m_unknownEncodingHandler
;
490 XML_ElementDeclHandler m_elementDeclHandler
;
491 XML_AttlistDeclHandler m_attlistDeclHandler
;
492 XML_EntityDeclHandler m_entityDeclHandler
;
493 XML_XmlDeclHandler m_xmlDeclHandler
;
494 const ENCODING
*m_encoding
;
495 INIT_ENCODING m_initEncoding
;
496 const ENCODING
*m_internalEncoding
;
497 const XML_Char
*m_protocolEncodingName
;
499 XML_Bool m_ns_triplets
;
500 void *m_unknownEncodingMem
;
501 void *m_unknownEncodingData
;
502 void *m_unknownEncodingHandlerData
;
503 void (XMLCALL
*m_unknownEncodingRelease
)(void *);
504 PROLOG_STATE m_prologState
;
505 Processor
*m_processor
;
506 enum XML_Error m_errorCode
;
507 const char *m_eventPtr
;
508 const char *m_eventEndPtr
;
509 const char *m_positionPtr
;
510 OPEN_INTERNAL_ENTITY
*m_openInternalEntities
;
511 OPEN_INTERNAL_ENTITY
*m_freeInternalEntities
;
512 XML_Bool m_defaultExpandInternalEntities
;
514 ENTITY
*m_declEntity
;
515 const XML_Char
*m_doctypeName
;
516 const XML_Char
*m_doctypeSysid
;
517 const XML_Char
*m_doctypePubid
;
518 const XML_Char
*m_declAttributeType
;
519 const XML_Char
*m_declNotationName
;
520 const XML_Char
*m_declNotationPublicId
;
521 ELEMENT_TYPE
*m_declElementType
;
522 ATTRIBUTE_ID
*m_declAttributeId
;
523 XML_Bool m_declAttributeIsCdata
;
524 XML_Bool m_declAttributeIsId
;
526 const XML_Char
*m_curBase
;
529 BINDING
*m_inheritedBindings
;
530 BINDING
*m_freeBindingList
;
532 int m_nSpecifiedAtts
;
536 unsigned long m_nsAttsVersion
;
537 unsigned char m_nsAttsPower
;
539 STRING_POOL m_tempPool
;
540 STRING_POOL m_temp2Pool
;
541 char *m_groupConnector
;
542 unsigned int m_groupSize
;
543 XML_Char m_namespaceSeparator
;
544 XML_Parser m_parentParser
;
545 XML_ParsingStatus m_parsingStatus
;
547 XML_Bool m_isParamEntity
;
548 XML_Bool m_useForeignDTD
;
549 enum XML_ParamEntityParsing m_paramEntityParsing
;
551 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
552 const XML_Char
* m_mismatch
;
553 /* END MOZILLA CHANGE */
556 #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
557 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
558 #define FREE(p) (parser->m_mem.free_fcn((p)))
560 #define userData (parser->m_userData)
561 #define handlerArg (parser->m_handlerArg)
562 #define startElementHandler (parser->m_startElementHandler)
563 #define endElementHandler (parser->m_endElementHandler)
564 #define characterDataHandler (parser->m_characterDataHandler)
565 #define processingInstructionHandler \
566 (parser->m_processingInstructionHandler)
567 #define commentHandler (parser->m_commentHandler)
568 #define startCdataSectionHandler \
569 (parser->m_startCdataSectionHandler)
570 #define endCdataSectionHandler (parser->m_endCdataSectionHandler)
571 #define defaultHandler (parser->m_defaultHandler)
572 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
573 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
574 #define unparsedEntityDeclHandler \
575 (parser->m_unparsedEntityDeclHandler)
576 #define notationDeclHandler (parser->m_notationDeclHandler)
577 #define startNamespaceDeclHandler \
578 (parser->m_startNamespaceDeclHandler)
579 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
580 #define notStandaloneHandler (parser->m_notStandaloneHandler)
581 #define externalEntityRefHandler \
582 (parser->m_externalEntityRefHandler)
583 #define externalEntityRefHandlerArg \
584 (parser->m_externalEntityRefHandlerArg)
585 #define internalEntityRefHandler \
586 (parser->m_internalEntityRefHandler)
587 #define skippedEntityHandler (parser->m_skippedEntityHandler)
588 #define unknownEncodingHandler (parser->m_unknownEncodingHandler)
589 #define elementDeclHandler (parser->m_elementDeclHandler)
590 #define attlistDeclHandler (parser->m_attlistDeclHandler)
591 #define entityDeclHandler (parser->m_entityDeclHandler)
592 #define xmlDeclHandler (parser->m_xmlDeclHandler)
593 #define encoding (parser->m_encoding)
594 #define initEncoding (parser->m_initEncoding)
595 #define internalEncoding (parser->m_internalEncoding)
596 #define unknownEncodingMem (parser->m_unknownEncodingMem)
597 #define unknownEncodingData (parser->m_unknownEncodingData)
598 #define unknownEncodingHandlerData \
599 (parser->m_unknownEncodingHandlerData)
600 #define unknownEncodingRelease (parser->m_unknownEncodingRelease)
601 #define protocolEncodingName (parser->m_protocolEncodingName)
602 #define ns (parser->m_ns)
603 #define ns_triplets (parser->m_ns_triplets)
604 #define prologState (parser->m_prologState)
605 #define processor (parser->m_processor)
606 #define errorCode (parser->m_errorCode)
607 #define eventPtr (parser->m_eventPtr)
608 #define eventEndPtr (parser->m_eventEndPtr)
609 #define positionPtr (parser->m_positionPtr)
610 #define position (parser->m_position)
611 #define openInternalEntities (parser->m_openInternalEntities)
612 #define freeInternalEntities (parser->m_freeInternalEntities)
613 #define defaultExpandInternalEntities \
614 (parser->m_defaultExpandInternalEntities)
615 #define tagLevel (parser->m_tagLevel)
616 #define buffer (parser->m_buffer)
617 #define bufferPtr (parser->m_bufferPtr)
618 #define bufferEnd (parser->m_bufferEnd)
619 #define parseEndByteIndex (parser->m_parseEndByteIndex)
620 #define parseEndPtr (parser->m_parseEndPtr)
621 #define bufferLim (parser->m_bufferLim)
622 #define dataBuf (parser->m_dataBuf)
623 #define dataBufEnd (parser->m_dataBufEnd)
624 #define _dtd (parser->m_dtd)
625 #define curBase (parser->m_curBase)
626 #define declEntity (parser->m_declEntity)
627 #define doctypeName (parser->m_doctypeName)
628 #define doctypeSysid (parser->m_doctypeSysid)
629 #define doctypePubid (parser->m_doctypePubid)
630 #define declAttributeType (parser->m_declAttributeType)
631 #define declNotationName (parser->m_declNotationName)
632 #define declNotationPublicId (parser->m_declNotationPublicId)
633 #define declElementType (parser->m_declElementType)
634 #define declAttributeId (parser->m_declAttributeId)
635 #define declAttributeIsCdata (parser->m_declAttributeIsCdata)
636 #define declAttributeIsId (parser->m_declAttributeIsId)
637 #define freeTagList (parser->m_freeTagList)
638 #define freeBindingList (parser->m_freeBindingList)
639 #define inheritedBindings (parser->m_inheritedBindings)
640 #define tagStack (parser->m_tagStack)
641 #define atts (parser->m_atts)
642 #define attsSize (parser->m_attsSize)
643 #define nSpecifiedAtts (parser->m_nSpecifiedAtts)
644 #define idAttIndex (parser->m_idAttIndex)
645 #define nsAtts (parser->m_nsAtts)
646 #define nsAttsVersion (parser->m_nsAttsVersion)
647 #define nsAttsPower (parser->m_nsAttsPower)
648 #define tempPool (parser->m_tempPool)
649 #define temp2Pool (parser->m_temp2Pool)
650 #define groupConnector (parser->m_groupConnector)
651 #define groupSize (parser->m_groupSize)
652 #define namespaceSeparator (parser->m_namespaceSeparator)
653 #define parentParser (parser->m_parentParser)
654 #define ps_parsing (parser->m_parsingStatus.parsing)
655 #define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
657 #define isParamEntity (parser->m_isParamEntity)
658 #define useForeignDTD (parser->m_useForeignDTD)
659 #define paramEntityParsing (parser->m_paramEntityParsing)
661 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
662 #define mismatch (parser->m_mismatch)
663 /* END MOZILLA CHANGE */
665 /* BEGIN MOZILLA CHANGE (unused API) */
668 XML_ParserCreate(const XML_Char
*encodingName
)
670 return XML_ParserCreate_MM(encodingName
, NULL
, NULL
);
676 XML_ParserCreateNS(const XML_Char
*encodingName
, XML_Char nsSep
)
680 return XML_ParserCreate_MM(encodingName
, NULL
, tmp
);
683 /* END MOZILLA CHANGE */
685 static const XML_Char implicitContext
[] = {
686 'x', 'm', 'l', '=', 'h', 't', 't', 'p', ':', '/', '/',
687 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
688 'X', 'M', 'L', '/', '1', '9', '9', '8', '/',
689 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0'
693 XML_ParserCreate_MM(const XML_Char
*encodingName
,
694 const XML_Memory_Handling_Suite
*memsuite
,
695 const XML_Char
*nameSep
)
697 XML_Parser parser
= parserCreate(encodingName
, memsuite
, nameSep
, NULL
);
698 if (parser
!= NULL
&& ns
) {
699 /* implicit context only set for root parser, since child
700 parsers (i.e. external entity parsers) will inherit it
702 if (!setContext(parser
, implicitContext
)) {
703 XML_ParserFree(parser
);
711 parserCreate(const XML_Char
*encodingName
,
712 const XML_Memory_Handling_Suite
*memsuite
,
713 const XML_Char
*nameSep
,
719 XML_Memory_Handling_Suite
*mtemp
;
720 parser
= (XML_Parser
)
721 memsuite
->malloc_fcn(sizeof(struct XML_ParserStruct
));
722 if (parser
!= NULL
) {
723 mtemp
= (XML_Memory_Handling_Suite
*)&(parser
->m_mem
);
724 mtemp
->malloc_fcn
= memsuite
->malloc_fcn
;
725 mtemp
->realloc_fcn
= memsuite
->realloc_fcn
;
726 mtemp
->free_fcn
= memsuite
->free_fcn
;
730 XML_Memory_Handling_Suite
*mtemp
;
731 parser
= (XML_Parser
)malloc(sizeof(struct XML_ParserStruct
));
732 if (parser
!= NULL
) {
733 mtemp
= (XML_Memory_Handling_Suite
*)&(parser
->m_mem
);
734 mtemp
->malloc_fcn
= malloc
;
735 mtemp
->realloc_fcn
= realloc
;
736 mtemp
->free_fcn
= free
;
746 attsSize
= INIT_ATTS_SIZE
;
747 atts
= (ATTRIBUTE
*)MALLOC(attsSize
* sizeof(ATTRIBUTE
));
752 dataBuf
= (XML_Char
*)MALLOC(INIT_DATA_BUF_SIZE
* sizeof(XML_Char
));
753 if (dataBuf
== NULL
) {
758 dataBufEnd
= dataBuf
+ INIT_DATA_BUF_SIZE
;
763 _dtd
= dtdCreate(&parser
->m_mem
);
772 freeBindingList
= NULL
;
774 freeInternalEntities
= NULL
;
777 groupConnector
= NULL
;
779 unknownEncodingHandler
= NULL
;
780 unknownEncodingHandlerData
= NULL
;
782 namespaceSeparator
= '!';
784 ns_triplets
= XML_FALSE
;
790 poolInit(&tempPool
, &(parser
->m_mem
));
791 poolInit(&temp2Pool
, &(parser
->m_mem
));
792 parserInit(parser
, encodingName
);
794 if (encodingName
&& !protocolEncodingName
) {
795 XML_ParserFree(parser
);
801 internalEncoding
= XmlGetInternalEncodingNS();
802 namespaceSeparator
= *nameSep
;
805 internalEncoding
= XmlGetInternalEncoding();
808 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
810 /* END MOZILLA CHANGE */
816 parserInit(XML_Parser parser
, const XML_Char
*encodingName
)
818 processor
= prologInitProcessor
;
819 XmlPrologStateInit(&prologState
);
820 protocolEncodingName
= (encodingName
!= NULL
821 ? poolCopyString(&tempPool
, encodingName
)
824 XmlInitEncoding(&initEncoding
, &encoding
, 0);
827 startElementHandler
= NULL
;
828 endElementHandler
= NULL
;
829 characterDataHandler
= NULL
;
830 processingInstructionHandler
= NULL
;
831 commentHandler
= NULL
;
832 startCdataSectionHandler
= NULL
;
833 endCdataSectionHandler
= NULL
;
834 defaultHandler
= NULL
;
835 startDoctypeDeclHandler
= NULL
;
836 endDoctypeDeclHandler
= NULL
;
837 unparsedEntityDeclHandler
= NULL
;
838 notationDeclHandler
= NULL
;
839 startNamespaceDeclHandler
= NULL
;
840 endNamespaceDeclHandler
= NULL
;
841 notStandaloneHandler
= NULL
;
842 externalEntityRefHandler
= NULL
;
843 externalEntityRefHandlerArg
= parser
;
844 skippedEntityHandler
= NULL
;
845 elementDeclHandler
= NULL
;
846 attlistDeclHandler
= NULL
;
847 entityDeclHandler
= NULL
;
848 xmlDeclHandler
= NULL
;
851 parseEndByteIndex
= 0;
853 declElementType
= NULL
;
854 declAttributeId
= NULL
;
859 declAttributeType
= NULL
;
860 declNotationName
= NULL
;
861 declNotationPublicId
= NULL
;
862 declAttributeIsCdata
= XML_FALSE
;
863 declAttributeIsId
= XML_FALSE
;
864 memset(&position
, 0, sizeof(POSITION
));
865 errorCode
= XML_ERROR_NONE
;
869 openInternalEntities
= NULL
;
870 defaultExpandInternalEntities
= XML_TRUE
;
873 inheritedBindings
= NULL
;
875 unknownEncodingMem
= NULL
;
876 unknownEncodingRelease
= NULL
;
877 unknownEncodingData
= NULL
;
879 ps_parsing
= XML_INITIALIZED
;
881 isParamEntity
= XML_FALSE
;
882 useForeignDTD
= XML_FALSE
;
883 paramEntityParsing
= XML_PARAM_ENTITY_PARSING_NEVER
;
887 /* moves list of bindings to freeBindingList */
889 moveToFreeBindingList(XML_Parser parser
, BINDING
*bindings
)
892 BINDING
*b
= bindings
;
893 bindings
= bindings
->nextTagBinding
;
894 b
->nextTagBinding
= freeBindingList
;
899 /* BEGIN MOZILLA CHANGE (unused API) */
902 XML_ParserReset(XML_Parser parser
, const XML_Char
*encodingName
)
905 OPEN_INTERNAL_ENTITY
*openEntityList
;
908 /* move tagStack to freeTagList */
913 tag
->parent
= freeTagList
;
914 moveToFreeBindingList(parser
, tag
->bindings
);
915 tag
->bindings
= NULL
;
918 /* move openInternalEntities to freeInternalEntities */
919 openEntityList
= openInternalEntities
;
920 while (openEntityList
) {
921 OPEN_INTERNAL_ENTITY
*openEntity
= openEntityList
;
922 openEntityList
= openEntity
->next
;
923 openEntity
->next
= freeInternalEntities
;
924 freeInternalEntities
= openEntity
;
926 moveToFreeBindingList(parser
, inheritedBindings
);
927 FREE(unknownEncodingMem
);
928 if (unknownEncodingRelease
)
929 unknownEncodingRelease(unknownEncodingData
);
930 poolClear(&tempPool
);
931 poolClear(&temp2Pool
);
932 parserInit(parser
, encodingName
);
933 dtdReset(_dtd
, &parser
->m_mem
);
934 return setContext(parser
, implicitContext
);
937 enum XML_Status XMLCALL
938 XML_SetEncoding(XML_Parser parser
, const XML_Char
*encodingName
)
940 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
941 XXX There's no way for the caller to determine which of the
942 XXX possible error cases caused the XML_STATUS_ERROR return.
944 if (ps_parsing
== XML_PARSING
|| ps_parsing
== XML_SUSPENDED
)
945 return XML_STATUS_ERROR
;
946 if (encodingName
== NULL
)
947 protocolEncodingName
= NULL
;
949 protocolEncodingName
= poolCopyString(&tempPool
, encodingName
);
950 if (!protocolEncodingName
)
951 return XML_STATUS_ERROR
;
953 return XML_STATUS_OK
;
956 /* END MOZILLA CHANGE */
959 XML_ExternalEntityParserCreate(XML_Parser oldParser
,
960 const XML_Char
*context
,
961 const XML_Char
*encodingName
)
963 XML_Parser parser
= oldParser
;
966 XML_StartElementHandler oldStartElementHandler
= startElementHandler
;
967 XML_EndElementHandler oldEndElementHandler
= endElementHandler
;
968 XML_CharacterDataHandler oldCharacterDataHandler
= characterDataHandler
;
969 XML_ProcessingInstructionHandler oldProcessingInstructionHandler
970 = processingInstructionHandler
;
971 XML_CommentHandler oldCommentHandler
= commentHandler
;
972 XML_StartCdataSectionHandler oldStartCdataSectionHandler
973 = startCdataSectionHandler
;
974 XML_EndCdataSectionHandler oldEndCdataSectionHandler
975 = endCdataSectionHandler
;
976 XML_DefaultHandler oldDefaultHandler
= defaultHandler
;
977 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
978 = unparsedEntityDeclHandler
;
979 XML_NotationDeclHandler oldNotationDeclHandler
= notationDeclHandler
;
980 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
981 = startNamespaceDeclHandler
;
982 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
983 = endNamespaceDeclHandler
;
984 XML_NotStandaloneHandler oldNotStandaloneHandler
= notStandaloneHandler
;
985 XML_ExternalEntityRefHandler oldExternalEntityRefHandler
986 = externalEntityRefHandler
;
987 XML_SkippedEntityHandler oldSkippedEntityHandler
= skippedEntityHandler
;
988 XML_UnknownEncodingHandler oldUnknownEncodingHandler
989 = unknownEncodingHandler
;
990 XML_ElementDeclHandler oldElementDeclHandler
= elementDeclHandler
;
991 XML_AttlistDeclHandler oldAttlistDeclHandler
= attlistDeclHandler
;
992 XML_EntityDeclHandler oldEntityDeclHandler
= entityDeclHandler
;
993 XML_XmlDeclHandler oldXmlDeclHandler
= xmlDeclHandler
;
994 ELEMENT_TYPE
* oldDeclElementType
= declElementType
;
996 void *oldUserData
= userData
;
997 void *oldHandlerArg
= handlerArg
;
998 XML_Bool oldDefaultExpandInternalEntities
= defaultExpandInternalEntities
;
999 XML_Parser oldExternalEntityRefHandlerArg
= externalEntityRefHandlerArg
;
1001 enum XML_ParamEntityParsing oldParamEntityParsing
= paramEntityParsing
;
1002 int oldInEntityValue
= prologState
.inEntityValue
;
1004 XML_Bool oldns_triplets
= ns_triplets
;
1009 #endif /* XML_DTD */
1011 /* Note that the magical uses of the pre-processor to make field
1012 access look more like C++ require that `parser' be overwritten
1013 here. This makes this function more painful to follow than it
1018 *tmp
= namespaceSeparator
;
1019 parser
= parserCreate(encodingName
, &parser
->m_mem
, tmp
, newDtd
);
1022 parser
= parserCreate(encodingName
, &parser
->m_mem
, NULL
, newDtd
);
1028 startElementHandler
= oldStartElementHandler
;
1029 endElementHandler
= oldEndElementHandler
;
1030 characterDataHandler
= oldCharacterDataHandler
;
1031 processingInstructionHandler
= oldProcessingInstructionHandler
;
1032 commentHandler
= oldCommentHandler
;
1033 startCdataSectionHandler
= oldStartCdataSectionHandler
;
1034 endCdataSectionHandler
= oldEndCdataSectionHandler
;
1035 defaultHandler
= oldDefaultHandler
;
1036 unparsedEntityDeclHandler
= oldUnparsedEntityDeclHandler
;
1037 notationDeclHandler
= oldNotationDeclHandler
;
1038 startNamespaceDeclHandler
= oldStartNamespaceDeclHandler
;
1039 endNamespaceDeclHandler
= oldEndNamespaceDeclHandler
;
1040 notStandaloneHandler
= oldNotStandaloneHandler
;
1041 externalEntityRefHandler
= oldExternalEntityRefHandler
;
1042 skippedEntityHandler
= oldSkippedEntityHandler
;
1043 unknownEncodingHandler
= oldUnknownEncodingHandler
;
1044 elementDeclHandler
= oldElementDeclHandler
;
1045 attlistDeclHandler
= oldAttlistDeclHandler
;
1046 entityDeclHandler
= oldEntityDeclHandler
;
1047 xmlDeclHandler
= oldXmlDeclHandler
;
1048 declElementType
= oldDeclElementType
;
1049 userData
= oldUserData
;
1050 if (oldUserData
== oldHandlerArg
)
1051 handlerArg
= userData
;
1053 handlerArg
= parser
;
1054 if (oldExternalEntityRefHandlerArg
!= oldParser
)
1055 externalEntityRefHandlerArg
= oldExternalEntityRefHandlerArg
;
1056 defaultExpandInternalEntities
= oldDefaultExpandInternalEntities
;
1057 ns_triplets
= oldns_triplets
;
1058 parentParser
= oldParser
;
1060 paramEntityParsing
= oldParamEntityParsing
;
1061 prologState
.inEntityValue
= oldInEntityValue
;
1063 #endif /* XML_DTD */
1064 if (!dtdCopy(_dtd
, oldDtd
, &parser
->m_mem
)
1065 || !setContext(parser
, context
)) {
1066 XML_ParserFree(parser
);
1069 processor
= externalEntityInitProcessor
;
1073 /* The DTD instance referenced by _dtd is shared between the document's
1074 root parser and external PE parsers, therefore one does not need to
1075 call setContext. In addition, one also *must* not call setContext,
1076 because this would overwrite existing prefix->binding pointers in
1077 _dtd with ones that get destroyed with the external PE parser.
1078 This would leave those prefixes with dangling pointers.
1080 isParamEntity
= XML_TRUE
;
1081 XmlPrologStateInitExternalEntity(&prologState
);
1082 processor
= externalParEntInitProcessor
;
1084 #endif /* XML_DTD */
1088 static void FASTCALL
1089 destroyBindings(BINDING
*bindings
, XML_Parser parser
)
1092 BINDING
*b
= bindings
;
1095 bindings
= b
->nextTagBinding
;
1102 XML_ParserFree(XML_Parser parser
)
1105 OPEN_INTERNAL_ENTITY
*entityList
;
1108 /* free tagStack and freeTagList */
1112 if (tagList
== NULL
) {
1113 if (freeTagList
== NULL
)
1115 tagList
= freeTagList
;
1119 tagList
= tagList
->parent
;
1121 destroyBindings(p
->bindings
, parser
);
1124 /* free openInternalEntities and freeInternalEntities */
1125 entityList
= openInternalEntities
;
1127 OPEN_INTERNAL_ENTITY
*openEntity
;
1128 if (entityList
== NULL
) {
1129 if (freeInternalEntities
== NULL
)
1131 entityList
= freeInternalEntities
;
1132 freeInternalEntities
= NULL
;
1134 openEntity
= entityList
;
1135 entityList
= entityList
->next
;
1139 destroyBindings(freeBindingList
, parser
);
1140 destroyBindings(inheritedBindings
, parser
);
1141 poolDestroy(&tempPool
);
1142 poolDestroy(&temp2Pool
);
1144 /* external parameter entity parsers share the DTD structure
1145 parser->m_dtd with the root parser, so we must not destroy it
1147 if (!isParamEntity
&& _dtd
)
1150 #endif /* XML_DTD */
1151 dtdDestroy(_dtd
, (XML_Bool
)!parentParser
, &parser
->m_mem
);
1153 FREE(groupConnector
);
1157 FREE(unknownEncodingMem
);
1158 if (unknownEncodingRelease
)
1159 unknownEncodingRelease(unknownEncodingData
);
1164 XML_UseParserAsHandlerArg(XML_Parser parser
)
1166 handlerArg
= parser
;
1169 /* BEGIN MOZILLA CHANGE (unused API) */
1171 enum XML_Error XMLCALL
1172 XML_UseForeignDTD(XML_Parser parser
, XML_Bool useDTD
)
1175 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1176 if (ps_parsing
== XML_PARSING
|| ps_parsing
== XML_SUSPENDED
)
1177 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING
;
1178 useForeignDTD
= useDTD
;
1179 return XML_ERROR_NONE
;
1181 return XML_ERROR_FEATURE_REQUIRES_XML_DTD
;
1185 /* END MOZILLA CHANGE */
1188 XML_SetReturnNSTriplet(XML_Parser parser
, int do_nst
)
1190 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1191 if (ps_parsing
== XML_PARSING
|| ps_parsing
== XML_SUSPENDED
)
1193 ns_triplets
= do_nst
? XML_TRUE
: XML_FALSE
;
1197 XML_SetUserData(XML_Parser parser
, void *p
)
1199 if (handlerArg
== userData
)
1200 handlerArg
= userData
= p
;
1205 enum XML_Status XMLCALL
1206 XML_SetBase(XML_Parser parser
, const XML_Char
*p
)
1209 p
= poolCopyString(&_dtd
->pool
, p
);
1211 return XML_STATUS_ERROR
;
1216 return XML_STATUS_OK
;
1219 const XML_Char
* XMLCALL
1220 XML_GetBase(XML_Parser parser
)
1226 XML_GetSpecifiedAttributeCount(XML_Parser parser
)
1228 return nSpecifiedAtts
;
1232 XML_GetIdAttributeIndex(XML_Parser parser
)
1238 XML_SetElementHandler(XML_Parser parser
,
1239 XML_StartElementHandler start
,
1240 XML_EndElementHandler end
)
1242 startElementHandler
= start
;
1243 endElementHandler
= end
;
1246 /* BEGIN MOZILLA CHANGE (unused API) */
1249 XML_SetStartElementHandler(XML_Parser parser
,
1250 XML_StartElementHandler start
) {
1251 startElementHandler
= start
;
1255 XML_SetEndElementHandler(XML_Parser parser
,
1256 XML_EndElementHandler end
) {
1257 endElementHandler
= end
;
1260 /* END MOZILLA CHANGE */
1263 XML_SetCharacterDataHandler(XML_Parser parser
,
1264 XML_CharacterDataHandler handler
)
1266 characterDataHandler
= handler
;
1270 XML_SetProcessingInstructionHandler(XML_Parser parser
,
1271 XML_ProcessingInstructionHandler handler
)
1273 processingInstructionHandler
= handler
;
1277 XML_SetCommentHandler(XML_Parser parser
,
1278 XML_CommentHandler handler
)
1280 commentHandler
= handler
;
1284 XML_SetCdataSectionHandler(XML_Parser parser
,
1285 XML_StartCdataSectionHandler start
,
1286 XML_EndCdataSectionHandler end
)
1288 startCdataSectionHandler
= start
;
1289 endCdataSectionHandler
= end
;
1292 /* BEGIN MOZILLA CHANGE (unused API) */
1295 XML_SetStartCdataSectionHandler(XML_Parser parser
,
1296 XML_StartCdataSectionHandler start
) {
1297 startCdataSectionHandler
= start
;
1301 XML_SetEndCdataSectionHandler(XML_Parser parser
,
1302 XML_EndCdataSectionHandler end
) {
1303 endCdataSectionHandler
= end
;
1307 XML_SetDefaultHandler(XML_Parser parser
,
1308 XML_DefaultHandler handler
)
1310 defaultHandler
= handler
;
1311 defaultExpandInternalEntities
= XML_FALSE
;
1314 /* END MOZILLA CHANGE */
1317 XML_SetDefaultHandlerExpand(XML_Parser parser
,
1318 XML_DefaultHandler handler
)
1320 defaultHandler
= handler
;
1321 defaultExpandInternalEntities
= XML_TRUE
;
1325 XML_SetDoctypeDeclHandler(XML_Parser parser
,
1326 XML_StartDoctypeDeclHandler start
,
1327 XML_EndDoctypeDeclHandler end
)
1329 startDoctypeDeclHandler
= start
;
1330 endDoctypeDeclHandler
= end
;
1333 /* BEGIN MOZILLA CHANGE (unused API) */
1336 XML_SetStartDoctypeDeclHandler(XML_Parser parser
,
1337 XML_StartDoctypeDeclHandler start
) {
1338 startDoctypeDeclHandler
= start
;
1342 XML_SetEndDoctypeDeclHandler(XML_Parser parser
,
1343 XML_EndDoctypeDeclHandler end
) {
1344 endDoctypeDeclHandler
= end
;
1347 /* END MOZILLA CHANGE */
1350 XML_SetUnparsedEntityDeclHandler(XML_Parser parser
,
1351 XML_UnparsedEntityDeclHandler handler
)
1353 unparsedEntityDeclHandler
= handler
;
1357 XML_SetNotationDeclHandler(XML_Parser parser
,
1358 XML_NotationDeclHandler handler
)
1360 notationDeclHandler
= handler
;
1364 XML_SetNamespaceDeclHandler(XML_Parser parser
,
1365 XML_StartNamespaceDeclHandler start
,
1366 XML_EndNamespaceDeclHandler end
)
1368 startNamespaceDeclHandler
= start
;
1369 endNamespaceDeclHandler
= end
;
1373 /* BEGIN MOZILLA CHANGE (unused API) */
1376 XML_SetStartNamespaceDeclHandler(XML_Parser parser
,
1377 XML_StartNamespaceDeclHandler start
) {
1378 startNamespaceDeclHandler
= start
;
1382 XML_SetEndNamespaceDeclHandler(XML_Parser parser
,
1383 XML_EndNamespaceDeclHandler end
) {
1384 endNamespaceDeclHandler
= end
;
1388 XML_SetNotStandaloneHandler(XML_Parser parser
,
1389 XML_NotStandaloneHandler handler
)
1391 notStandaloneHandler
= handler
;
1394 /* END MOZILLA CHANGE */
1397 XML_SetExternalEntityRefHandler(XML_Parser parser
,
1398 XML_ExternalEntityRefHandler handler
)
1400 externalEntityRefHandler
= handler
;
1404 XML_SetExternalEntityRefHandlerArg(XML_Parser parser
, void *arg
)
1407 externalEntityRefHandlerArg
= (XML_Parser
)arg
;
1409 externalEntityRefHandlerArg
= parser
;
1412 /* BEGIN MOZILLA CHANGE (unused API) */
1415 XML_SetSkippedEntityHandler(XML_Parser parser
,
1416 XML_SkippedEntityHandler handler
)
1418 skippedEntityHandler
= handler
;
1422 XML_SetUnknownEncodingHandler(XML_Parser parser
,
1423 XML_UnknownEncodingHandler handler
,
1426 unknownEncodingHandler
= handler
;
1427 unknownEncodingHandlerData
= data
;
1431 XML_SetElementDeclHandler(XML_Parser parser
,
1432 XML_ElementDeclHandler eldecl
)
1434 elementDeclHandler
= eldecl
;
1438 XML_SetAttlistDeclHandler(XML_Parser parser
,
1439 XML_AttlistDeclHandler attdecl
)
1441 attlistDeclHandler
= attdecl
;
1445 XML_SetEntityDeclHandler(XML_Parser parser
,
1446 XML_EntityDeclHandler handler
)
1448 entityDeclHandler
= handler
;
1451 /* END MOZILLA CHANGE */
1454 XML_SetXmlDeclHandler(XML_Parser parser
,
1455 XML_XmlDeclHandler handler
) {
1456 xmlDeclHandler
= handler
;
1460 XML_SetParamEntityParsing(XML_Parser parser
,
1461 enum XML_ParamEntityParsing peParsing
)
1463 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1464 if (ps_parsing
== XML_PARSING
|| ps_parsing
== XML_SUSPENDED
)
1467 paramEntityParsing
= peParsing
;
1470 return peParsing
== XML_PARAM_ENTITY_PARSING_NEVER
;
1474 enum XML_Status XMLCALL
1475 XML_Parse(XML_Parser parser
, const char *s
, int len
, int isFinal
)
1477 switch (ps_parsing
) {
1479 errorCode
= XML_ERROR_SUSPENDED
;
1480 return XML_STATUS_ERROR
;
1482 errorCode
= XML_ERROR_FINISHED
;
1483 return XML_STATUS_ERROR
;
1485 ps_parsing
= XML_PARSING
;
1489 ps_finalBuffer
= (XML_Bool
)isFinal
;
1491 return XML_STATUS_OK
;
1492 positionPtr
= bufferPtr
;
1493 parseEndPtr
= bufferEnd
;
1495 /* If data are left over from last buffer, and we now know that these
1496 data are the final chunk of input, then we have to check them again
1497 to detect errors based on that fact.
1499 errorCode
= processor(parser
, bufferPtr
, parseEndPtr
, &bufferPtr
);
1501 if (errorCode
== XML_ERROR_NONE
) {
1502 switch (ps_parsing
) {
1504 XmlUpdatePosition(encoding
, positionPtr
, bufferPtr
, &position
);
1505 positionPtr
= bufferPtr
;
1506 return XML_STATUS_SUSPENDED
;
1507 case XML_INITIALIZED
:
1509 ps_parsing
= XML_FINISHED
;
1512 return XML_STATUS_OK
;
1515 eventEndPtr
= eventPtr
;
1516 processor
= errorProcessor
;
1517 return XML_STATUS_ERROR
;
1519 #ifndef XML_CONTEXT_BYTES
1520 else if (bufferPtr
== bufferEnd
) {
1523 enum XML_Error result
;
1524 parseEndByteIndex
+= len
;
1526 ps_finalBuffer
= (XML_Bool
)isFinal
;
1528 errorCode
= processor(parser
, s
, parseEndPtr
= s
+ len
, &end
);
1530 if (errorCode
!= XML_ERROR_NONE
) {
1531 eventEndPtr
= eventPtr
;
1532 processor
= errorProcessor
;
1533 return XML_STATUS_ERROR
;
1536 switch (ps_parsing
) {
1538 result
= XML_STATUS_SUSPENDED
;
1540 case XML_INITIALIZED
:
1542 result
= XML_STATUS_OK
;
1544 ps_parsing
= XML_FINISHED
;
1550 XmlUpdatePosition(encoding
, positionPtr
, end
, &position
);
1551 nLeftOver
= s
+ len
- end
;
1553 if (buffer
== NULL
|| nLeftOver
> bufferLim
- buffer
) {
1554 /* FIXME avoid integer overflow */
1556 temp
= (buffer
== NULL
1557 ? (char *)MALLOC(len
* 2)
1558 : (char *)REALLOC(buffer
, len
* 2));
1560 errorCode
= XML_ERROR_NO_MEMORY
;
1561 return XML_STATUS_ERROR
;
1565 errorCode
= XML_ERROR_NO_MEMORY
;
1566 eventPtr
= eventEndPtr
= NULL
;
1567 processor
= errorProcessor
;
1568 return XML_STATUS_ERROR
;
1570 bufferLim
= buffer
+ len
* 2;
1572 memcpy(buffer
, end
, nLeftOver
);
1575 bufferEnd
= buffer
+ nLeftOver
;
1576 positionPtr
= bufferPtr
;
1577 parseEndPtr
= bufferEnd
;
1578 eventPtr
= bufferPtr
;
1579 eventEndPtr
= bufferPtr
;
1582 #endif /* not defined XML_CONTEXT_BYTES */
1584 void *buff
= XML_GetBuffer(parser
, len
);
1586 return XML_STATUS_ERROR
;
1588 memcpy(buff
, s
, len
);
1589 return XML_ParseBuffer(parser
, len
, isFinal
);
1594 enum XML_Status XMLCALL
1595 XML_ParseBuffer(XML_Parser parser
, int len
, int isFinal
)
1598 enum XML_Status result
= XML_STATUS_OK
;
1600 switch (ps_parsing
) {
1602 errorCode
= XML_ERROR_SUSPENDED
;
1603 return XML_STATUS_ERROR
;
1605 errorCode
= XML_ERROR_FINISHED
;
1606 return XML_STATUS_ERROR
;
1608 ps_parsing
= XML_PARSING
;
1612 positionPtr
= start
;
1614 parseEndPtr
= bufferEnd
;
1615 parseEndByteIndex
+= len
;
1616 ps_finalBuffer
= (XML_Bool
)isFinal
;
1618 errorCode
= processor(parser
, start
, parseEndPtr
, &bufferPtr
);
1620 if (errorCode
!= XML_ERROR_NONE
) {
1621 eventEndPtr
= eventPtr
;
1622 processor
= errorProcessor
;
1623 return XML_STATUS_ERROR
;
1626 switch (ps_parsing
) {
1628 result
= XML_STATUS_SUSPENDED
;
1630 case XML_INITIALIZED
:
1633 ps_parsing
= XML_FINISHED
;
1636 default: ; /* should not happen */
1640 XmlUpdatePosition(encoding
, positionPtr
, bufferPtr
, &position
);
1641 positionPtr
= bufferPtr
;
1646 XML_GetBuffer(XML_Parser parser
, int len
)
1648 switch (ps_parsing
) {
1650 errorCode
= XML_ERROR_SUSPENDED
;
1653 errorCode
= XML_ERROR_FINISHED
;
1658 if (len
> bufferLim
- bufferEnd
) {
1659 /* FIXME avoid integer overflow */
1660 int neededSize
= len
+ (int)(bufferEnd
- bufferPtr
);
1661 #ifdef XML_CONTEXT_BYTES
1662 int keep
= (int)(bufferPtr
- buffer
);
1664 if (keep
> XML_CONTEXT_BYTES
)
1665 keep
= XML_CONTEXT_BYTES
;
1667 #endif /* defined XML_CONTEXT_BYTES */
1668 if (neededSize
<= bufferLim
- buffer
) {
1669 #ifdef XML_CONTEXT_BYTES
1670 if (keep
< bufferPtr
- buffer
) {
1671 int offset
= (int)(bufferPtr
- buffer
) - keep
;
1672 memmove(buffer
, &buffer
[offset
], bufferEnd
- bufferPtr
+ keep
);
1673 bufferEnd
-= offset
;
1674 bufferPtr
-= offset
;
1677 memmove(buffer
, bufferPtr
, bufferEnd
- bufferPtr
);
1678 bufferEnd
= buffer
+ (bufferEnd
- bufferPtr
);
1680 #endif /* not defined XML_CONTEXT_BYTES */
1684 int bufferSize
= (int)(bufferLim
- bufferPtr
);
1685 if (bufferSize
== 0)
1686 bufferSize
= INIT_BUFFER_SIZE
;
1689 } while (bufferSize
< neededSize
);
1690 newBuf
= (char *)MALLOC(bufferSize
);
1692 errorCode
= XML_ERROR_NO_MEMORY
;
1695 bufferLim
= newBuf
+ bufferSize
;
1696 #ifdef XML_CONTEXT_BYTES
1698 int keep
= (int)(bufferPtr
- buffer
);
1699 if (keep
> XML_CONTEXT_BYTES
)
1700 keep
= XML_CONTEXT_BYTES
;
1701 memcpy(newBuf
, &bufferPtr
[-keep
], bufferEnd
- bufferPtr
+ keep
);
1704 bufferEnd
= buffer
+ (bufferEnd
- bufferPtr
) + keep
;
1705 bufferPtr
= buffer
+ keep
;
1708 bufferEnd
= newBuf
+ (bufferEnd
- bufferPtr
);
1709 bufferPtr
= buffer
= newBuf
;
1713 memcpy(newBuf
, bufferPtr
, bufferEnd
- bufferPtr
);
1716 bufferEnd
= newBuf
+ (bufferEnd
- bufferPtr
);
1717 bufferPtr
= buffer
= newBuf
;
1718 #endif /* not defined XML_CONTEXT_BYTES */
1724 enum XML_Status XMLCALL
1725 XML_StopParser(XML_Parser parser
, XML_Bool resumable
)
1727 switch (ps_parsing
) {
1730 errorCode
= XML_ERROR_SUSPENDED
;
1731 return XML_STATUS_ERROR
;
1733 ps_parsing
= XML_FINISHED
;
1736 errorCode
= XML_ERROR_FINISHED
;
1737 return XML_STATUS_ERROR
;
1741 if (isParamEntity
) {
1742 errorCode
= XML_ERROR_SUSPEND_PE
;
1743 return XML_STATUS_ERROR
;
1746 ps_parsing
= XML_SUSPENDED
;
1749 ps_parsing
= XML_FINISHED
;
1751 return XML_STATUS_OK
;
1754 enum XML_Status XMLCALL
1755 XML_ResumeParser(XML_Parser parser
)
1757 enum XML_Status result
= XML_STATUS_OK
;
1759 if (ps_parsing
!= XML_SUSPENDED
) {
1760 errorCode
= XML_ERROR_NOT_SUSPENDED
;
1761 return XML_STATUS_ERROR
;
1763 ps_parsing
= XML_PARSING
;
1765 errorCode
= processor(parser
, bufferPtr
, parseEndPtr
, &bufferPtr
);
1767 if (errorCode
!= XML_ERROR_NONE
) {
1768 eventEndPtr
= eventPtr
;
1769 processor
= errorProcessor
;
1770 return XML_STATUS_ERROR
;
1773 switch (ps_parsing
) {
1775 result
= XML_STATUS_SUSPENDED
;
1777 case XML_INITIALIZED
:
1779 if (ps_finalBuffer
) {
1780 ps_parsing
= XML_FINISHED
;
1787 XmlUpdatePosition(encoding
, positionPtr
, bufferPtr
, &position
);
1788 positionPtr
= bufferPtr
;
1789 /* BEGIN MOZILLA CHANGE (always set eventPtr/eventEndPtr) */
1790 eventPtr
= bufferPtr
;
1791 eventEndPtr
= bufferPtr
;
1792 /* END MOZILLA CHANGE */
1797 XML_GetParsingStatus(XML_Parser parser
, XML_ParsingStatus
*status
)
1799 assert(status
!= NULL
);
1800 *status
= parser
->m_parsingStatus
;
1803 enum XML_Error XMLCALL
1804 XML_GetErrorCode(XML_Parser parser
)
1810 XML_GetCurrentByteIndex(XML_Parser parser
)
1813 return parseEndByteIndex
- (parseEndPtr
- eventPtr
);
1814 /* BEGIN MOZILLA CHANGE (fix XML_GetCurrentByteIndex) */
1818 return parseEndByteIndex
;
1820 /* END MOZILLA CHANGE */
1823 /* BEGIN MOZILLA CHANGE (unused API) */
1826 XML_GetCurrentByteCount(XML_Parser parser
)
1828 if (eventEndPtr
&& eventPtr
)
1829 return (int)(eventEndPtr
- eventPtr
);
1833 const char * XMLCALL
1834 XML_GetInputContext(XML_Parser parser
, int *offset
, int *size
)
1836 #ifdef XML_CONTEXT_BYTES
1837 if (eventPtr
&& buffer
) {
1838 *offset
= (int)(eventPtr
- buffer
);
1839 *size
= (int)(bufferEnd
- buffer
);
1842 #endif /* defined XML_CONTEXT_BYTES */
1846 /* END MOZILLA CHANGE */
1849 XML_GetCurrentLineNumber(XML_Parser parser
)
1851 if (eventPtr
&& eventPtr
>= positionPtr
) {
1852 XmlUpdatePosition(encoding
, positionPtr
, eventPtr
, &position
);
1853 positionPtr
= eventPtr
;
1855 return position
.lineNumber
+ 1;
1859 XML_GetCurrentColumnNumber(XML_Parser parser
)
1861 if (eventPtr
&& eventPtr
>= positionPtr
) {
1862 XmlUpdatePosition(encoding
, positionPtr
, eventPtr
, &position
);
1863 positionPtr
= eventPtr
;
1865 return position
.columnNumber
;
1868 /* BEGIN MOZILLA CHANGE (unused API) */
1871 XML_FreeContentModel(XML_Parser parser
, XML_Content
*model
)
1877 XML_MemMalloc(XML_Parser parser
, size_t size
)
1879 return MALLOC(size
);
1883 XML_MemRealloc(XML_Parser parser
, void *ptr
, size_t size
)
1885 return REALLOC(ptr
, size
);
1889 XML_MemFree(XML_Parser parser
, void *ptr
)
1895 XML_DefaultCurrent(XML_Parser parser
)
1897 if (defaultHandler
) {
1898 if (openInternalEntities
)
1899 reportDefault(parser
,
1901 openInternalEntities
->internalEventPtr
,
1902 openInternalEntities
->internalEventEndPtr
);
1904 reportDefault(parser
, encoding
, eventPtr
, eventEndPtr
);
1910 const XML_LChar
* XMLCALL
1911 XML_ErrorString(enum XML_Error code
)
1913 static const XML_LChar
* const message
[] = {
1915 XML_L("out of memory"),
1916 XML_L("syntax error"),
1917 XML_L("no element found"),
1918 XML_L("not well-formed (invalid token)"),
1919 XML_L("unclosed token"),
1920 XML_L("partial character"),
1921 XML_L("mismatched tag"),
1922 XML_L("duplicate attribute"),
1923 XML_L("junk after document element"),
1924 XML_L("illegal parameter entity reference"),
1925 XML_L("undefined entity"),
1926 XML_L("recursive entity reference"),
1927 XML_L("asynchronous entity"),
1928 XML_L("reference to invalid character number"),
1929 XML_L("reference to binary entity"),
1930 XML_L("reference to external entity in attribute"),
1931 XML_L("XML or text declaration not at start of entity"),
1932 XML_L("unknown encoding"),
1933 XML_L("encoding specified in XML declaration is incorrect"),
1934 XML_L("unclosed CDATA section"),
1935 XML_L("error in processing external entity reference"),
1936 XML_L("document is not standalone"),
1937 XML_L("unexpected parser state - please send a bug report"),
1938 XML_L("entity declared in parameter entity"),
1939 XML_L("requested feature requires XML_DTD support in Expat"),
1940 XML_L("cannot change setting once parsing has begun"),
1941 XML_L("unbound prefix"),
1942 XML_L("must not undeclare prefix"),
1943 XML_L("incomplete markup in parameter entity"),
1944 XML_L("XML declaration not well-formed"),
1945 XML_L("text declaration not well-formed"),
1946 XML_L("illegal character(s) in public id"),
1947 XML_L("parser suspended"),
1948 XML_L("parser not suspended"),
1949 XML_L("parsing aborted"),
1950 XML_L("parsing finished"),
1951 XML_L("cannot suspend in external parameter entity"),
1952 XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
1953 XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
1954 XML_L("prefix must not be bound to one of the reserved namespace names")
1956 if (code
> 0 && code
< sizeof(message
)/sizeof(message
[0]))
1957 return message
[code
];
1963 const XML_LChar
* XMLCALL
1964 XML_ExpatVersion(void) {
1966 /* V1 is used to string-ize the version number. However, it would
1967 string-ize the actual version macro *names* unless we get them
1968 substituted before being passed to V1. CPP is defined to expand
1969 a macro, then rescan for more expansions. Thus, we use V2 to expand
1970 the version macros, then CPP will expand the resulting V1() macro
1971 with the correct numerals. */
1972 /* ### I'm assuming cpp is portable in this respect... */
1974 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
1975 #define V2(a,b,c) XML_L("expat_")V1(a,b,c)
1977 return V2(XML_MAJOR_VERSION
, XML_MINOR_VERSION
, XML_MICRO_VERSION
);
1983 XML_Expat_Version XMLCALL
1984 XML_ExpatVersionInfo(void)
1986 XML_Expat_Version version
;
1988 version
.major
= XML_MAJOR_VERSION
;
1989 version
.minor
= XML_MINOR_VERSION
;
1990 version
.micro
= XML_MICRO_VERSION
;
1995 const XML_Feature
* XMLCALL
1996 XML_GetFeatureList(void)
1998 static const XML_Feature features
[] = {
1999 {XML_FEATURE_SIZEOF_XML_CHAR
, XML_L("sizeof(XML_Char)"),
2001 {XML_FEATURE_SIZEOF_XML_LCHAR
, XML_L("sizeof(XML_LChar)"),
2004 {XML_FEATURE_UNICODE
, XML_L("XML_UNICODE"), 0},
2006 #ifdef XML_UNICODE_WCHAR_T
2007 {XML_FEATURE_UNICODE_WCHAR_T
, XML_L("XML_UNICODE_WCHAR_T"), 0},
2010 {XML_FEATURE_DTD
, XML_L("XML_DTD"), 0},
2012 #ifdef XML_CONTEXT_BYTES
2013 {XML_FEATURE_CONTEXT_BYTES
, XML_L("XML_CONTEXT_BYTES"),
2017 {XML_FEATURE_MIN_SIZE
, XML_L("XML_MIN_SIZE"), 0},
2020 {XML_FEATURE_NS
, XML_L("XML_NS"), 0},
2022 {XML_FEATURE_END
, NULL
, 0}
2028 /* END MOZILLA CHANGE */
2030 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
2031 const XML_Char
* XMLCALL
2032 MOZ_XML_GetMismatchedTag(XML_Parser parser
)
2036 /* END MOZILLA CHANGE */
2038 /* Initially tag->rawName always points into the parse buffer;
2039 for those TAG instances opened while the current parse buffer was
2040 processed, and not yet closed, we need to store tag->rawName in a more
2041 permanent location, since the parse buffer is about to be discarded.
2044 storeRawNames(XML_Parser parser
)
2046 TAG
*tag
= tagStack
;
2049 int nameLen
= sizeof(XML_Char
) * (tag
->name
.strLen
+ 1);
2050 char *rawNameBuf
= tag
->buf
+ nameLen
;
2051 /* Stop if already stored. Since tagStack is a stack, we can stop
2052 at the first entry that has already been copied; everything
2053 below it in the stack is already been accounted for in a
2054 previous call to this function.
2056 if (tag
->rawName
== rawNameBuf
)
2058 /* For re-use purposes we need to ensure that the
2059 size of tag->buf is a multiple of sizeof(XML_Char).
2061 bufSize
= nameLen
+ ROUND_UP(tag
->rawNameLength
, sizeof(XML_Char
));
2062 if (bufSize
> tag
->bufEnd
- tag
->buf
) {
2063 char *temp
= (char *)REALLOC(tag
->buf
, bufSize
);
2066 /* if tag->name.str points to tag->buf (only when namespace
2067 processing is off) then we have to update it
2069 if (tag
->name
.str
== (XML_Char
*)tag
->buf
)
2070 tag
->name
.str
= (XML_Char
*)temp
;
2071 /* if tag->name.localPart is set (when namespace processing is on)
2072 then update it as well, since it will always point into tag->buf
2074 if (tag
->name
.localPart
)
2075 tag
->name
.localPart
= (XML_Char
*)temp
+ (tag
->name
.localPart
-
2076 (XML_Char
*)tag
->buf
);
2078 tag
->bufEnd
= temp
+ bufSize
;
2079 rawNameBuf
= temp
+ nameLen
;
2081 memcpy(rawNameBuf
, tag
->rawName
, tag
->rawNameLength
);
2082 tag
->rawName
= rawNameBuf
;
2088 static enum XML_Error PTRCALL
2089 contentProcessor(XML_Parser parser
,
2092 const char **endPtr
)
2094 enum XML_Error result
= doContent(parser
, 0, encoding
, start
, end
,
2095 endPtr
, (XML_Bool
)!ps_finalBuffer
);
2096 if (result
== XML_ERROR_NONE
) {
2097 if (!storeRawNames(parser
))
2098 return XML_ERROR_NO_MEMORY
;
2103 static enum XML_Error PTRCALL
2104 externalEntityInitProcessor(XML_Parser parser
,
2107 const char **endPtr
)
2109 enum XML_Error result
= initializeEncoding(parser
);
2110 if (result
!= XML_ERROR_NONE
)
2112 processor
= externalEntityInitProcessor2
;
2113 return externalEntityInitProcessor2(parser
, start
, end
, endPtr
);
2116 static enum XML_Error PTRCALL
2117 externalEntityInitProcessor2(XML_Parser parser
,
2120 const char **endPtr
)
2122 const char *next
= start
; /* XmlContentTok doesn't always set the last arg */
2123 int tok
= XmlContentTok(encoding
, start
, end
, &next
);
2126 /* If we are at the end of the buffer, this would cause the next stage,
2127 i.e. externalEntityInitProcessor3, to pass control directly to
2128 doContent (by detecting XML_TOK_NONE) without processing any xml text
2129 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2131 if (next
== end
&& !ps_finalBuffer
) {
2133 return XML_ERROR_NONE
;
2137 case XML_TOK_PARTIAL
:
2138 if (!ps_finalBuffer
) {
2140 return XML_ERROR_NONE
;
2143 return XML_ERROR_UNCLOSED_TOKEN
;
2144 case XML_TOK_PARTIAL_CHAR
:
2145 if (!ps_finalBuffer
) {
2147 return XML_ERROR_NONE
;
2150 return XML_ERROR_PARTIAL_CHAR
;
2152 processor
= externalEntityInitProcessor3
;
2153 return externalEntityInitProcessor3(parser
, start
, end
, endPtr
);
2156 static enum XML_Error PTRCALL
2157 externalEntityInitProcessor3(XML_Parser parser
,
2160 const char **endPtr
)
2163 const char *next
= start
; /* XmlContentTok doesn't always set the last arg */
2165 tok
= XmlContentTok(encoding
, start
, end
, &next
);
2169 case XML_TOK_XML_DECL
:
2171 enum XML_Error result
;
2172 result
= processXmlDecl(parser
, 1, start
, next
);
2173 if (result
!= XML_ERROR_NONE
)
2175 switch (ps_parsing
) {
2178 return XML_ERROR_NONE
;
2180 return XML_ERROR_ABORTED
;
2186 case XML_TOK_PARTIAL
:
2187 if (!ps_finalBuffer
) {
2189 return XML_ERROR_NONE
;
2191 return XML_ERROR_UNCLOSED_TOKEN
;
2192 case XML_TOK_PARTIAL_CHAR
:
2193 if (!ps_finalBuffer
) {
2195 return XML_ERROR_NONE
;
2197 return XML_ERROR_PARTIAL_CHAR
;
2199 processor
= externalEntityContentProcessor
;
2201 return externalEntityContentProcessor(parser
, start
, end
, endPtr
);
2204 static enum XML_Error PTRCALL
2205 externalEntityContentProcessor(XML_Parser parser
,
2208 const char **endPtr
)
2210 enum XML_Error result
= doContent(parser
, 1, encoding
, start
, end
,
2211 endPtr
, (XML_Bool
)!ps_finalBuffer
);
2212 if (result
== XML_ERROR_NONE
) {
2213 if (!storeRawNames(parser
))
2214 return XML_ERROR_NO_MEMORY
;
2219 static enum XML_Error
2220 doContent(XML_Parser parser
,
2222 const ENCODING
*enc
,
2225 const char **nextPtr
,
2228 /* save one level of indirection */
2229 DTD
* const dtd
= _dtd
;
2231 const char **eventPP
;
2232 const char **eventEndPP
;
2233 if (enc
== encoding
) {
2234 eventPP
= &eventPtr
;
2235 eventEndPP
= &eventEndPtr
;
2238 eventPP
= &(openInternalEntities
->internalEventPtr
);
2239 eventEndPP
= &(openInternalEntities
->internalEventEndPtr
);
2244 const char *next
= s
; /* XmlContentTok doesn't always set the last arg */
2245 int tok
= XmlContentTok(enc
, s
, end
, &next
);
2248 case XML_TOK_TRAILING_CR
:
2251 return XML_ERROR_NONE
;
2254 if (characterDataHandler
) {
2256 characterDataHandler(handlerArg
, &c
, 1);
2258 else if (defaultHandler
)
2259 reportDefault(parser
, enc
, s
, end
);
2260 /* We are at the end of the final buffer, should we check for
2261 XML_SUSPENDED, XML_FINISHED?
2263 if (startTagLevel
== 0)
2264 return XML_ERROR_NO_ELEMENTS
;
2265 if (tagLevel
!= startTagLevel
)
2266 return XML_ERROR_ASYNC_ENTITY
;
2268 return XML_ERROR_NONE
;
2272 return XML_ERROR_NONE
;
2274 if (startTagLevel
> 0) {
2275 if (tagLevel
!= startTagLevel
)
2276 return XML_ERROR_ASYNC_ENTITY
;
2278 return XML_ERROR_NONE
;
2280 return XML_ERROR_NO_ELEMENTS
;
2281 case XML_TOK_INVALID
:
2283 return XML_ERROR_INVALID_TOKEN
;
2284 case XML_TOK_PARTIAL
:
2287 return XML_ERROR_NONE
;
2289 return XML_ERROR_UNCLOSED_TOKEN
;
2290 case XML_TOK_PARTIAL_CHAR
:
2293 return XML_ERROR_NONE
;
2295 return XML_ERROR_PARTIAL_CHAR
;
2296 case XML_TOK_ENTITY_REF
:
2298 const XML_Char
*name
;
2300 XML_Char ch
= (XML_Char
) XmlPredefinedEntityName(enc
,
2301 s
+ enc
->minBytesPerChar
,
2302 next
- enc
->minBytesPerChar
);
2304 if (characterDataHandler
)
2305 characterDataHandler(handlerArg
, &ch
, 1);
2306 else if (defaultHandler
)
2307 reportDefault(parser
, enc
, s
, next
);
2310 name
= poolStoreString(&dtd
->pool
, enc
,
2311 s
+ enc
->minBytesPerChar
,
2312 next
- enc
->minBytesPerChar
);
2314 return XML_ERROR_NO_MEMORY
;
2315 entity
= (ENTITY
*)lookup(&dtd
->generalEntities
, name
, 0);
2316 poolDiscard(&dtd
->pool
);
2317 /* First, determine if a check for an existing declaration is needed;
2318 if yes, check that the entity exists, and that it is internal,
2319 otherwise call the skipped entity or default handler.
2321 if (!dtd
->hasParamEntityRefs
|| dtd
->standalone
) {
2323 return XML_ERROR_UNDEFINED_ENTITY
;
2324 else if (!entity
->is_internal
)
2325 return XML_ERROR_ENTITY_DECLARED_IN_PE
;
2328 if (skippedEntityHandler
)
2329 skippedEntityHandler(handlerArg
, name
, 0);
2330 /* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=35984) */
2332 else if (defaultHandler
)
2333 reportDefault(parser
, enc
, s
, next
);
2336 return XML_ERROR_UNDEFINED_ENTITY
;
2338 /* END MOZILLA CHANGE */
2341 return XML_ERROR_RECURSIVE_ENTITY_REF
;
2342 if (entity
->notation
)
2343 return XML_ERROR_BINARY_ENTITY_REF
;
2344 if (entity
->textPtr
) {
2345 enum XML_Error result
;
2346 if (!defaultExpandInternalEntities
) {
2347 if (skippedEntityHandler
)
2348 skippedEntityHandler(handlerArg
, entity
->name
, 0);
2349 else if (defaultHandler
)
2350 reportDefault(parser
, enc
, s
, next
);
2353 result
= processInternalEntity(parser
, entity
, XML_FALSE
);
2354 if (result
!= XML_ERROR_NONE
)
2357 else if (externalEntityRefHandler
) {
2358 const XML_Char
*context
;
2359 entity
->open
= XML_TRUE
;
2360 context
= getContext(parser
);
2361 entity
->open
= XML_FALSE
;
2363 return XML_ERROR_NO_MEMORY
;
2364 if (!externalEntityRefHandler(externalEntityRefHandlerArg
,
2369 return XML_ERROR_EXTERNAL_ENTITY_HANDLING
;
2370 poolDiscard(&tempPool
);
2372 else if (defaultHandler
)
2373 reportDefault(parser
, enc
, s
, next
);
2376 case XML_TOK_START_TAG_NO_ATTS
:
2378 case XML_TOK_START_TAG_WITH_ATTS
:
2381 enum XML_Error result
;
2385 freeTagList
= freeTagList
->parent
;
2388 tag
= (TAG
*)MALLOC(sizeof(TAG
));
2390 return XML_ERROR_NO_MEMORY
;
2391 tag
->buf
= (char *)MALLOC(INIT_TAG_BUF_SIZE
);
2394 return XML_ERROR_NO_MEMORY
;
2396 tag
->bufEnd
= tag
->buf
+ INIT_TAG_BUF_SIZE
;
2398 tag
->bindings
= NULL
;
2399 tag
->parent
= tagStack
;
2401 tag
->name
.localPart
= NULL
;
2402 tag
->name
.prefix
= NULL
;
2403 tag
->rawName
= s
+ enc
->minBytesPerChar
;
2404 tag
->rawNameLength
= XmlNameLength(enc
, tag
->rawName
);
2407 const char *rawNameEnd
= tag
->rawName
+ tag
->rawNameLength
;
2408 const char *fromPtr
= tag
->rawName
;
2409 toPtr
= (XML_Char
*)tag
->buf
;
2414 &fromPtr
, rawNameEnd
,
2415 (ICHAR
**)&toPtr
, (ICHAR
*)tag
->bufEnd
- 1);
2416 convLen
= (int)(toPtr
- (XML_Char
*)tag
->buf
);
2417 if (fromPtr
== rawNameEnd
) {
2418 tag
->name
.strLen
= convLen
;
2421 bufSize
= (int)(tag
->bufEnd
- tag
->buf
) << 1;
2423 char *temp
= (char *)REALLOC(tag
->buf
, bufSize
);
2425 return XML_ERROR_NO_MEMORY
;
2427 tag
->bufEnd
= temp
+ bufSize
;
2428 toPtr
= (XML_Char
*)temp
+ convLen
;
2432 tag
->name
.str
= (XML_Char
*)tag
->buf
;
2433 *toPtr
= XML_T('\0');
2434 result
= storeAtts(parser
, enc
, s
, &(tag
->name
), &(tag
->bindings
));
2437 if (startElementHandler
)
2438 startElementHandler(handlerArg
, tag
->name
.str
,
2439 (const XML_Char
**)atts
);
2440 else if (defaultHandler
)
2441 reportDefault(parser
, enc
, s
, next
);
2442 poolClear(&tempPool
);
2445 case XML_TOK_EMPTY_ELEMENT_NO_ATTS
:
2447 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS
:
2449 const char *rawName
= s
+ enc
->minBytesPerChar
;
2450 enum XML_Error result
;
2451 BINDING
*bindings
= NULL
;
2452 XML_Bool noElmHandlers
= XML_TRUE
;
2454 name
.str
= poolStoreString(&tempPool
, enc
, rawName
,
2455 rawName
+ XmlNameLength(enc
, rawName
));
2457 return XML_ERROR_NO_MEMORY
;
2458 poolFinish(&tempPool
);
2459 result
= storeAtts(parser
, enc
, s
, &name
, &bindings
);
2462 poolFinish(&tempPool
);
2463 if (startElementHandler
) {
2464 startElementHandler(handlerArg
, name
.str
, (const XML_Char
**)atts
);
2465 noElmHandlers
= XML_FALSE
;
2467 if (endElementHandler
) {
2468 if (startElementHandler
)
2469 *eventPP
= *eventEndPP
;
2470 endElementHandler(handlerArg
, name
.str
);
2471 noElmHandlers
= XML_FALSE
;
2473 if (noElmHandlers
&& defaultHandler
)
2474 reportDefault(parser
, enc
, s
, next
);
2475 poolClear(&tempPool
);
2477 BINDING
*b
= bindings
;
2478 if (endNamespaceDeclHandler
)
2479 endNamespaceDeclHandler(handlerArg
, b
->prefix
->name
);
2480 bindings
= bindings
->nextTagBinding
;
2481 b
->nextTagBinding
= freeBindingList
;
2482 freeBindingList
= b
;
2483 b
->prefix
->binding
= b
->prevPrefixBinding
;
2487 return epilogProcessor(parser
, next
, end
, nextPtr
);
2489 case XML_TOK_END_TAG
:
2490 if (tagLevel
== startTagLevel
)
2491 return XML_ERROR_ASYNC_ENTITY
;
2494 const char *rawName
;
2495 TAG
*tag
= tagStack
;
2496 tagStack
= tag
->parent
;
2497 tag
->parent
= freeTagList
;
2499 rawName
= s
+ enc
->minBytesPerChar
*2;
2500 len
= XmlNameLength(enc
, rawName
);
2501 if (len
!= tag
->rawNameLength
2502 || memcmp(tag
->rawName
, rawName
, len
) != 0) {
2503 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
2504 /* This code is copied from the |if (endElementHandler)| block below */
2505 const XML_Char
*localPart
;
2506 const XML_Char
*prefix
;
2508 localPart
= tag
->name
.localPart
;
2509 if (ns
&& localPart
) {
2510 /* localPart and prefix may have been overwritten in
2511 tag->name.str, since this points to the binding->uri
2512 buffer which gets re-used; so we have to add them again
2514 uri
= (XML_Char
*)tag
->name
.str
+ tag
->name
.uriLen
;
2515 /* don't need to check for space - already done in storeAtts() */
2516 while (*localPart
) *uri
++ = *localPart
++;
2517 prefix
= (XML_Char
*)tag
->name
.prefix
;
2518 if (ns_triplets
&& prefix
) {
2519 *uri
++ = namespaceSeparator
;
2520 while (*prefix
) *uri
++ = *prefix
++;
2524 mismatch
= tag
->name
.str
;
2525 /* END MOZILLA CHANGE */
2527 return XML_ERROR_TAG_MISMATCH
;
2530 if (endElementHandler
) {
2531 const XML_Char
*localPart
;
2532 const XML_Char
*prefix
;
2534 localPart
= tag
->name
.localPart
;
2535 if (ns
&& localPart
) {
2536 /* localPart and prefix may have been overwritten in
2537 tag->name.str, since this points to the binding->uri
2538 buffer which gets re-used; so we have to add them again
2540 uri
= (XML_Char
*)tag
->name
.str
+ tag
->name
.uriLen
;
2541 /* don't need to check for space - already done in storeAtts() */
2542 while (*localPart
) *uri
++ = *localPart
++;
2543 prefix
= (XML_Char
*)tag
->name
.prefix
;
2544 if (ns_triplets
&& prefix
) {
2545 *uri
++ = namespaceSeparator
;
2546 while (*prefix
) *uri
++ = *prefix
++;
2550 endElementHandler(handlerArg
, tag
->name
.str
);
2552 else if (defaultHandler
)
2553 reportDefault(parser
, enc
, s
, next
);
2554 while (tag
->bindings
) {
2555 BINDING
*b
= tag
->bindings
;
2556 if (endNamespaceDeclHandler
)
2557 endNamespaceDeclHandler(handlerArg
, b
->prefix
->name
);
2558 tag
->bindings
= tag
->bindings
->nextTagBinding
;
2559 b
->nextTagBinding
= freeBindingList
;
2560 freeBindingList
= b
;
2561 b
->prefix
->binding
= b
->prevPrefixBinding
;
2564 return epilogProcessor(parser
, next
, end
, nextPtr
);
2567 case XML_TOK_CHAR_REF
:
2569 int n
= XmlCharRefNumber(enc
, s
);
2571 return XML_ERROR_BAD_CHAR_REF
;
2572 if (characterDataHandler
) {
2573 XML_Char buf
[XML_ENCODE_MAX
];
2574 characterDataHandler(handlerArg
, buf
, XmlEncode(n
, (ICHAR
*)buf
));
2576 else if (defaultHandler
)
2577 reportDefault(parser
, enc
, s
, next
);
2580 case XML_TOK_XML_DECL
:
2581 return XML_ERROR_MISPLACED_XML_PI
;
2582 case XML_TOK_DATA_NEWLINE
:
2583 if (characterDataHandler
) {
2585 characterDataHandler(handlerArg
, &c
, 1);
2587 else if (defaultHandler
)
2588 reportDefault(parser
, enc
, s
, next
);
2590 case XML_TOK_CDATA_SECT_OPEN
:
2592 enum XML_Error result
;
2593 if (startCdataSectionHandler
)
2594 startCdataSectionHandler(handlerArg
);
2596 /* Suppose you doing a transformation on a document that involves
2597 changing only the character data. You set up a defaultHandler
2598 and a characterDataHandler. The defaultHandler simply copies
2599 characters through. The characterDataHandler does the
2600 transformation and writes the characters out escaping them as
2601 necessary. This case will fail to work if we leave out the
2602 following two lines (because & and < inside CDATA sections will
2603 be incorrectly escaped).
2605 However, now we have a start/endCdataSectionHandler, so it seems
2606 easier to let the user deal with this.
2608 else if (characterDataHandler
)
2609 characterDataHandler(handlerArg
, dataBuf
, 0);
2611 else if (defaultHandler
)
2612 reportDefault(parser
, enc
, s
, next
);
2613 result
= doCdataSection(parser
, enc
, &next
, end
, nextPtr
, haveMore
);
2614 if (result
!= XML_ERROR_NONE
)
2617 processor
= cdataSectionProcessor
;
2622 case XML_TOK_TRAILING_RSQB
:
2625 return XML_ERROR_NONE
;
2627 if (characterDataHandler
) {
2628 if (MUST_CONVERT(enc
, s
)) {
2629 ICHAR
*dataPtr
= (ICHAR
*)dataBuf
;
2630 XmlConvert(enc
, &s
, end
, &dataPtr
, (ICHAR
*)dataBufEnd
);
2631 characterDataHandler(handlerArg
, dataBuf
,
2632 (int)(dataPtr
- (ICHAR
*)dataBuf
));
2635 characterDataHandler(handlerArg
,
2637 (int)((XML_Char
*)end
- (XML_Char
*)s
));
2639 else if (defaultHandler
)
2640 reportDefault(parser
, enc
, s
, end
);
2641 /* We are at the end of the final buffer, should we check for
2642 XML_SUSPENDED, XML_FINISHED?
2644 if (startTagLevel
== 0) {
2646 return XML_ERROR_NO_ELEMENTS
;
2648 if (tagLevel
!= startTagLevel
) {
2650 return XML_ERROR_ASYNC_ENTITY
;
2653 return XML_ERROR_NONE
;
2654 case XML_TOK_DATA_CHARS
:
2655 if (characterDataHandler
) {
2656 if (MUST_CONVERT(enc
, s
)) {
2658 ICHAR
*dataPtr
= (ICHAR
*)dataBuf
;
2659 XmlConvert(enc
, &s
, next
, &dataPtr
, (ICHAR
*)dataBufEnd
);
2661 characterDataHandler(handlerArg
, dataBuf
,
2662 (int)(dataPtr
- (ICHAR
*)dataBuf
));
2669 characterDataHandler(handlerArg
,
2671 (int)((XML_Char
*)next
- (XML_Char
*)s
));
2673 else if (defaultHandler
)
2674 reportDefault(parser
, enc
, s
, next
);
2677 if (!reportProcessingInstruction(parser
, enc
, s
, next
))
2678 return XML_ERROR_NO_MEMORY
;
2680 case XML_TOK_COMMENT
:
2681 if (!reportComment(parser
, enc
, s
, next
))
2682 return XML_ERROR_NO_MEMORY
;
2686 reportDefault(parser
, enc
, s
, next
);
2689 *eventPP
= s
= next
;
2690 switch (ps_parsing
) {
2693 return XML_ERROR_NONE
;
2695 return XML_ERROR_ABORTED
;
2702 /* Precondition: all arguments must be non-NULL;
2704 - normalize attributes
2705 - check attributes for well-formedness
2706 - generate namespace aware attribute names (URI, prefix)
2707 - build list of attributes for startElementHandler
2708 - default attributes
2709 - process namespace declarations (check and report them)
2710 - generate namespace aware element name (URI, prefix)
2712 static enum XML_Error
2713 storeAtts(XML_Parser parser
, const ENCODING
*enc
,
2714 const char *attStr
, TAG_NAME
*tagNamePtr
,
2715 BINDING
**bindingsPtr
)
2717 DTD
* const dtd
= _dtd
; /* save one level of indirection */
2718 ELEMENT_TYPE
*elementType
;
2720 const XML_Char
**appAtts
; /* the attribute list for the application */
2727 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
2728 int nXMLNSDeclarations
= 0;
2729 /* END MOZILLA CHANGE */
2731 const XML_Char
*localPart
;
2733 /* lookup the element type name */
2734 elementType
= (ELEMENT_TYPE
*)lookup(&dtd
->elementTypes
, tagNamePtr
->str
,0);
2736 const XML_Char
*name
= poolCopyString(&dtd
->pool
, tagNamePtr
->str
);
2738 return XML_ERROR_NO_MEMORY
;
2739 elementType
= (ELEMENT_TYPE
*)lookup(&dtd
->elementTypes
, name
,
2740 sizeof(ELEMENT_TYPE
));
2742 return XML_ERROR_NO_MEMORY
;
2743 if (ns
&& !setElementTypePrefix(parser
, elementType
))
2744 return XML_ERROR_NO_MEMORY
;
2746 nDefaultAtts
= elementType
->nDefaultAtts
;
2748 /* get the attributes from the tokenizer */
2749 n
= XmlGetAttributes(enc
, attStr
, attsSize
, atts
);
2750 if (n
+ nDefaultAtts
> attsSize
) {
2751 int oldAttsSize
= attsSize
;
2753 attsSize
= n
+ nDefaultAtts
+ INIT_ATTS_SIZE
;
2754 temp
= (ATTRIBUTE
*)REALLOC((void *)atts
, attsSize
* sizeof(ATTRIBUTE
));
2756 return XML_ERROR_NO_MEMORY
;
2758 if (n
> oldAttsSize
)
2759 XmlGetAttributes(enc
, attStr
, n
, atts
);
2762 appAtts
= (const XML_Char
**)atts
;
2763 for (i
= 0; i
< n
; i
++) {
2764 /* add the name and value to the attribute list */
2765 ATTRIBUTE_ID
*attId
= getAttributeId(parser
, enc
, atts
[i
].name
,
2767 + XmlNameLength(enc
, atts
[i
].name
));
2769 return XML_ERROR_NO_MEMORY
;
2770 /* Detect duplicate attributes by their QNames. This does not work when
2771 namespace processing is turned on and different prefixes for the same
2772 namespace are used. For this case we have a check further down.
2774 if ((attId
->name
)[-1]) {
2775 if (enc
== encoding
)
2776 eventPtr
= atts
[i
].name
;
2777 return XML_ERROR_DUPLICATE_ATTRIBUTE
;
2779 (attId
->name
)[-1] = 1;
2780 appAtts
[attIndex
++] = attId
->name
;
2781 if (!atts
[i
].normalized
) {
2782 enum XML_Error result
;
2783 XML_Bool isCdata
= XML_TRUE
;
2785 /* figure out whether declared as other than CDATA */
2786 if (attId
->maybeTokenized
) {
2788 for (j
= 0; j
< nDefaultAtts
; j
++) {
2789 if (attId
== elementType
->defaultAtts
[j
].id
) {
2790 isCdata
= elementType
->defaultAtts
[j
].isCdata
;
2796 /* normalize the attribute value */
2797 result
= storeAttributeValue(parser
, enc
, isCdata
,
2798 atts
[i
].valuePtr
, atts
[i
].valueEnd
,
2802 appAtts
[attIndex
] = poolStart(&tempPool
);
2803 poolFinish(&tempPool
);
2806 /* the value did not need normalizing */
2807 appAtts
[attIndex
] = poolStoreString(&tempPool
, enc
, atts
[i
].valuePtr
,
2809 if (appAtts
[attIndex
] == 0)
2810 return XML_ERROR_NO_MEMORY
;
2811 poolFinish(&tempPool
);
2813 /* handle prefixed attribute names */
2814 if (attId
->prefix
) {
2816 /* deal with namespace declarations here */
2817 enum XML_Error result
= addBinding(parser
, attId
->prefix
, attId
,
2818 appAtts
[attIndex
], bindingsPtr
);
2821 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
2826 nXMLNSDeclarations
++;
2827 (attId
->name
)[-1] = 3;
2829 /* END MOZILLA CHANGE */
2832 /* deal with other prefixed names later */
2835 (attId
->name
)[-1] = 2;
2842 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
2843 nSpecifiedAtts
= attIndex
;
2844 if (elementType
->idAtt
&& (elementType
->idAtt
->name
)[-1]) {
2845 for (i
= 0; i
< attIndex
; i
+= 2)
2846 if (appAtts
[i
] == elementType
->idAtt
->name
) {
2854 /* do attribute defaulting */
2855 for (i
= 0; i
< nDefaultAtts
; i
++) {
2856 const DEFAULT_ATTRIBUTE
*da
= elementType
->defaultAtts
+ i
;
2857 if (!(da
->id
->name
)[-1] && da
->value
) {
2858 if (da
->id
->prefix
) {
2859 if (da
->id
->xmlns
) {
2860 enum XML_Error result
= addBinding(parser
, da
->id
->prefix
, da
->id
,
2861 da
->value
, bindingsPtr
);
2864 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
2865 (da
->id
->name
)[-1] = 3;
2866 nXMLNSDeclarations
++;
2867 appAtts
[attIndex
++] = da
->id
->name
;
2868 appAtts
[attIndex
++] = da
->value
;
2869 /* END MOZILLA CHANGE */
2872 (da
->id
->name
)[-1] = 2;
2874 appAtts
[attIndex
++] = da
->id
->name
;
2875 appAtts
[attIndex
++] = da
->value
;
2879 (da
->id
->name
)[-1] = 1;
2880 appAtts
[attIndex
++] = da
->id
->name
;
2881 appAtts
[attIndex
++] = da
->value
;
2885 appAtts
[attIndex
] = 0;
2887 /* expand prefixed attribute names, check for duplicates,
2888 and clear flags that say whether attributes were specified */
2890 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
2894 if (nPrefixes
|| nXMLNSDeclarations
) {
2896 /* END MOZILLA CHANGE */
2897 int j
; /* hash table index */
2898 unsigned long version
= nsAttsVersion
;
2899 int nsAttsSize
= (int)1 << nsAttsPower
;
2900 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
2902 /* END MOZILLA CHANGE */
2903 /* size of hash table must be at least 2 * (# of prefixed attributes) */
2904 if ((nPrefixes
<< 1) >> nsAttsPower
) { /* true for nsAttsPower = 0 */
2906 /* hash table size must also be a power of 2 and >= 8 */
2907 while (nPrefixes
>> nsAttsPower
++);
2908 if (nsAttsPower
< 3)
2910 nsAttsSize
= (int)1 << nsAttsPower
;
2911 temp
= (NS_ATT
*)REALLOC(nsAtts
, nsAttsSize
* sizeof(NS_ATT
));
2913 return XML_ERROR_NO_MEMORY
;
2915 version
= 0; /* force re-initialization of nsAtts hash table */
2917 /* using a version flag saves us from initializing nsAtts every time */
2918 if (!version
) { /* initialize version flags when version wraps around */
2919 version
= INIT_ATTS_VERSION
;
2920 for (j
= nsAttsSize
; j
!= 0; )
2921 nsAtts
[--j
].version
= version
;
2923 nsAttsVersion
= --version
;
2924 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
2926 /* END MOZILLA CHANGE */
2928 /* expand prefixed names and check for duplicates */
2929 for (; i
< attIndex
; i
+= 2) {
2930 const XML_Char
*s
= appAtts
[i
];
2931 if (s
[-1] == 2) { /* prefixed */
2934 unsigned long uriHash
= 0;
2935 ((XML_Char
*)s
)[-1] = 0; /* clear flag */
2936 id
= (ATTRIBUTE_ID
*)lookup(&dtd
->attributeIds
, s
, 0);
2937 b
= id
->prefix
->binding
;
2939 return XML_ERROR_UNBOUND_PREFIX
;
2941 /* as we expand the name we also calculate its hash value */
2942 for (j
= 0; j
< b
->uriLen
; j
++) {
2943 const XML_Char c
= b
->uri
[j
];
2944 if (!poolAppendChar(&tempPool
, c
))
2945 return XML_ERROR_NO_MEMORY
;
2946 uriHash
= CHAR_HASH(uriHash
, c
);
2948 while (*s
++ != XML_T(':'))
2950 do { /* copies null terminator */
2951 const XML_Char c
= *s
;
2952 if (!poolAppendChar(&tempPool
, *s
))
2953 return XML_ERROR_NO_MEMORY
;
2954 uriHash
= CHAR_HASH(uriHash
, c
);
2957 { /* Check hash table for duplicate of expanded name (uriName).
2958 Derived from code in lookup(HASH_TABLE *table, ...).
2960 unsigned char step
= 0;
2961 unsigned long mask
= nsAttsSize
- 1;
2962 j
= uriHash
& mask
; /* index into hash table */
2963 while (nsAtts
[j
].version
== version
) {
2964 /* for speed we compare stored hash values first */
2965 if (uriHash
== nsAtts
[j
].hash
) {
2966 const XML_Char
*s1
= poolStart(&tempPool
);
2967 const XML_Char
*s2
= nsAtts
[j
].uriName
;
2968 /* s1 is null terminated, but not s2 */
2969 for (; *s1
== *s2
&& *s1
!= 0; s1
++, s2
++);
2971 return XML_ERROR_DUPLICATE_ATTRIBUTE
;
2974 step
= PROBE_STEP(uriHash
, mask
, nsAttsPower
);
2975 j
< step
? (j
+= nsAttsSize
- step
) : (j
-= step
);
2979 if (ns_triplets
) { /* append namespace separator and prefix */
2980 tempPool
.ptr
[-1] = namespaceSeparator
;
2981 s
= b
->prefix
->name
;
2983 if (!poolAppendChar(&tempPool
, *s
))
2984 return XML_ERROR_NO_MEMORY
;
2988 /* store expanded name in attribute list */
2989 s
= poolStart(&tempPool
);
2990 poolFinish(&tempPool
);
2993 /* fill empty slot with new version, uriName and hash value */
2994 nsAtts
[j
].version
= version
;
2995 nsAtts
[j
].hash
= uriHash
;
2996 nsAtts
[j
].uriName
= s
;
2998 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
3002 if (!--nPrefixes
&& !nXMLNSDeclarations
) {
3004 /* END MOZILLA CHANGE */
3009 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
3010 else if (s
[-1] == 3) { /* xmlns attribute */
3011 static const XML_Char xmlnsNamespace
[] = {
3012 'h', 't', 't', 'p', ':', '/', '/',
3013 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
3014 '2', '0', '0', '0', '/', 'x', 'm', 'l', 'n', 's', '/', '\0'
3016 static const XML_Char xmlnsPrefix
[] = {
3017 'x', 'm', 'l', 'n', 's', '\0'
3019 XML_Bool appendXMLNS
= XML_TRUE
;
3021 ((XML_Char
*)s
)[-1] = 0; /* clear flag */
3022 if (!poolAppendString(&tempPool
, xmlnsNamespace
)
3023 || !poolAppendChar(&tempPool
, namespaceSeparator
))
3024 return XML_ERROR_NO_MEMORY
;
3025 s
+= sizeof(xmlnsPrefix
) / sizeof(xmlnsPrefix
[0]) - 1;
3026 if (*s
== XML_T(':')) {
3028 do { /* copies null terminator */
3029 if (!poolAppendChar(&tempPool
, *s
))
3030 return XML_ERROR_NO_MEMORY
;
3032 if (ns_triplets
) { /* append namespace separator and prefix */
3033 tempPool
.ptr
[-1] = namespaceSeparator
;
3034 if (!poolAppendString(&tempPool
, xmlnsPrefix
)
3035 || !poolAppendChar(&tempPool
, '\0'))
3036 return XML_ERROR_NO_MEMORY
;
3040 /* xlmns attribute without a prefix. */
3041 if (!poolAppendString(&tempPool
, xmlnsPrefix
)
3042 || !poolAppendChar(&tempPool
, '\0'))
3043 return XML_ERROR_NO_MEMORY
;
3046 /* store expanded name in attribute list */
3047 s
= poolStart(&tempPool
);
3048 poolFinish(&tempPool
);
3051 if (!--nXMLNSDeclarations
&& !nPrefixes
) {
3056 /* END MOZILLA CHANGE */
3057 else /* not prefixed */
3058 ((XML_Char
*)s
)[-1] = 0; /* clear flag */
3061 /* clear flags for the remaining attributes */
3062 for (; i
< attIndex
; i
+= 2)
3063 ((XML_Char
*)(appAtts
[i
]))[-1] = 0;
3064 for (binding
= *bindingsPtr
; binding
; binding
= binding
->nextTagBinding
)
3065 binding
->attId
->name
[-1] = 0;
3068 return XML_ERROR_NONE
;
3070 /* expand the element type name */
3071 if (elementType
->prefix
) {
3072 binding
= elementType
->prefix
->binding
;
3074 return XML_ERROR_UNBOUND_PREFIX
;
3075 localPart
= tagNamePtr
->str
;
3076 while (*localPart
++ != XML_T(':'))
3079 else if (dtd
->defaultPrefix
.binding
) {
3080 binding
= dtd
->defaultPrefix
.binding
;
3081 localPart
= tagNamePtr
->str
;
3084 return XML_ERROR_NONE
;
3086 if (ns_triplets
&& binding
->prefix
->name
) {
3087 for (; binding
->prefix
->name
[prefixLen
++];)
3088 ; /* prefixLen includes null terminator */
3090 tagNamePtr
->localPart
= localPart
;
3091 tagNamePtr
->uriLen
= binding
->uriLen
;
3092 tagNamePtr
->prefix
= binding
->prefix
->name
;
3093 tagNamePtr
->prefixLen
= prefixLen
;
3094 for (i
= 0; localPart
[i
++];)
3095 ; /* i includes null terminator */
3096 n
= i
+ binding
->uriLen
+ prefixLen
;
3097 if (n
> binding
->uriAlloc
) {
3099 uri
= (XML_Char
*)MALLOC((n
+ EXPAND_SPARE
) * sizeof(XML_Char
));
3101 return XML_ERROR_NO_MEMORY
;
3102 binding
->uriAlloc
= n
+ EXPAND_SPARE
;
3103 memcpy(uri
, binding
->uri
, binding
->uriLen
* sizeof(XML_Char
));
3104 for (p
= tagStack
; p
; p
= p
->parent
)
3105 if (p
->name
.str
== binding
->uri
)
3110 /* if namespaceSeparator != '\0' then uri includes it already */
3111 uri
= binding
->uri
+ binding
->uriLen
;
3112 memcpy(uri
, localPart
, i
* sizeof(XML_Char
));
3113 /* we always have a namespace separator between localPart and prefix */
3116 *uri
= namespaceSeparator
; /* replace null terminator */
3117 memcpy(uri
+ 1, binding
->prefix
->name
, prefixLen
* sizeof(XML_Char
));
3119 tagNamePtr
->str
= binding
->uri
;
3120 return XML_ERROR_NONE
;
3123 /* addBinding() overwrites the value of prefix->binding without checking.
3124 Therefore one must keep track of the old value outside of addBinding().
3126 static enum XML_Error
3127 addBinding(XML_Parser parser
, PREFIX
*prefix
, const ATTRIBUTE_ID
*attId
,
3128 const XML_Char
*uri
, BINDING
**bindingsPtr
)
3130 static const XML_Char xmlNamespace
[] = {
3131 'h', 't', 't', 'p', ':', '/', '/',
3132 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
3133 'X', 'M', 'L', '/', '1', '9', '9', '8', '/',
3134 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0'
3136 static const int xmlLen
=
3137 (int)sizeof(xmlNamespace
)/sizeof(XML_Char
) - 1;
3138 static const XML_Char xmlnsNamespace
[] = {
3139 'h', 't', 't', 'p', ':', '/', '/',
3140 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
3141 '2', '0', '0', '0', '/', 'x', 'm', 'l', 'n', 's', '/', '\0'
3143 static const int xmlnsLen
=
3144 (int)sizeof(xmlnsNamespace
)/sizeof(XML_Char
) - 1;
3146 XML_Bool mustBeXML
= XML_FALSE
;
3147 XML_Bool isXML
= XML_TRUE
;
3148 XML_Bool isXMLNS
= XML_TRUE
;
3153 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
3154 if (*uri
== XML_T('\0') && prefix
->name
)
3155 return XML_ERROR_UNDECLARING_PREFIX
;
3158 && prefix
->name
[0] == XML_T('x')
3159 && prefix
->name
[1] == XML_T('m')
3160 && prefix
->name
[2] == XML_T('l')) {
3162 /* Not allowed to bind xmlns */
3163 if (prefix
->name
[3] == XML_T('n')
3164 && prefix
->name
[4] == XML_T('s')
3165 && prefix
->name
[5] == XML_T('\0'))
3166 return XML_ERROR_RESERVED_PREFIX_XMLNS
;
3168 if (prefix
->name
[3] == XML_T('\0'))
3169 mustBeXML
= XML_TRUE
;
3172 for (len
= 0; uri
[len
]; len
++) {
3173 if (isXML
&& (len
> xmlLen
|| uri
[len
] != xmlNamespace
[len
]))
3176 if (!mustBeXML
&& isXMLNS
3177 && (len
> xmlnsLen
|| uri
[len
] != xmlnsNamespace
[len
]))
3178 isXMLNS
= XML_FALSE
;
3180 isXML
= isXML
&& len
== xmlLen
;
3181 isXMLNS
= isXMLNS
&& len
== xmlnsLen
;
3183 if (mustBeXML
!= isXML
)
3184 return mustBeXML
? XML_ERROR_RESERVED_PREFIX_XML
3185 : XML_ERROR_RESERVED_NAMESPACE_URI
;
3188 return XML_ERROR_RESERVED_NAMESPACE_URI
;
3190 if (namespaceSeparator
)
3192 if (freeBindingList
) {
3193 b
= freeBindingList
;
3194 if (len
> b
->uriAlloc
) {
3195 XML_Char
*temp
= (XML_Char
*)REALLOC(b
->uri
,
3196 sizeof(XML_Char
) * (len
+ EXPAND_SPARE
));
3198 return XML_ERROR_NO_MEMORY
;
3200 b
->uriAlloc
= len
+ EXPAND_SPARE
;
3202 freeBindingList
= b
->nextTagBinding
;
3205 b
= (BINDING
*)MALLOC(sizeof(BINDING
));
3207 return XML_ERROR_NO_MEMORY
;
3208 b
->uri
= (XML_Char
*)MALLOC(sizeof(XML_Char
) * (len
+ EXPAND_SPARE
));
3211 return XML_ERROR_NO_MEMORY
;
3213 b
->uriAlloc
= len
+ EXPAND_SPARE
;
3216 memcpy(b
->uri
, uri
, len
* sizeof(XML_Char
));
3217 if (namespaceSeparator
)
3218 b
->uri
[len
- 1] = namespaceSeparator
;
3221 b
->prevPrefixBinding
= prefix
->binding
;
3222 /* NULL binding when default namespace undeclared */
3223 if (*uri
== XML_T('\0') && prefix
== &_dtd
->defaultPrefix
)
3224 prefix
->binding
= NULL
;
3226 prefix
->binding
= b
;
3227 b
->nextTagBinding
= *bindingsPtr
;
3229 /* if attId == NULL then we are not starting a namespace scope */
3230 if (attId
&& startNamespaceDeclHandler
)
3231 startNamespaceDeclHandler(handlerArg
, prefix
->name
,
3232 prefix
->binding
? uri
: 0);
3233 return XML_ERROR_NONE
;
3236 /* The idea here is to avoid using stack for each CDATA section when
3237 the whole file is parsed with one call.
3239 static enum XML_Error PTRCALL
3240 cdataSectionProcessor(XML_Parser parser
,
3243 const char **endPtr
)
3245 enum XML_Error result
= doCdataSection(parser
, encoding
, &start
, end
,
3246 endPtr
, (XML_Bool
)!ps_finalBuffer
);
3247 if (result
!= XML_ERROR_NONE
)
3250 if (parentParser
) { /* we are parsing an external entity */
3251 processor
= externalEntityContentProcessor
;
3252 return externalEntityContentProcessor(parser
, start
, end
, endPtr
);
3255 processor
= contentProcessor
;
3256 return contentProcessor(parser
, start
, end
, endPtr
);
3262 /* startPtr gets set to non-null if the section is closed, and to null if
3263 the section is not yet closed.
3265 static enum XML_Error
3266 doCdataSection(XML_Parser parser
,
3267 const ENCODING
*enc
,
3268 const char **startPtr
,
3270 const char **nextPtr
,
3273 const char *s
= *startPtr
;
3274 const char **eventPP
;
3275 const char **eventEndPP
;
3276 if (enc
== encoding
) {
3277 eventPP
= &eventPtr
;
3279 eventEndPP
= &eventEndPtr
;
3282 eventPP
= &(openInternalEntities
->internalEventPtr
);
3283 eventEndPP
= &(openInternalEntities
->internalEventEndPtr
);
3290 int tok
= XmlCdataSectionTok(enc
, s
, end
, &next
);
3293 case XML_TOK_CDATA_SECT_CLOSE
:
3294 if (endCdataSectionHandler
)
3295 endCdataSectionHandler(handlerArg
);
3297 /* see comment under XML_TOK_CDATA_SECT_OPEN */
3298 else if (characterDataHandler
)
3299 characterDataHandler(handlerArg
, dataBuf
, 0);
3301 else if (defaultHandler
)
3302 reportDefault(parser
, enc
, s
, next
);
3305 if (ps_parsing
== XML_FINISHED
)
3306 return XML_ERROR_ABORTED
;
3308 return XML_ERROR_NONE
;
3309 case XML_TOK_DATA_NEWLINE
:
3310 if (characterDataHandler
) {
3312 characterDataHandler(handlerArg
, &c
, 1);
3314 else if (defaultHandler
)
3315 reportDefault(parser
, enc
, s
, next
);
3317 case XML_TOK_DATA_CHARS
:
3318 if (characterDataHandler
) {
3319 if (MUST_CONVERT(enc
, s
)) {
3321 ICHAR
*dataPtr
= (ICHAR
*)dataBuf
;
3322 XmlConvert(enc
, &s
, next
, &dataPtr
, (ICHAR
*)dataBufEnd
);
3324 characterDataHandler(handlerArg
, dataBuf
,
3325 (int)(dataPtr
- (ICHAR
*)dataBuf
));
3332 characterDataHandler(handlerArg
,
3334 (int)((XML_Char
*)next
- (XML_Char
*)s
));
3336 else if (defaultHandler
)
3337 reportDefault(parser
, enc
, s
, next
);
3339 case XML_TOK_INVALID
:
3341 return XML_ERROR_INVALID_TOKEN
;
3342 case XML_TOK_PARTIAL_CHAR
:
3345 return XML_ERROR_NONE
;
3347 return XML_ERROR_PARTIAL_CHAR
;
3348 case XML_TOK_PARTIAL
:
3352 return XML_ERROR_NONE
;
3354 return XML_ERROR_UNCLOSED_CDATA_SECTION
;
3357 return XML_ERROR_UNEXPECTED_STATE
;
3360 *eventPP
= s
= next
;
3361 switch (ps_parsing
) {
3364 return XML_ERROR_NONE
;
3366 return XML_ERROR_ABORTED
;
3375 /* The idea here is to avoid using stack for each IGNORE section when
3376 the whole file is parsed with one call.
3378 static enum XML_Error PTRCALL
3379 ignoreSectionProcessor(XML_Parser parser
,
3382 const char **endPtr
)
3384 enum XML_Error result
= doIgnoreSection(parser
, encoding
, &start
, end
,
3385 endPtr
, (XML_Bool
)!ps_finalBuffer
);
3386 if (result
!= XML_ERROR_NONE
)
3389 processor
= prologProcessor
;
3390 return prologProcessor(parser
, start
, end
, endPtr
);
3395 /* startPtr gets set to non-null is the section is closed, and to null
3396 if the section is not yet closed.
3398 static enum XML_Error
3399 doIgnoreSection(XML_Parser parser
,
3400 const ENCODING
*enc
,
3401 const char **startPtr
,
3403 const char **nextPtr
,
3408 const char *s
= *startPtr
;
3409 const char **eventPP
;
3410 const char **eventEndPP
;
3411 if (enc
== encoding
) {
3412 eventPP
= &eventPtr
;
3414 eventEndPP
= &eventEndPtr
;
3417 eventPP
= &(openInternalEntities
->internalEventPtr
);
3418 eventEndPP
= &(openInternalEntities
->internalEventEndPtr
);
3422 tok
= XmlIgnoreSectionTok(enc
, s
, end
, &next
);
3425 case XML_TOK_IGNORE_SECT
:
3427 reportDefault(parser
, enc
, s
, next
);
3430 if (ps_parsing
== XML_FINISHED
)
3431 return XML_ERROR_ABORTED
;
3433 return XML_ERROR_NONE
;
3434 case XML_TOK_INVALID
:
3436 return XML_ERROR_INVALID_TOKEN
;
3437 case XML_TOK_PARTIAL_CHAR
:
3440 return XML_ERROR_NONE
;
3442 return XML_ERROR_PARTIAL_CHAR
;
3443 case XML_TOK_PARTIAL
:
3447 return XML_ERROR_NONE
;
3449 return XML_ERROR_SYNTAX
; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3452 return XML_ERROR_UNEXPECTED_STATE
;
3457 #endif /* XML_DTD */
3459 static enum XML_Error
3460 initializeEncoding(XML_Parser parser
)
3464 char encodingBuf
[128];
3465 if (!protocolEncodingName
)
3469 for (i
= 0; protocolEncodingName
[i
]; i
++) {
3470 if (i
== sizeof(encodingBuf
) - 1
3471 || (protocolEncodingName
[i
] & ~0x7f) != 0) {
3472 encodingBuf
[0] = '\0';
3475 encodingBuf
[i
] = (char)protocolEncodingName
[i
];
3477 encodingBuf
[i
] = '\0';
3481 s
= protocolEncodingName
;
3483 if ((ns
? XmlInitEncodingNS
: XmlInitEncoding
)(&initEncoding
, &encoding
, s
))
3484 return XML_ERROR_NONE
;
3485 return handleUnknownEncoding(parser
, protocolEncodingName
);
3488 static enum XML_Error
3489 processXmlDecl(XML_Parser parser
, int isGeneralTextEntity
,
3490 const char *s
, const char *next
)
3492 const char *encodingName
= NULL
;
3493 const XML_Char
*storedEncName
= NULL
;
3494 const ENCODING
*newEncoding
= NULL
;
3495 const char *version
= NULL
;
3496 const char *versionend
;
3497 const XML_Char
*storedversion
= NULL
;
3498 int standalone
= -1;
3501 : XmlParseXmlDecl
)(isGeneralTextEntity
,
3511 if (isGeneralTextEntity
)
3512 return XML_ERROR_TEXT_DECL
;
3514 return XML_ERROR_XML_DECL
;
3516 if (!isGeneralTextEntity
&& standalone
== 1) {
3517 _dtd
->standalone
= XML_TRUE
;
3519 if (paramEntityParsing
== XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE
)
3520 paramEntityParsing
= XML_PARAM_ENTITY_PARSING_NEVER
;
3521 #endif /* XML_DTD */
3523 if (xmlDeclHandler
) {
3524 if (encodingName
!= NULL
) {
3525 storedEncName
= poolStoreString(&temp2Pool
,
3529 + XmlNameLength(encoding
, encodingName
));
3531 return XML_ERROR_NO_MEMORY
;
3532 poolFinish(&temp2Pool
);
3535 storedversion
= poolStoreString(&temp2Pool
,
3538 versionend
- encoding
->minBytesPerChar
);
3540 return XML_ERROR_NO_MEMORY
;
3542 xmlDeclHandler(handlerArg
, storedversion
, storedEncName
, standalone
);
3544 else if (defaultHandler
)
3545 reportDefault(parser
, encoding
, s
, next
);
3546 if (protocolEncodingName
== NULL
) {
3548 if (newEncoding
->minBytesPerChar
!= encoding
->minBytesPerChar
) {
3549 eventPtr
= encodingName
;
3550 return XML_ERROR_INCORRECT_ENCODING
;
3552 encoding
= newEncoding
;
3554 else if (encodingName
) {
3555 enum XML_Error result
;
3556 if (!storedEncName
) {
3557 storedEncName
= poolStoreString(
3558 &temp2Pool
, encoding
, encodingName
,
3559 encodingName
+ XmlNameLength(encoding
, encodingName
));
3561 return XML_ERROR_NO_MEMORY
;
3563 result
= handleUnknownEncoding(parser
, storedEncName
);
3564 poolClear(&temp2Pool
);
3565 if (result
== XML_ERROR_UNKNOWN_ENCODING
)
3566 eventPtr
= encodingName
;
3571 if (storedEncName
|| storedversion
)
3572 poolClear(&temp2Pool
);
3574 return XML_ERROR_NONE
;
3577 static enum XML_Error
3578 handleUnknownEncoding(XML_Parser parser
, const XML_Char
*encodingName
)
3580 if (unknownEncodingHandler
) {
3583 for (i
= 0; i
< 256; i
++)
3585 info
.convert
= NULL
;
3587 info
.release
= NULL
;
3588 if (unknownEncodingHandler(unknownEncodingHandlerData
, encodingName
,
3591 unknownEncodingMem
= MALLOC(XmlSizeOfUnknownEncoding());
3592 if (!unknownEncodingMem
) {
3594 info
.release(info
.data
);
3595 return XML_ERROR_NO_MEMORY
;
3598 ? XmlInitUnknownEncodingNS
3599 : XmlInitUnknownEncoding
)(unknownEncodingMem
,
3604 unknownEncodingData
= info
.data
;
3605 unknownEncodingRelease
= info
.release
;
3607 return XML_ERROR_NONE
;
3610 if (info
.release
!= NULL
)
3611 info
.release(info
.data
);
3613 return XML_ERROR_UNKNOWN_ENCODING
;
3616 static enum XML_Error PTRCALL
3617 prologInitProcessor(XML_Parser parser
,
3620 const char **nextPtr
)
3622 enum XML_Error result
= initializeEncoding(parser
);
3623 if (result
!= XML_ERROR_NONE
)
3625 processor
= prologProcessor
;
3626 return prologProcessor(parser
, s
, end
, nextPtr
);
3631 static enum XML_Error PTRCALL
3632 externalParEntInitProcessor(XML_Parser parser
,
3635 const char **nextPtr
)
3637 enum XML_Error result
= initializeEncoding(parser
);
3638 if (result
!= XML_ERROR_NONE
)
3641 /* we know now that XML_Parse(Buffer) has been called,
3642 so we consider the external parameter entity read */
3643 _dtd
->paramEntityRead
= XML_TRUE
;
3645 if (prologState
.inEntityValue
) {
3646 processor
= entityValueInitProcessor
;
3647 return entityValueInitProcessor(parser
, s
, end
, nextPtr
);
3650 processor
= externalParEntProcessor
;
3651 return externalParEntProcessor(parser
, s
, end
, nextPtr
);
3655 static enum XML_Error PTRCALL
3656 entityValueInitProcessor(XML_Parser parser
,
3659 const char **nextPtr
)
3662 const char *start
= s
;
3663 const char *next
= start
;
3667 tok
= XmlPrologTok(encoding
, start
, end
, &next
);
3670 if (!ps_finalBuffer
&& tok
!= XML_TOK_INVALID
) {
3672 return XML_ERROR_NONE
;
3675 case XML_TOK_INVALID
:
3676 return XML_ERROR_INVALID_TOKEN
;
3677 case XML_TOK_PARTIAL
:
3678 return XML_ERROR_UNCLOSED_TOKEN
;
3679 case XML_TOK_PARTIAL_CHAR
:
3680 return XML_ERROR_PARTIAL_CHAR
;
3681 case XML_TOK_NONE
: /* start == end */
3685 /* found end of entity value - can store it now */
3686 return storeEntityValue(parser
, encoding
, s
, end
);
3688 else if (tok
== XML_TOK_XML_DECL
) {
3689 enum XML_Error result
;
3690 result
= processXmlDecl(parser
, 0, start
, next
);
3691 if (result
!= XML_ERROR_NONE
)
3693 switch (ps_parsing
) {
3696 return XML_ERROR_NONE
;
3698 return XML_ERROR_ABORTED
;
3702 /* stop scanning for text declaration - we found one */
3703 processor
= entityValueProcessor
;
3704 return entityValueProcessor(parser
, next
, end
, nextPtr
);
3706 /* If we are at the end of the buffer, this would cause XmlPrologTok to
3707 return XML_TOK_NONE on the next call, which would then cause the
3708 function to exit with *nextPtr set to s - that is what we want for other
3709 tokens, but not for the BOM - we would rather like to skip it;
3710 then, when this routine is entered the next time, XmlPrologTok will
3711 return XML_TOK_INVALID, since the BOM is still in the buffer
3713 else if (tok
== XML_TOK_BOM
&& next
== end
&& !ps_finalBuffer
) {
3715 return XML_ERROR_NONE
;
3722 static enum XML_Error PTRCALL
3723 externalParEntProcessor(XML_Parser parser
,
3726 const char **nextPtr
)
3728 const char *next
= s
;
3731 tok
= XmlPrologTok(encoding
, s
, end
, &next
);
3733 if (!ps_finalBuffer
&& tok
!= XML_TOK_INVALID
) {
3735 return XML_ERROR_NONE
;
3738 case XML_TOK_INVALID
:
3739 return XML_ERROR_INVALID_TOKEN
;
3740 case XML_TOK_PARTIAL
:
3741 return XML_ERROR_UNCLOSED_TOKEN
;
3742 case XML_TOK_PARTIAL_CHAR
:
3743 return XML_ERROR_PARTIAL_CHAR
;
3744 case XML_TOK_NONE
: /* start == end */
3749 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
3750 However, when parsing an external subset, doProlog will not accept a BOM
3751 as valid, and report a syntax error, so we have to skip the BOM
3753 else if (tok
== XML_TOK_BOM
) {
3755 tok
= XmlPrologTok(encoding
, s
, end
, &next
);
3758 processor
= prologProcessor
;
3759 return doProlog(parser
, encoding
, s
, end
, tok
, next
,
3760 nextPtr
, (XML_Bool
)!ps_finalBuffer
);
3763 static enum XML_Error PTRCALL
3764 entityValueProcessor(XML_Parser parser
,
3767 const char **nextPtr
)
3769 const char *start
= s
;
3770 const char *next
= s
;
3771 const ENCODING
*enc
= encoding
;
3775 tok
= XmlPrologTok(enc
, start
, end
, &next
);
3777 if (!ps_finalBuffer
&& tok
!= XML_TOK_INVALID
) {
3779 return XML_ERROR_NONE
;
3782 case XML_TOK_INVALID
:
3783 return XML_ERROR_INVALID_TOKEN
;
3784 case XML_TOK_PARTIAL
:
3785 return XML_ERROR_UNCLOSED_TOKEN
;
3786 case XML_TOK_PARTIAL_CHAR
:
3787 return XML_ERROR_PARTIAL_CHAR
;
3788 case XML_TOK_NONE
: /* start == end */
3792 /* found end of entity value - can store it now */
3793 return storeEntityValue(parser
, enc
, s
, end
);
3799 #endif /* XML_DTD */
3801 static enum XML_Error PTRCALL
3802 prologProcessor(XML_Parser parser
,
3805 const char **nextPtr
)
3807 const char *next
= s
;
3808 int tok
= XmlPrologTok(encoding
, s
, end
, &next
);
3809 return doProlog(parser
, encoding
, s
, end
, tok
, next
,
3810 nextPtr
, (XML_Bool
)!ps_finalBuffer
);
3813 static enum XML_Error
3814 doProlog(XML_Parser parser
,
3815 const ENCODING
*enc
,
3820 const char **nextPtr
,
3824 static const XML_Char externalSubsetName
[] = { '#' , '\0' };
3825 #endif /* XML_DTD */
3826 static const XML_Char atypeCDATA
[] = { 'C', 'D', 'A', 'T', 'A', '\0' };
3827 static const XML_Char atypeID
[] = { 'I', 'D', '\0' };
3828 static const XML_Char atypeIDREF
[] = { 'I', 'D', 'R', 'E', 'F', '\0' };
3829 static const XML_Char atypeIDREFS
[] = { 'I', 'D', 'R', 'E', 'F', 'S', '\0' };
3830 static const XML_Char atypeENTITY
[] = { 'E', 'N', 'T', 'I', 'T', 'Y', '\0' };
3831 static const XML_Char atypeENTITIES
[] =
3832 { 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S', '\0' };
3833 static const XML_Char atypeNMTOKEN
[] = {
3834 'N', 'M', 'T', 'O', 'K', 'E', 'N', '\0' };
3835 static const XML_Char atypeNMTOKENS
[] = {
3836 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S', '\0' };
3837 static const XML_Char notationPrefix
[] = {
3838 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', '(', '\0' };
3839 static const XML_Char enumValueSep
[] = { '|', '\0' };
3840 static const XML_Char enumValueStart
[] = { '(', '\0' };
3842 /* save one level of indirection */
3843 DTD
* const dtd
= _dtd
;
3845 const char **eventPP
;
3846 const char **eventEndPP
;
3847 enum XML_Content_Quant quant
;
3849 if (enc
== encoding
) {
3850 eventPP
= &eventPtr
;
3851 eventEndPP
= &eventEndPtr
;
3854 eventPP
= &(openInternalEntities
->internalEventPtr
);
3855 eventEndPP
= &(openInternalEntities
->internalEventEndPtr
);
3860 XML_Bool handleDefault
= XML_TRUE
;
3864 if (haveMore
&& tok
!= XML_TOK_INVALID
) {
3866 return XML_ERROR_NONE
;
3869 case XML_TOK_INVALID
:
3871 return XML_ERROR_INVALID_TOKEN
;
3872 case XML_TOK_PARTIAL
:
3873 return XML_ERROR_UNCLOSED_TOKEN
;
3874 case XML_TOK_PARTIAL_CHAR
:
3875 return XML_ERROR_PARTIAL_CHAR
;
3878 /* for internal PE NOT referenced between declarations */
3879 if (enc
!= encoding
&& !openInternalEntities
->betweenDecl
) {
3881 return XML_ERROR_NONE
;
3883 /* WFC: PE Between Declarations - must check that PE contains
3884 complete markup, not only for external PEs, but also for
3885 internal PEs if the reference occurs between declarations.
3887 if (isParamEntity
|| enc
!= encoding
) {
3888 if (XmlTokenRole(&prologState
, XML_TOK_NONE
, end
, end
, enc
)
3890 return XML_ERROR_INCOMPLETE_PE
;
3892 return XML_ERROR_NONE
;
3894 #endif /* XML_DTD */
3895 return XML_ERROR_NO_ELEMENTS
;
3902 role
= XmlTokenRole(&prologState
, tok
, s
, next
, enc
);
3904 case XML_ROLE_XML_DECL
:
3906 enum XML_Error result
= processXmlDecl(parser
, 0, s
, next
);
3907 if (result
!= XML_ERROR_NONE
)
3910 handleDefault
= XML_FALSE
;
3913 case XML_ROLE_DOCTYPE_NAME
:
3914 if (startDoctypeDeclHandler
) {
3915 doctypeName
= poolStoreString(&tempPool
, enc
, s
, next
);
3917 return XML_ERROR_NO_MEMORY
;
3918 poolFinish(&tempPool
);
3919 doctypePubid
= NULL
;
3920 handleDefault
= XML_FALSE
;
3922 doctypeSysid
= NULL
; /* always initialize to NULL */
3924 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET
:
3925 if (startDoctypeDeclHandler
) {
3926 startDoctypeDeclHandler(handlerArg
, doctypeName
, doctypeSysid
,
3929 poolClear(&tempPool
);
3930 handleDefault
= XML_FALSE
;
3934 case XML_ROLE_TEXT_DECL
:
3936 enum XML_Error result
= processXmlDecl(parser
, 1, s
, next
);
3937 if (result
!= XML_ERROR_NONE
)
3940 handleDefault
= XML_FALSE
;
3943 #endif /* XML_DTD */
3944 case XML_ROLE_DOCTYPE_PUBLIC_ID
:
3946 useForeignDTD
= XML_FALSE
;
3947 declEntity
= (ENTITY
*)lookup(&dtd
->paramEntities
,
3951 return XML_ERROR_NO_MEMORY
;
3952 #endif /* XML_DTD */
3953 dtd
->hasParamEntityRefs
= XML_TRUE
;
3954 if (startDoctypeDeclHandler
) {
3955 if (!XmlIsPublicId(enc
, s
, next
, eventPP
))
3956 return XML_ERROR_PUBLICID
;
3957 doctypePubid
= poolStoreString(&tempPool
, enc
,
3958 s
+ enc
->minBytesPerChar
,
3959 next
- enc
->minBytesPerChar
);
3961 return XML_ERROR_NO_MEMORY
;
3962 normalizePublicId((XML_Char
*)doctypePubid
);
3963 poolFinish(&tempPool
);
3964 handleDefault
= XML_FALSE
;
3965 goto alreadyChecked
;
3968 case XML_ROLE_ENTITY_PUBLIC_ID
:
3969 if (!XmlIsPublicId(enc
, s
, next
, eventPP
))
3970 return XML_ERROR_PUBLICID
;
3972 if (dtd
->keepProcessing
&& declEntity
) {
3973 XML_Char
*tem
= poolStoreString(&dtd
->pool
,
3975 s
+ enc
->minBytesPerChar
,
3976 next
- enc
->minBytesPerChar
);
3978 return XML_ERROR_NO_MEMORY
;
3979 normalizePublicId(tem
);
3980 declEntity
->publicId
= tem
;
3981 poolFinish(&dtd
->pool
);
3982 if (entityDeclHandler
)
3983 handleDefault
= XML_FALSE
;
3986 case XML_ROLE_DOCTYPE_CLOSE
:
3988 startDoctypeDeclHandler(handlerArg
, doctypeName
,
3989 doctypeSysid
, doctypePubid
, 0);
3990 poolClear(&tempPool
);
3991 handleDefault
= XML_FALSE
;
3993 /* doctypeSysid will be non-NULL in the case of a previous
3994 XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
3995 was not set, indicating an external subset
3998 if (doctypeSysid
|| useForeignDTD
) {
3999 XML_Bool hadParamEntityRefs
= dtd
->hasParamEntityRefs
;
4000 dtd
->hasParamEntityRefs
= XML_TRUE
;
4001 if (paramEntityParsing
&& externalEntityRefHandler
) {
4002 ENTITY
*entity
= (ENTITY
*)lookup(&dtd
->paramEntities
,
4006 return XML_ERROR_NO_MEMORY
;
4008 entity
->base
= curBase
;
4009 dtd
->paramEntityRead
= XML_FALSE
;
4010 if (!externalEntityRefHandler(externalEntityRefHandlerArg
,
4015 return XML_ERROR_EXTERNAL_ENTITY_HANDLING
;
4016 if (dtd
->paramEntityRead
) {
4017 if (!dtd
->standalone
&&
4018 notStandaloneHandler
&&
4019 !notStandaloneHandler(handlerArg
))
4020 return XML_ERROR_NOT_STANDALONE
;
4022 /* if we didn't read the foreign DTD then this means that there
4023 is no external subset and we must reset dtd->hasParamEntityRefs
4025 else if (!doctypeSysid
)
4026 dtd
->hasParamEntityRefs
= hadParamEntityRefs
;
4027 /* end of DTD - no need to update dtd->keepProcessing */
4029 useForeignDTD
= XML_FALSE
;
4031 #endif /* XML_DTD */
4032 if (endDoctypeDeclHandler
) {
4033 endDoctypeDeclHandler(handlerArg
);
4034 handleDefault
= XML_FALSE
;
4037 case XML_ROLE_INSTANCE_START
:
4039 /* if there is no DOCTYPE declaration then now is the
4040 last chance to read the foreign DTD
4042 if (useForeignDTD
) {
4043 XML_Bool hadParamEntityRefs
= dtd
->hasParamEntityRefs
;
4044 dtd
->hasParamEntityRefs
= XML_TRUE
;
4045 if (paramEntityParsing
&& externalEntityRefHandler
) {
4046 ENTITY
*entity
= (ENTITY
*)lookup(&dtd
->paramEntities
,
4050 return XML_ERROR_NO_MEMORY
;
4051 entity
->base
= curBase
;
4052 dtd
->paramEntityRead
= XML_FALSE
;
4053 if (!externalEntityRefHandler(externalEntityRefHandlerArg
,
4058 return XML_ERROR_EXTERNAL_ENTITY_HANDLING
;
4059 if (dtd
->paramEntityRead
) {
4060 if (!dtd
->standalone
&&
4061 notStandaloneHandler
&&
4062 !notStandaloneHandler(handlerArg
))
4063 return XML_ERROR_NOT_STANDALONE
;
4065 /* if we didn't read the foreign DTD then this means that there
4066 is no external subset and we must reset dtd->hasParamEntityRefs
4069 dtd
->hasParamEntityRefs
= hadParamEntityRefs
;
4070 /* end of DTD - no need to update dtd->keepProcessing */
4073 #endif /* XML_DTD */
4074 processor
= contentProcessor
;
4075 return contentProcessor(parser
, s
, end
, nextPtr
);
4076 case XML_ROLE_ATTLIST_ELEMENT_NAME
:
4077 declElementType
= getElementType(parser
, enc
, s
, next
);
4078 if (!declElementType
)
4079 return XML_ERROR_NO_MEMORY
;
4080 goto checkAttListDeclHandler
;
4081 case XML_ROLE_ATTRIBUTE_NAME
:
4082 declAttributeId
= getAttributeId(parser
, enc
, s
, next
);
4083 if (!declAttributeId
)
4084 return XML_ERROR_NO_MEMORY
;
4085 declAttributeIsCdata
= XML_FALSE
;
4086 declAttributeType
= NULL
;
4087 declAttributeIsId
= XML_FALSE
;
4088 goto checkAttListDeclHandler
;
4089 case XML_ROLE_ATTRIBUTE_TYPE_CDATA
:
4090 declAttributeIsCdata
= XML_TRUE
;
4091 declAttributeType
= atypeCDATA
;
4092 goto checkAttListDeclHandler
;
4093 case XML_ROLE_ATTRIBUTE_TYPE_ID
:
4094 declAttributeIsId
= XML_TRUE
;
4095 declAttributeType
= atypeID
;
4096 goto checkAttListDeclHandler
;
4097 case XML_ROLE_ATTRIBUTE_TYPE_IDREF
:
4098 declAttributeType
= atypeIDREF
;
4099 goto checkAttListDeclHandler
;
4100 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS
:
4101 declAttributeType
= atypeIDREFS
;
4102 goto checkAttListDeclHandler
;
4103 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY
:
4104 declAttributeType
= atypeENTITY
;
4105 goto checkAttListDeclHandler
;
4106 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES
:
4107 declAttributeType
= atypeENTITIES
;
4108 goto checkAttListDeclHandler
;
4109 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN
:
4110 declAttributeType
= atypeNMTOKEN
;
4111 goto checkAttListDeclHandler
;
4112 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS
:
4113 declAttributeType
= atypeNMTOKENS
;
4114 checkAttListDeclHandler
:
4115 if (dtd
->keepProcessing
&& attlistDeclHandler
)
4116 handleDefault
= XML_FALSE
;
4118 case XML_ROLE_ATTRIBUTE_ENUM_VALUE
:
4119 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE
:
4120 if (dtd
->keepProcessing
&& attlistDeclHandler
) {
4121 const XML_Char
*prefix
;
4122 if (declAttributeType
) {
4123 prefix
= enumValueSep
;
4126 prefix
= (role
== XML_ROLE_ATTRIBUTE_NOTATION_VALUE
4130 if (!poolAppendString(&tempPool
, prefix
))
4131 return XML_ERROR_NO_MEMORY
;
4132 if (!poolAppend(&tempPool
, enc
, s
, next
))
4133 return XML_ERROR_NO_MEMORY
;
4134 declAttributeType
= tempPool
.start
;
4135 handleDefault
= XML_FALSE
;
4138 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE
:
4139 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE
:
4140 if (dtd
->keepProcessing
) {
4141 if (!defineAttribute(declElementType
, declAttributeId
,
4142 declAttributeIsCdata
, declAttributeIsId
,
4144 return XML_ERROR_NO_MEMORY
;
4145 if (attlistDeclHandler
&& declAttributeType
) {
4146 if (*declAttributeType
== XML_T('(')
4147 || (*declAttributeType
== XML_T('N')
4148 && declAttributeType
[1] == XML_T('O'))) {
4149 /* Enumerated or Notation type */
4150 if (!poolAppendChar(&tempPool
, XML_T(')'))
4151 || !poolAppendChar(&tempPool
, XML_T('\0')))
4152 return XML_ERROR_NO_MEMORY
;
4153 declAttributeType
= tempPool
.start
;
4154 poolFinish(&tempPool
);
4157 attlistDeclHandler(handlerArg
, declElementType
->name
,
4158 declAttributeId
->name
, declAttributeType
,
4159 0, role
== XML_ROLE_REQUIRED_ATTRIBUTE_VALUE
);
4160 poolClear(&tempPool
);
4161 handleDefault
= XML_FALSE
;
4165 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE
:
4166 case XML_ROLE_FIXED_ATTRIBUTE_VALUE
:
4167 if (dtd
->keepProcessing
) {
4168 const XML_Char
*attVal
;
4169 enum XML_Error result
=
4170 storeAttributeValue(parser
, enc
, declAttributeIsCdata
,
4171 s
+ enc
->minBytesPerChar
,
4172 next
- enc
->minBytesPerChar
,
4176 attVal
= poolStart(&dtd
->pool
);
4177 poolFinish(&dtd
->pool
);
4178 /* ID attributes aren't allowed to have a default */
4179 if (!defineAttribute(declElementType
, declAttributeId
,
4180 declAttributeIsCdata
, XML_FALSE
, attVal
, parser
))
4181 return XML_ERROR_NO_MEMORY
;
4182 if (attlistDeclHandler
&& declAttributeType
) {
4183 if (*declAttributeType
== XML_T('(')
4184 || (*declAttributeType
== XML_T('N')
4185 && declAttributeType
[1] == XML_T('O'))) {
4186 /* Enumerated or Notation type */
4187 if (!poolAppendChar(&tempPool
, XML_T(')'))
4188 || !poolAppendChar(&tempPool
, XML_T('\0')))
4189 return XML_ERROR_NO_MEMORY
;
4190 declAttributeType
= tempPool
.start
;
4191 poolFinish(&tempPool
);
4194 attlistDeclHandler(handlerArg
, declElementType
->name
,
4195 declAttributeId
->name
, declAttributeType
,
4197 role
== XML_ROLE_FIXED_ATTRIBUTE_VALUE
);
4198 poolClear(&tempPool
);
4199 handleDefault
= XML_FALSE
;
4203 case XML_ROLE_ENTITY_VALUE
:
4204 if (dtd
->keepProcessing
) {
4205 enum XML_Error result
= storeEntityValue(parser
, enc
,
4206 s
+ enc
->minBytesPerChar
,
4207 next
- enc
->minBytesPerChar
);
4209 declEntity
->textPtr
= poolStart(&dtd
->entityValuePool
);
4210 declEntity
->textLen
= (int)(poolLength(&dtd
->entityValuePool
));
4211 poolFinish(&dtd
->entityValuePool
);
4212 if (entityDeclHandler
) {
4214 entityDeclHandler(handlerArg
,
4216 declEntity
->is_param
,
4217 declEntity
->textPtr
,
4218 declEntity
->textLen
,
4220 handleDefault
= XML_FALSE
;
4224 poolDiscard(&dtd
->entityValuePool
);
4225 if (result
!= XML_ERROR_NONE
)
4229 case XML_ROLE_DOCTYPE_SYSTEM_ID
:
4231 useForeignDTD
= XML_FALSE
;
4232 #endif /* XML_DTD */
4233 dtd
->hasParamEntityRefs
= XML_TRUE
;
4234 if (startDoctypeDeclHandler
) {
4235 doctypeSysid
= poolStoreString(&tempPool
, enc
,
4236 s
+ enc
->minBytesPerChar
,
4237 next
- enc
->minBytesPerChar
);
4238 if (doctypeSysid
== NULL
)
4239 return XML_ERROR_NO_MEMORY
;
4240 poolFinish(&tempPool
);
4241 handleDefault
= XML_FALSE
;
4245 /* use externalSubsetName to make doctypeSysid non-NULL
4246 for the case where no startDoctypeDeclHandler is set */
4247 doctypeSysid
= externalSubsetName
;
4248 #endif /* XML_DTD */
4249 if (!dtd
->standalone
4251 && !paramEntityParsing
4252 #endif /* XML_DTD */
4253 && notStandaloneHandler
4254 && !notStandaloneHandler(handlerArg
))
4255 return XML_ERROR_NOT_STANDALONE
;
4260 declEntity
= (ENTITY
*)lookup(&dtd
->paramEntities
,
4264 return XML_ERROR_NO_MEMORY
;
4265 declEntity
->publicId
= NULL
;
4268 #endif /* XML_DTD */
4269 case XML_ROLE_ENTITY_SYSTEM_ID
:
4270 if (dtd
->keepProcessing
&& declEntity
) {
4271 declEntity
->systemId
= poolStoreString(&dtd
->pool
, enc
,
4272 s
+ enc
->minBytesPerChar
,
4273 next
- enc
->minBytesPerChar
);
4274 if (!declEntity
->systemId
)
4275 return XML_ERROR_NO_MEMORY
;
4276 declEntity
->base
= curBase
;
4277 poolFinish(&dtd
->pool
);
4278 if (entityDeclHandler
)
4279 handleDefault
= XML_FALSE
;
4282 case XML_ROLE_ENTITY_COMPLETE
:
4283 if (dtd
->keepProcessing
&& declEntity
&& entityDeclHandler
) {
4285 entityDeclHandler(handlerArg
,
4287 declEntity
->is_param
,
4290 declEntity
->systemId
,
4291 declEntity
->publicId
,
4293 handleDefault
= XML_FALSE
;
4296 case XML_ROLE_ENTITY_NOTATION_NAME
:
4297 if (dtd
->keepProcessing
&& declEntity
) {
4298 declEntity
->notation
= poolStoreString(&dtd
->pool
, enc
, s
, next
);
4299 if (!declEntity
->notation
)
4300 return XML_ERROR_NO_MEMORY
;
4301 poolFinish(&dtd
->pool
);
4302 if (unparsedEntityDeclHandler
) {
4304 unparsedEntityDeclHandler(handlerArg
,
4307 declEntity
->systemId
,
4308 declEntity
->publicId
,
4309 declEntity
->notation
);
4310 handleDefault
= XML_FALSE
;
4312 else if (entityDeclHandler
) {
4314 entityDeclHandler(handlerArg
,
4318 declEntity
->systemId
,
4319 declEntity
->publicId
,
4320 declEntity
->notation
);
4321 handleDefault
= XML_FALSE
;
4325 case XML_ROLE_GENERAL_ENTITY_NAME
:
4327 if (XmlPredefinedEntityName(enc
, s
, next
)) {
4331 if (dtd
->keepProcessing
) {
4332 const XML_Char
*name
= poolStoreString(&dtd
->pool
, enc
, s
, next
);
4334 return XML_ERROR_NO_MEMORY
;
4335 declEntity
= (ENTITY
*)lookup(&dtd
->generalEntities
, name
,
4338 return XML_ERROR_NO_MEMORY
;
4339 if (declEntity
->name
!= name
) {
4340 poolDiscard(&dtd
->pool
);
4344 poolFinish(&dtd
->pool
);
4345 declEntity
->publicId
= NULL
;
4346 declEntity
->is_param
= XML_FALSE
;
4347 /* if we have a parent parser or are reading an internal parameter
4348 entity, then the entity declaration is not considered "internal"
4350 declEntity
->is_internal
= !(parentParser
|| openInternalEntities
);
4351 if (entityDeclHandler
)
4352 handleDefault
= XML_FALSE
;
4356 poolDiscard(&dtd
->pool
);
4361 case XML_ROLE_PARAM_ENTITY_NAME
:
4363 if (dtd
->keepProcessing
) {
4364 const XML_Char
*name
= poolStoreString(&dtd
->pool
, enc
, s
, next
);
4366 return XML_ERROR_NO_MEMORY
;
4367 declEntity
= (ENTITY
*)lookup(&dtd
->paramEntities
,
4368 name
, sizeof(ENTITY
));
4370 return XML_ERROR_NO_MEMORY
;
4371 if (declEntity
->name
!= name
) {
4372 poolDiscard(&dtd
->pool
);
4376 poolFinish(&dtd
->pool
);
4377 declEntity
->publicId
= NULL
;
4378 declEntity
->is_param
= XML_TRUE
;
4379 /* if we have a parent parser or are reading an internal parameter
4380 entity, then the entity declaration is not considered "internal"
4382 declEntity
->is_internal
= !(parentParser
|| openInternalEntities
);
4383 if (entityDeclHandler
)
4384 handleDefault
= XML_FALSE
;
4388 poolDiscard(&dtd
->pool
);
4391 #else /* not XML_DTD */
4393 #endif /* XML_DTD */
4395 case XML_ROLE_NOTATION_NAME
:
4396 declNotationPublicId
= NULL
;
4397 declNotationName
= NULL
;
4398 if (notationDeclHandler
) {
4399 declNotationName
= poolStoreString(&tempPool
, enc
, s
, next
);
4400 if (!declNotationName
)
4401 return XML_ERROR_NO_MEMORY
;
4402 poolFinish(&tempPool
);
4403 handleDefault
= XML_FALSE
;
4406 case XML_ROLE_NOTATION_PUBLIC_ID
:
4407 if (!XmlIsPublicId(enc
, s
, next
, eventPP
))
4408 return XML_ERROR_PUBLICID
;
4409 if (declNotationName
) { /* means notationDeclHandler != NULL */
4410 XML_Char
*tem
= poolStoreString(&tempPool
,
4412 s
+ enc
->minBytesPerChar
,
4413 next
- enc
->minBytesPerChar
);
4415 return XML_ERROR_NO_MEMORY
;
4416 normalizePublicId(tem
);
4417 declNotationPublicId
= tem
;
4418 poolFinish(&tempPool
);
4419 handleDefault
= XML_FALSE
;
4422 case XML_ROLE_NOTATION_SYSTEM_ID
:
4423 if (declNotationName
&& notationDeclHandler
) {
4424 const XML_Char
*systemId
4425 = poolStoreString(&tempPool
, enc
,
4426 s
+ enc
->minBytesPerChar
,
4427 next
- enc
->minBytesPerChar
);
4429 return XML_ERROR_NO_MEMORY
;
4431 notationDeclHandler(handlerArg
,
4435 declNotationPublicId
);
4436 handleDefault
= XML_FALSE
;
4438 poolClear(&tempPool
);
4440 case XML_ROLE_NOTATION_NO_SYSTEM_ID
:
4441 if (declNotationPublicId
&& notationDeclHandler
) {
4443 notationDeclHandler(handlerArg
,
4447 declNotationPublicId
);
4448 handleDefault
= XML_FALSE
;
4450 poolClear(&tempPool
);
4452 case XML_ROLE_ERROR
:
4454 case XML_TOK_PARAM_ENTITY_REF
:
4455 /* PE references in internal subset are
4456 not allowed within declarations. */
4457 return XML_ERROR_PARAM_ENTITY_REF
;
4458 case XML_TOK_XML_DECL
:
4459 return XML_ERROR_MISPLACED_XML_PI
;
4461 return XML_ERROR_SYNTAX
;
4464 case XML_ROLE_IGNORE_SECT
:
4466 enum XML_Error result
;
4468 reportDefault(parser
, enc
, s
, next
);
4469 handleDefault
= XML_FALSE
;
4470 result
= doIgnoreSection(parser
, enc
, &next
, end
, nextPtr
, haveMore
);
4471 if (result
!= XML_ERROR_NONE
)
4474 processor
= ignoreSectionProcessor
;
4479 #endif /* XML_DTD */
4480 case XML_ROLE_GROUP_OPEN
:
4481 if (prologState
.level
>= groupSize
) {
4483 char *temp
= (char *)REALLOC(groupConnector
, groupSize
*= 2);
4485 return XML_ERROR_NO_MEMORY
;
4486 groupConnector
= temp
;
4487 if (dtd
->scaffIndex
) {
4488 int *temp
= (int *)REALLOC(dtd
->scaffIndex
,
4489 groupSize
* sizeof(int));
4491 return XML_ERROR_NO_MEMORY
;
4492 dtd
->scaffIndex
= temp
;
4496 groupConnector
= (char *)MALLOC(groupSize
= 32);
4497 if (!groupConnector
)
4498 return XML_ERROR_NO_MEMORY
;
4501 groupConnector
[prologState
.level
] = 0;
4502 if (dtd
->in_eldecl
) {
4503 int myindex
= nextScaffoldPart(parser
);
4505 return XML_ERROR_NO_MEMORY
;
4506 dtd
->scaffIndex
[dtd
->scaffLevel
] = myindex
;
4508 dtd
->scaffold
[myindex
].type
= XML_CTYPE_SEQ
;
4509 if (elementDeclHandler
)
4510 handleDefault
= XML_FALSE
;
4513 case XML_ROLE_GROUP_SEQUENCE
:
4514 if (groupConnector
[prologState
.level
] == '|')
4515 return XML_ERROR_SYNTAX
;
4516 groupConnector
[prologState
.level
] = ',';
4517 if (dtd
->in_eldecl
&& elementDeclHandler
)
4518 handleDefault
= XML_FALSE
;
4520 case XML_ROLE_GROUP_CHOICE
:
4521 if (groupConnector
[prologState
.level
] == ',')
4522 return XML_ERROR_SYNTAX
;
4524 && !groupConnector
[prologState
.level
]
4525 && (dtd
->scaffold
[dtd
->scaffIndex
[dtd
->scaffLevel
- 1]].type
4528 dtd
->scaffold
[dtd
->scaffIndex
[dtd
->scaffLevel
- 1]].type
4530 if (elementDeclHandler
)
4531 handleDefault
= XML_FALSE
;
4533 groupConnector
[prologState
.level
] = '|';
4535 case XML_ROLE_PARAM_ENTITY_REF
:
4537 case XML_ROLE_INNER_PARAM_ENTITY_REF
:
4538 dtd
->hasParamEntityRefs
= XML_TRUE
;
4539 if (!paramEntityParsing
)
4540 dtd
->keepProcessing
= dtd
->standalone
;
4542 const XML_Char
*name
;
4544 name
= poolStoreString(&dtd
->pool
, enc
,
4545 s
+ enc
->minBytesPerChar
,
4546 next
- enc
->minBytesPerChar
);
4548 return XML_ERROR_NO_MEMORY
;
4549 entity
= (ENTITY
*)lookup(&dtd
->paramEntities
, name
, 0);
4550 poolDiscard(&dtd
->pool
);
4551 /* first, determine if a check for an existing declaration is needed;
4552 if yes, check that the entity exists, and that it is internal,
4553 otherwise call the skipped entity handler
4555 if (prologState
.documentEntity
&&
4557 ? !openInternalEntities
4558 : !dtd
->hasParamEntityRefs
)) {
4560 return XML_ERROR_UNDEFINED_ENTITY
;
4561 else if (!entity
->is_internal
)
4562 return XML_ERROR_ENTITY_DECLARED_IN_PE
;
4565 dtd
->keepProcessing
= dtd
->standalone
;
4566 /* cannot report skipped entities in declarations */
4567 if ((role
== XML_ROLE_PARAM_ENTITY_REF
) && skippedEntityHandler
) {
4568 skippedEntityHandler(handlerArg
, name
, 1);
4569 handleDefault
= XML_FALSE
;
4574 return XML_ERROR_RECURSIVE_ENTITY_REF
;
4575 if (entity
->textPtr
) {
4576 enum XML_Error result
;
4577 XML_Bool betweenDecl
=
4578 (role
== XML_ROLE_PARAM_ENTITY_REF
? XML_TRUE
: XML_FALSE
);
4579 result
= processInternalEntity(parser
, entity
, betweenDecl
);
4580 if (result
!= XML_ERROR_NONE
)
4582 handleDefault
= XML_FALSE
;
4585 if (externalEntityRefHandler
) {
4586 dtd
->paramEntityRead
= XML_FALSE
;
4587 entity
->open
= XML_TRUE
;
4588 if (!externalEntityRefHandler(externalEntityRefHandlerArg
,
4589 /* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=191482) */
4595 /* END MOZILLA CHANGE */
4598 entity
->publicId
)) {
4599 entity
->open
= XML_FALSE
;
4600 return XML_ERROR_EXTERNAL_ENTITY_HANDLING
;
4602 entity
->open
= XML_FALSE
;
4603 handleDefault
= XML_FALSE
;
4604 if (!dtd
->paramEntityRead
) {
4605 dtd
->keepProcessing
= dtd
->standalone
;
4610 dtd
->keepProcessing
= dtd
->standalone
;
4614 #endif /* XML_DTD */
4615 if (!dtd
->standalone
&&
4616 notStandaloneHandler
&&
4617 !notStandaloneHandler(handlerArg
))
4618 return XML_ERROR_NOT_STANDALONE
;
4621 /* Element declaration stuff */
4623 case XML_ROLE_ELEMENT_NAME
:
4624 if (elementDeclHandler
) {
4625 declElementType
= getElementType(parser
, enc
, s
, next
);
4626 if (!declElementType
)
4627 return XML_ERROR_NO_MEMORY
;
4628 dtd
->scaffLevel
= 0;
4629 dtd
->scaffCount
= 0;
4630 dtd
->in_eldecl
= XML_TRUE
;
4631 handleDefault
= XML_FALSE
;
4635 case XML_ROLE_CONTENT_ANY
:
4636 case XML_ROLE_CONTENT_EMPTY
:
4637 if (dtd
->in_eldecl
) {
4638 if (elementDeclHandler
) {
4639 XML_Content
* content
= (XML_Content
*) MALLOC(sizeof(XML_Content
));
4641 return XML_ERROR_NO_MEMORY
;
4642 content
->quant
= XML_CQUANT_NONE
;
4643 content
->name
= NULL
;
4644 content
->numchildren
= 0;
4645 content
->children
= NULL
;
4646 content
->type
= ((role
== XML_ROLE_CONTENT_ANY
) ?
4650 elementDeclHandler(handlerArg
, declElementType
->name
, content
);
4651 handleDefault
= XML_FALSE
;
4653 dtd
->in_eldecl
= XML_FALSE
;
4657 case XML_ROLE_CONTENT_PCDATA
:
4658 if (dtd
->in_eldecl
) {
4659 dtd
->scaffold
[dtd
->scaffIndex
[dtd
->scaffLevel
- 1]].type
4661 if (elementDeclHandler
)
4662 handleDefault
= XML_FALSE
;
4666 case XML_ROLE_CONTENT_ELEMENT
:
4667 quant
= XML_CQUANT_NONE
;
4668 goto elementContent
;
4669 case XML_ROLE_CONTENT_ELEMENT_OPT
:
4670 quant
= XML_CQUANT_OPT
;
4671 goto elementContent
;
4672 case XML_ROLE_CONTENT_ELEMENT_REP
:
4673 quant
= XML_CQUANT_REP
;
4674 goto elementContent
;
4675 case XML_ROLE_CONTENT_ELEMENT_PLUS
:
4676 quant
= XML_CQUANT_PLUS
;
4678 if (dtd
->in_eldecl
) {
4680 const XML_Char
*name
;
4682 const char *nxt
= (quant
== XML_CQUANT_NONE
4684 : next
- enc
->minBytesPerChar
);
4685 int myindex
= nextScaffoldPart(parser
);
4687 return XML_ERROR_NO_MEMORY
;
4688 dtd
->scaffold
[myindex
].type
= XML_CTYPE_NAME
;
4689 dtd
->scaffold
[myindex
].quant
= quant
;
4690 el
= getElementType(parser
, enc
, s
, nxt
);
4692 return XML_ERROR_NO_MEMORY
;
4694 dtd
->scaffold
[myindex
].name
= name
;
4696 for (; name
[nameLen
++]; );
4697 dtd
->contentStringLen
+= nameLen
;
4698 if (elementDeclHandler
)
4699 handleDefault
= XML_FALSE
;
4703 case XML_ROLE_GROUP_CLOSE
:
4704 quant
= XML_CQUANT_NONE
;
4706 case XML_ROLE_GROUP_CLOSE_OPT
:
4707 quant
= XML_CQUANT_OPT
;
4709 case XML_ROLE_GROUP_CLOSE_REP
:
4710 quant
= XML_CQUANT_REP
;
4712 case XML_ROLE_GROUP_CLOSE_PLUS
:
4713 quant
= XML_CQUANT_PLUS
;
4715 if (dtd
->in_eldecl
) {
4716 if (elementDeclHandler
)
4717 handleDefault
= XML_FALSE
;
4719 dtd
->scaffold
[dtd
->scaffIndex
[dtd
->scaffLevel
]].quant
= quant
;
4720 if (dtd
->scaffLevel
== 0) {
4721 if (!handleDefault
) {
4722 XML_Content
*model
= build_model(parser
);
4724 return XML_ERROR_NO_MEMORY
;
4726 elementDeclHandler(handlerArg
, declElementType
->name
, model
);
4728 dtd
->in_eldecl
= XML_FALSE
;
4729 dtd
->contentStringLen
= 0;
4733 /* End element declaration stuff */
4736 if (!reportProcessingInstruction(parser
, enc
, s
, next
))
4737 return XML_ERROR_NO_MEMORY
;
4738 handleDefault
= XML_FALSE
;
4740 case XML_ROLE_COMMENT
:
4741 if (!reportComment(parser
, enc
, s
, next
))
4742 return XML_ERROR_NO_MEMORY
;
4743 handleDefault
= XML_FALSE
;
4748 handleDefault
= XML_FALSE
;
4752 case XML_ROLE_DOCTYPE_NONE
:
4753 if (startDoctypeDeclHandler
)
4754 handleDefault
= XML_FALSE
;
4756 case XML_ROLE_ENTITY_NONE
:
4757 if (dtd
->keepProcessing
&& entityDeclHandler
)
4758 handleDefault
= XML_FALSE
;
4760 case XML_ROLE_NOTATION_NONE
:
4761 if (notationDeclHandler
)
4762 handleDefault
= XML_FALSE
;
4764 case XML_ROLE_ATTLIST_NONE
:
4765 if (dtd
->keepProcessing
&& attlistDeclHandler
)
4766 handleDefault
= XML_FALSE
;
4768 case XML_ROLE_ELEMENT_NONE
:
4769 if (elementDeclHandler
)
4770 handleDefault
= XML_FALSE
;
4772 } /* end of big switch */
4774 if (handleDefault
&& defaultHandler
)
4775 reportDefault(parser
, enc
, s
, next
);
4777 switch (ps_parsing
) {
4780 return XML_ERROR_NONE
;
4782 return XML_ERROR_ABORTED
;
4785 tok
= XmlPrologTok(enc
, s
, end
, &next
);
4791 static enum XML_Error PTRCALL
4792 epilogProcessor(XML_Parser parser
,
4795 const char **nextPtr
)
4797 processor
= epilogProcessor
;
4800 const char *next
= NULL
;
4801 int tok
= XmlPrologTok(encoding
, s
, end
, &next
);
4804 /* report partial linebreak - it might be the last token */
4805 case -XML_TOK_PROLOG_S
:
4806 if (defaultHandler
) {
4807 reportDefault(parser
, encoding
, s
, next
);
4808 if (ps_parsing
== XML_FINISHED
)
4809 return XML_ERROR_ABORTED
;
4812 return XML_ERROR_NONE
;
4815 return XML_ERROR_NONE
;
4816 case XML_TOK_PROLOG_S
:
4818 reportDefault(parser
, encoding
, s
, next
);
4821 if (!reportProcessingInstruction(parser
, encoding
, s
, next
))
4822 return XML_ERROR_NO_MEMORY
;
4824 case XML_TOK_COMMENT
:
4825 if (!reportComment(parser
, encoding
, s
, next
))
4826 return XML_ERROR_NO_MEMORY
;
4828 case XML_TOK_INVALID
:
4830 return XML_ERROR_INVALID_TOKEN
;
4831 case XML_TOK_PARTIAL
:
4832 if (!ps_finalBuffer
) {
4834 return XML_ERROR_NONE
;
4836 return XML_ERROR_UNCLOSED_TOKEN
;
4837 case XML_TOK_PARTIAL_CHAR
:
4838 if (!ps_finalBuffer
) {
4840 return XML_ERROR_NONE
;
4842 return XML_ERROR_PARTIAL_CHAR
;
4844 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT
;
4846 eventPtr
= s
= next
;
4847 switch (ps_parsing
) {
4850 return XML_ERROR_NONE
;
4852 return XML_ERROR_ABORTED
;
4858 static enum XML_Error
4859 processInternalEntity(XML_Parser parser
, ENTITY
*entity
,
4860 XML_Bool betweenDecl
)
4862 const char *textStart
, *textEnd
;
4864 enum XML_Error result
;
4865 OPEN_INTERNAL_ENTITY
*openEntity
;
4867 if (freeInternalEntities
) {
4868 openEntity
= freeInternalEntities
;
4869 freeInternalEntities
= openEntity
->next
;
4872 openEntity
= (OPEN_INTERNAL_ENTITY
*)MALLOC(sizeof(OPEN_INTERNAL_ENTITY
));
4874 return XML_ERROR_NO_MEMORY
;
4876 entity
->open
= XML_TRUE
;
4877 entity
->processed
= 0;
4878 openEntity
->next
= openInternalEntities
;
4879 openInternalEntities
= openEntity
;
4880 openEntity
->entity
= entity
;
4881 openEntity
->startTagLevel
= tagLevel
;
4882 openEntity
->betweenDecl
= betweenDecl
;
4883 openEntity
->internalEventPtr
= NULL
;
4884 openEntity
->internalEventEndPtr
= NULL
;
4885 textStart
= (char *)entity
->textPtr
;
4886 textEnd
= (char *)(entity
->textPtr
+ entity
->textLen
);
4889 if (entity
->is_param
) {
4890 int tok
= XmlPrologTok(internalEncoding
, textStart
, textEnd
, &next
);
4891 result
= doProlog(parser
, internalEncoding
, textStart
, textEnd
, tok
,
4892 next
, &next
, XML_FALSE
);
4895 #endif /* XML_DTD */
4896 result
= doContent(parser
, tagLevel
, internalEncoding
, textStart
,
4897 textEnd
, &next
, XML_FALSE
);
4899 if (result
== XML_ERROR_NONE
) {
4900 if (textEnd
!= next
&& ps_parsing
== XML_SUSPENDED
) {
4901 entity
->processed
= (int)(next
- textStart
);
4902 processor
= internalEntityProcessor
;
4905 entity
->open
= XML_FALSE
;
4906 openInternalEntities
= openEntity
->next
;
4907 /* put openEntity back in list of free instances */
4908 openEntity
->next
= freeInternalEntities
;
4909 freeInternalEntities
= openEntity
;
4915 static enum XML_Error PTRCALL
4916 internalEntityProcessor(XML_Parser parser
,
4919 const char **nextPtr
)
4922 const char *textStart
, *textEnd
;
4924 enum XML_Error result
;
4925 OPEN_INTERNAL_ENTITY
*openEntity
= openInternalEntities
;
4927 return XML_ERROR_UNEXPECTED_STATE
;
4929 entity
= openEntity
->entity
;
4930 textStart
= ((char *)entity
->textPtr
) + entity
->processed
;
4931 textEnd
= (char *)(entity
->textPtr
+ entity
->textLen
);
4934 if (entity
->is_param
) {
4935 int tok
= XmlPrologTok(internalEncoding
, textStart
, textEnd
, &next
);
4936 result
= doProlog(parser
, internalEncoding
, textStart
, textEnd
, tok
,
4937 next
, &next
, XML_FALSE
);
4940 #endif /* XML_DTD */
4941 result
= doContent(parser
, openEntity
->startTagLevel
, internalEncoding
,
4942 textStart
, textEnd
, &next
, XML_FALSE
);
4944 if (result
!= XML_ERROR_NONE
)
4946 else if (textEnd
!= next
&& ps_parsing
== XML_SUSPENDED
) {
4947 entity
->processed
= (int)(next
- (char *)entity
->textPtr
);
4951 entity
->open
= XML_FALSE
;
4952 openInternalEntities
= openEntity
->next
;
4953 /* put openEntity back in list of free instances */
4954 openEntity
->next
= freeInternalEntities
;
4955 freeInternalEntities
= openEntity
;
4959 if (entity
->is_param
) {
4961 processor
= prologProcessor
;
4962 tok
= XmlPrologTok(encoding
, s
, end
, &next
);
4963 return doProlog(parser
, encoding
, s
, end
, tok
, next
, nextPtr
,
4964 (XML_Bool
)!ps_finalBuffer
);
4967 #endif /* XML_DTD */
4969 processor
= contentProcessor
;
4970 /* see externalEntityContentProcessor vs contentProcessor */
4971 return doContent(parser
, parentParser
? 1 : 0, encoding
, s
, end
,
4972 nextPtr
, (XML_Bool
)!ps_finalBuffer
);
4976 static enum XML_Error PTRCALL
4977 errorProcessor(XML_Parser parser
,
4980 const char **nextPtr
)
4985 static enum XML_Error
4986 storeAttributeValue(XML_Parser parser
, const ENCODING
*enc
, XML_Bool isCdata
,
4987 const char *ptr
, const char *end
,
4990 enum XML_Error result
= appendAttributeValue(parser
, enc
, isCdata
, ptr
,
4994 if (!isCdata
&& poolLength(pool
) && poolLastChar(pool
) == 0x20)
4996 if (!poolAppendChar(pool
, XML_T('\0')))
4997 return XML_ERROR_NO_MEMORY
;
4998 return XML_ERROR_NONE
;
5001 static enum XML_Error
5002 appendAttributeValue(XML_Parser parser
, const ENCODING
*enc
, XML_Bool isCdata
,
5003 const char *ptr
, const char *end
,
5006 DTD
* const dtd
= _dtd
; /* save one level of indirection */
5009 int tok
= XmlAttributeValueTok(enc
, ptr
, end
, &next
);
5012 return XML_ERROR_NONE
;
5013 case XML_TOK_INVALID
:
5014 if (enc
== encoding
)
5016 return XML_ERROR_INVALID_TOKEN
;
5017 case XML_TOK_PARTIAL
:
5018 if (enc
== encoding
)
5020 return XML_ERROR_INVALID_TOKEN
;
5021 case XML_TOK_CHAR_REF
:
5023 XML_Char buf
[XML_ENCODE_MAX
];
5025 int n
= XmlCharRefNumber(enc
, ptr
);
5027 if (enc
== encoding
)
5029 return XML_ERROR_BAD_CHAR_REF
;
5032 && n
== 0x20 /* space */
5033 && (poolLength(pool
) == 0 || poolLastChar(pool
) == 0x20))
5035 n
= XmlEncode(n
, (ICHAR
*)buf
);
5037 if (enc
== encoding
)
5039 return XML_ERROR_BAD_CHAR_REF
;
5041 for (i
= 0; i
< n
; i
++) {
5042 if (!poolAppendChar(pool
, buf
[i
]))
5043 return XML_ERROR_NO_MEMORY
;
5047 case XML_TOK_DATA_CHARS
:
5048 if (!poolAppend(pool
, enc
, ptr
, next
))
5049 return XML_ERROR_NO_MEMORY
;
5051 case XML_TOK_TRAILING_CR
:
5052 next
= ptr
+ enc
->minBytesPerChar
;
5054 case XML_TOK_ATTRIBUTE_VALUE_S
:
5055 case XML_TOK_DATA_NEWLINE
:
5056 if (!isCdata
&& (poolLength(pool
) == 0 || poolLastChar(pool
) == 0x20))
5058 if (!poolAppendChar(pool
, 0x20))
5059 return XML_ERROR_NO_MEMORY
;
5061 case XML_TOK_ENTITY_REF
:
5063 const XML_Char
*name
;
5065 char checkEntityDecl
;
5066 XML_Char ch
= (XML_Char
) XmlPredefinedEntityName(enc
,
5067 ptr
+ enc
->minBytesPerChar
,
5068 next
- enc
->minBytesPerChar
);
5070 if (!poolAppendChar(pool
, ch
))
5071 return XML_ERROR_NO_MEMORY
;
5074 name
= poolStoreString(&temp2Pool
, enc
,
5075 ptr
+ enc
->minBytesPerChar
,
5076 next
- enc
->minBytesPerChar
);
5078 return XML_ERROR_NO_MEMORY
;
5079 entity
= (ENTITY
*)lookup(&dtd
->generalEntities
, name
, 0);
5080 poolDiscard(&temp2Pool
);
5081 /* First, determine if a check for an existing declaration is needed;
5082 if yes, check that the entity exists, and that it is internal.
5084 if (pool
== &dtd
->pool
) /* are we called from prolog? */
5087 prologState
.documentEntity
&&
5088 #endif /* XML_DTD */
5090 ? !openInternalEntities
5091 : !dtd
->hasParamEntityRefs
);
5092 else /* if (pool == &tempPool): we are called from content */
5093 checkEntityDecl
= !dtd
->hasParamEntityRefs
|| dtd
->standalone
;
5094 if (checkEntityDecl
) {
5096 return XML_ERROR_UNDEFINED_ENTITY
;
5097 else if (!entity
->is_internal
)
5098 return XML_ERROR_ENTITY_DECLARED_IN_PE
;
5101 /* Cannot report skipped entity here - see comments on
5102 skippedEntityHandler.
5103 if (skippedEntityHandler)
5104 skippedEntityHandler(handlerArg, name, 0);
5106 /* Cannot call the default handler because this would be
5107 out of sync with the call to the startElementHandler.
5108 if ((pool == &tempPool) && defaultHandler)
5109 reportDefault(parser, enc, ptr, next);
5111 /* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=35984) */
5115 return XML_ERROR_UNDEFINED_ENTITY
;
5117 /* END MOZILLA CHANGE */
5120 if (enc
== encoding
)
5122 return XML_ERROR_RECURSIVE_ENTITY_REF
;
5124 if (entity
->notation
) {
5125 if (enc
== encoding
)
5127 return XML_ERROR_BINARY_ENTITY_REF
;
5129 if (!entity
->textPtr
) {
5130 if (enc
== encoding
)
5132 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF
;
5135 enum XML_Error result
;
5136 const XML_Char
*textEnd
= entity
->textPtr
+ entity
->textLen
;
5137 entity
->open
= XML_TRUE
;
5138 result
= appendAttributeValue(parser
, internalEncoding
, isCdata
,
5139 (char *)entity
->textPtr
,
5140 (char *)textEnd
, pool
);
5141 entity
->open
= XML_FALSE
;
5148 if (enc
== encoding
)
5150 return XML_ERROR_UNEXPECTED_STATE
;
5157 static enum XML_Error
5158 storeEntityValue(XML_Parser parser
,
5159 const ENCODING
*enc
,
5160 const char *entityTextPtr
,
5161 const char *entityTextEnd
)
5163 DTD
* const dtd
= _dtd
; /* save one level of indirection */
5164 STRING_POOL
*pool
= &(dtd
->entityValuePool
);
5165 enum XML_Error result
= XML_ERROR_NONE
;
5167 int oldInEntityValue
= prologState
.inEntityValue
;
5168 prologState
.inEntityValue
= 1;
5169 #endif /* XML_DTD */
5170 /* never return Null for the value argument in EntityDeclHandler,
5171 since this would indicate an external entity; therefore we
5172 have to make sure that entityValuePool.start is not null */
5173 if (!pool
->blocks
) {
5174 if (!poolGrow(pool
))
5175 return XML_ERROR_NO_MEMORY
;
5180 int tok
= XmlEntityValueTok(enc
, entityTextPtr
, entityTextEnd
, &next
);
5182 case XML_TOK_PARAM_ENTITY_REF
:
5184 if (isParamEntity
|| enc
!= encoding
) {
5185 const XML_Char
*name
;
5187 name
= poolStoreString(&tempPool
, enc
,
5188 entityTextPtr
+ enc
->minBytesPerChar
,
5189 next
- enc
->minBytesPerChar
);
5191 result
= XML_ERROR_NO_MEMORY
;
5192 goto endEntityValue
;
5194 entity
= (ENTITY
*)lookup(&dtd
->paramEntities
, name
, 0);
5195 poolDiscard(&tempPool
);
5197 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5198 /* cannot report skipped entity here - see comments on
5199 skippedEntityHandler
5200 if (skippedEntityHandler)
5201 skippedEntityHandler(handlerArg, name, 0);
5203 dtd
->keepProcessing
= dtd
->standalone
;
5204 goto endEntityValue
;
5207 if (enc
== encoding
)
5208 eventPtr
= entityTextPtr
;
5209 result
= XML_ERROR_RECURSIVE_ENTITY_REF
;
5210 goto endEntityValue
;
5212 if (entity
->systemId
) {
5213 if (externalEntityRefHandler
) {
5214 dtd
->paramEntityRead
= XML_FALSE
;
5215 entity
->open
= XML_TRUE
;
5216 if (!externalEntityRefHandler(externalEntityRefHandlerArg
,
5220 entity
->publicId
)) {
5221 entity
->open
= XML_FALSE
;
5222 result
= XML_ERROR_EXTERNAL_ENTITY_HANDLING
;
5223 goto endEntityValue
;
5225 entity
->open
= XML_FALSE
;
5226 if (!dtd
->paramEntityRead
)
5227 dtd
->keepProcessing
= dtd
->standalone
;
5230 dtd
->keepProcessing
= dtd
->standalone
;
5233 entity
->open
= XML_TRUE
;
5234 result
= storeEntityValue(parser
,
5236 (char *)entity
->textPtr
,
5237 (char *)(entity
->textPtr
5238 + entity
->textLen
));
5239 entity
->open
= XML_FALSE
;
5241 goto endEntityValue
;
5245 #endif /* XML_DTD */
5246 /* In the internal subset, PE references are not legal
5247 within markup declarations, e.g entity values in this case. */
5248 eventPtr
= entityTextPtr
;
5249 result
= XML_ERROR_PARAM_ENTITY_REF
;
5250 goto endEntityValue
;
5252 result
= XML_ERROR_NONE
;
5253 goto endEntityValue
;
5254 case XML_TOK_ENTITY_REF
:
5255 case XML_TOK_DATA_CHARS
:
5256 if (!poolAppend(pool
, enc
, entityTextPtr
, next
)) {
5257 result
= XML_ERROR_NO_MEMORY
;
5258 goto endEntityValue
;
5261 case XML_TOK_TRAILING_CR
:
5262 next
= entityTextPtr
+ enc
->minBytesPerChar
;
5264 case XML_TOK_DATA_NEWLINE
:
5265 if (pool
->end
== pool
->ptr
&& !poolGrow(pool
)) {
5266 result
= XML_ERROR_NO_MEMORY
;
5267 goto endEntityValue
;
5269 *(pool
->ptr
)++ = 0xA;
5271 case XML_TOK_CHAR_REF
:
5273 XML_Char buf
[XML_ENCODE_MAX
];
5275 int n
= XmlCharRefNumber(enc
, entityTextPtr
);
5277 if (enc
== encoding
)
5278 eventPtr
= entityTextPtr
;
5279 result
= XML_ERROR_BAD_CHAR_REF
;
5280 goto endEntityValue
;
5282 n
= XmlEncode(n
, (ICHAR
*)buf
);
5284 if (enc
== encoding
)
5285 eventPtr
= entityTextPtr
;
5286 result
= XML_ERROR_BAD_CHAR_REF
;
5287 goto endEntityValue
;
5289 for (i
= 0; i
< n
; i
++) {
5290 if (pool
->end
== pool
->ptr
&& !poolGrow(pool
)) {
5291 result
= XML_ERROR_NO_MEMORY
;
5292 goto endEntityValue
;
5294 *(pool
->ptr
)++ = buf
[i
];
5298 case XML_TOK_PARTIAL
:
5299 if (enc
== encoding
)
5300 eventPtr
= entityTextPtr
;
5301 result
= XML_ERROR_INVALID_TOKEN
;
5302 goto endEntityValue
;
5303 case XML_TOK_INVALID
:
5304 if (enc
== encoding
)
5306 result
= XML_ERROR_INVALID_TOKEN
;
5307 goto endEntityValue
;
5309 if (enc
== encoding
)
5310 eventPtr
= entityTextPtr
;
5311 result
= XML_ERROR_UNEXPECTED_STATE
;
5312 goto endEntityValue
;
5314 entityTextPtr
= next
;
5318 prologState
.inEntityValue
= oldInEntityValue
;
5319 #endif /* XML_DTD */
5323 static void FASTCALL
5324 normalizeLines(XML_Char
*s
)
5328 if (*s
== XML_T('\0'))
5347 reportProcessingInstruction(XML_Parser parser
, const ENCODING
*enc
,
5348 const char *start
, const char *end
)
5350 const XML_Char
*target
;
5353 if (!processingInstructionHandler
) {
5355 reportDefault(parser
, enc
, start
, end
);
5358 start
+= enc
->minBytesPerChar
* 2;
5359 tem
= start
+ XmlNameLength(enc
, start
);
5360 target
= poolStoreString(&tempPool
, enc
, start
, tem
);
5363 poolFinish(&tempPool
);
5364 data
= poolStoreString(&tempPool
, enc
,
5366 end
- enc
->minBytesPerChar
*2);
5369 normalizeLines(data
);
5370 processingInstructionHandler(handlerArg
, target
, data
);
5371 poolClear(&tempPool
);
5376 reportComment(XML_Parser parser
, const ENCODING
*enc
,
5377 const char *start
, const char *end
)
5380 if (!commentHandler
) {
5382 reportDefault(parser
, enc
, start
, end
);
5385 data
= poolStoreString(&tempPool
,
5387 start
+ enc
->minBytesPerChar
* 4,
5388 end
- enc
->minBytesPerChar
* 3);
5391 normalizeLines(data
);
5392 commentHandler(handlerArg
, data
);
5393 poolClear(&tempPool
);
5398 reportDefault(XML_Parser parser
, const ENCODING
*enc
,
5399 const char *s
, const char *end
)
5401 if (MUST_CONVERT(enc
, s
)) {
5402 const char **eventPP
;
5403 const char **eventEndPP
;
5404 if (enc
== encoding
) {
5405 eventPP
= &eventPtr
;
5406 eventEndPP
= &eventEndPtr
;
5409 eventPP
= &(openInternalEntities
->internalEventPtr
);
5410 eventEndPP
= &(openInternalEntities
->internalEventEndPtr
);
5413 ICHAR
*dataPtr
= (ICHAR
*)dataBuf
;
5414 XmlConvert(enc
, &s
, end
, &dataPtr
, (ICHAR
*)dataBufEnd
);
5416 defaultHandler(handlerArg
, dataBuf
, (int)(dataPtr
- (ICHAR
*)dataBuf
));
5421 defaultHandler(handlerArg
, (XML_Char
*)s
, (int)((XML_Char
*)end
- (XML_Char
*)s
));
5426 defineAttribute(ELEMENT_TYPE
*type
, ATTRIBUTE_ID
*attId
, XML_Bool isCdata
,
5427 XML_Bool isId
, const XML_Char
*value
, XML_Parser parser
)
5429 DEFAULT_ATTRIBUTE
*att
;
5430 if (value
|| isId
) {
5431 /* The handling of default attributes gets messed up if we have
5432 a default which duplicates a non-default. */
5434 for (i
= 0; i
< type
->nDefaultAtts
; i
++)
5435 if (attId
== type
->defaultAtts
[i
].id
)
5437 if (isId
&& !type
->idAtt
&& !attId
->xmlns
)
5438 type
->idAtt
= attId
;
5440 if (type
->nDefaultAtts
== type
->allocDefaultAtts
) {
5441 if (type
->allocDefaultAtts
== 0) {
5442 type
->allocDefaultAtts
= 8;
5443 type
->defaultAtts
= (DEFAULT_ATTRIBUTE
*)MALLOC(type
->allocDefaultAtts
5444 * sizeof(DEFAULT_ATTRIBUTE
));
5445 if (!type
->defaultAtts
)
5449 DEFAULT_ATTRIBUTE
*temp
;
5450 int count
= type
->allocDefaultAtts
* 2;
5451 temp
= (DEFAULT_ATTRIBUTE
*)
5452 REALLOC(type
->defaultAtts
, (count
* sizeof(DEFAULT_ATTRIBUTE
)));
5455 type
->allocDefaultAtts
= count
;
5456 type
->defaultAtts
= temp
;
5459 att
= type
->defaultAtts
+ type
->nDefaultAtts
;
5462 att
->isCdata
= isCdata
;
5464 attId
->maybeTokenized
= XML_TRUE
;
5465 type
->nDefaultAtts
+= 1;
5470 setElementTypePrefix(XML_Parser parser
, ELEMENT_TYPE
*elementType
)
5472 DTD
* const dtd
= _dtd
; /* save one level of indirection */
5473 const XML_Char
*name
;
5474 for (name
= elementType
->name
; *name
; name
++) {
5475 if (*name
== XML_T(':')) {
5478 for (s
= elementType
->name
; s
!= name
; s
++) {
5479 if (!poolAppendChar(&dtd
->pool
, *s
))
5482 if (!poolAppendChar(&dtd
->pool
, XML_T('\0')))
5484 prefix
= (PREFIX
*)lookup(&dtd
->prefixes
, poolStart(&dtd
->pool
),
5488 if (prefix
->name
== poolStart(&dtd
->pool
))
5489 poolFinish(&dtd
->pool
);
5491 poolDiscard(&dtd
->pool
);
5492 elementType
->prefix
= prefix
;
5499 static ATTRIBUTE_ID
*
5500 getAttributeId(XML_Parser parser
, const ENCODING
*enc
,
5501 const char *start
, const char *end
)
5503 DTD
* const dtd
= _dtd
; /* save one level of indirection */
5505 const XML_Char
*name
;
5506 if (!poolAppendChar(&dtd
->pool
, XML_T('\0')))
5508 name
= poolStoreString(&dtd
->pool
, enc
, start
, end
);
5511 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
5513 id
= (ATTRIBUTE_ID
*)lookup(&dtd
->attributeIds
, name
, sizeof(ATTRIBUTE_ID
));
5516 if (id
->name
!= name
)
5517 poolDiscard(&dtd
->pool
);
5519 poolFinish(&dtd
->pool
);
5522 else if (name
[0] == XML_T('x')
5523 && name
[1] == XML_T('m')
5524 && name
[2] == XML_T('l')
5525 && name
[3] == XML_T('n')
5526 && name
[4] == XML_T('s')
5527 && (name
[5] == XML_T('\0') || name
[5] == XML_T(':'))) {
5528 if (name
[5] == XML_T('\0'))
5529 id
->prefix
= &dtd
->defaultPrefix
;
5531 id
->prefix
= (PREFIX
*)lookup(&dtd
->prefixes
, name
+ 6, sizeof(PREFIX
));
5532 id
->xmlns
= XML_TRUE
;
5536 for (i
= 0; name
[i
]; i
++) {
5537 /* attributes without prefix are *not* in the default namespace */
5538 if (name
[i
] == XML_T(':')) {
5540 for (j
= 0; j
< i
; j
++) {
5541 if (!poolAppendChar(&dtd
->pool
, name
[j
]))
5544 if (!poolAppendChar(&dtd
->pool
, XML_T('\0')))
5546 id
->prefix
= (PREFIX
*)lookup(&dtd
->prefixes
, poolStart(&dtd
->pool
),
5548 if (id
->prefix
->name
== poolStart(&dtd
->pool
))
5549 poolFinish(&dtd
->pool
);
5551 poolDiscard(&dtd
->pool
);
5560 #define CONTEXT_SEP XML_T('\f')
5562 static const XML_Char
*
5563 getContext(XML_Parser parser
)
5565 DTD
* const dtd
= _dtd
; /* save one level of indirection */
5566 HASH_TABLE_ITER iter
;
5567 XML_Bool needSep
= XML_FALSE
;
5569 if (dtd
->defaultPrefix
.binding
) {
5572 if (!poolAppendChar(&tempPool
, XML_T('=')))
5574 len
= dtd
->defaultPrefix
.binding
->uriLen
;
5575 if (namespaceSeparator
)
5577 for (i
= 0; i
< len
; i
++)
5578 if (!poolAppendChar(&tempPool
, dtd
->defaultPrefix
.binding
->uri
[i
]))
5583 hashTableIterInit(&iter
, &(dtd
->prefixes
));
5588 PREFIX
*prefix
= (PREFIX
*)hashTableIterNext(&iter
);
5591 if (!prefix
->binding
)
5593 if (needSep
&& !poolAppendChar(&tempPool
, CONTEXT_SEP
))
5595 for (s
= prefix
->name
; *s
; s
++)
5596 if (!poolAppendChar(&tempPool
, *s
))
5598 if (!poolAppendChar(&tempPool
, XML_T('=')))
5600 len
= prefix
->binding
->uriLen
;
5601 if (namespaceSeparator
)
5603 for (i
= 0; i
< len
; i
++)
5604 if (!poolAppendChar(&tempPool
, prefix
->binding
->uri
[i
]))
5610 hashTableIterInit(&iter
, &(dtd
->generalEntities
));
5613 ENTITY
*e
= (ENTITY
*)hashTableIterNext(&iter
);
5618 if (needSep
&& !poolAppendChar(&tempPool
, CONTEXT_SEP
))
5620 for (s
= e
->name
; *s
; s
++)
5621 if (!poolAppendChar(&tempPool
, *s
))
5626 if (!poolAppendChar(&tempPool
, XML_T('\0')))
5628 return tempPool
.start
;
5632 setContext(XML_Parser parser
, const XML_Char
*context
)
5634 DTD
* const dtd
= _dtd
; /* save one level of indirection */
5635 const XML_Char
*s
= context
;
5637 while (*context
!= XML_T('\0')) {
5638 if (*s
== CONTEXT_SEP
|| *s
== XML_T('\0')) {
5640 if (!poolAppendChar(&tempPool
, XML_T('\0')))
5642 e
= (ENTITY
*)lookup(&dtd
->generalEntities
, poolStart(&tempPool
), 0);
5645 if (*s
!= XML_T('\0'))
5648 poolDiscard(&tempPool
);
5650 else if (*s
== XML_T('=')) {
5652 if (poolLength(&tempPool
) == 0)
5653 prefix
= &dtd
->defaultPrefix
;
5655 if (!poolAppendChar(&tempPool
, XML_T('\0')))
5657 prefix
= (PREFIX
*)lookup(&dtd
->prefixes
, poolStart(&tempPool
),
5661 if (prefix
->name
== poolStart(&tempPool
)) {
5662 prefix
->name
= poolCopyString(&dtd
->pool
, prefix
->name
);
5666 poolDiscard(&tempPool
);
5668 for (context
= s
+ 1;
5669 *context
!= CONTEXT_SEP
&& *context
!= XML_T('\0');
5671 if (!poolAppendChar(&tempPool
, *context
))
5673 if (!poolAppendChar(&tempPool
, XML_T('\0')))
5675 if (addBinding(parser
, prefix
, NULL
, poolStart(&tempPool
),
5676 &inheritedBindings
) != XML_ERROR_NONE
)
5678 poolDiscard(&tempPool
);
5679 if (*context
!= XML_T('\0'))
5684 if (!poolAppendChar(&tempPool
, *s
))
5692 static void FASTCALL
5693 normalizePublicId(XML_Char
*publicId
)
5695 XML_Char
*p
= publicId
;
5697 for (s
= publicId
; *s
; s
++) {
5702 if (p
!= publicId
&& p
[-1] != 0x20)
5709 if (p
!= publicId
&& p
[-1] == 0x20)
5715 dtdCreate(const XML_Memory_Handling_Suite
*ms
)
5717 DTD
*p
= (DTD
*)ms
->malloc_fcn(sizeof(DTD
));
5720 poolInit(&(p
->pool
), ms
);
5721 poolInit(&(p
->entityValuePool
), ms
);
5722 hashTableInit(&(p
->generalEntities
), ms
);
5723 hashTableInit(&(p
->elementTypes
), ms
);
5724 hashTableInit(&(p
->attributeIds
), ms
);
5725 hashTableInit(&(p
->prefixes
), ms
);
5727 p
->paramEntityRead
= XML_FALSE
;
5728 hashTableInit(&(p
->paramEntities
), ms
);
5729 #endif /* XML_DTD */
5730 p
->defaultPrefix
.name
= NULL
;
5731 p
->defaultPrefix
.binding
= NULL
;
5733 p
->in_eldecl
= XML_FALSE
;
5734 p
->scaffIndex
= NULL
;
5739 p
->contentStringLen
= 0;
5741 p
->keepProcessing
= XML_TRUE
;
5742 p
->hasParamEntityRefs
= XML_FALSE
;
5743 p
->standalone
= XML_FALSE
;
5748 dtdReset(DTD
*p
, const XML_Memory_Handling_Suite
*ms
)
5750 HASH_TABLE_ITER iter
;
5751 hashTableIterInit(&iter
, &(p
->elementTypes
));
5753 ELEMENT_TYPE
*e
= (ELEMENT_TYPE
*)hashTableIterNext(&iter
);
5756 if (e
->allocDefaultAtts
!= 0)
5757 ms
->free_fcn(e
->defaultAtts
);
5759 hashTableClear(&(p
->generalEntities
));
5761 p
->paramEntityRead
= XML_FALSE
;
5762 hashTableClear(&(p
->paramEntities
));
5763 #endif /* XML_DTD */
5764 hashTableClear(&(p
->elementTypes
));
5765 hashTableClear(&(p
->attributeIds
));
5766 hashTableClear(&(p
->prefixes
));
5767 poolClear(&(p
->pool
));
5768 poolClear(&(p
->entityValuePool
));
5769 p
->defaultPrefix
.name
= NULL
;
5770 p
->defaultPrefix
.binding
= NULL
;
5772 p
->in_eldecl
= XML_FALSE
;
5774 ms
->free_fcn(p
->scaffIndex
);
5775 p
->scaffIndex
= NULL
;
5776 ms
->free_fcn(p
->scaffold
);
5782 p
->contentStringLen
= 0;
5784 p
->keepProcessing
= XML_TRUE
;
5785 p
->hasParamEntityRefs
= XML_FALSE
;
5786 p
->standalone
= XML_FALSE
;
5790 dtdDestroy(DTD
*p
, XML_Bool isDocEntity
, const XML_Memory_Handling_Suite
*ms
)
5792 HASH_TABLE_ITER iter
;
5793 hashTableIterInit(&iter
, &(p
->elementTypes
));
5795 ELEMENT_TYPE
*e
= (ELEMENT_TYPE
*)hashTableIterNext(&iter
);
5798 if (e
->allocDefaultAtts
!= 0)
5799 ms
->free_fcn(e
->defaultAtts
);
5801 hashTableDestroy(&(p
->generalEntities
));
5803 hashTableDestroy(&(p
->paramEntities
));
5804 #endif /* XML_DTD */
5805 hashTableDestroy(&(p
->elementTypes
));
5806 hashTableDestroy(&(p
->attributeIds
));
5807 hashTableDestroy(&(p
->prefixes
));
5808 poolDestroy(&(p
->pool
));
5809 poolDestroy(&(p
->entityValuePool
));
5811 ms
->free_fcn(p
->scaffIndex
);
5812 ms
->free_fcn(p
->scaffold
);
5817 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
5818 The new DTD has already been initialized.
5821 dtdCopy(DTD
*newDtd
, const DTD
*oldDtd
, const XML_Memory_Handling_Suite
*ms
)
5823 HASH_TABLE_ITER iter
;
5825 /* Copy the prefix table. */
5827 hashTableIterInit(&iter
, &(oldDtd
->prefixes
));
5829 const XML_Char
*name
;
5830 const PREFIX
*oldP
= (PREFIX
*)hashTableIterNext(&iter
);
5833 name
= poolCopyString(&(newDtd
->pool
), oldP
->name
);
5836 if (!lookup(&(newDtd
->prefixes
), name
, sizeof(PREFIX
)))
5840 hashTableIterInit(&iter
, &(oldDtd
->attributeIds
));
5842 /* Copy the attribute id table. */
5846 const XML_Char
*name
;
5847 const ATTRIBUTE_ID
*oldA
= (ATTRIBUTE_ID
*)hashTableIterNext(&iter
);
5851 /* Remember to allocate the scratch byte before the name. */
5852 if (!poolAppendChar(&(newDtd
->pool
), XML_T('\0')))
5854 name
= poolCopyString(&(newDtd
->pool
), oldA
->name
);
5858 newA
= (ATTRIBUTE_ID
*)lookup(&(newDtd
->attributeIds
), name
,
5859 sizeof(ATTRIBUTE_ID
));
5862 newA
->maybeTokenized
= oldA
->maybeTokenized
;
5864 newA
->xmlns
= oldA
->xmlns
;
5865 if (oldA
->prefix
== &oldDtd
->defaultPrefix
)
5866 newA
->prefix
= &newDtd
->defaultPrefix
;
5868 newA
->prefix
= (PREFIX
*)lookup(&(newDtd
->prefixes
),
5869 oldA
->prefix
->name
, 0);
5873 /* Copy the element type table. */
5875 hashTableIterInit(&iter
, &(oldDtd
->elementTypes
));
5880 const XML_Char
*name
;
5881 const ELEMENT_TYPE
*oldE
= (ELEMENT_TYPE
*)hashTableIterNext(&iter
);
5884 name
= poolCopyString(&(newDtd
->pool
), oldE
->name
);
5887 newE
= (ELEMENT_TYPE
*)lookup(&(newDtd
->elementTypes
), name
,
5888 sizeof(ELEMENT_TYPE
));
5891 if (oldE
->nDefaultAtts
) {
5892 newE
->defaultAtts
= (DEFAULT_ATTRIBUTE
*)
5893 ms
->malloc_fcn(oldE
->nDefaultAtts
* sizeof(DEFAULT_ATTRIBUTE
));
5894 if (!newE
->defaultAtts
) {
5900 newE
->idAtt
= (ATTRIBUTE_ID
*)
5901 lookup(&(newDtd
->attributeIds
), oldE
->idAtt
->name
, 0);
5902 newE
->allocDefaultAtts
= newE
->nDefaultAtts
= oldE
->nDefaultAtts
;
5904 newE
->prefix
= (PREFIX
*)lookup(&(newDtd
->prefixes
),
5905 oldE
->prefix
->name
, 0);
5906 for (i
= 0; i
< newE
->nDefaultAtts
; i
++) {
5907 newE
->defaultAtts
[i
].id
= (ATTRIBUTE_ID
*)
5908 lookup(&(newDtd
->attributeIds
), oldE
->defaultAtts
[i
].id
->name
, 0);
5909 newE
->defaultAtts
[i
].isCdata
= oldE
->defaultAtts
[i
].isCdata
;
5910 if (oldE
->defaultAtts
[i
].value
) {
5911 newE
->defaultAtts
[i
].value
5912 = poolCopyString(&(newDtd
->pool
), oldE
->defaultAtts
[i
].value
);
5913 if (!newE
->defaultAtts
[i
].value
)
5917 newE
->defaultAtts
[i
].value
= NULL
;
5921 /* Copy the entity tables. */
5922 if (!copyEntityTable(&(newDtd
->generalEntities
),
5924 &(oldDtd
->generalEntities
)))
5928 if (!copyEntityTable(&(newDtd
->paramEntities
),
5930 &(oldDtd
->paramEntities
)))
5932 newDtd
->paramEntityRead
= oldDtd
->paramEntityRead
;
5933 #endif /* XML_DTD */
5935 newDtd
->keepProcessing
= oldDtd
->keepProcessing
;
5936 newDtd
->hasParamEntityRefs
= oldDtd
->hasParamEntityRefs
;
5937 newDtd
->standalone
= oldDtd
->standalone
;
5939 /* Don't want deep copying for scaffolding */
5940 newDtd
->in_eldecl
= oldDtd
->in_eldecl
;
5941 newDtd
->scaffold
= oldDtd
->scaffold
;
5942 newDtd
->contentStringLen
= oldDtd
->contentStringLen
;
5943 newDtd
->scaffSize
= oldDtd
->scaffSize
;
5944 newDtd
->scaffLevel
= oldDtd
->scaffLevel
;
5945 newDtd
->scaffIndex
= oldDtd
->scaffIndex
;
5951 copyEntityTable(HASH_TABLE
*newTable
,
5952 STRING_POOL
*newPool
,
5953 const HASH_TABLE
*oldTable
)
5955 HASH_TABLE_ITER iter
;
5956 const XML_Char
*cachedOldBase
= NULL
;
5957 const XML_Char
*cachedNewBase
= NULL
;
5959 hashTableIterInit(&iter
, oldTable
);
5963 const XML_Char
*name
;
5964 const ENTITY
*oldE
= (ENTITY
*)hashTableIterNext(&iter
);
5967 name
= poolCopyString(newPool
, oldE
->name
);
5970 newE
= (ENTITY
*)lookup(newTable
, name
, sizeof(ENTITY
));
5973 if (oldE
->systemId
) {
5974 const XML_Char
*tem
= poolCopyString(newPool
, oldE
->systemId
);
5977 newE
->systemId
= tem
;
5979 if (oldE
->base
== cachedOldBase
)
5980 newE
->base
= cachedNewBase
;
5982 cachedOldBase
= oldE
->base
;
5983 tem
= poolCopyString(newPool
, cachedOldBase
);
5986 cachedNewBase
= newE
->base
= tem
;
5989 if (oldE
->publicId
) {
5990 tem
= poolCopyString(newPool
, oldE
->publicId
);
5993 newE
->publicId
= tem
;
5997 const XML_Char
*tem
= poolCopyStringN(newPool
, oldE
->textPtr
,
6001 newE
->textPtr
= tem
;
6002 newE
->textLen
= oldE
->textLen
;
6004 if (oldE
->notation
) {
6005 const XML_Char
*tem
= poolCopyString(newPool
, oldE
->notation
);
6008 newE
->notation
= tem
;
6010 newE
->is_param
= oldE
->is_param
;
6011 newE
->is_internal
= oldE
->is_internal
;
6016 #define INIT_POWER 6
6018 static XML_Bool FASTCALL
6019 keyeq(KEY s1
, KEY s2
)
6021 for (; *s1
== *s2
; s1
++, s2
++)
6027 static unsigned long FASTCALL
6030 unsigned long h
= 0;
6032 h
= CHAR_HASH(h
, *s
++);
6037 lookup(HASH_TABLE
*table
, KEY name
, size_t createSize
)
6040 if (table
->size
== 0) {
6044 table
->power
= INIT_POWER
;
6045 /* table->size is a power of 2 */
6046 table
->size
= (size_t)1 << INIT_POWER
;
6047 tsize
= table
->size
* sizeof(NAMED
*);
6048 table
->v
= (NAMED
**)table
->mem
->malloc_fcn(tsize
);
6053 memset(table
->v
, 0, tsize
);
6054 i
= hash(name
) & ((unsigned long)table
->size
- 1);
6057 unsigned long h
= hash(name
);
6058 unsigned long mask
= (unsigned long)table
->size
- 1;
6059 unsigned char step
= 0;
6061 while (table
->v
[i
]) {
6062 if (keyeq(name
, table
->v
[i
]->name
))
6065 step
= PROBE_STEP(h
, mask
, table
->power
);
6066 i
< step
? (i
+= table
->size
- step
) : (i
-= step
);
6071 /* check for overflow (table is half full) */
6072 if (table
->used
>> (table
->power
- 1)) {
6073 unsigned char newPower
= table
->power
+ 1;
6074 size_t newSize
= (size_t)1 << newPower
;
6075 unsigned long newMask
= (unsigned long)newSize
- 1;
6076 size_t tsize
= newSize
* sizeof(NAMED
*);
6077 NAMED
**newV
= (NAMED
**)table
->mem
->malloc_fcn(tsize
);
6080 memset(newV
, 0, tsize
);
6081 for (i
= 0; i
< table
->size
; i
++)
6083 unsigned long newHash
= hash(table
->v
[i
]->name
);
6084 size_t j
= newHash
& newMask
;
6088 step
= PROBE_STEP(newHash
, newMask
, newPower
);
6089 j
< step
? (j
+= newSize
- step
) : (j
-= step
);
6091 newV
[j
] = table
->v
[i
];
6093 table
->mem
->free_fcn(table
->v
);
6095 table
->power
= newPower
;
6096 table
->size
= newSize
;
6099 while (table
->v
[i
]) {
6101 step
= PROBE_STEP(h
, newMask
, newPower
);
6102 i
< step
? (i
+= newSize
- step
) : (i
-= step
);
6106 table
->v
[i
] = (NAMED
*)table
->mem
->malloc_fcn(createSize
);
6109 memset(table
->v
[i
], 0, createSize
);
6110 table
->v
[i
]->name
= name
;
6115 static void FASTCALL
6116 hashTableClear(HASH_TABLE
*table
)
6119 for (i
= 0; i
< table
->size
; i
++) {
6120 table
->mem
->free_fcn(table
->v
[i
]);
6126 static void FASTCALL
6127 hashTableDestroy(HASH_TABLE
*table
)
6130 for (i
= 0; i
< table
->size
; i
++)
6131 table
->mem
->free_fcn(table
->v
[i
]);
6132 table
->mem
->free_fcn(table
->v
);
6135 static void FASTCALL
6136 hashTableInit(HASH_TABLE
*p
, const XML_Memory_Handling_Suite
*ms
)
6145 static void FASTCALL
6146 hashTableIterInit(HASH_TABLE_ITER
*iter
, const HASH_TABLE
*table
)
6149 iter
->end
= iter
->p
+ table
->size
;
6152 static NAMED
* FASTCALL
6153 hashTableIterNext(HASH_TABLE_ITER
*iter
)
6155 while (iter
->p
!= iter
->end
) {
6156 NAMED
*tem
= *(iter
->p
)++;
6163 static void FASTCALL
6164 poolInit(STRING_POOL
*pool
, const XML_Memory_Handling_Suite
*ms
)
6166 pool
->blocks
= NULL
;
6167 pool
->freeBlocks
= NULL
;
6174 static void FASTCALL
6175 poolClear(STRING_POOL
*pool
)
6177 if (!pool
->freeBlocks
)
6178 pool
->freeBlocks
= pool
->blocks
;
6180 BLOCK
*p
= pool
->blocks
;
6182 BLOCK
*tem
= p
->next
;
6183 p
->next
= pool
->freeBlocks
;
6184 pool
->freeBlocks
= p
;
6188 pool
->blocks
= NULL
;
6194 static void FASTCALL
6195 poolDestroy(STRING_POOL
*pool
)
6197 BLOCK
*p
= pool
->blocks
;
6199 BLOCK
*tem
= p
->next
;
6200 pool
->mem
->free_fcn(p
);
6203 p
= pool
->freeBlocks
;
6205 BLOCK
*tem
= p
->next
;
6206 pool
->mem
->free_fcn(p
);
6212 poolAppend(STRING_POOL
*pool
, const ENCODING
*enc
,
6213 const char *ptr
, const char *end
)
6215 if (!pool
->ptr
&& !poolGrow(pool
))
6218 XmlConvert(enc
, &ptr
, end
, (ICHAR
**)&(pool
->ptr
), (ICHAR
*)pool
->end
);
6221 if (!poolGrow(pool
))
6227 static const XML_Char
* FASTCALL
6228 poolCopyString(STRING_POOL
*pool
, const XML_Char
*s
)
6231 if (!poolAppendChar(pool
, *s
))
6239 static const XML_Char
*
6240 poolCopyStringN(STRING_POOL
*pool
, const XML_Char
*s
, int n
)
6242 if (!pool
->ptr
&& !poolGrow(pool
))
6244 for (; n
> 0; --n
, s
++) {
6245 if (!poolAppendChar(pool
, *s
))
6253 static const XML_Char
* FASTCALL
6254 poolAppendString(STRING_POOL
*pool
, const XML_Char
*s
)
6257 if (!poolAppendChar(pool
, *s
))
6265 poolStoreString(STRING_POOL
*pool
, const ENCODING
*enc
,
6266 const char *ptr
, const char *end
)
6268 if (!poolAppend(pool
, enc
, ptr
, end
))
6270 if (pool
->ptr
== pool
->end
&& !poolGrow(pool
))
6276 static XML_Bool FASTCALL
6277 poolGrow(STRING_POOL
*pool
)
6279 if (pool
->freeBlocks
) {
6280 if (pool
->start
== 0) {
6281 pool
->blocks
= pool
->freeBlocks
;
6282 pool
->freeBlocks
= pool
->freeBlocks
->next
;
6283 pool
->blocks
->next
= NULL
;
6284 pool
->start
= pool
->blocks
->s
;
6285 pool
->end
= pool
->start
+ pool
->blocks
->size
;
6286 pool
->ptr
= pool
->start
;
6289 if (pool
->end
- pool
->start
< pool
->freeBlocks
->size
) {
6290 BLOCK
*tem
= pool
->freeBlocks
->next
;
6291 pool
->freeBlocks
->next
= pool
->blocks
;
6292 pool
->blocks
= pool
->freeBlocks
;
6293 pool
->freeBlocks
= tem
;
6294 memcpy(pool
->blocks
->s
, pool
->start
,
6295 (pool
->end
- pool
->start
) * sizeof(XML_Char
));
6296 pool
->ptr
= pool
->blocks
->s
+ (pool
->ptr
- pool
->start
);
6297 pool
->start
= pool
->blocks
->s
;
6298 pool
->end
= pool
->start
+ pool
->blocks
->size
;
6302 if (pool
->blocks
&& pool
->start
== pool
->blocks
->s
) {
6303 int blockSize
= (int)(pool
->end
- pool
->start
)*2;
6304 pool
->blocks
= (BLOCK
*)
6305 pool
->mem
->realloc_fcn(pool
->blocks
,
6307 + blockSize
* sizeof(XML_Char
)));
6308 if (pool
->blocks
== NULL
)
6310 pool
->blocks
->size
= blockSize
;
6311 pool
->ptr
= pool
->blocks
->s
+ (pool
->ptr
- pool
->start
);
6312 pool
->start
= pool
->blocks
->s
;
6313 pool
->end
= pool
->start
+ blockSize
;
6317 int blockSize
= (int)(pool
->end
- pool
->start
);
6318 if (blockSize
< INIT_BLOCK_SIZE
)
6319 blockSize
= INIT_BLOCK_SIZE
;
6322 tem
= (BLOCK
*)pool
->mem
->malloc_fcn(offsetof(BLOCK
, s
)
6323 + blockSize
* sizeof(XML_Char
));
6326 tem
->size
= blockSize
;
6327 tem
->next
= pool
->blocks
;
6329 if (pool
->ptr
!= pool
->start
)
6330 memcpy(tem
->s
, pool
->start
,
6331 (pool
->ptr
- pool
->start
) * sizeof(XML_Char
));
6332 pool
->ptr
= tem
->s
+ (pool
->ptr
- pool
->start
);
6333 pool
->start
= tem
->s
;
6334 pool
->end
= tem
->s
+ blockSize
;
6340 nextScaffoldPart(XML_Parser parser
)
6342 DTD
* const dtd
= _dtd
; /* save one level of indirection */
6343 CONTENT_SCAFFOLD
* me
;
6346 if (!dtd
->scaffIndex
) {
6347 dtd
->scaffIndex
= (int *)MALLOC(groupSize
* sizeof(int));
6348 if (!dtd
->scaffIndex
)
6350 dtd
->scaffIndex
[0] = 0;
6353 if (dtd
->scaffCount
>= dtd
->scaffSize
) {
6354 CONTENT_SCAFFOLD
*temp
;
6355 if (dtd
->scaffold
) {
6356 temp
= (CONTENT_SCAFFOLD
*)
6357 REALLOC(dtd
->scaffold
, dtd
->scaffSize
* 2 * sizeof(CONTENT_SCAFFOLD
));
6360 dtd
->scaffSize
*= 2;
6363 temp
= (CONTENT_SCAFFOLD
*)MALLOC(INIT_SCAFFOLD_ELEMENTS
6364 * sizeof(CONTENT_SCAFFOLD
));
6367 dtd
->scaffSize
= INIT_SCAFFOLD_ELEMENTS
;
6369 dtd
->scaffold
= temp
;
6371 next
= dtd
->scaffCount
++;
6372 me
= &dtd
->scaffold
[next
];
6373 if (dtd
->scaffLevel
) {
6374 CONTENT_SCAFFOLD
*parent
= &dtd
->scaffold
[dtd
->scaffIndex
[dtd
->scaffLevel
-1]];
6375 if (parent
->lastchild
) {
6376 dtd
->scaffold
[parent
->lastchild
].nextsib
= next
;
6378 if (!parent
->childcnt
)
6379 parent
->firstchild
= next
;
6380 parent
->lastchild
= next
;
6383 me
->firstchild
= me
->lastchild
= me
->childcnt
= me
->nextsib
= 0;
6388 build_node(XML_Parser parser
,
6391 XML_Content
**contpos
,
6394 DTD
* const dtd
= _dtd
; /* save one level of indirection */
6395 dest
->type
= dtd
->scaffold
[src_node
].type
;
6396 dest
->quant
= dtd
->scaffold
[src_node
].quant
;
6397 if (dest
->type
== XML_CTYPE_NAME
) {
6398 const XML_Char
*src
;
6399 dest
->name
= *strpos
;
6400 src
= dtd
->scaffold
[src_node
].name
;
6402 *(*strpos
)++ = *src
;
6407 dest
->numchildren
= 0;
6408 dest
->children
= NULL
;
6413 dest
->numchildren
= dtd
->scaffold
[src_node
].childcnt
;
6414 dest
->children
= *contpos
;
6415 *contpos
+= dest
->numchildren
;
6416 for (i
= 0, cn
= dtd
->scaffold
[src_node
].firstchild
;
6417 i
< dest
->numchildren
;
6418 i
++, cn
= dtd
->scaffold
[cn
].nextsib
) {
6419 build_node(parser
, cn
, &(dest
->children
[i
]), contpos
, strpos
);
6425 static XML_Content
*
6426 build_model (XML_Parser parser
)
6428 DTD
* const dtd
= _dtd
; /* save one level of indirection */
6432 int allocsize
= (dtd
->scaffCount
* sizeof(XML_Content
)
6433 + (dtd
->contentStringLen
* sizeof(XML_Char
)));
6435 ret
= (XML_Content
*)MALLOC(allocsize
);
6439 str
= (XML_Char
*) (&ret
[dtd
->scaffCount
]);
6442 build_node(parser
, 0, ret
, &cpos
, &str
);
6446 static ELEMENT_TYPE
*
6447 getElementType(XML_Parser parser
,
6448 const ENCODING
*enc
,
6452 DTD
* const dtd
= _dtd
; /* save one level of indirection */
6453 const XML_Char
*name
= poolStoreString(&dtd
->pool
, enc
, ptr
, end
);
6458 ret
= (ELEMENT_TYPE
*) lookup(&dtd
->elementTypes
, name
, sizeof(ELEMENT_TYPE
));
6461 if (ret
->name
!= name
)
6462 poolDiscard(&dtd
->pool
);
6464 poolFinish(&dtd
->pool
);
6465 if (!setElementTypePrefix(parser
, ret
))