1 /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
2 See the file COPYING for copying permission.
6 #include <string.h> /* memset(), memcpy() */
8 #define XML_BUILDING_EXPAT 1
10 #ifdef COMPILED_FROM_DSP
11 #include "winconfig.h"
12 #elif defined(MACOS_CLASSIC)
13 #include "macconfig.h"
15 #ifdef HAVE_EXPAT_CONFIG_H
16 #include <expat_config.h>
18 #endif /* ndef COMPILED_FROM_DSP */
23 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
24 #define XmlConvert XmlUtf16Convert
25 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
26 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
27 #define XmlEncode XmlUtf16Encode
28 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
29 typedef unsigned short ICHAR;
31 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
32 #define XmlConvert XmlUtf8Convert
33 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
34 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
35 #define XmlEncode XmlUtf8Encode
36 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
43 #define XmlInitEncodingNS XmlInitEncoding
44 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
45 #undef XmlGetInternalEncodingNS
46 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
47 #define XmlParseXmlDeclNS XmlParseXmlDecl
53 #ifdef XML_UNICODE_WCHAR_T
54 #define XML_T(x) (const wchar_t)x
55 #define XML_L(x) L ## x
57 #define XML_T(x) (const unsigned short)x
68 /* Round up n to be a multiple of sz, where sz is a power of 2. */
69 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
71 /* Handle the case where memmove() doesn't exist. */
74 #define memmove(d,s,l) bcopy((s),(d),(l))
76 #error memmove does not exist on this platform, nor is a substitute available
77 #endif /* HAVE_BCOPY */
78 #endif /* HAVE_MEMMOVE */
84 typedef const XML_Char *KEY;
95 const XML_Memory_Handling_Suite *mem;
98 /* Basic character hash algorithm, taken from Python's string hash:
99 h = h * 1000003 ^ character, the constant being a prime number.
103 #define CHAR_HASH(h, c) \
104 (((h) * 0xF4243) ^ (unsigned short)(c))
106 #define CHAR_HASH(h, c) \
107 (((h) * 0xF4243) ^ (unsigned char)(c))
110 /* For probing (after a collision) we need a step size relative prime
111 to the hash table size, which is a power of 2. We use double-hashing,
112 since we can calculate a second hash value cheaply by taking those bits
113 of the first hash value that were discarded (masked out) when the table
114 index was calculated: index = hash & mask, where mask = table->size - 1.
115 We limit the maximum step size to table->size / 4 (mask >> 2) and make
116 it odd, since odd numbers are always relative prime to a power of 2.
118 #define SECOND_HASH(hash, mask, power) \
119 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
120 #define PROBE_STEP(hash, mask, power) \
121 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
128 #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
129 #define INIT_DATA_BUF_SIZE 1024
130 #define INIT_ATTS_SIZE 16
131 #define INIT_ATTS_VERSION 0xFFFFFFFF
132 #define INIT_BLOCK_SIZE 1024
133 #define INIT_BUFFER_SIZE 1024
135 #define EXPAND_SPARE 24
137 typedef struct binding {
138 struct prefix *prefix;
139 struct binding *nextTagBinding;
140 struct binding *prevPrefixBinding;
141 const struct attribute_id *attId;
147 typedef struct prefix {
148 const XML_Char *name;
154 const XML_Char *localPart;
155 const XML_Char *prefix;
161 /* TAG represents an open element.
162 The name of the element is stored in both the document and API
163 encodings. The memory buffer 'buf' is a separately-allocated
164 memory area which stores the name. During the XML_Parse()/
165 XMLParseBuffer() when the element is open, the memory for the 'raw'
166 version of the name (in the document encoding) is shared with the
167 document buffer. If the element is open across calls to
168 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
169 contain the 'raw' name as well.
171 A parser re-uses these structures, maintaining a list of allocated
172 TAG objects in a free list.
175 struct tag *parent; /* parent of this element */
176 const char *rawName; /* tagName in the original encoding */
178 TAG_NAME name; /* tagName in the API encoding */
179 char *buf; /* buffer for name components */
180 char *bufEnd; /* end of the buffer */
185 const XML_Char *name;
186 const XML_Char *textPtr;
188 const XML_Char *systemId;
189 const XML_Char *base;
190 const XML_Char *publicId;
191 const XML_Char *notation;
194 XML_Bool is_internal; /* true if declared in internal subset outside PE */
198 enum XML_Content_Type type;
199 enum XML_Content_Quant quant;
200 const XML_Char * name;
207 #define INIT_SCAFFOLD_ELEMENTS 32
209 typedef struct block {
221 const XML_Memory_Handling_Suite *mem;
224 /* The XML_Char before the name is used to determine whether
225 an attribute has been specified. */
226 typedef struct attribute_id {
229 XML_Bool maybeTokenized;
234 const ATTRIBUTE_ID *id;
236 const XML_Char *value;
240 unsigned long version;
242 const XML_Char *uriName;
246 const XML_Char *name;
248 const ATTRIBUTE_ID *idAtt;
250 int allocDefaultAtts;
251 DEFAULT_ATTRIBUTE *defaultAtts;
255 HASH_TABLE generalEntities;
256 HASH_TABLE elementTypes;
257 HASH_TABLE attributeIds;
260 STRING_POOL entityValuePool;
261 /* false once a parameter entity reference has been skipped */
262 XML_Bool keepProcessing;
263 /* true once an internal or external PE reference has been encountered;
264 this includes the reference to an external subset */
265 XML_Bool hasParamEntityRefs;
268 /* indicates if external PE has been read */
269 XML_Bool paramEntityRead;
270 HASH_TABLE paramEntities;
272 PREFIX defaultPrefix;
273 /* === scaffolding for building content model === */
275 CONTENT_SCAFFOLD *scaffold;
276 unsigned contentStringLen;
283 typedef struct open_internal_entity {
284 const char *internalEventPtr;
285 const char *internalEventEndPtr;
286 struct open_internal_entity *next;
288 } OPEN_INTERNAL_ENTITY;
290 typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
293 const char **endPtr);
295 static Processor prologProcessor;
296 static Processor prologInitProcessor;
297 static Processor contentProcessor;
298 static Processor cdataSectionProcessor;
300 static Processor ignoreSectionProcessor;
301 static Processor externalParEntProcessor;
302 static Processor externalParEntInitProcessor;
303 static Processor entityValueProcessor;
304 static Processor entityValueInitProcessor;
306 static Processor epilogProcessor;
307 static Processor errorProcessor;
308 static Processor externalEntityInitProcessor;
309 static Processor externalEntityInitProcessor2;
310 static Processor externalEntityInitProcessor3;
311 static Processor externalEntityContentProcessor;
313 static enum XML_Error
314 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
315 static enum XML_Error
316 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
317 const char *, const char *);
318 static enum XML_Error
319 initializeEncoding(XML_Parser parser);
320 static enum XML_Error
321 doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
322 const char *end, int tok, const char *next, const char **nextPtr);
323 static enum XML_Error
324 processInternalParamEntity(XML_Parser parser, ENTITY *entity);
325 static enum XML_Error
326 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
327 const char *start, const char *end, const char **endPtr);
328 static enum XML_Error
329 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
330 const char *end, const char **nextPtr);
332 static enum XML_Error
333 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
334 const char *end, const char **nextPtr);
337 static enum XML_Error
338 storeAtts(XML_Parser parser, const ENCODING *, const char *s,
339 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
340 static enum XML_Error
341 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
342 const XML_Char *uri, BINDING **bindingsPtr);
344 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *,
345 XML_Bool isCdata, XML_Bool isId, const XML_Char *dfltValue,
347 static enum XML_Error
348 storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
349 const char *, const char *, STRING_POOL *);
350 static enum XML_Error
351 appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
352 const char *, const char *, STRING_POOL *);
353 static ATTRIBUTE_ID *
354 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
357 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
358 static enum XML_Error
359 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
362 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
363 const char *start, const char *end);
365 reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
368 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
371 static const XML_Char * getContext(XML_Parser parser);
373 setContext(XML_Parser parser, const XML_Char *context);
375 static void FASTCALL normalizePublicId(XML_Char *s);
377 static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
378 /* do not call if parentParser != NULL */
379 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
381 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
383 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
385 copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
388 lookup(HASH_TABLE *table, KEY name, size_t createSize);
390 hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
391 static void FASTCALL hashTableClear(HASH_TABLE *);
392 static void FASTCALL hashTableDestroy(HASH_TABLE *);
394 hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
395 static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
398 poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
399 static void FASTCALL poolClear(STRING_POOL *);
400 static void FASTCALL poolDestroy(STRING_POOL *);
402 poolAppend(STRING_POOL *pool, const ENCODING *enc,
403 const char *ptr, const char *end);
405 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
406 const char *ptr, const char *end);
407 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
408 static const XML_Char * FASTCALL
409 poolCopyString(STRING_POOL *pool, const XML_Char *s);
410 static const XML_Char *
411 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
412 static const XML_Char * FASTCALL
413 poolAppendString(STRING_POOL *pool, const XML_Char *s);
415 static int FASTCALL nextScaffoldPart(XML_Parser parser);
416 static XML_Content * build_model(XML_Parser parser);
417 static ELEMENT_TYPE *
418 getElementType(XML_Parser parser, const ENCODING *enc,
419 const char *ptr, const char *end);
422 parserCreate(const XML_Char *encodingName,
423 const XML_Memory_Handling_Suite *memsuite,
424 const XML_Char *nameSep,
427 parserInit(XML_Parser parser, const XML_Char *encodingName);
429 #define poolStart(pool) ((pool)->start)
430 #define poolEnd(pool) ((pool)->ptr)
431 #define poolLength(pool) ((pool)->ptr - (pool)->start)
432 #define poolChop(pool) ((void)--(pool->ptr))
433 #define poolLastChar(pool) (((pool)->ptr)[-1])
434 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
435 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
436 #define poolAppendChar(pool, c) \
437 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
439 : ((*((pool)->ptr)++ = c), 1))
441 struct XML_ParserStruct {
442 /* The first member must be userData so that the XML_GetUserData
447 const XML_Memory_Handling_Suite m_mem;
448 /* first character to be parsed */
449 const char *m_bufferPtr;
450 /* past last character to be parsed */
452 /* allocated end of buffer */
453 const char *m_bufferLim;
454 long m_parseEndByteIndex;
455 const char *m_parseEndPtr;
457 XML_Char *m_dataBufEnd;
458 XML_StartElementHandler m_startElementHandler;
459 XML_EndElementHandler m_endElementHandler;
460 XML_CharacterDataHandler m_characterDataHandler;
461 XML_ProcessingInstructionHandler m_processingInstructionHandler;
462 XML_CommentHandler m_commentHandler;
463 XML_StartCdataSectionHandler m_startCdataSectionHandler;
464 XML_EndCdataSectionHandler m_endCdataSectionHandler;
465 XML_DefaultHandler m_defaultHandler;
466 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
467 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
468 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
469 XML_NotationDeclHandler m_notationDeclHandler;
470 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
471 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
472 XML_NotStandaloneHandler m_notStandaloneHandler;
473 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
474 XML_Parser m_externalEntityRefHandlerArg;
475 XML_SkippedEntityHandler m_skippedEntityHandler;
476 XML_UnknownEncodingHandler m_unknownEncodingHandler;
477 XML_ElementDeclHandler m_elementDeclHandler;
478 XML_AttlistDeclHandler m_attlistDeclHandler;
479 XML_EntityDeclHandler m_entityDeclHandler;
480 XML_XmlDeclHandler m_xmlDeclHandler;
481 const ENCODING *m_encoding;
482 INIT_ENCODING m_initEncoding;
483 const ENCODING *m_internalEncoding;
484 const XML_Char *m_protocolEncodingName;
486 XML_Bool m_ns_triplets;
487 void *m_unknownEncodingMem;
488 void *m_unknownEncodingData;
489 void *m_unknownEncodingHandlerData;
490 void (*m_unknownEncodingRelease)(void *);
491 PROLOG_STATE m_prologState;
492 Processor *m_processor;
493 enum XML_Error m_errorCode;
494 const char *m_eventPtr;
495 const char *m_eventEndPtr;
496 const char *m_positionPtr;
497 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
498 XML_Bool m_defaultExpandInternalEntities;
500 ENTITY *m_declEntity;
501 const XML_Char *m_doctypeName;
502 const XML_Char *m_doctypeSysid;
503 const XML_Char *m_doctypePubid;
504 const XML_Char *m_declAttributeType;
505 const XML_Char *m_declNotationName;
506 const XML_Char *m_declNotationPublicId;
507 ELEMENT_TYPE *m_declElementType;
508 ATTRIBUTE_ID *m_declAttributeId;
509 XML_Bool m_declAttributeIsCdata;
510 XML_Bool m_declAttributeIsId;
512 const XML_Char *m_curBase;
515 BINDING *m_inheritedBindings;
516 BINDING *m_freeBindingList;
518 int m_nSpecifiedAtts;
522 unsigned long m_nsAttsVersion;
523 unsigned char m_nsAttsPower;
525 STRING_POOL m_tempPool;
526 STRING_POOL m_temp2Pool;
527 char *m_groupConnector;
528 unsigned int m_groupSize;
529 XML_Char m_namespaceSeparator;
530 XML_Parser m_parentParser;
532 XML_Bool m_isParamEntity;
533 XML_Bool m_useForeignDTD;
534 enum XML_ParamEntityParsing m_paramEntityParsing;
538 #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
539 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
540 #define FREE(p) (parser->m_mem.free_fcn((p)))
542 #define userData (parser->m_userData)
543 #define handlerArg (parser->m_handlerArg)
544 #define startElementHandler (parser->m_startElementHandler)
545 #define endElementHandler (parser->m_endElementHandler)
546 #define characterDataHandler (parser->m_characterDataHandler)
547 #define processingInstructionHandler \
548 (parser->m_processingInstructionHandler)
549 #define commentHandler (parser->m_commentHandler)
550 #define startCdataSectionHandler \
551 (parser->m_startCdataSectionHandler)
552 #define endCdataSectionHandler (parser->m_endCdataSectionHandler)
553 #define defaultHandler (parser->m_defaultHandler)
554 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
555 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
556 #define unparsedEntityDeclHandler \
557 (parser->m_unparsedEntityDeclHandler)
558 #define notationDeclHandler (parser->m_notationDeclHandler)
559 #define startNamespaceDeclHandler \
560 (parser->m_startNamespaceDeclHandler)
561 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
562 #define notStandaloneHandler (parser->m_notStandaloneHandler)
563 #define externalEntityRefHandler \
564 (parser->m_externalEntityRefHandler)
565 #define externalEntityRefHandlerArg \
566 (parser->m_externalEntityRefHandlerArg)
567 #define internalEntityRefHandler \
568 (parser->m_internalEntityRefHandler)
569 #define skippedEntityHandler (parser->m_skippedEntityHandler)
570 #define unknownEncodingHandler (parser->m_unknownEncodingHandler)
571 #define elementDeclHandler (parser->m_elementDeclHandler)
572 #define attlistDeclHandler (parser->m_attlistDeclHandler)
573 #define entityDeclHandler (parser->m_entityDeclHandler)
574 #define xmlDeclHandler (parser->m_xmlDeclHandler)
575 #define encoding (parser->m_encoding)
576 #define initEncoding (parser->m_initEncoding)
577 #define internalEncoding (parser->m_internalEncoding)
578 #define unknownEncodingMem (parser->m_unknownEncodingMem)
579 #define unknownEncodingData (parser->m_unknownEncodingData)
580 #define unknownEncodingHandlerData \
581 (parser->m_unknownEncodingHandlerData)
582 #define unknownEncodingRelease (parser->m_unknownEncodingRelease)
583 #define protocolEncodingName (parser->m_protocolEncodingName)
584 #define ns (parser->m_ns)
585 #define ns_triplets (parser->m_ns_triplets)
586 #define prologState (parser->m_prologState)
587 #define processor (parser->m_processor)
588 #define errorCode (parser->m_errorCode)
589 #define eventPtr (parser->m_eventPtr)
590 #define eventEndPtr (parser->m_eventEndPtr)
591 #define positionPtr (parser->m_positionPtr)
592 #define position (parser->m_position)
593 #define openInternalEntities (parser->m_openInternalEntities)
594 #define defaultExpandInternalEntities \
595 (parser->m_defaultExpandInternalEntities)
596 #define tagLevel (parser->m_tagLevel)
597 #define buffer (parser->m_buffer)
598 #define bufferPtr (parser->m_bufferPtr)
599 #define bufferEnd (parser->m_bufferEnd)
600 #define parseEndByteIndex (parser->m_parseEndByteIndex)
601 #define parseEndPtr (parser->m_parseEndPtr)
602 #define bufferLim (parser->m_bufferLim)
603 #define dataBuf (parser->m_dataBuf)
604 #define dataBufEnd (parser->m_dataBufEnd)
605 #define _dtd (parser->m_dtd)
606 #define curBase (parser->m_curBase)
607 #define declEntity (parser->m_declEntity)
608 #define doctypeName (parser->m_doctypeName)
609 #define doctypeSysid (parser->m_doctypeSysid)
610 #define doctypePubid (parser->m_doctypePubid)
611 #define declAttributeType (parser->m_declAttributeType)
612 #define declNotationName (parser->m_declNotationName)
613 #define declNotationPublicId (parser->m_declNotationPublicId)
614 #define declElementType (parser->m_declElementType)
615 #define declAttributeId (parser->m_declAttributeId)
616 #define declAttributeIsCdata (parser->m_declAttributeIsCdata)
617 #define declAttributeIsId (parser->m_declAttributeIsId)
618 #define freeTagList (parser->m_freeTagList)
619 #define freeBindingList (parser->m_freeBindingList)
620 #define inheritedBindings (parser->m_inheritedBindings)
621 #define tagStack (parser->m_tagStack)
622 #define atts (parser->m_atts)
623 #define attsSize (parser->m_attsSize)
624 #define nSpecifiedAtts (parser->m_nSpecifiedAtts)
625 #define idAttIndex (parser->m_idAttIndex)
626 #define nsAtts (parser->m_nsAtts)
627 #define nsAttsVersion (parser->m_nsAttsVersion)
628 #define nsAttsPower (parser->m_nsAttsPower)
629 #define tempPool (parser->m_tempPool)
630 #define temp2Pool (parser->m_temp2Pool)
631 #define groupConnector (parser->m_groupConnector)
632 #define groupSize (parser->m_groupSize)
633 #define namespaceSeparator (parser->m_namespaceSeparator)
634 #define parentParser (parser->m_parentParser)
636 #define isParamEntity (parser->m_isParamEntity)
637 #define useForeignDTD (parser->m_useForeignDTD)
638 #define paramEntityParsing (parser->m_paramEntityParsing)
647 (processor != externalParEntInitProcessor) \
649 (processor != externalEntityInitProcessor)) \
651 (processor != prologInitProcessor))
656 (processor != externalEntityInitProcessor) \
658 (processor != prologInitProcessor))
662 XML_ParserCreate(const XML_Char *encodingName)
664 return XML_ParserCreate_MM(encodingName, NULL, NULL);
668 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
672 return XML_ParserCreate_MM(encodingName, NULL, tmp);
675 static const XML_Char implicitContext[] = {
676 'x', 'm', 'l', '=', 'h', 't', 't', 'p', ':', '/', '/',
677 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
678 'X', 'M', 'L', '/', '1', '9', '9', '8', '/',
679 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0'
683 XML_ParserCreate_MM(const XML_Char *encodingName,
684 const XML_Memory_Handling_Suite *memsuite,
685 const XML_Char *nameSep)
687 XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL);
688 if (parser != NULL && ns) {
689 /* implicit context only set for root parser, since child
690 parsers (i.e. external entity parsers) will inherit it
692 if (!setContext(parser, implicitContext)) {
693 XML_ParserFree(parser);
701 parserCreate(const XML_Char *encodingName,
702 const XML_Memory_Handling_Suite *memsuite,
703 const XML_Char *nameSep,
709 XML_Memory_Handling_Suite *mtemp;
710 parser = (XML_Parser)
711 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
712 if (parser != NULL) {
713 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
714 mtemp->malloc_fcn = memsuite->malloc_fcn;
715 mtemp->realloc_fcn = memsuite->realloc_fcn;
716 mtemp->free_fcn = memsuite->free_fcn;
720 XML_Memory_Handling_Suite *mtemp;
721 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
722 if (parser != NULL) {
723 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
724 mtemp->malloc_fcn = malloc;
725 mtemp->realloc_fcn = realloc;
726 mtemp->free_fcn = free;
736 attsSize = INIT_ATTS_SIZE;
737 atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
742 dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
743 if (dataBuf == NULL) {
748 dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
753 _dtd = dtdCreate(&parser->m_mem);
762 freeBindingList = NULL;
766 groupConnector = NULL;
768 unknownEncodingHandler = NULL;
769 unknownEncodingHandlerData = NULL;
771 namespaceSeparator = '!';
773 ns_triplets = XML_FALSE;
779 poolInit(&tempPool, &(parser->m_mem));
780 poolInit(&temp2Pool, &(parser->m_mem));
781 parserInit(parser, encodingName);
783 if (encodingName && !protocolEncodingName) {
784 XML_ParserFree(parser);
790 internalEncoding = XmlGetInternalEncodingNS();
791 namespaceSeparator = *nameSep;
794 internalEncoding = XmlGetInternalEncoding();
801 parserInit(XML_Parser parser, const XML_Char *encodingName)
803 processor = prologInitProcessor;
804 XmlPrologStateInit(&prologState);
805 protocolEncodingName = (encodingName != NULL
806 ? poolCopyString(&tempPool, encodingName)
809 XmlInitEncoding(&initEncoding, &encoding, 0);
812 startElementHandler = NULL;
813 endElementHandler = NULL;
814 characterDataHandler = NULL;
815 processingInstructionHandler = NULL;
816 commentHandler = NULL;
817 startCdataSectionHandler = NULL;
818 endCdataSectionHandler = NULL;
819 defaultHandler = NULL;
820 startDoctypeDeclHandler = NULL;
821 endDoctypeDeclHandler = NULL;
822 unparsedEntityDeclHandler = NULL;
823 notationDeclHandler = NULL;
824 startNamespaceDeclHandler = NULL;
825 endNamespaceDeclHandler = NULL;
826 notStandaloneHandler = NULL;
827 externalEntityRefHandler = NULL;
828 externalEntityRefHandlerArg = parser;
829 skippedEntityHandler = NULL;
830 elementDeclHandler = NULL;
831 attlistDeclHandler = NULL;
832 entityDeclHandler = NULL;
833 xmlDeclHandler = NULL;
836 parseEndByteIndex = 0;
838 declElementType = NULL;
839 declAttributeId = NULL;
844 declAttributeType = NULL;
845 declNotationName = NULL;
846 declNotationPublicId = NULL;
847 declAttributeIsCdata = XML_FALSE;
848 declAttributeIsId = XML_FALSE;
849 memset(&position, 0, sizeof(POSITION));
850 errorCode = XML_ERROR_NONE;
854 openInternalEntities = 0;
855 defaultExpandInternalEntities = XML_TRUE;
858 inheritedBindings = NULL;
860 unknownEncodingMem = NULL;
861 unknownEncodingRelease = NULL;
862 unknownEncodingData = NULL;
865 isParamEntity = XML_FALSE;
866 useForeignDTD = XML_FALSE;
867 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
871 /* moves list of bindings to freeBindingList */
873 moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
876 BINDING *b = bindings;
877 bindings = bindings->nextTagBinding;
878 b->nextTagBinding = freeBindingList;
884 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
889 /* move tagStack to freeTagList */
894 tag->parent = freeTagList;
895 moveToFreeBindingList(parser, tag->bindings);
896 tag->bindings = NULL;
899 moveToFreeBindingList(parser, inheritedBindings);
900 FREE(unknownEncodingMem);
901 if (unknownEncodingRelease)
902 unknownEncodingRelease(unknownEncodingData);
903 poolClear(&tempPool);
904 poolClear(&temp2Pool);
905 parserInit(parser, encodingName);
906 dtdReset(_dtd, &parser->m_mem);
907 return setContext(parser, implicitContext);
910 enum XML_Status XMLCALL
911 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
913 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
914 XXX There's no way for the caller to determine which of the
915 XXX possible error cases caused the XML_STATUS_ERROR return.
918 return XML_STATUS_ERROR;
919 if (encodingName == NULL)
920 protocolEncodingName = NULL;
922 protocolEncodingName = poolCopyString(&tempPool, encodingName);
923 if (!protocolEncodingName)
924 return XML_STATUS_ERROR;
926 return XML_STATUS_OK;
930 XML_ExternalEntityParserCreate(XML_Parser oldParser,
931 const XML_Char *context,
932 const XML_Char *encodingName)
934 XML_Parser parser = oldParser;
937 XML_StartElementHandler oldStartElementHandler = startElementHandler;
938 XML_EndElementHandler oldEndElementHandler = endElementHandler;
939 XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
940 XML_ProcessingInstructionHandler oldProcessingInstructionHandler
941 = processingInstructionHandler;
942 XML_CommentHandler oldCommentHandler = commentHandler;
943 XML_StartCdataSectionHandler oldStartCdataSectionHandler
944 = startCdataSectionHandler;
945 XML_EndCdataSectionHandler oldEndCdataSectionHandler
946 = endCdataSectionHandler;
947 XML_DefaultHandler oldDefaultHandler = defaultHandler;
948 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
949 = unparsedEntityDeclHandler;
950 XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
951 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
952 = startNamespaceDeclHandler;
953 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
954 = endNamespaceDeclHandler;
955 XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
956 XML_ExternalEntityRefHandler oldExternalEntityRefHandler
957 = externalEntityRefHandler;
958 XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
959 XML_UnknownEncodingHandler oldUnknownEncodingHandler
960 = unknownEncodingHandler;
961 XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
962 XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
963 XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
964 XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
965 ELEMENT_TYPE * oldDeclElementType = declElementType;
967 void *oldUserData = userData;
968 void *oldHandlerArg = handlerArg;
969 XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
970 XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
972 enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
973 int oldInEntityValue = prologState.inEntityValue;
975 XML_Bool oldns_triplets = ns_triplets;
982 /* Note that the magical uses of the pre-processor to make field
983 access look more like C++ require that `parser' be overwritten
984 here. This makes this function more painful to follow than it
989 *tmp = namespaceSeparator;
990 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
993 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
999 startElementHandler = oldStartElementHandler;
1000 endElementHandler = oldEndElementHandler;
1001 characterDataHandler = oldCharacterDataHandler;
1002 processingInstructionHandler = oldProcessingInstructionHandler;
1003 commentHandler = oldCommentHandler;
1004 startCdataSectionHandler = oldStartCdataSectionHandler;
1005 endCdataSectionHandler = oldEndCdataSectionHandler;
1006 defaultHandler = oldDefaultHandler;
1007 unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1008 notationDeclHandler = oldNotationDeclHandler;
1009 startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1010 endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1011 notStandaloneHandler = oldNotStandaloneHandler;
1012 externalEntityRefHandler = oldExternalEntityRefHandler;
1013 skippedEntityHandler = oldSkippedEntityHandler;
1014 unknownEncodingHandler = oldUnknownEncodingHandler;
1015 elementDeclHandler = oldElementDeclHandler;
1016 attlistDeclHandler = oldAttlistDeclHandler;
1017 entityDeclHandler = oldEntityDeclHandler;
1018 xmlDeclHandler = oldXmlDeclHandler;
1019 declElementType = oldDeclElementType;
1020 userData = oldUserData;
1021 if (oldUserData == oldHandlerArg)
1022 handlerArg = userData;
1024 handlerArg = parser;
1025 if (oldExternalEntityRefHandlerArg != oldParser)
1026 externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1027 defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1028 ns_triplets = oldns_triplets;
1029 parentParser = oldParser;
1031 paramEntityParsing = oldParamEntityParsing;
1032 prologState.inEntityValue = oldInEntityValue;
1034 #endif /* XML_DTD */
1035 if (!dtdCopy(_dtd, oldDtd, &parser->m_mem)
1036 || !setContext(parser, context)) {
1037 XML_ParserFree(parser);
1040 processor = externalEntityInitProcessor;
1044 /* The DTD instance referenced by _dtd is shared between the document's
1045 root parser and external PE parsers, therefore one does not need to
1046 call setContext. In addition, one also *must* not call setContext,
1047 because this would overwrite existing prefix->binding pointers in
1048 _dtd with ones that get destroyed with the external PE parser.
1049 This would leave those prefixes with dangling pointers.
1051 isParamEntity = XML_TRUE;
1052 XmlPrologStateInitExternalEntity(&prologState);
1053 processor = externalParEntInitProcessor;
1055 #endif /* XML_DTD */
1059 static void FASTCALL
1060 destroyBindings(BINDING *bindings, XML_Parser parser)
1063 BINDING *b = bindings;
1066 bindings = b->nextTagBinding;
1073 XML_ParserFree(XML_Parser parser)
1077 if (tagStack == NULL) {
1078 if (freeTagList == NULL)
1080 tagStack = freeTagList;
1084 tagStack = tagStack->parent;
1086 destroyBindings(p->bindings, parser);
1089 destroyBindings(freeBindingList, parser);
1090 destroyBindings(inheritedBindings, parser);
1091 poolDestroy(&tempPool);
1092 poolDestroy(&temp2Pool);
1094 /* external parameter entity parsers share the DTD structure
1095 parser->m_dtd with the root parser, so we must not destroy it
1097 if (!isParamEntity && _dtd)
1100 #endif /* XML_DTD */
1101 dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
1103 FREE(groupConnector);
1107 FREE(unknownEncodingMem);
1108 if (unknownEncodingRelease)
1109 unknownEncodingRelease(unknownEncodingData);
1114 XML_UseParserAsHandlerArg(XML_Parser parser)
1116 handlerArg = parser;
1119 enum XML_Error XMLCALL
1120 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
1123 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1125 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
1126 useForeignDTD = useDTD;
1127 return XML_ERROR_NONE;
1129 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1134 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
1136 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1139 ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
1143 XML_SetUserData(XML_Parser parser, void *p)
1145 if (handlerArg == userData)
1146 handlerArg = userData = p;
1151 enum XML_Status XMLCALL
1152 XML_SetBase(XML_Parser parser, const XML_Char *p)
1155 p = poolCopyString(&_dtd->pool, p);
1157 return XML_STATUS_ERROR;
1162 return XML_STATUS_OK;
1165 const XML_Char * XMLCALL
1166 XML_GetBase(XML_Parser parser)
1172 XML_GetSpecifiedAttributeCount(XML_Parser parser)
1174 return nSpecifiedAtts;
1178 XML_GetIdAttributeIndex(XML_Parser parser)
1184 XML_SetElementHandler(XML_Parser parser,
1185 XML_StartElementHandler start,
1186 XML_EndElementHandler end)
1188 startElementHandler = start;
1189 endElementHandler = end;
1193 XML_SetStartElementHandler(XML_Parser parser,
1194 XML_StartElementHandler start) {
1195 startElementHandler = start;
1199 XML_SetEndElementHandler(XML_Parser parser,
1200 XML_EndElementHandler end) {
1201 endElementHandler = end;
1205 XML_SetCharacterDataHandler(XML_Parser parser,
1206 XML_CharacterDataHandler handler)
1208 characterDataHandler = handler;
1212 XML_SetProcessingInstructionHandler(XML_Parser parser,
1213 XML_ProcessingInstructionHandler handler)
1215 processingInstructionHandler = handler;
1219 XML_SetCommentHandler(XML_Parser parser,
1220 XML_CommentHandler handler)
1222 commentHandler = handler;
1226 XML_SetCdataSectionHandler(XML_Parser parser,
1227 XML_StartCdataSectionHandler start,
1228 XML_EndCdataSectionHandler end)
1230 startCdataSectionHandler = start;
1231 endCdataSectionHandler = end;
1235 XML_SetStartCdataSectionHandler(XML_Parser parser,
1236 XML_StartCdataSectionHandler start) {
1237 startCdataSectionHandler = start;
1241 XML_SetEndCdataSectionHandler(XML_Parser parser,
1242 XML_EndCdataSectionHandler end) {
1243 endCdataSectionHandler = end;
1247 XML_SetDefaultHandler(XML_Parser parser,
1248 XML_DefaultHandler handler)
1250 defaultHandler = handler;
1251 defaultExpandInternalEntities = XML_FALSE;
1255 XML_SetDefaultHandlerExpand(XML_Parser parser,
1256 XML_DefaultHandler handler)
1258 defaultHandler = handler;
1259 defaultExpandInternalEntities = XML_TRUE;
1263 XML_SetDoctypeDeclHandler(XML_Parser parser,
1264 XML_StartDoctypeDeclHandler start,
1265 XML_EndDoctypeDeclHandler end)
1267 startDoctypeDeclHandler = start;
1268 endDoctypeDeclHandler = end;
1272 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1273 XML_StartDoctypeDeclHandler start) {
1274 startDoctypeDeclHandler = start;
1278 XML_SetEndDoctypeDeclHandler(XML_Parser parser,
1279 XML_EndDoctypeDeclHandler end) {
1280 endDoctypeDeclHandler = end;
1284 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1285 XML_UnparsedEntityDeclHandler handler)
1287 unparsedEntityDeclHandler = handler;
1291 XML_SetNotationDeclHandler(XML_Parser parser,
1292 XML_NotationDeclHandler handler)
1294 notationDeclHandler = handler;
1298 XML_SetNamespaceDeclHandler(XML_Parser parser,
1299 XML_StartNamespaceDeclHandler start,
1300 XML_EndNamespaceDeclHandler end)
1302 startNamespaceDeclHandler = start;
1303 endNamespaceDeclHandler = end;
1307 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1308 XML_StartNamespaceDeclHandler start) {
1309 startNamespaceDeclHandler = start;
1313 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1314 XML_EndNamespaceDeclHandler end) {
1315 endNamespaceDeclHandler = end;
1319 XML_SetNotStandaloneHandler(XML_Parser parser,
1320 XML_NotStandaloneHandler handler)
1322 notStandaloneHandler = handler;
1326 XML_SetExternalEntityRefHandler(XML_Parser parser,
1327 XML_ExternalEntityRefHandler handler)
1329 externalEntityRefHandler = handler;
1333 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
1336 externalEntityRefHandlerArg = (XML_Parser)arg;
1338 externalEntityRefHandlerArg = parser;
1342 XML_SetSkippedEntityHandler(XML_Parser parser,
1343 XML_SkippedEntityHandler handler)
1345 skippedEntityHandler = handler;
1349 XML_SetUnknownEncodingHandler(XML_Parser parser,
1350 XML_UnknownEncodingHandler handler,
1353 unknownEncodingHandler = handler;
1354 unknownEncodingHandlerData = data;
1358 XML_SetElementDeclHandler(XML_Parser parser,
1359 XML_ElementDeclHandler eldecl)
1361 elementDeclHandler = eldecl;
1365 XML_SetAttlistDeclHandler(XML_Parser parser,
1366 XML_AttlistDeclHandler attdecl)
1368 attlistDeclHandler = attdecl;
1372 XML_SetEntityDeclHandler(XML_Parser parser,
1373 XML_EntityDeclHandler handler)
1375 entityDeclHandler = handler;
1379 XML_SetXmlDeclHandler(XML_Parser parser,
1380 XML_XmlDeclHandler handler) {
1381 xmlDeclHandler = handler;
1385 XML_SetParamEntityParsing(XML_Parser parser,
1386 enum XML_ParamEntityParsing peParsing)
1388 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1392 paramEntityParsing = peParsing;
1395 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1399 enum XML_Status XMLCALL
1400 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
1404 return XML_STATUS_OK;
1405 positionPtr = bufferPtr;
1406 errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0);
1407 if (errorCode == XML_ERROR_NONE)
1408 return XML_STATUS_OK;
1409 eventEndPtr = eventPtr;
1410 processor = errorProcessor;
1411 return XML_STATUS_ERROR;
1413 #ifndef XML_CONTEXT_BYTES
1414 else if (bufferPtr == bufferEnd) {
1417 parseEndByteIndex += len;
1420 errorCode = processor(parser, s, parseEndPtr = s + len, 0);
1421 if (errorCode == XML_ERROR_NONE)
1422 return XML_STATUS_OK;
1423 eventEndPtr = eventPtr;
1424 processor = errorProcessor;
1425 return XML_STATUS_ERROR;
1427 errorCode = processor(parser, s, parseEndPtr = s + len, &end);
1428 if (errorCode != XML_ERROR_NONE) {
1429 eventEndPtr = eventPtr;
1430 processor = errorProcessor;
1431 return XML_STATUS_ERROR;
1433 XmlUpdatePosition(encoding, positionPtr, end, &position);
1435 nLeftOver = s + len - end;
1437 if (buffer == NULL || nLeftOver > bufferLim - buffer) {
1438 /* FIXME avoid integer overflow */
1440 temp = (buffer == NULL
1441 ? (char *)MALLOC(len * 2)
1442 : (char *)REALLOC(buffer, len * 2));
1444 errorCode = XML_ERROR_NO_MEMORY;
1445 return XML_STATUS_ERROR;
1449 errorCode = XML_ERROR_NO_MEMORY;
1450 eventPtr = eventEndPtr = NULL;
1451 processor = errorProcessor;
1452 return XML_STATUS_ERROR;
1454 bufferLim = buffer + len * 2;
1456 memcpy(buffer, end, nLeftOver);
1458 bufferEnd = buffer + nLeftOver;
1460 return XML_STATUS_OK;
1462 #endif /* not defined XML_CONTEXT_BYTES */
1464 void *buff = XML_GetBuffer(parser, len);
1466 return XML_STATUS_ERROR;
1468 memcpy(buff, s, len);
1469 return XML_ParseBuffer(parser, len, isFinal);
1474 enum XML_Status XMLCALL
1475 XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
1477 const char *start = bufferPtr;
1478 positionPtr = start;
1480 parseEndByteIndex += len;
1481 errorCode = processor(parser, start, parseEndPtr = bufferEnd,
1482 isFinal ? (const char **)NULL : &bufferPtr);
1483 if (errorCode == XML_ERROR_NONE) {
1485 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1486 positionPtr = bufferPtr;
1488 return XML_STATUS_OK;
1491 eventEndPtr = eventPtr;
1492 processor = errorProcessor;
1493 return XML_STATUS_ERROR;
1498 XML_GetBuffer(XML_Parser parser, int len)
1500 if (len > bufferLim - bufferEnd) {
1501 /* FIXME avoid integer overflow */
1502 int neededSize = len + (bufferEnd - bufferPtr);
1503 #ifdef XML_CONTEXT_BYTES
1504 int keep = bufferPtr - buffer;
1506 if (keep > XML_CONTEXT_BYTES)
1507 keep = XML_CONTEXT_BYTES;
1509 #endif /* defined XML_CONTEXT_BYTES */
1510 if (neededSize <= bufferLim - buffer) {
1511 #ifdef XML_CONTEXT_BYTES
1512 if (keep < bufferPtr - buffer) {
1513 int offset = (bufferPtr - buffer) - keep;
1514 memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
1515 bufferEnd -= offset;
1516 bufferPtr -= offset;
1519 memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
1520 bufferEnd = buffer + (bufferEnd - bufferPtr);
1522 #endif /* not defined XML_CONTEXT_BYTES */
1526 int bufferSize = bufferLim - bufferPtr;
1527 if (bufferSize == 0)
1528 bufferSize = INIT_BUFFER_SIZE;
1531 } while (bufferSize < neededSize);
1532 newBuf = (char *)MALLOC(bufferSize);
1534 errorCode = XML_ERROR_NO_MEMORY;
1537 bufferLim = newBuf + bufferSize;
1538 #ifdef XML_CONTEXT_BYTES
1540 int keep = bufferPtr - buffer;
1541 if (keep > XML_CONTEXT_BYTES)
1542 keep = XML_CONTEXT_BYTES;
1543 memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
1546 bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
1547 bufferPtr = buffer + keep;
1550 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1551 bufferPtr = buffer = newBuf;
1555 memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
1558 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1559 bufferPtr = buffer = newBuf;
1560 #endif /* not defined XML_CONTEXT_BYTES */
1566 enum XML_Error XMLCALL
1567 XML_GetErrorCode(XML_Parser parser)
1573 XML_GetCurrentByteIndex(XML_Parser parser)
1576 return parseEndByteIndex - (parseEndPtr - eventPtr);
1581 XML_GetCurrentByteCount(XML_Parser parser)
1583 if (eventEndPtr && eventPtr)
1584 return eventEndPtr - eventPtr;
1588 const char * XMLCALL
1589 XML_GetInputContext(XML_Parser parser, int *offset, int *size)
1591 #ifdef XML_CONTEXT_BYTES
1592 if (eventPtr && buffer) {
1593 *offset = eventPtr - buffer;
1594 *size = bufferEnd - buffer;
1597 #endif /* defined XML_CONTEXT_BYTES */
1602 XML_GetCurrentLineNumber(XML_Parser parser)
1605 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1606 positionPtr = eventPtr;
1608 return position.lineNumber + 1;
1612 XML_GetCurrentColumnNumber(XML_Parser parser)
1615 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1616 positionPtr = eventPtr;
1618 return position.columnNumber;
1622 XML_FreeContentModel(XML_Parser parser, XML_Content *model)
1628 XML_MemMalloc(XML_Parser parser, size_t size)
1630 return MALLOC(size);
1634 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
1636 return REALLOC(ptr, size);
1640 XML_MemFree(XML_Parser parser, void *ptr)
1646 XML_DefaultCurrent(XML_Parser parser)
1648 if (defaultHandler) {
1649 if (openInternalEntities)
1650 reportDefault(parser,
1652 openInternalEntities->internalEventPtr,
1653 openInternalEntities->internalEventEndPtr);
1655 reportDefault(parser, encoding, eventPtr, eventEndPtr);
1659 const XML_LChar * XMLCALL
1660 XML_ErrorString(enum XML_Error code)
1662 static const XML_LChar *message[] = {
1664 XML_L("out of memory"),
1665 XML_L("syntax error"),
1666 XML_L("no element found"),
1667 XML_L("not well-formed (invalid token)"),
1668 XML_L("unclosed token"),
1669 XML_L("partial character"),
1670 XML_L("mismatched tag"),
1671 XML_L("duplicate attribute"),
1672 XML_L("junk after document element"),
1673 XML_L("illegal parameter entity reference"),
1674 XML_L("undefined entity"),
1675 XML_L("recursive entity reference"),
1676 XML_L("asynchronous entity"),
1677 XML_L("reference to invalid character number"),
1678 XML_L("reference to binary entity"),
1679 XML_L("reference to external entity in attribute"),
1680 XML_L("xml declaration not at start of external entity"),
1681 XML_L("unknown encoding"),
1682 XML_L("encoding specified in XML declaration is incorrect"),
1683 XML_L("unclosed CDATA section"),
1684 XML_L("error in processing external entity reference"),
1685 XML_L("document is not standalone"),
1686 XML_L("unexpected parser state - please send a bug report"),
1687 XML_L("entity declared in parameter entity"),
1688 XML_L("requested feature requires XML_DTD support in Expat"),
1689 XML_L("cannot change setting once parsing has begun"),
1690 XML_L("unbound prefix")
1692 if (code > 0 && code < sizeof(message)/sizeof(message[0]))
1693 return message[code];
1697 const XML_LChar * XMLCALL
1698 XML_ExpatVersion(void) {
1700 /* V1 is used to string-ize the version number. However, it would
1701 string-ize the actual version macro *names* unless we get them
1702 substituted before being passed to V1. CPP is defined to expand
1703 a macro, then rescan for more expansions. Thus, we use V2 to expand
1704 the version macros, then CPP will expand the resulting V1() macro
1705 with the correct numerals. */
1706 /* ### I'm assuming cpp is portable in this respect... */
1708 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
1709 #define V2(a,b,c) XML_L("expat_")V1(a,b,c)
1711 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
1717 XML_Expat_Version XMLCALL
1718 XML_ExpatVersionInfo(void)
1720 XML_Expat_Version version;
1722 version.major = XML_MAJOR_VERSION;
1723 version.minor = XML_MINOR_VERSION;
1724 version.micro = XML_MICRO_VERSION;
1729 const XML_Feature * XMLCALL
1730 XML_GetFeatureList(void)
1732 static XML_Feature features[] = {
1733 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"), 0},
1734 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"), 0},
1736 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
1738 #ifdef XML_UNICODE_WCHAR_T
1739 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
1742 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
1744 #ifdef XML_CONTEXT_BYTES
1745 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
1749 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
1751 {XML_FEATURE_END, NULL, 0}
1754 features[0].value = sizeof(XML_Char);
1755 features[1].value = sizeof(XML_LChar);
1759 /* Initially tag->rawName always points into the parse buffer;
1760 for those TAG instances opened while the current parse buffer was
1761 processed, and not yet closed, we need to store tag->rawName in a more
1762 permanent location, since the parse buffer is about to be discarded.
1765 storeRawNames(XML_Parser parser)
1767 TAG *tag = tagStack;
1770 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
1771 char *rawNameBuf = tag->buf + nameLen;
1772 /* Stop if already stored. Since tagStack is a stack, we can stop
1773 at the first entry that has already been copied; everything
1774 below it in the stack is already been accounted for in a
1775 previous call to this function.
1777 if (tag->rawName == rawNameBuf)
1779 /* For re-use purposes we need to ensure that the
1780 size of tag->buf is a multiple of sizeof(XML_Char).
1782 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
1783 if (bufSize > tag->bufEnd - tag->buf) {
1784 char *temp = (char *)REALLOC(tag->buf, bufSize);
1787 /* if tag->name.str points to tag->buf (only when namespace
1788 processing is off) then we have to update it
1790 if (tag->name.str == (XML_Char *)tag->buf)
1791 tag->name.str = (XML_Char *)temp;
1792 /* if tag->name.localPart is set (when namespace processing is on)
1793 then update it as well, since it will always point into tag->buf
1795 if (tag->name.localPart)
1796 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
1797 (XML_Char *)tag->buf);
1799 tag->bufEnd = temp + bufSize;
1800 rawNameBuf = temp + nameLen;
1802 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
1803 tag->rawName = rawNameBuf;
1809 static enum XML_Error PTRCALL
1810 contentProcessor(XML_Parser parser,
1813 const char **endPtr)
1815 enum XML_Error result =
1816 doContent(parser, 0, encoding, start, end, endPtr);
1817 if (result != XML_ERROR_NONE)
1819 if (!storeRawNames(parser))
1820 return XML_ERROR_NO_MEMORY;
1824 static enum XML_Error PTRCALL
1825 externalEntityInitProcessor(XML_Parser parser,
1828 const char **endPtr)
1830 enum XML_Error result = initializeEncoding(parser);
1831 if (result != XML_ERROR_NONE)
1833 processor = externalEntityInitProcessor2;
1834 return externalEntityInitProcessor2(parser, start, end, endPtr);
1837 static enum XML_Error PTRCALL
1838 externalEntityInitProcessor2(XML_Parser parser,
1841 const char **endPtr)
1843 const char *next = start; /* XmlContentTok doesn't always set the last arg */
1844 int tok = XmlContentTok(encoding, start, end, &next);
1847 /* If we are at the end of the buffer, this would cause the next stage,
1848 i.e. externalEntityInitProcessor3, to pass control directly to
1849 doContent (by detecting XML_TOK_NONE) without processing any xml text
1850 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
1852 if (next == end && endPtr) {
1854 return XML_ERROR_NONE;
1858 case XML_TOK_PARTIAL:
1861 return XML_ERROR_NONE;
1864 return XML_ERROR_UNCLOSED_TOKEN;
1865 case XML_TOK_PARTIAL_CHAR:
1868 return XML_ERROR_NONE;
1871 return XML_ERROR_PARTIAL_CHAR;
1873 processor = externalEntityInitProcessor3;
1874 return externalEntityInitProcessor3(parser, start, end, endPtr);
1877 static enum XML_Error PTRCALL
1878 externalEntityInitProcessor3(XML_Parser parser,
1881 const char **endPtr)
1883 const char *next = start; /* XmlContentTok doesn't always set the last arg */
1884 int tok = XmlContentTok(encoding, start, end, &next);
1886 case XML_TOK_XML_DECL:
1888 enum XML_Error result = processXmlDecl(parser, 1, start, next);
1889 if (result != XML_ERROR_NONE)
1894 case XML_TOK_PARTIAL:
1897 return XML_ERROR_NONE;
1900 return XML_ERROR_UNCLOSED_TOKEN;
1901 case XML_TOK_PARTIAL_CHAR:
1904 return XML_ERROR_NONE;
1907 return XML_ERROR_PARTIAL_CHAR;
1909 processor = externalEntityContentProcessor;
1911 return externalEntityContentProcessor(parser, start, end, endPtr);
1914 static enum XML_Error PTRCALL
1915 externalEntityContentProcessor(XML_Parser parser,
1918 const char **endPtr)
1920 enum XML_Error result =
1921 doContent(parser, 1, encoding, start, end, endPtr);
1922 if (result != XML_ERROR_NONE)
1924 if (!storeRawNames(parser))
1925 return XML_ERROR_NO_MEMORY;
1929 static enum XML_Error
1930 doContent(XML_Parser parser,
1932 const ENCODING *enc,
1935 const char **nextPtr)
1937 DTD * const dtd = _dtd; /* save one level of indirection */
1938 const char **eventPP;
1939 const char **eventEndPP;
1940 if (enc == encoding) {
1941 eventPP = &eventPtr;
1942 eventEndPP = &eventEndPtr;
1945 eventPP = &(openInternalEntities->internalEventPtr);
1946 eventEndPP = &(openInternalEntities->internalEventEndPtr);
1950 const char *next = s; /* XmlContentTok doesn't always set the last arg */
1951 int tok = XmlContentTok(enc, s, end, &next);
1954 case XML_TOK_TRAILING_CR:
1957 return XML_ERROR_NONE;
1960 if (characterDataHandler) {
1962 characterDataHandler(handlerArg, &c, 1);
1964 else if (defaultHandler)
1965 reportDefault(parser, enc, s, end);
1966 if (startTagLevel == 0)
1967 return XML_ERROR_NO_ELEMENTS;
1968 if (tagLevel != startTagLevel)
1969 return XML_ERROR_ASYNC_ENTITY;
1970 return XML_ERROR_NONE;
1974 return XML_ERROR_NONE;
1976 if (startTagLevel > 0) {
1977 if (tagLevel != startTagLevel)
1978 return XML_ERROR_ASYNC_ENTITY;
1979 return XML_ERROR_NONE;
1981 return XML_ERROR_NO_ELEMENTS;
1982 case XML_TOK_INVALID:
1984 return XML_ERROR_INVALID_TOKEN;
1985 case XML_TOK_PARTIAL:
1988 return XML_ERROR_NONE;
1990 return XML_ERROR_UNCLOSED_TOKEN;
1991 case XML_TOK_PARTIAL_CHAR:
1994 return XML_ERROR_NONE;
1996 return XML_ERROR_PARTIAL_CHAR;
1997 case XML_TOK_ENTITY_REF:
1999 const XML_Char *name;
2001 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
2002 s + enc->minBytesPerChar,
2003 next - enc->minBytesPerChar);
2005 if (characterDataHandler)
2006 characterDataHandler(handlerArg, &ch, 1);
2007 else if (defaultHandler)
2008 reportDefault(parser, enc, s, next);
2011 name = poolStoreString(&dtd->pool, enc,
2012 s + enc->minBytesPerChar,
2013 next - enc->minBytesPerChar);
2015 return XML_ERROR_NO_MEMORY;
2016 entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
2017 poolDiscard(&dtd->pool);
2018 /* First, determine if a check for an existing declaration is needed;
2019 if yes, check that the entity exists, and that it is internal,
2020 otherwise call the skipped entity or default handler.
2022 if (!dtd->hasParamEntityRefs || dtd->standalone) {
2024 return XML_ERROR_UNDEFINED_ENTITY;
2025 else if (!entity->is_internal)
2026 return XML_ERROR_ENTITY_DECLARED_IN_PE;
2029 if (skippedEntityHandler)
2030 skippedEntityHandler(handlerArg, name, 0);
2031 else if (defaultHandler)
2032 reportDefault(parser, enc, s, next);
2036 return XML_ERROR_RECURSIVE_ENTITY_REF;
2037 if (entity->notation)
2038 return XML_ERROR_BINARY_ENTITY_REF;
2039 if (entity->textPtr) {
2040 enum XML_Error result;
2041 OPEN_INTERNAL_ENTITY openEntity;
2042 if (!defaultExpandInternalEntities) {
2043 if (skippedEntityHandler)
2044 skippedEntityHandler(handlerArg, entity->name, 0);
2045 else if (defaultHandler)
2046 reportDefault(parser, enc, s, next);
2049 entity->open = XML_TRUE;
2050 openEntity.next = openInternalEntities;
2051 openInternalEntities = &openEntity;
2052 openEntity.entity = entity;
2053 openEntity.internalEventPtr = NULL;
2054 openEntity.internalEventEndPtr = NULL;
2055 result = doContent(parser,
2058 (char *)entity->textPtr,
2059 (char *)(entity->textPtr + entity->textLen),
2061 entity->open = XML_FALSE;
2062 openInternalEntities = openEntity.next;
2066 else if (externalEntityRefHandler) {
2067 const XML_Char *context;
2068 entity->open = XML_TRUE;
2069 context = getContext(parser);
2070 entity->open = XML_FALSE;
2072 return XML_ERROR_NO_MEMORY;
2073 if (!externalEntityRefHandler((XML_Parser)externalEntityRefHandlerArg,
2078 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2079 poolDiscard(&tempPool);
2081 else if (defaultHandler)
2082 reportDefault(parser, enc, s, next);
2085 case XML_TOK_START_TAG_NO_ATTS:
2087 case XML_TOK_START_TAG_WITH_ATTS:
2090 enum XML_Error result;
2094 freeTagList = freeTagList->parent;
2097 tag = (TAG *)MALLOC(sizeof(TAG));
2099 return XML_ERROR_NO_MEMORY;
2100 tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
2103 return XML_ERROR_NO_MEMORY;
2105 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2107 tag->bindings = NULL;
2108 tag->parent = tagStack;
2110 tag->name.localPart = NULL;
2111 tag->name.prefix = NULL;
2112 tag->rawName = s + enc->minBytesPerChar;
2113 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
2116 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2117 const char *fromPtr = tag->rawName;
2118 toPtr = (XML_Char *)tag->buf;
2123 &fromPtr, rawNameEnd,
2124 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
2125 convLen = toPtr - (XML_Char *)tag->buf;
2126 if (fromPtr == rawNameEnd) {
2127 tag->name.strLen = convLen;
2130 bufSize = (tag->bufEnd - tag->buf) << 1;
2132 char *temp = (char *)REALLOC(tag->buf, bufSize);
2134 return XML_ERROR_NO_MEMORY;
2136 tag->bufEnd = temp + bufSize;
2137 toPtr = (XML_Char *)temp + convLen;
2141 tag->name.str = (XML_Char *)tag->buf;
2142 *toPtr = XML_T('\0');
2143 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2146 if (startElementHandler)
2147 startElementHandler(handlerArg, tag->name.str,
2148 (const XML_Char **)atts);
2149 else if (defaultHandler)
2150 reportDefault(parser, enc, s, next);
2151 poolClear(&tempPool);
2154 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2156 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
2158 const char *rawName = s + enc->minBytesPerChar;
2159 enum XML_Error result;
2160 BINDING *bindings = NULL;
2161 XML_Bool noElmHandlers = XML_TRUE;
2163 name.str = poolStoreString(&tempPool, enc, rawName,
2164 rawName + XmlNameLength(enc, rawName));
2166 return XML_ERROR_NO_MEMORY;
2167 poolFinish(&tempPool);
2168 result = storeAtts(parser, enc, s, &name, &bindings);
2171 poolFinish(&tempPool);
2172 if (startElementHandler) {
2173 startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
2174 noElmHandlers = XML_FALSE;
2176 if (endElementHandler) {
2177 if (startElementHandler)
2178 *eventPP = *eventEndPP;
2179 endElementHandler(handlerArg, name.str);
2180 noElmHandlers = XML_FALSE;
2182 if (noElmHandlers && defaultHandler)
2183 reportDefault(parser, enc, s, next);
2184 poolClear(&tempPool);
2186 BINDING *b = bindings;
2187 if (endNamespaceDeclHandler)
2188 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2189 bindings = bindings->nextTagBinding;
2190 b->nextTagBinding = freeBindingList;
2191 freeBindingList = b;
2192 b->prefix->binding = b->prevPrefixBinding;
2196 return epilogProcessor(parser, next, end, nextPtr);
2198 case XML_TOK_END_TAG:
2199 if (tagLevel == startTagLevel)
2200 return XML_ERROR_ASYNC_ENTITY;
2203 const char *rawName;
2204 TAG *tag = tagStack;
2205 tagStack = tag->parent;
2206 tag->parent = freeTagList;
2208 rawName = s + enc->minBytesPerChar*2;
2209 len = XmlNameLength(enc, rawName);
2210 if (len != tag->rawNameLength
2211 || memcmp(tag->rawName, rawName, len) != 0) {
2213 return XML_ERROR_TAG_MISMATCH;
2216 if (endElementHandler) {
2217 const XML_Char *localPart;
2218 const XML_Char *prefix;
2220 localPart = tag->name.localPart;
2221 if (ns && localPart) {
2222 /* localPart and prefix may have been overwritten in
2223 tag->name.str, since this points to the binding->uri
2224 buffer which gets re-used; so we have to add them again
2226 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2227 /* don't need to check for space - already done in storeAtts() */
2228 while (*localPart) *uri++ = *localPart++;
2229 prefix = (XML_Char *)tag->name.prefix;
2230 if (ns_triplets && prefix) {
2231 *uri++ = namespaceSeparator;
2232 while (*prefix) *uri++ = *prefix++;
2236 endElementHandler(handlerArg, tag->name.str);
2238 else if (defaultHandler)
2239 reportDefault(parser, enc, s, next);
2240 while (tag->bindings) {
2241 BINDING *b = tag->bindings;
2242 if (endNamespaceDeclHandler)
2243 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2244 tag->bindings = tag->bindings->nextTagBinding;
2245 b->nextTagBinding = freeBindingList;
2246 freeBindingList = b;
2247 b->prefix->binding = b->prevPrefixBinding;
2250 return epilogProcessor(parser, next, end, nextPtr);
2253 case XML_TOK_CHAR_REF:
2255 int n = XmlCharRefNumber(enc, s);
2257 return XML_ERROR_BAD_CHAR_REF;
2258 if (characterDataHandler) {
2259 XML_Char buf[XML_ENCODE_MAX];
2260 characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
2262 else if (defaultHandler)
2263 reportDefault(parser, enc, s, next);
2266 case XML_TOK_XML_DECL:
2267 return XML_ERROR_MISPLACED_XML_PI;
2268 case XML_TOK_DATA_NEWLINE:
2269 if (characterDataHandler) {
2271 characterDataHandler(handlerArg, &c, 1);
2273 else if (defaultHandler)
2274 reportDefault(parser, enc, s, next);
2276 case XML_TOK_CDATA_SECT_OPEN:
2278 enum XML_Error result;
2279 if (startCdataSectionHandler)
2280 startCdataSectionHandler(handlerArg);
2282 /* Suppose you doing a transformation on a document that involves
2283 changing only the character data. You set up a defaultHandler
2284 and a characterDataHandler. The defaultHandler simply copies
2285 characters through. The characterDataHandler does the
2286 transformation and writes the characters out escaping them as
2287 necessary. This case will fail to work if we leave out the
2288 following two lines (because & and < inside CDATA sections will
2289 be incorrectly escaped).
2291 However, now we have a start/endCdataSectionHandler, so it seems
2292 easier to let the user deal with this.
2294 else if (characterDataHandler)
2295 characterDataHandler(handlerArg, dataBuf, 0);
2297 else if (defaultHandler)
2298 reportDefault(parser, enc, s, next);
2299 result = doCdataSection(parser, enc, &next, end, nextPtr);
2301 processor = cdataSectionProcessor;
2306 case XML_TOK_TRAILING_RSQB:
2309 return XML_ERROR_NONE;
2311 if (characterDataHandler) {
2312 if (MUST_CONVERT(enc, s)) {
2313 ICHAR *dataPtr = (ICHAR *)dataBuf;
2314 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
2315 characterDataHandler(handlerArg, dataBuf,
2316 dataPtr - (ICHAR *)dataBuf);
2319 characterDataHandler(handlerArg,
2321 (XML_Char *)end - (XML_Char *)s);
2323 else if (defaultHandler)
2324 reportDefault(parser, enc, s, end);
2325 if (startTagLevel == 0) {
2327 return XML_ERROR_NO_ELEMENTS;
2329 if (tagLevel != startTagLevel) {
2331 return XML_ERROR_ASYNC_ENTITY;
2333 return XML_ERROR_NONE;
2334 case XML_TOK_DATA_CHARS:
2335 if (characterDataHandler) {
2336 if (MUST_CONVERT(enc, s)) {
2338 ICHAR *dataPtr = (ICHAR *)dataBuf;
2339 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
2341 characterDataHandler(handlerArg, dataBuf,
2342 dataPtr - (ICHAR *)dataBuf);
2349 characterDataHandler(handlerArg,
2351 (XML_Char *)next - (XML_Char *)s);
2353 else if (defaultHandler)
2354 reportDefault(parser, enc, s, next);
2357 if (!reportProcessingInstruction(parser, enc, s, next))
2358 return XML_ERROR_NO_MEMORY;
2360 case XML_TOK_COMMENT:
2361 if (!reportComment(parser, enc, s, next))
2362 return XML_ERROR_NO_MEMORY;
2366 reportDefault(parser, enc, s, next);
2369 *eventPP = s = next;
2374 /* Precondition: all arguments must be non-NULL;
2376 - normalize attributes
2377 - check attributes for well-formedness
2378 - generate namespace aware attribute names (URI, prefix)
2379 - build list of attributes for startElementHandler
2380 - default attributes
2381 - process namespace declarations (check and report them)
2382 - generate namespace aware element name (URI, prefix)
2384 static enum XML_Error
2385 storeAtts(XML_Parser parser, const ENCODING *enc,
2386 const char *attStr, TAG_NAME *tagNamePtr,
2387 BINDING **bindingsPtr)
2389 DTD * const dtd = _dtd; /* save one level of indirection */
2390 ELEMENT_TYPE *elementType;
2392 const XML_Char **appAtts; /* the attribute list for the application */
2400 const XML_Char *localPart;
2402 /* lookup the element type name */
2403 elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0);
2405 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
2407 return XML_ERROR_NO_MEMORY;
2408 elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name,
2409 sizeof(ELEMENT_TYPE));
2411 return XML_ERROR_NO_MEMORY;
2412 if (ns && !setElementTypePrefix(parser, elementType))
2413 return XML_ERROR_NO_MEMORY;
2415 nDefaultAtts = elementType->nDefaultAtts;
2417 /* get the attributes from the tokenizer */
2418 n = XmlGetAttributes(enc, attStr, attsSize, atts);
2419 if (n + nDefaultAtts > attsSize) {
2420 int oldAttsSize = attsSize;
2422 attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
2423 temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
2425 return XML_ERROR_NO_MEMORY;
2427 if (n > oldAttsSize)
2428 XmlGetAttributes(enc, attStr, n, atts);
2431 appAtts = (const XML_Char **)atts;
2432 for (i = 0; i < n; i++) {
2433 /* add the name and value to the attribute list */
2434 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
2436 + XmlNameLength(enc, atts[i].name));
2438 return XML_ERROR_NO_MEMORY;
2439 /* Detect duplicate attributes by their QNames. This does not work when
2440 namespace processing is turned on and different prefixes for the same
2441 namespace are used. For this case we have a check further down.
2443 if ((attId->name)[-1]) {
2444 if (enc == encoding)
2445 eventPtr = atts[i].name;
2446 return XML_ERROR_DUPLICATE_ATTRIBUTE;
2448 (attId->name)[-1] = 1;
2449 appAtts[attIndex++] = attId->name;
2450 if (!atts[i].normalized) {
2451 enum XML_Error result;
2452 XML_Bool isCdata = XML_TRUE;
2454 /* figure out whether declared as other than CDATA */
2455 if (attId->maybeTokenized) {
2457 for (j = 0; j < nDefaultAtts; j++) {
2458 if (attId == elementType->defaultAtts[j].id) {
2459 isCdata = elementType->defaultAtts[j].isCdata;
2465 /* normalize the attribute value */
2466 result = storeAttributeValue(parser, enc, isCdata,
2467 atts[i].valuePtr, atts[i].valueEnd,
2471 appAtts[attIndex] = poolStart(&tempPool);
2472 poolFinish(&tempPool);
2475 /* the value did not need normalizing */
2476 appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
2478 if (appAtts[attIndex] == 0)
2479 return XML_ERROR_NO_MEMORY;
2480 poolFinish(&tempPool);
2482 /* handle prefixed attribute names */
2483 if (attId->prefix) {
2485 /* deal with namespace declarations here */
2486 enum XML_Error result = addBinding(parser, attId->prefix, attId,
2487 appAtts[attIndex], bindingsPtr);
2493 /* deal with other prefixed names later */
2496 (attId->name)[-1] = 2;
2503 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
2504 nSpecifiedAtts = attIndex;
2505 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
2506 for (i = 0; i < attIndex; i += 2)
2507 if (appAtts[i] == elementType->idAtt->name) {
2515 /* do attribute defaulting */
2516 for (i = 0; i < nDefaultAtts; i++) {
2517 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
2518 if (!(da->id->name)[-1] && da->value) {
2519 if (da->id->prefix) {
2520 if (da->id->xmlns) {
2521 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
2522 da->value, bindingsPtr);
2527 (da->id->name)[-1] = 2;
2529 appAtts[attIndex++] = da->id->name;
2530 appAtts[attIndex++] = da->value;
2534 (da->id->name)[-1] = 1;
2535 appAtts[attIndex++] = da->id->name;
2536 appAtts[attIndex++] = da->value;
2540 appAtts[attIndex] = 0;
2542 /* expand prefixed attribute names, check for duplicates,
2543 and clear flags that say whether attributes were specified */
2546 int j; /* hash table index */
2547 unsigned long version = nsAttsVersion;
2548 int nsAttsSize = (int)1 << nsAttsPower;
2549 /* size of hash table must be at least 2 * (# of prefixed attributes) */
2550 if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */
2552 /* hash table size must also be a power of 2 and >= 8 */
2553 while (nPrefixes >> nsAttsPower++);
2554 if (nsAttsPower < 3)
2556 nsAttsSize = (int)1 << nsAttsPower;
2557 temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
2559 return XML_ERROR_NO_MEMORY;
2561 version = 0; /* force re-initialization of nsAtts hash table */
2563 /* using a version flag saves us from initializing nsAtts every time */
2564 if (!version) { /* initialize version flags when version wraps around */
2565 version = INIT_ATTS_VERSION;
2566 for (j = nsAttsSize; j != 0; )
2567 nsAtts[--j].version = version;
2569 nsAttsVersion = --version;
2571 /* expand prefixed names and check for duplicates */
2572 for (; i < attIndex; i += 2) {
2573 const XML_Char *s = appAtts[i];
2574 if (s[-1] == 2) { /* prefixed */
2577 unsigned long uriHash = 0;
2578 ((XML_Char *)s)[-1] = 0; /* clear flag */
2579 id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);
2580 b = id->prefix->binding;
2582 return XML_ERROR_UNBOUND_PREFIX;
2584 /* as we expand the name we also calculate its hash value */
2585 for (j = 0; j < b->uriLen; j++) {
2586 const XML_Char c = b->uri[j];
2587 if (!poolAppendChar(&tempPool, c))
2588 return XML_ERROR_NO_MEMORY;
2589 uriHash = CHAR_HASH(uriHash, c);
2591 while (*s++ != XML_T(':'))
2593 do { /* copies null terminator */
2594 const XML_Char c = *s;
2595 if (!poolAppendChar(&tempPool, *s))
2596 return XML_ERROR_NO_MEMORY;
2597 uriHash = CHAR_HASH(uriHash, c);
2600 { /* Check hash table for duplicate of expanded name (uriName).
2601 Derived from code in lookup(HASH_TABLE *table, ...).
2603 unsigned char step = 0;
2604 unsigned long mask = nsAttsSize - 1;
2605 j = uriHash & mask; /* index into hash table */
2606 while (nsAtts[j].version == version) {
2607 /* for speed we compare stored hash values first */
2608 if (uriHash == nsAtts[j].hash) {
2609 const XML_Char *s1 = poolStart(&tempPool);
2610 const XML_Char *s2 = nsAtts[j].uriName;
2611 /* s1 is null terminated, but not s2 */
2612 for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
2614 return XML_ERROR_DUPLICATE_ATTRIBUTE;
2617 step = PROBE_STEP(uriHash, mask, nsAttsPower);
2618 j < step ? ( j += nsAttsSize - step) : (j -= step);
2622 if (ns_triplets) { /* append namespace separator and prefix */
2623 tempPool.ptr[-1] = namespaceSeparator;
2624 s = b->prefix->name;
2626 if (!poolAppendChar(&tempPool, *s))
2627 return XML_ERROR_NO_MEMORY;
2631 /* store expanded name in attribute list */
2632 s = poolStart(&tempPool);
2633 poolFinish(&tempPool);
2636 /* fill empty slot with new version, uriName and hash value */
2637 nsAtts[j].version = version;
2638 nsAtts[j].hash = uriHash;
2639 nsAtts[j].uriName = s;
2644 else /* not prefixed */
2645 ((XML_Char *)s)[-1] = 0; /* clear flag */
2648 /* clear flags for the remaining attributes */
2649 for (; i < attIndex; i += 2)
2650 ((XML_Char *)(appAtts[i]))[-1] = 0;
2651 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
2652 binding->attId->name[-1] = 0;
2655 return XML_ERROR_NONE;
2657 /* expand the element type name */
2658 if (elementType->prefix) {
2659 binding = elementType->prefix->binding;
2661 return XML_ERROR_UNBOUND_PREFIX;
2662 localPart = tagNamePtr->str;
2663 while (*localPart++ != XML_T(':'))
2666 else if (dtd->defaultPrefix.binding) {
2667 binding = dtd->defaultPrefix.binding;
2668 localPart = tagNamePtr->str;
2671 return XML_ERROR_NONE;
2673 if (ns_triplets && binding->prefix->name) {
2674 for (; binding->prefix->name[prefixLen++];)
2677 tagNamePtr->localPart = localPart;
2678 tagNamePtr->uriLen = binding->uriLen;
2679 tagNamePtr->prefix = binding->prefix->name;
2680 tagNamePtr->prefixLen = prefixLen;
2681 for (i = 0; localPart[i++];)
2683 n = i + binding->uriLen + prefixLen;
2684 if (n > binding->uriAlloc) {
2686 uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
2688 return XML_ERROR_NO_MEMORY;
2689 binding->uriAlloc = n + EXPAND_SPARE;
2690 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
2691 for (p = tagStack; p; p = p->parent)
2692 if (p->name.str == binding->uri)
2697 uri = binding->uri + binding->uriLen;
2698 memcpy(uri, localPart, i * sizeof(XML_Char));
2700 uri = uri + (i - 1);
2701 if (namespaceSeparator)
2702 *uri = namespaceSeparator;
2703 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
2705 tagNamePtr->str = binding->uri;
2706 return XML_ERROR_NONE;
2709 /* addBinding() overwrites the value of prefix->binding without checking.
2710 Therefore one must keep track of the old value outside of addBinding().
2712 static enum XML_Error
2713 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
2714 const XML_Char *uri, BINDING **bindingsPtr)
2719 /* empty string is only valid when there is no prefix per XML NS 1.0 */
2720 if (*uri == XML_T('\0') && prefix->name)
2721 return XML_ERROR_SYNTAX;
2723 for (len = 0; uri[len]; len++)
2725 if (namespaceSeparator)
2727 if (freeBindingList) {
2728 b = freeBindingList;
2729 if (len > b->uriAlloc) {
2730 XML_Char *temp = (XML_Char *)REALLOC(b->uri,
2731 sizeof(XML_Char) * (len + EXPAND_SPARE));
2733 return XML_ERROR_NO_MEMORY;
2735 b->uriAlloc = len + EXPAND_SPARE;
2737 freeBindingList = b->nextTagBinding;
2740 b = (BINDING *)MALLOC(sizeof(BINDING));
2742 return XML_ERROR_NO_MEMORY;
2743 b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
2746 return XML_ERROR_NO_MEMORY;
2748 b->uriAlloc = len + EXPAND_SPARE;
2751 memcpy(b->uri, uri, len * sizeof(XML_Char));
2752 if (namespaceSeparator)
2753 b->uri[len - 1] = namespaceSeparator;
2756 b->prevPrefixBinding = prefix->binding;
2757 /* NULL binding when default namespace undeclared */
2758 if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
2759 prefix->binding = NULL;
2761 prefix->binding = b;
2762 b->nextTagBinding = *bindingsPtr;
2764 if (startNamespaceDeclHandler)
2765 startNamespaceDeclHandler(handlerArg, prefix->name,
2766 prefix->binding ? uri : 0);
2767 return XML_ERROR_NONE;
2770 /* The idea here is to avoid using stack for each CDATA section when
2771 the whole file is parsed with one call.
2773 static enum XML_Error PTRCALL
2774 cdataSectionProcessor(XML_Parser parser,
2777 const char **endPtr)
2779 enum XML_Error result = doCdataSection(parser, encoding, &start,
2782 if (parentParser) { /* we are parsing an external entity */
2783 processor = externalEntityContentProcessor;
2784 return externalEntityContentProcessor(parser, start, end, endPtr);
2787 processor = contentProcessor;
2788 return contentProcessor(parser, start, end, endPtr);
2794 /* startPtr gets set to non-null is the section is closed, and to null if
2795 the section is not yet closed.
2797 static enum XML_Error
2798 doCdataSection(XML_Parser parser,
2799 const ENCODING *enc,
2800 const char **startPtr,
2802 const char **nextPtr)
2804 const char *s = *startPtr;
2805 const char **eventPP;
2806 const char **eventEndPP;
2807 if (enc == encoding) {
2808 eventPP = &eventPtr;
2810 eventEndPP = &eventEndPtr;
2813 eventPP = &(openInternalEntities->internalEventPtr);
2814 eventEndPP = &(openInternalEntities->internalEventEndPtr);
2820 int tok = XmlCdataSectionTok(enc, s, end, &next);
2823 case XML_TOK_CDATA_SECT_CLOSE:
2824 if (endCdataSectionHandler)
2825 endCdataSectionHandler(handlerArg);
2827 /* see comment under XML_TOK_CDATA_SECT_OPEN */
2828 else if (characterDataHandler)
2829 characterDataHandler(handlerArg, dataBuf, 0);
2831 else if (defaultHandler)
2832 reportDefault(parser, enc, s, next);
2834 return XML_ERROR_NONE;
2835 case XML_TOK_DATA_NEWLINE:
2836 if (characterDataHandler) {
2838 characterDataHandler(handlerArg, &c, 1);
2840 else if (defaultHandler)
2841 reportDefault(parser, enc, s, next);
2843 case XML_TOK_DATA_CHARS:
2844 if (characterDataHandler) {
2845 if (MUST_CONVERT(enc, s)) {
2847 ICHAR *dataPtr = (ICHAR *)dataBuf;
2848 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
2850 characterDataHandler(handlerArg, dataBuf,
2851 dataPtr - (ICHAR *)dataBuf);
2858 characterDataHandler(handlerArg,
2860 (XML_Char *)next - (XML_Char *)s);
2862 else if (defaultHandler)
2863 reportDefault(parser, enc, s, next);
2865 case XML_TOK_INVALID:
2867 return XML_ERROR_INVALID_TOKEN;
2868 case XML_TOK_PARTIAL_CHAR:
2871 return XML_ERROR_NONE;
2873 return XML_ERROR_PARTIAL_CHAR;
2874 case XML_TOK_PARTIAL:
2878 return XML_ERROR_NONE;
2880 return XML_ERROR_UNCLOSED_CDATA_SECTION;
2883 return XML_ERROR_UNEXPECTED_STATE;
2885 *eventPP = s = next;
2892 /* The idea here is to avoid using stack for each IGNORE section when
2893 the whole file is parsed with one call.
2895 static enum XML_Error PTRCALL
2896 ignoreSectionProcessor(XML_Parser parser,
2899 const char **endPtr)
2901 enum XML_Error result = doIgnoreSection(parser, encoding, &start,
2904 processor = prologProcessor;
2905 return prologProcessor(parser, start, end, endPtr);
2910 /* startPtr gets set to non-null is the section is closed, and to null
2911 if the section is not yet closed.
2913 static enum XML_Error
2914 doIgnoreSection(XML_Parser parser,
2915 const ENCODING *enc,
2916 const char **startPtr,
2918 const char **nextPtr)
2922 const char *s = *startPtr;
2923 const char **eventPP;
2924 const char **eventEndPP;
2925 if (enc == encoding) {
2926 eventPP = &eventPtr;
2928 eventEndPP = &eventEndPtr;
2931 eventPP = &(openInternalEntities->internalEventPtr);
2932 eventEndPP = &(openInternalEntities->internalEventEndPtr);
2936 tok = XmlIgnoreSectionTok(enc, s, end, &next);
2939 case XML_TOK_IGNORE_SECT:
2941 reportDefault(parser, enc, s, next);
2943 return XML_ERROR_NONE;
2944 case XML_TOK_INVALID:
2946 return XML_ERROR_INVALID_TOKEN;
2947 case XML_TOK_PARTIAL_CHAR:
2950 return XML_ERROR_NONE;
2952 return XML_ERROR_PARTIAL_CHAR;
2953 case XML_TOK_PARTIAL:
2957 return XML_ERROR_NONE;
2959 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
2962 return XML_ERROR_UNEXPECTED_STATE;
2967 #endif /* XML_DTD */
2969 static enum XML_Error
2970 initializeEncoding(XML_Parser parser)
2974 char encodingBuf[128];
2975 if (!protocolEncodingName)
2979 for (i = 0; protocolEncodingName[i]; i++) {
2980 if (i == sizeof(encodingBuf) - 1
2981 || (protocolEncodingName[i] & ~0x7f) != 0) {
2982 encodingBuf[0] = '\0';
2985 encodingBuf[i] = (char)protocolEncodingName[i];
2987 encodingBuf[i] = '\0';
2991 s = protocolEncodingName;
2993 if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
2994 return XML_ERROR_NONE;
2995 return handleUnknownEncoding(parser, protocolEncodingName);
2998 static enum XML_Error
2999 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
3000 const char *s, const char *next)
3002 const char *encodingName = NULL;
3003 const XML_Char *storedEncName = NULL;
3004 const ENCODING *newEncoding = NULL;
3005 const char *version = NULL;
3006 const char *versionend;
3007 const XML_Char *storedversion = NULL;
3008 int standalone = -1;
3011 : XmlParseXmlDecl)(isGeneralTextEntity,
3021 return XML_ERROR_SYNTAX;
3022 if (!isGeneralTextEntity && standalone == 1) {
3023 _dtd->standalone = XML_TRUE;
3025 if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
3026 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
3027 #endif /* XML_DTD */
3029 if (xmlDeclHandler) {
3030 if (encodingName != NULL) {
3031 storedEncName = poolStoreString(&temp2Pool,
3035 + XmlNameLength(encoding, encodingName));
3037 return XML_ERROR_NO_MEMORY;
3038 poolFinish(&temp2Pool);
3041 storedversion = poolStoreString(&temp2Pool,
3044 versionend - encoding->minBytesPerChar);
3046 return XML_ERROR_NO_MEMORY;
3048 xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
3050 else if (defaultHandler)
3051 reportDefault(parser, encoding, s, next);
3052 if (protocolEncodingName == NULL) {
3054 if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
3055 eventPtr = encodingName;
3056 return XML_ERROR_INCORRECT_ENCODING;
3058 encoding = newEncoding;
3060 else if (encodingName) {
3061 enum XML_Error result;
3062 if (!storedEncName) {
3063 storedEncName = poolStoreString(
3064 &temp2Pool, encoding, encodingName,
3065 encodingName + XmlNameLength(encoding, encodingName));
3067 return XML_ERROR_NO_MEMORY;
3069 result = handleUnknownEncoding(parser, storedEncName);
3070 poolClear(&temp2Pool);
3071 if (result == XML_ERROR_UNKNOWN_ENCODING)
3072 eventPtr = encodingName;
3077 if (storedEncName || storedversion)
3078 poolClear(&temp2Pool);
3080 return XML_ERROR_NONE;
3083 static enum XML_Error
3084 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
3086 if (unknownEncodingHandler) {
3089 for (i = 0; i < 256; i++)
3091 info.convert = NULL;
3093 info.release = NULL;
3094 if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
3097 unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
3098 if (!unknownEncodingMem) {
3100 info.release(info.data);
3101 return XML_ERROR_NO_MEMORY;
3104 ? XmlInitUnknownEncodingNS
3105 : XmlInitUnknownEncoding)(unknownEncodingMem,
3110 unknownEncodingData = info.data;
3111 unknownEncodingRelease = info.release;
3113 return XML_ERROR_NONE;
3116 if (info.release != NULL)
3117 info.release(info.data);
3119 return XML_ERROR_UNKNOWN_ENCODING;
3122 static enum XML_Error PTRCALL
3123 prologInitProcessor(XML_Parser parser,
3126 const char **nextPtr)
3128 enum XML_Error result = initializeEncoding(parser);
3129 if (result != XML_ERROR_NONE)
3131 processor = prologProcessor;
3132 return prologProcessor(parser, s, end, nextPtr);
3137 static enum XML_Error PTRCALL
3138 externalParEntInitProcessor(XML_Parser parser,
3141 const char **nextPtr)
3143 enum XML_Error result = initializeEncoding(parser);
3144 if (result != XML_ERROR_NONE)
3147 /* we know now that XML_Parse(Buffer) has been called,
3148 so we consider the external parameter entity read */
3149 _dtd->paramEntityRead = XML_TRUE;
3151 if (prologState.inEntityValue) {
3152 processor = entityValueInitProcessor;
3153 return entityValueInitProcessor(parser, s, end, nextPtr);
3156 processor = externalParEntProcessor;
3157 return externalParEntProcessor(parser, s, end, nextPtr);
3161 static enum XML_Error PTRCALL
3162 entityValueInitProcessor(XML_Parser parser,
3165 const char **nextPtr)
3167 const char *start = s;
3168 const char *next = s;
3172 tok = XmlPrologTok(encoding, start, end, &next);
3174 if (nextPtr != 0 && tok != XML_TOK_INVALID) {
3176 return XML_ERROR_NONE;
3179 case XML_TOK_INVALID:
3180 return XML_ERROR_INVALID_TOKEN;
3181 case XML_TOK_PARTIAL:
3182 return XML_ERROR_UNCLOSED_TOKEN;
3183 case XML_TOK_PARTIAL_CHAR:
3184 return XML_ERROR_PARTIAL_CHAR;
3185 case XML_TOK_NONE: /* start == end */
3189 return storeEntityValue(parser, encoding, s, end);
3191 else if (tok == XML_TOK_XML_DECL) {
3192 enum XML_Error result = processXmlDecl(parser, 0, start, next);
3193 if (result != XML_ERROR_NONE)
3195 if (nextPtr) *nextPtr = next;
3196 /* stop scanning for text declaration - we found one */
3197 processor = entityValueProcessor;
3198 return entityValueProcessor(parser, next, end, nextPtr);
3200 /* If we are at the end of the buffer, this would cause XmlPrologTok to
3201 return XML_TOK_NONE on the next call, which would then cause the
3202 function to exit with *nextPtr set to s - that is what we want for other
3203 tokens, but not for the BOM - we would rather like to skip it;
3204 then, when this routine is entered the next time, XmlPrologTok will
3205 return XML_TOK_INVALID, since the BOM is still in the buffer
3207 else if (tok == XML_TOK_BOM && next == end && nextPtr) {
3209 return XML_ERROR_NONE;
3215 static enum XML_Error PTRCALL
3216 externalParEntProcessor(XML_Parser parser,
3219 const char **nextPtr)
3221 const char *start = s;
3222 const char *next = s;
3225 tok = XmlPrologTok(encoding, start, end, &next);
3227 if (nextPtr != 0 && tok != XML_TOK_INVALID) {
3229 return XML_ERROR_NONE;
3232 case XML_TOK_INVALID:
3233 return XML_ERROR_INVALID_TOKEN;
3234 case XML_TOK_PARTIAL:
3235 return XML_ERROR_UNCLOSED_TOKEN;
3236 case XML_TOK_PARTIAL_CHAR:
3237 return XML_ERROR_PARTIAL_CHAR;
3238 case XML_TOK_NONE: /* start == end */
3243 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
3244 However, when parsing an external subset, doProlog will not accept a BOM
3245 as valid, and report a syntax error, so we have to skip the BOM
3247 else if (tok == XML_TOK_BOM) {
3249 tok = XmlPrologTok(encoding, s, end, &next);
3252 processor = prologProcessor;
3253 return doProlog(parser, encoding, s, end, tok, next, nextPtr);
3256 static enum XML_Error PTRCALL
3257 entityValueProcessor(XML_Parser parser,
3260 const char **nextPtr)
3262 const char *start = s;
3263 const char *next = s;
3264 const ENCODING *enc = encoding;
3268 tok = XmlPrologTok(enc, start, end, &next);
3270 if (nextPtr != 0 && tok != XML_TOK_INVALID) {
3272 return XML_ERROR_NONE;
3275 case XML_TOK_INVALID:
3276 return XML_ERROR_INVALID_TOKEN;
3277 case XML_TOK_PARTIAL:
3278 return XML_ERROR_UNCLOSED_TOKEN;
3279 case XML_TOK_PARTIAL_CHAR:
3280 return XML_ERROR_PARTIAL_CHAR;
3281 case XML_TOK_NONE: /* start == end */
3285 return storeEntityValue(parser, enc, s, end);
3291 #endif /* XML_DTD */
3293 static enum XML_Error PTRCALL
3294 prologProcessor(XML_Parser parser,
3297 const char **nextPtr)
3299 const char *next = s;
3300 int tok = XmlPrologTok(encoding, s, end, &next);
3301 return doProlog(parser, encoding, s, end, tok, next, nextPtr);
3304 static enum XML_Error
3305 doProlog(XML_Parser parser,
3306 const ENCODING *enc,
3311 const char **nextPtr)
3314 static const XML_Char externalSubsetName[] = { '#' , '\0' };
3315 #endif /* XML_DTD */
3316 static const XML_Char atypeCDATA[] = { 'C', 'D', 'A', 'T', 'A', '\0' };
3317 static const XML_Char atypeID[] = { 'I', 'D', '\0' };
3318 static const XML_Char atypeIDREF[] = { 'I', 'D', 'R', 'E', 'F', '\0' };
3319 static const XML_Char atypeIDREFS[] = { 'I', 'D', 'R', 'E', 'F', 'S', '\0' };
3320 static const XML_Char atypeENTITY[] = { 'E', 'N', 'T', 'I', 'T', 'Y', '\0' };
3321 static const XML_Char atypeENTITIES[] =
3322 { 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S', '\0' };
3323 static const XML_Char atypeNMTOKEN[] = {
3324 'N', 'M', 'T', 'O', 'K', 'E', 'N', '\0' };
3325 static const XML_Char atypeNMTOKENS[] = {
3326 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S', '\0' };
3327 static const XML_Char notationPrefix[] = {
3328 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', '(', '\0' };
3329 static const XML_Char enumValueSep[] = { '|', '\0' };
3330 static const XML_Char enumValueStart[] = { '(', '\0' };
3332 DTD * const dtd = _dtd; /* save one level of indirection */
3334 const char **eventPP;
3335 const char **eventEndPP;
3336 enum XML_Content_Quant quant;
3338 if (enc == encoding) {
3339 eventPP = &eventPtr;
3340 eventEndPP = &eventEndPtr;
3343 eventPP = &(openInternalEntities->internalEventPtr);
3344 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3348 XML_Bool handleDefault = XML_TRUE;
3352 if (nextPtr != 0 && tok != XML_TOK_INVALID) {
3354 return XML_ERROR_NONE;
3357 case XML_TOK_INVALID:
3359 return XML_ERROR_INVALID_TOKEN;
3360 case XML_TOK_PARTIAL:
3361 return XML_ERROR_UNCLOSED_TOKEN;
3362 case XML_TOK_PARTIAL_CHAR:
3363 return XML_ERROR_PARTIAL_CHAR;
3364 case -XML_TOK_PROLOG_S:
3369 if (enc != encoding)
3370 return XML_ERROR_NONE;
3371 if (isParamEntity) {
3372 if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
3374 return XML_ERROR_SYNTAX;
3375 return XML_ERROR_NONE;
3377 #endif /* XML_DTD */
3378 return XML_ERROR_NO_ELEMENTS;
3385 role = XmlTokenRole(&prologState, tok, s, next, enc);
3387 case XML_ROLE_XML_DECL:
3389 enum XML_Error result = processXmlDecl(parser, 0, s, next);
3390 if (result != XML_ERROR_NONE)
3393 handleDefault = XML_FALSE;
3396 case XML_ROLE_DOCTYPE_NAME:
3397 if (startDoctypeDeclHandler) {
3398 doctypeName = poolStoreString(&tempPool, enc, s, next);
3400 return XML_ERROR_NO_MEMORY;
3401 poolFinish(&tempPool);
3402 doctypePubid = NULL;
3403 handleDefault = XML_FALSE;
3405 doctypeSysid = NULL; /* always initialize to NULL */
3407 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
3408 if (startDoctypeDeclHandler) {
3409 startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
3412 poolClear(&tempPool);
3413 handleDefault = XML_FALSE;
3417 case XML_ROLE_TEXT_DECL:
3419 enum XML_Error result = processXmlDecl(parser, 1, s, next);
3420 if (result != XML_ERROR_NONE)
3423 handleDefault = XML_FALSE;
3426 #endif /* XML_DTD */
3427 case XML_ROLE_DOCTYPE_PUBLIC_ID:
3429 useForeignDTD = XML_FALSE;
3430 #endif /* XML_DTD */
3431 dtd->hasParamEntityRefs = XML_TRUE;
3432 if (startDoctypeDeclHandler) {
3433 doctypePubid = poolStoreString(&tempPool, enc,
3434 s + enc->minBytesPerChar,
3435 next - enc->minBytesPerChar);
3437 return XML_ERROR_NO_MEMORY;
3438 poolFinish(&tempPool);
3439 handleDefault = XML_FALSE;
3442 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
3446 return XML_ERROR_NO_MEMORY;
3447 #endif /* XML_DTD */
3449 case XML_ROLE_ENTITY_PUBLIC_ID:
3450 if (!XmlIsPublicId(enc, s, next, eventPP))
3451 return XML_ERROR_SYNTAX;
3452 if (dtd->keepProcessing && declEntity) {
3453 XML_Char *tem = poolStoreString(&dtd->pool,
3455 s + enc->minBytesPerChar,
3456 next - enc->minBytesPerChar);
3458 return XML_ERROR_NO_MEMORY;
3459 normalizePublicId(tem);
3460 declEntity->publicId = tem;
3461 poolFinish(&dtd->pool);
3462 if (entityDeclHandler)
3463 handleDefault = XML_FALSE;
3466 case XML_ROLE_DOCTYPE_CLOSE:
3468 startDoctypeDeclHandler(handlerArg, doctypeName,
3469 doctypeSysid, doctypePubid, 0);
3470 poolClear(&tempPool);
3471 handleDefault = XML_FALSE;
3473 /* doctypeSysid will be non-NULL in the case of a previous
3474 XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
3475 was not set, indicating an external subset
3478 if (doctypeSysid || useForeignDTD) {
3479 dtd->hasParamEntityRefs = XML_TRUE; /* when docTypeSysid == NULL */
3480 if (paramEntityParsing && externalEntityRefHandler) {
3481 ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
3485 return XML_ERROR_NO_MEMORY;
3487 entity->base = curBase;
3488 dtd->paramEntityRead = XML_FALSE;
3489 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3494 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3495 if (dtd->paramEntityRead &&
3497 notStandaloneHandler &&
3498 !notStandaloneHandler(handlerArg))
3499 return XML_ERROR_NOT_STANDALONE;
3500 /* end of DTD - no need to update dtd->keepProcessing */
3502 useForeignDTD = XML_FALSE;
3504 #endif /* XML_DTD */
3505 if (endDoctypeDeclHandler) {
3506 endDoctypeDeclHandler(handlerArg);
3507 handleDefault = XML_FALSE;
3510 case XML_ROLE_INSTANCE_START:
3512 /* if there is no DOCTYPE declaration then now is the
3513 last chance to read the foreign DTD
3515 if (useForeignDTD) {
3516 dtd->hasParamEntityRefs = XML_TRUE;
3517 if (paramEntityParsing && externalEntityRefHandler) {
3518 ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
3522 return XML_ERROR_NO_MEMORY;
3523 entity->base = curBase;
3524 dtd->paramEntityRead = XML_FALSE;
3525 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3530 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3531 if (dtd->paramEntityRead &&
3533 notStandaloneHandler &&
3534 !notStandaloneHandler(handlerArg))
3535 return XML_ERROR_NOT_STANDALONE;
3536 /* end of DTD - no need to update dtd->keepProcessing */
3539 #endif /* XML_DTD */
3540 processor = contentProcessor;
3541 return contentProcessor(parser, s, end, nextPtr);
3542 case XML_ROLE_ATTLIST_ELEMENT_NAME:
3543 declElementType = getElementType(parser, enc, s, next);
3544 if (!declElementType)
3545 return XML_ERROR_NO_MEMORY;
3546 goto checkAttListDeclHandler;
3547 case XML_ROLE_ATTRIBUTE_NAME:
3548 declAttributeId = getAttributeId(parser, enc, s, next);
3549 if (!declAttributeId)
3550 return XML_ERROR_NO_MEMORY;
3551 declAttributeIsCdata = XML_FALSE;
3552 declAttributeType = NULL;
3553 declAttributeIsId = XML_FALSE;
3554 goto checkAttListDeclHandler;
3555 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
3556 declAttributeIsCdata = XML_TRUE;
3557 declAttributeType = atypeCDATA;
3558 goto checkAttListDeclHandler;
3559 case XML_ROLE_ATTRIBUTE_TYPE_ID:
3560 declAttributeIsId = XML_TRUE;
3561 declAttributeType = atypeID;
3562 goto checkAttListDeclHandler;
3563 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
3564 declAttributeType = atypeIDREF;
3565 goto checkAttListDeclHandler;
3566 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
3567 declAttributeType = atypeIDREFS;
3568 goto checkAttListDeclHandler;
3569 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
3570 declAttributeType = atypeENTITY;
3571 goto checkAttListDeclHandler;
3572 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
3573 declAttributeType = atypeENTITIES;
3574 goto checkAttListDeclHandler;
3575 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
3576 declAttributeType = atypeNMTOKEN;
3577 goto checkAttListDeclHandler;
3578 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
3579 declAttributeType = atypeNMTOKENS;
3580 checkAttListDeclHandler:
3581 if (dtd->keepProcessing && attlistDeclHandler)
3582 handleDefault = XML_FALSE;
3584 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
3585 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
3586 if (dtd->keepProcessing && attlistDeclHandler) {
3587 const XML_Char *prefix;
3588 if (declAttributeType) {
3589 prefix = enumValueSep;
3592 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
3596 if (!poolAppendString(&tempPool, prefix))
3597 return XML_ERROR_NO_MEMORY;
3598 if (!poolAppend(&tempPool, enc, s, next))
3599 return XML_ERROR_NO_MEMORY;
3600 declAttributeType = tempPool.start;
3601 handleDefault = XML_FALSE;
3604 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
3605 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
3606 if (dtd->keepProcessing) {
3607 if (!defineAttribute(declElementType, declAttributeId,
3608 declAttributeIsCdata, declAttributeIsId,
3610 return XML_ERROR_NO_MEMORY;
3611 if (attlistDeclHandler && declAttributeType) {
3612 if (*declAttributeType == XML_T('(')
3613 || (*declAttributeType == XML_T('N')
3614 && declAttributeType[1] == XML_T('O'))) {
3615 /* Enumerated or Notation type */
3616 if (!poolAppendChar(&tempPool, XML_T(')'))
3617 || !poolAppendChar(&tempPool, XML_T('\0')))
3618 return XML_ERROR_NO_MEMORY;
3619 declAttributeType = tempPool.start;
3620 poolFinish(&tempPool);
3623 attlistDeclHandler(handlerArg, declElementType->name,
3624 declAttributeId->name, declAttributeType,
3625 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
3626 poolClear(&tempPool);
3627 handleDefault = XML_FALSE;
3631 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
3632 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
3633 if (dtd->keepProcessing) {
3634 const XML_Char *attVal;
3635 enum XML_Error result =
3636 storeAttributeValue(parser, enc, declAttributeIsCdata,
3637 s + enc->minBytesPerChar,
3638 next - enc->minBytesPerChar,
3642 attVal = poolStart(&dtd->pool);
3643 poolFinish(&dtd->pool);
3644 /* ID attributes aren't allowed to have a default */
3645 if (!defineAttribute(declElementType, declAttributeId,
3646 declAttributeIsCdata, XML_FALSE, attVal, parser))
3647 return XML_ERROR_NO_MEMORY;
3648 if (attlistDeclHandler && declAttributeType) {
3649 if (*declAttributeType == XML_T('(')
3650 || (*declAttributeType == XML_T('N')
3651 && declAttributeType[1] == XML_T('O'))) {
3652 /* Enumerated or Notation type */
3653 if (!poolAppendChar(&tempPool, XML_T(')'))
3654 || !poolAppendChar(&tempPool, XML_T('\0')))
3655 return XML_ERROR_NO_MEMORY;
3656 declAttributeType = tempPool.start;
3657 poolFinish(&tempPool);
3660 attlistDeclHandler(handlerArg, declElementType->name,
3661 declAttributeId->name, declAttributeType,
3663 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
3664 poolClear(&tempPool);
3665 handleDefault = XML_FALSE;
3669 case XML_ROLE_ENTITY_VALUE:
3670 if (dtd->keepProcessing) {
3671 enum XML_Error result = storeEntityValue(parser, enc,
3672 s + enc->minBytesPerChar,
3673 next - enc->minBytesPerChar);
3675 declEntity->textPtr = poolStart(&dtd->entityValuePool);
3676 declEntity->textLen = poolLength(&dtd->entityValuePool);
3677 poolFinish(&dtd->entityValuePool);
3678 if (entityDeclHandler) {
3680 entityDeclHandler(handlerArg,
3682 declEntity->is_param,
3683 declEntity->textPtr,
3684 declEntity->textLen,
3686 handleDefault = XML_FALSE;
3690 poolDiscard(&dtd->entityValuePool);
3691 if (result != XML_ERROR_NONE)
3695 case XML_ROLE_DOCTYPE_SYSTEM_ID:
3697 useForeignDTD = XML_FALSE;
3698 #endif /* XML_DTD */
3699 dtd->hasParamEntityRefs = XML_TRUE;
3700 if (startDoctypeDeclHandler) {
3701 doctypeSysid = poolStoreString(&tempPool, enc,
3702 s + enc->minBytesPerChar,
3703 next - enc->minBytesPerChar);
3704 if (doctypeSysid == NULL)
3705 return XML_ERROR_NO_MEMORY;
3706 poolFinish(&tempPool);
3707 handleDefault = XML_FALSE;
3711 /* use externalSubsetName to make doctypeSysid non-NULL
3712 for the case where no startDoctypeDeclHandler is set */
3713 doctypeSysid = externalSubsetName;
3714 #endif /* XML_DTD */
3715 if (!dtd->standalone
3717 && !paramEntityParsing
3718 #endif /* XML_DTD */
3719 && notStandaloneHandler
3720 && !notStandaloneHandler(handlerArg))
3721 return XML_ERROR_NOT_STANDALONE;
3726 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
3730 return XML_ERROR_NO_MEMORY;
3731 declEntity->publicId = NULL;
3734 #endif /* XML_DTD */
3735 case XML_ROLE_ENTITY_SYSTEM_ID:
3736 if (dtd->keepProcessing && declEntity) {
3737 declEntity->systemId = poolStoreString(&dtd->pool, enc,
3738 s + enc->minBytesPerChar,
3739 next - enc->minBytesPerChar);
3740 if (!declEntity->systemId)
3741 return XML_ERROR_NO_MEMORY;
3742 declEntity->base = curBase;
3743 poolFinish(&dtd->pool);
3744 if (entityDeclHandler)
3745 handleDefault = XML_FALSE;
3748 case XML_ROLE_ENTITY_COMPLETE:
3749 if (dtd->keepProcessing && declEntity && entityDeclHandler) {
3751 entityDeclHandler(handlerArg,
3753 declEntity->is_param,
3756 declEntity->systemId,
3757 declEntity->publicId,
3759 handleDefault = XML_FALSE;
3762 case XML_ROLE_ENTITY_NOTATION_NAME:
3763 if (dtd->keepProcessing && declEntity) {
3764 declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
3765 if (!declEntity->notation)
3766 return XML_ERROR_NO_MEMORY;
3767 poolFinish(&dtd->pool);
3768 if (unparsedEntityDeclHandler) {
3770 unparsedEntityDeclHandler(handlerArg,
3773 declEntity->systemId,
3774 declEntity->publicId,
3775 declEntity->notation);
3776 handleDefault = XML_FALSE;
3778 else if (entityDeclHandler) {
3780 entityDeclHandler(handlerArg,
3784 declEntity->systemId,
3785 declEntity->publicId,
3786 declEntity->notation);
3787 handleDefault = XML_FALSE;
3791 case XML_ROLE_GENERAL_ENTITY_NAME:
3793 if (XmlPredefinedEntityName(enc, s, next)) {
3797 if (dtd->keepProcessing) {
3798 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
3800 return XML_ERROR_NO_MEMORY;
3801 declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
3804 return XML_ERROR_NO_MEMORY;
3805 if (declEntity->name != name) {
3806 poolDiscard(&dtd->pool);
3810 poolFinish(&dtd->pool);
3811 declEntity->publicId = NULL;
3812 declEntity->is_param = XML_FALSE;
3813 /* if we have a parent parser or are reading an internal parameter
3814 entity, then the entity declaration is not considered "internal"
3816 declEntity->is_internal = !(parentParser || openInternalEntities);
3817 if (entityDeclHandler)
3818 handleDefault = XML_FALSE;
3822 poolDiscard(&dtd->pool);
3827 case XML_ROLE_PARAM_ENTITY_NAME:
3829 if (dtd->keepProcessing) {
3830 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
3832 return XML_ERROR_NO_MEMORY;
3833 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
3834 name, sizeof(ENTITY));
3836 return XML_ERROR_NO_MEMORY;
3837 if (declEntity->name != name) {
3838 poolDiscard(&dtd->pool);
3842 poolFinish(&dtd->pool);
3843 declEntity->publicId = NULL;
3844 declEntity->is_param = XML_TRUE;
3845 /* if we have a parent parser or are reading an internal parameter
3846 entity, then the entity declaration is not considered "internal"
3848 declEntity->is_internal = !(parentParser || openInternalEntities);
3849 if (entityDeclHandler)
3850 handleDefault = XML_FALSE;
3854 poolDiscard(&dtd->pool);
3857 #else /* not XML_DTD */
3859 #endif /* XML_DTD */
3861 case XML_ROLE_NOTATION_NAME:
3862 declNotationPublicId = NULL;
3863 declNotationName = NULL;
3864 if (notationDeclHandler) {
3865 declNotationName = poolStoreString(&tempPool, enc, s, next);
3866 if (!declNotationName)
3867 return XML_ERROR_NO_MEMORY;
3868 poolFinish(&tempPool);
3869 handleDefault = XML_FALSE;
3872 case XML_ROLE_NOTATION_PUBLIC_ID:
3873 if (!XmlIsPublicId(enc, s, next, eventPP))
3874 return XML_ERROR_SYNTAX;
3875 if (declNotationName) { /* means notationDeclHandler != NULL */
3876 XML_Char *tem = poolStoreString(&tempPool,
3878 s + enc->minBytesPerChar,
3879 next - enc->minBytesPerChar);
3881 return XML_ERROR_NO_MEMORY;
3882 normalizePublicId(tem);
3883 declNotationPublicId = tem;
3884 poolFinish(&tempPool);
3885 handleDefault = XML_FALSE;
3888 case XML_ROLE_NOTATION_SYSTEM_ID:
3889 if (declNotationName && notationDeclHandler) {
3890 const XML_Char *systemId
3891 = poolStoreString(&tempPool, enc,
3892 s + enc->minBytesPerChar,
3893 next - enc->minBytesPerChar);
3895 return XML_ERROR_NO_MEMORY;
3897 notationDeclHandler(handlerArg,
3901 declNotationPublicId);
3902 handleDefault = XML_FALSE;
3904 poolClear(&tempPool);
3906 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
3907 if (declNotationPublicId && notationDeclHandler) {
3909 notationDeclHandler(handlerArg,
3913 declNotationPublicId);
3914 handleDefault = XML_FALSE;
3916 poolClear(&tempPool);
3918 case XML_ROLE_ERROR:
3920 case XML_TOK_PARAM_ENTITY_REF:
3921 return XML_ERROR_PARAM_ENTITY_REF;
3922 case XML_TOK_XML_DECL:
3923 return XML_ERROR_MISPLACED_XML_PI;
3925 return XML_ERROR_SYNTAX;
3928 case XML_ROLE_IGNORE_SECT:
3930 enum XML_Error result;
3932 reportDefault(parser, enc, s, next);
3933 handleDefault = XML_FALSE;
3934 result = doIgnoreSection(parser, enc, &next, end, nextPtr);
3936 processor = ignoreSectionProcessor;
3941 #endif /* XML_DTD */
3942 case XML_ROLE_GROUP_OPEN:
3943 if (prologState.level >= groupSize) {
3945 char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
3947 return XML_ERROR_NO_MEMORY;
3948 groupConnector = temp;
3949 if (dtd->scaffIndex) {
3950 int *temp = (int *)REALLOC(dtd->scaffIndex,
3951 groupSize * sizeof(int));
3953 return XML_ERROR_NO_MEMORY;
3954 dtd->scaffIndex = temp;
3958 groupConnector = (char *)MALLOC(groupSize = 32);
3959 if (!groupConnector)
3960 return XML_ERROR_NO_MEMORY;
3963 groupConnector[prologState.level] = 0;
3964 if (dtd->in_eldecl) {
3965 int myindex = nextScaffoldPart(parser);
3967 return XML_ERROR_NO_MEMORY;
3968 dtd->scaffIndex[dtd->scaffLevel] = myindex;
3970 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
3971 if (elementDeclHandler)
3972 handleDefault = XML_FALSE;
3975 case XML_ROLE_GROUP_SEQUENCE:
3976 if (groupConnector[prologState.level] == '|')
3977 return XML_ERROR_SYNTAX;
3978 groupConnector[prologState.level] = ',';
3979 if (dtd->in_eldecl && elementDeclHandler)
3980 handleDefault = XML_FALSE;
3982 case XML_ROLE_GROUP_CHOICE:
3983 if (groupConnector[prologState.level] == ',')
3984 return XML_ERROR_SYNTAX;
3986 && !groupConnector[prologState.level]
3987 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
3990 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
3992 if (elementDeclHandler)
3993 handleDefault = XML_FALSE;
3995 groupConnector[prologState.level] = '|';
3997 case XML_ROLE_PARAM_ENTITY_REF:
3999 case XML_ROLE_INNER_PARAM_ENTITY_REF:
4000 /* PE references in internal subset are
4001 not allowed within declarations */
4002 if (prologState.documentEntity &&
4003 role == XML_ROLE_INNER_PARAM_ENTITY_REF)
4004 return XML_ERROR_PARAM_ENTITY_REF;
4005 dtd->hasParamEntityRefs = XML_TRUE;
4006 if (!paramEntityParsing)
4007 dtd->keepProcessing = dtd->standalone;
4009 const XML_Char *name;
4011 name = poolStoreString(&dtd->pool, enc,
4012 s + enc->minBytesPerChar,
4013 next - enc->minBytesPerChar);
4015 return XML_ERROR_NO_MEMORY;
4016 entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
4017 poolDiscard(&dtd->pool);
4018 /* first, determine if a check for an existing declaration is needed;
4019 if yes, check that the entity exists, and that it is internal,
4020 otherwise call the skipped entity handler
4022 if (prologState.documentEntity &&
4024 ? !openInternalEntities
4025 : !dtd->hasParamEntityRefs)) {
4027 return XML_ERROR_UNDEFINED_ENTITY;
4028 else if (!entity->is_internal)
4029 return XML_ERROR_ENTITY_DECLARED_IN_PE;
4032 dtd->keepProcessing = dtd->standalone;
4033 /* cannot report skipped entities in declarations */
4034 if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
4035 skippedEntityHandler(handlerArg, name, 1);
4036 handleDefault = XML_FALSE;
4041 return XML_ERROR_RECURSIVE_ENTITY_REF;
4042 if (entity->textPtr) {
4043 enum XML_Error result;
4044 result = processInternalParamEntity(parser, entity);
4045 if (result != XML_ERROR_NONE)
4047 handleDefault = XML_FALSE;
4050 if (externalEntityRefHandler) {
4051 dtd->paramEntityRead = XML_FALSE;
4052 entity->open = XML_TRUE;
4053 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4057 entity->publicId)) {
4058 entity->open = XML_FALSE;
4059 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4061 entity->open = XML_FALSE;
4062 handleDefault = XML_FALSE;
4063 if (!dtd->paramEntityRead) {
4064 dtd->keepProcessing = dtd->standalone;
4069 dtd->keepProcessing = dtd->standalone;
4073 #endif /* XML_DTD */
4074 if (!dtd->standalone &&
4075 notStandaloneHandler &&
4076 !notStandaloneHandler(handlerArg))
4077 return XML_ERROR_NOT_STANDALONE;
4080 /* Element declaration stuff */
4082 case XML_ROLE_ELEMENT_NAME:
4083 if (elementDeclHandler) {
4084 declElementType = getElementType(parser, enc, s, next);
4085 if (!declElementType)
4086 return XML_ERROR_NO_MEMORY;
4087 dtd->scaffLevel = 0;
4088 dtd->scaffCount = 0;
4089 dtd->in_eldecl = XML_TRUE;
4090 handleDefault = XML_FALSE;
4094 case XML_ROLE_CONTENT_ANY:
4095 case XML_ROLE_CONTENT_EMPTY:
4096 if (dtd->in_eldecl) {
4097 if (elementDeclHandler) {
4098 XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
4100 return XML_ERROR_NO_MEMORY;
4101 content->quant = XML_CQUANT_NONE;
4102 content->name = NULL;
4103 content->numchildren = 0;
4104 content->children = NULL;
4105 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
4109 elementDeclHandler(handlerArg, declElementType->name, content);
4110 handleDefault = XML_FALSE;
4112 dtd->in_eldecl = XML_FALSE;
4116 case XML_ROLE_CONTENT_PCDATA:
4117 if (dtd->in_eldecl) {
4118 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4120 if (elementDeclHandler)
4121 handleDefault = XML_FALSE;
4125 case XML_ROLE_CONTENT_ELEMENT:
4126 quant = XML_CQUANT_NONE;
4127 goto elementContent;
4128 case XML_ROLE_CONTENT_ELEMENT_OPT:
4129 quant = XML_CQUANT_OPT;
4130 goto elementContent;
4131 case XML_ROLE_CONTENT_ELEMENT_REP:
4132 quant = XML_CQUANT_REP;
4133 goto elementContent;
4134 case XML_ROLE_CONTENT_ELEMENT_PLUS:
4135 quant = XML_CQUANT_PLUS;
4137 if (dtd->in_eldecl) {
4139 const XML_Char *name;
4141 const char *nxt = (quant == XML_CQUANT_NONE
4143 : next - enc->minBytesPerChar);
4144 int myindex = nextScaffoldPart(parser);
4146 return XML_ERROR_NO_MEMORY;
4147 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
4148 dtd->scaffold[myindex].quant = quant;
4149 el = getElementType(parser, enc, s, nxt);
4151 return XML_ERROR_NO_MEMORY;
4153 dtd->scaffold[myindex].name = name;
4155 for (; name[nameLen++]; );
4156 dtd->contentStringLen += nameLen;
4157 if (elementDeclHandler)
4158 handleDefault = XML_FALSE;
4162 case XML_ROLE_GROUP_CLOSE:
4163 quant = XML_CQUANT_NONE;
4165 case XML_ROLE_GROUP_CLOSE_OPT:
4166 quant = XML_CQUANT_OPT;
4168 case XML_ROLE_GROUP_CLOSE_REP:
4169 quant = XML_CQUANT_REP;
4171 case XML_ROLE_GROUP_CLOSE_PLUS:
4172 quant = XML_CQUANT_PLUS;
4174 if (dtd->in_eldecl) {
4175 if (elementDeclHandler)
4176 handleDefault = XML_FALSE;
4178 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
4179 if (dtd->scaffLevel == 0) {
4180 if (!handleDefault) {
4181 XML_Content *model = build_model(parser);
4183 return XML_ERROR_NO_MEMORY;
4185 elementDeclHandler(handlerArg, declElementType->name, model);
4187 dtd->in_eldecl = XML_FALSE;
4188 dtd->contentStringLen = 0;
4192 /* End element declaration stuff */
4195 if (!reportProcessingInstruction(parser, enc, s, next))
4196 return XML_ERROR_NO_MEMORY;
4197 handleDefault = XML_FALSE;
4199 case XML_ROLE_COMMENT:
4200 if (!reportComment(parser, enc, s, next))
4201 return XML_ERROR_NO_MEMORY;
4202 handleDefault = XML_FALSE;
4207 handleDefault = XML_FALSE;
4211 case XML_ROLE_DOCTYPE_NONE:
4212 if (startDoctypeDeclHandler)
4213 handleDefault = XML_FALSE;
4215 case XML_ROLE_ENTITY_NONE:
4216 if (dtd->keepProcessing && entityDeclHandler)
4217 handleDefault = XML_FALSE;
4219 case XML_ROLE_NOTATION_NONE:
4220 if (notationDeclHandler)
4221 handleDefault = XML_FALSE;
4223 case XML_ROLE_ATTLIST_NONE:
4224 if (dtd->keepProcessing && attlistDeclHandler)
4225 handleDefault = XML_FALSE;
4227 case XML_ROLE_ELEMENT_NONE:
4228 if (elementDeclHandler)
4229 handleDefault = XML_FALSE;
4231 } /* end of big switch */
4233 if (handleDefault && defaultHandler)
4234 reportDefault(parser, enc, s, next);
4237 tok = XmlPrologTok(enc, s, end, &next);
4242 static enum XML_Error PTRCALL
4243 epilogProcessor(XML_Parser parser,
4246 const char **nextPtr)
4248 processor = epilogProcessor;
4251 const char *next = NULL;
4252 int tok = XmlPrologTok(encoding, s, end, &next);
4255 /* report partial linebreak - it might be the last token */
4256 case -XML_TOK_PROLOG_S:
4257 if (defaultHandler) {
4259 reportDefault(parser, encoding, s, next);
4263 return XML_ERROR_NONE;
4267 return XML_ERROR_NONE;
4268 case XML_TOK_PROLOG_S:
4270 reportDefault(parser, encoding, s, next);
4273 if (!reportProcessingInstruction(parser, encoding, s, next))
4274 return XML_ERROR_NO_MEMORY;
4276 case XML_TOK_COMMENT:
4277 if (!reportComment(parser, encoding, s, next))
4278 return XML_ERROR_NO_MEMORY;
4280 case XML_TOK_INVALID:
4282 return XML_ERROR_INVALID_TOKEN;
4283 case XML_TOK_PARTIAL:
4286 return XML_ERROR_NONE;
4288 return XML_ERROR_UNCLOSED_TOKEN;
4289 case XML_TOK_PARTIAL_CHAR:
4292 return XML_ERROR_NONE;
4294 return XML_ERROR_PARTIAL_CHAR;
4296 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
4298 eventPtr = s = next;
4304 static enum XML_Error
4305 processInternalParamEntity(XML_Parser parser, ENTITY *entity)
4307 const char *s, *end, *next;
4309 enum XML_Error result;
4310 OPEN_INTERNAL_ENTITY openEntity;
4311 entity->open = XML_TRUE;
4312 openEntity.next = openInternalEntities;
4313 openInternalEntities = &openEntity;
4314 openEntity.entity = entity;
4315 openEntity.internalEventPtr = NULL;
4316 openEntity.internalEventEndPtr = NULL;
4317 s = (char *)entity->textPtr;
4318 end = (char *)(entity->textPtr + entity->textLen);
4319 tok = XmlPrologTok(internalEncoding, s, end, &next);
4320 result = doProlog(parser, internalEncoding, s, end, tok, next, 0);
4321 entity->open = XML_FALSE;
4322 openInternalEntities = openEntity.next;
4326 #endif /* XML_DTD */
4328 static enum XML_Error PTRCALL
4329 errorProcessor(XML_Parser parser,
4332 const char **nextPtr)
4337 static enum XML_Error
4338 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4339 const char *ptr, const char *end,
4342 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
4346 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
4348 if (!poolAppendChar(pool, XML_T('\0')))
4349 return XML_ERROR_NO_MEMORY;
4350 return XML_ERROR_NONE;
4353 static enum XML_Error
4354 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4355 const char *ptr, const char *end,
4358 DTD * const dtd = _dtd; /* save one level of indirection */
4361 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
4364 return XML_ERROR_NONE;
4365 case XML_TOK_INVALID:
4366 if (enc == encoding)
4368 return XML_ERROR_INVALID_TOKEN;
4369 case XML_TOK_PARTIAL:
4370 if (enc == encoding)
4372 return XML_ERROR_INVALID_TOKEN;
4373 case XML_TOK_CHAR_REF:
4375 XML_Char buf[XML_ENCODE_MAX];
4377 int n = XmlCharRefNumber(enc, ptr);
4379 if (enc == encoding)
4381 return XML_ERROR_BAD_CHAR_REF;
4384 && n == 0x20 /* space */
4385 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4387 n = XmlEncode(n, (ICHAR *)buf);
4389 if (enc == encoding)
4391 return XML_ERROR_BAD_CHAR_REF;
4393 for (i = 0; i < n; i++) {
4394 if (!poolAppendChar(pool, buf[i]))
4395 return XML_ERROR_NO_MEMORY;
4399 case XML_TOK_DATA_CHARS:
4400 if (!poolAppend(pool, enc, ptr, next))
4401 return XML_ERROR_NO_MEMORY;
4403 case XML_TOK_TRAILING_CR:
4404 next = ptr + enc->minBytesPerChar;
4406 case XML_TOK_ATTRIBUTE_VALUE_S:
4407 case XML_TOK_DATA_NEWLINE:
4408 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4410 if (!poolAppendChar(pool, 0x20))
4411 return XML_ERROR_NO_MEMORY;
4413 case XML_TOK_ENTITY_REF:
4415 const XML_Char *name;
4417 char checkEntityDecl;
4418 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
4419 ptr + enc->minBytesPerChar,
4420 next - enc->minBytesPerChar);
4422 if (!poolAppendChar(pool, ch))
4423 return XML_ERROR_NO_MEMORY;
4426 name = poolStoreString(&temp2Pool, enc,
4427 ptr + enc->minBytesPerChar,
4428 next - enc->minBytesPerChar);
4430 return XML_ERROR_NO_MEMORY;
4431 entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
4432 poolDiscard(&temp2Pool);
4433 /* first, determine if a check for an existing declaration is needed;
4434 if yes, check that the entity exists, and that it is internal,
4435 otherwise call the default handler (if called from content)
4437 if (pool == &dtd->pool) /* are we called from prolog? */
4440 prologState.documentEntity &&
4441 #endif /* XML_DTD */
4443 ? !openInternalEntities
4444 : !dtd->hasParamEntityRefs);
4445 else /* if (pool == &tempPool): we are called from content */
4446 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
4447 if (checkEntityDecl) {
4449 return XML_ERROR_UNDEFINED_ENTITY;
4450 else if (!entity->is_internal)
4451 return XML_ERROR_ENTITY_DECLARED_IN_PE;
4454 /* cannot report skipped entity here - see comments on
4455 skippedEntityHandler
4456 if (skippedEntityHandler)
4457 skippedEntityHandler(handlerArg, name, 0);
4459 if ((pool == &tempPool) && defaultHandler)
4460 reportDefault(parser, enc, ptr, next);
4464 if (enc == encoding)
4466 return XML_ERROR_RECURSIVE_ENTITY_REF;
4468 if (entity->notation) {
4469 if (enc == encoding)
4471 return XML_ERROR_BINARY_ENTITY_REF;
4473 if (!entity->textPtr) {
4474 if (enc == encoding)
4476 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
4479 enum XML_Error result;
4480 const XML_Char *textEnd = entity->textPtr + entity->textLen;
4481 entity->open = XML_TRUE;
4482 result = appendAttributeValue(parser, internalEncoding, isCdata,
4483 (char *)entity->textPtr,
4484 (char *)textEnd, pool);
4485 entity->open = XML_FALSE;
4492 if (enc == encoding)
4494 return XML_ERROR_UNEXPECTED_STATE;
4501 static enum XML_Error
4502 storeEntityValue(XML_Parser parser,
4503 const ENCODING *enc,
4504 const char *entityTextPtr,
4505 const char *entityTextEnd)
4507 DTD * const dtd = _dtd; /* save one level of indirection */
4508 STRING_POOL *pool = &(dtd->entityValuePool);
4509 enum XML_Error result = XML_ERROR_NONE;
4511 int oldInEntityValue = prologState.inEntityValue;
4512 prologState.inEntityValue = 1;
4513 #endif /* XML_DTD */
4514 /* never return Null for the value argument in EntityDeclHandler,
4515 since this would indicate an external entity; therefore we
4516 have to make sure that entityValuePool.start is not null */
4517 if (!pool->blocks) {
4518 if (!poolGrow(pool))
4519 return XML_ERROR_NO_MEMORY;
4524 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
4526 case XML_TOK_PARAM_ENTITY_REF:
4528 if (isParamEntity || enc != encoding) {
4529 const XML_Char *name;
4531 name = poolStoreString(&tempPool, enc,
4532 entityTextPtr + enc->minBytesPerChar,
4533 next - enc->minBytesPerChar);
4535 result = XML_ERROR_NO_MEMORY;
4536 goto endEntityValue;
4538 entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
4539 poolDiscard(&tempPool);
4541 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
4542 /* cannot report skipped entity here - see comments on
4543 skippedEntityHandler
4544 if (skippedEntityHandler)
4545 skippedEntityHandler(handlerArg, name, 0);
4547 dtd->keepProcessing = dtd->standalone;
4548 goto endEntityValue;
4551 if (enc == encoding)
4552 eventPtr = entityTextPtr;
4553 result = XML_ERROR_RECURSIVE_ENTITY_REF;
4554 goto endEntityValue;
4556 if (entity->systemId) {
4557 if (externalEntityRefHandler) {
4558 dtd->paramEntityRead = XML_FALSE;
4559 entity->open = XML_TRUE;
4560 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4564 entity->publicId)) {
4565 entity->open = XML_FALSE;
4566 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4567 goto endEntityValue;
4569 entity->open = XML_FALSE;
4570 if (!dtd->paramEntityRead)
4571 dtd->keepProcessing = dtd->standalone;
4574 dtd->keepProcessing = dtd->standalone;
4577 entity->open = XML_TRUE;
4578 result = storeEntityValue(parser,
4580 (char *)entity->textPtr,
4581 (char *)(entity->textPtr
4582 + entity->textLen));
4583 entity->open = XML_FALSE;
4585 goto endEntityValue;
4589 #endif /* XML_DTD */
4590 /* in the internal subset, PE references are not legal
4591 within markup declarations, e.g entity values in this case */
4592 eventPtr = entityTextPtr;
4593 result = XML_ERROR_PARAM_ENTITY_REF;
4594 goto endEntityValue;
4596 result = XML_ERROR_NONE;
4597 goto endEntityValue;
4598 case XML_TOK_ENTITY_REF:
4599 case XML_TOK_DATA_CHARS:
4600 if (!poolAppend(pool, enc, entityTextPtr, next)) {
4601 result = XML_ERROR_NO_MEMORY;
4602 goto endEntityValue;
4605 case XML_TOK_TRAILING_CR:
4606 next = entityTextPtr + enc->minBytesPerChar;
4608 case XML_TOK_DATA_NEWLINE:
4609 if (pool->end == pool->ptr && !poolGrow(pool)) {
4610 result = XML_ERROR_NO_MEMORY;
4611 goto endEntityValue;
4613 *(pool->ptr)++ = 0xA;
4615 case XML_TOK_CHAR_REF:
4617 XML_Char buf[XML_ENCODE_MAX];
4619 int n = XmlCharRefNumber(enc, entityTextPtr);
4621 if (enc == encoding)
4622 eventPtr = entityTextPtr;
4623 result = XML_ERROR_BAD_CHAR_REF;
4624 goto endEntityValue;
4626 n = XmlEncode(n, (ICHAR *)buf);
4628 if (enc == encoding)
4629 eventPtr = entityTextPtr;
4630 result = XML_ERROR_BAD_CHAR_REF;
4631 goto endEntityValue;
4633 for (i = 0; i < n; i++) {
4634 if (pool->end == pool->ptr && !poolGrow(pool)) {
4635 result = XML_ERROR_NO_MEMORY;
4636 goto endEntityValue;
4638 *(pool->ptr)++ = buf[i];
4642 case XML_TOK_PARTIAL:
4643 if (enc == encoding)
4644 eventPtr = entityTextPtr;
4645 result = XML_ERROR_INVALID_TOKEN;
4646 goto endEntityValue;
4647 case XML_TOK_INVALID:
4648 if (enc == encoding)
4650 result = XML_ERROR_INVALID_TOKEN;
4651 goto endEntityValue;
4653 if (enc == encoding)
4654 eventPtr = entityTextPtr;
4655 result = XML_ERROR_UNEXPECTED_STATE;
4656 goto endEntityValue;
4658 entityTextPtr = next;
4662 prologState.inEntityValue = oldInEntityValue;
4663 #endif /* XML_DTD */
4667 static void FASTCALL
4668 normalizeLines(XML_Char *s)
4672 if (*s == XML_T('\0'))
4691 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
4692 const char *start, const char *end)
4694 const XML_Char *target;
4697 if (!processingInstructionHandler) {
4699 reportDefault(parser, enc, start, end);
4702 start += enc->minBytesPerChar * 2;
4703 tem = start + XmlNameLength(enc, start);
4704 target = poolStoreString(&tempPool, enc, start, tem);
4707 poolFinish(&tempPool);
4708 data = poolStoreString(&tempPool, enc,
4710 end - enc->minBytesPerChar*2);
4713 normalizeLines(data);
4714 processingInstructionHandler(handlerArg, target, data);
4715 poolClear(&tempPool);
4720 reportComment(XML_Parser parser, const ENCODING *enc,
4721 const char *start, const char *end)
4724 if (!commentHandler) {
4726 reportDefault(parser, enc, start, end);
4729 data = poolStoreString(&tempPool,
4731 start + enc->minBytesPerChar * 4,
4732 end - enc->minBytesPerChar * 3);
4735 normalizeLines(data);
4736 commentHandler(handlerArg, data);
4737 poolClear(&tempPool);
4742 reportDefault(XML_Parser parser, const ENCODING *enc,
4743 const char *s, const char *end)
4745 if (MUST_CONVERT(enc, s)) {
4746 const char **eventPP;
4747 const char **eventEndPP;
4748 if (enc == encoding) {
4749 eventPP = &eventPtr;
4750 eventEndPP = &eventEndPtr;
4753 eventPP = &(openInternalEntities->internalEventPtr);
4754 eventEndPP = &(openInternalEntities->internalEventEndPtr);
4757 ICHAR *dataPtr = (ICHAR *)dataBuf;
4758 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
4760 defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
4765 defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
4770 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
4771 XML_Bool isId, const XML_Char *value, XML_Parser parser)
4773 DEFAULT_ATTRIBUTE *att;
4774 if (value || isId) {
4775 /* The handling of default attributes gets messed up if we have
4776 a default which duplicates a non-default. */
4778 for (i = 0; i < type->nDefaultAtts; i++)
4779 if (attId == type->defaultAtts[i].id)
4781 if (isId && !type->idAtt && !attId->xmlns)
4782 type->idAtt = attId;
4784 if (type->nDefaultAtts == type->allocDefaultAtts) {
4785 if (type->allocDefaultAtts == 0) {
4786 type->allocDefaultAtts = 8;
4787 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
4788 * sizeof(DEFAULT_ATTRIBUTE));
4789 if (!type->defaultAtts)
4793 DEFAULT_ATTRIBUTE *temp;
4794 int count = type->allocDefaultAtts * 2;
4795 temp = (DEFAULT_ATTRIBUTE *)
4796 REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
4799 type->allocDefaultAtts = count;
4800 type->defaultAtts = temp;
4803 att = type->defaultAtts + type->nDefaultAtts;
4806 att->isCdata = isCdata;
4808 attId->maybeTokenized = XML_TRUE;
4809 type->nDefaultAtts += 1;
4814 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
4816 DTD * const dtd = _dtd; /* save one level of indirection */
4817 const XML_Char *name;
4818 for (name = elementType->name; *name; name++) {
4819 if (*name == XML_T(':')) {
4822 for (s = elementType->name; s != name; s++) {
4823 if (!poolAppendChar(&dtd->pool, *s))
4826 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
4828 prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
4832 if (prefix->name == poolStart(&dtd->pool))
4833 poolFinish(&dtd->pool);
4835 poolDiscard(&dtd->pool);
4836 elementType->prefix = prefix;
4843 static ATTRIBUTE_ID *
4844 getAttributeId(XML_Parser parser, const ENCODING *enc,
4845 const char *start, const char *end)
4847 DTD * const dtd = _dtd; /* save one level of indirection */
4849 const XML_Char *name;
4850 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
4852 name = poolStoreString(&dtd->pool, enc, start, end);
4855 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
4857 id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
4860 if (id->name != name)
4861 poolDiscard(&dtd->pool);
4863 poolFinish(&dtd->pool);
4866 else if (name[0] == XML_T('x')
4867 && name[1] == XML_T('m')
4868 && name[2] == XML_T('l')
4869 && name[3] == XML_T('n')
4870 && name[4] == XML_T('s')
4871 && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
4872 if (name[5] == XML_T('\0'))
4873 id->prefix = &dtd->defaultPrefix;
4875 id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
4876 id->xmlns = XML_TRUE;
4880 for (i = 0; name[i]; i++) {
4881 /* attributes without prefix are *not* in the default namespace */
4882 if (name[i] == XML_T(':')) {
4884 for (j = 0; j < i; j++) {
4885 if (!poolAppendChar(&dtd->pool, name[j]))
4888 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
4890 id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
4892 if (id->prefix->name == poolStart(&dtd->pool))
4893 poolFinish(&dtd->pool);
4895 poolDiscard(&dtd->pool);
4904 #define CONTEXT_SEP XML_T('\f')
4906 static const XML_Char *
4907 getContext(XML_Parser parser)
4909 DTD * const dtd = _dtd; /* save one level of indirection */
4910 HASH_TABLE_ITER iter;
4911 XML_Bool needSep = XML_FALSE;
4913 if (dtd->defaultPrefix.binding) {
4916 if (!poolAppendChar(&tempPool, XML_T('=')))
4918 len = dtd->defaultPrefix.binding->uriLen;
4919 if (namespaceSeparator != XML_T('\0'))
4921 for (i = 0; i < len; i++)
4922 if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
4927 hashTableIterInit(&iter, &(dtd->prefixes));
4932 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
4935 if (!prefix->binding)
4937 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
4939 for (s = prefix->name; *s; s++)
4940 if (!poolAppendChar(&tempPool, *s))
4942 if (!poolAppendChar(&tempPool, XML_T('=')))
4944 len = prefix->binding->uriLen;
4945 if (namespaceSeparator != XML_T('\0'))
4947 for (i = 0; i < len; i++)
4948 if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
4954 hashTableIterInit(&iter, &(dtd->generalEntities));
4957 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
4962 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
4964 for (s = e->name; *s; s++)
4965 if (!poolAppendChar(&tempPool, *s))
4970 if (!poolAppendChar(&tempPool, XML_T('\0')))
4972 return tempPool.start;
4976 setContext(XML_Parser parser, const XML_Char *context)
4978 DTD * const dtd = _dtd; /* save one level of indirection */
4979 const XML_Char *s = context;
4981 while (*context != XML_T('\0')) {
4982 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
4984 if (!poolAppendChar(&tempPool, XML_T('\0')))
4986 e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
4989 if (*s != XML_T('\0'))
4992 poolDiscard(&tempPool);
4994 else if (*s == XML_T('=')) {
4996 if (poolLength(&tempPool) == 0)
4997 prefix = &dtd->defaultPrefix;
4999 if (!poolAppendChar(&tempPool, XML_T('\0')))
5001 prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
5005 if (prefix->name == poolStart(&tempPool)) {
5006 prefix->name = poolCopyString(&dtd->pool, prefix->name);
5010 poolDiscard(&tempPool);
5012 for (context = s + 1;
5013 *context != CONTEXT_SEP && *context != XML_T('\0');
5015 if (!poolAppendChar(&tempPool, *context))
5017 if (!poolAppendChar(&tempPool, XML_T('\0')))
5019 if (addBinding(parser, prefix, 0, poolStart(&tempPool),
5020 &inheritedBindings) != XML_ERROR_NONE)
5022 poolDiscard(&tempPool);
5023 if (*context != XML_T('\0'))
5028 if (!poolAppendChar(&tempPool, *s))
5036 static void FASTCALL
5037 normalizePublicId(XML_Char *publicId)
5039 XML_Char *p = publicId;
5041 for (s = publicId; *s; s++) {
5046 if (p != publicId && p[-1] != 0x20)
5053 if (p != publicId && p[-1] == 0x20)
5059 dtdCreate(const XML_Memory_Handling_Suite *ms)
5061 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
5064 poolInit(&(p->pool), ms);
5066 poolInit(&(p->entityValuePool), ms);
5067 #endif /* XML_DTD */
5068 hashTableInit(&(p->generalEntities), ms);
5069 hashTableInit(&(p->elementTypes), ms);
5070 hashTableInit(&(p->attributeIds), ms);
5071 hashTableInit(&(p->prefixes), ms);
5073 p->paramEntityRead = XML_FALSE;
5074 hashTableInit(&(p->paramEntities), ms);
5075 #endif /* XML_DTD */
5076 p->defaultPrefix.name = NULL;
5077 p->defaultPrefix.binding = NULL;
5079 p->in_eldecl = XML_FALSE;
5080 p->scaffIndex = NULL;
5085 p->contentStringLen = 0;
5087 p->keepProcessing = XML_TRUE;
5088 p->hasParamEntityRefs = XML_FALSE;
5089 p->standalone = XML_FALSE;
5094 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
5096 HASH_TABLE_ITER iter;
5097 hashTableIterInit(&iter, &(p->elementTypes));
5099 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5102 if (e->allocDefaultAtts != 0)
5103 ms->free_fcn(e->defaultAtts);
5105 hashTableClear(&(p->generalEntities));
5107 p->paramEntityRead = XML_FALSE;
5108 hashTableClear(&(p->paramEntities));
5109 #endif /* XML_DTD */
5110 hashTableClear(&(p->elementTypes));
5111 hashTableClear(&(p->attributeIds));
5112 hashTableClear(&(p->prefixes));
5113 poolClear(&(p->pool));
5115 poolClear(&(p->entityValuePool));
5116 #endif /* XML_DTD */
5117 p->defaultPrefix.name = NULL;
5118 p->defaultPrefix.binding = NULL;
5120 p->in_eldecl = XML_FALSE;
5122 ms->free_fcn(p->scaffIndex);
5123 p->scaffIndex = NULL;
5124 ms->free_fcn(p->scaffold);
5130 p->contentStringLen = 0;
5132 p->keepProcessing = XML_TRUE;
5133 p->hasParamEntityRefs = XML_FALSE;
5134 p->standalone = XML_FALSE;
5138 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
5140 HASH_TABLE_ITER iter;
5141 hashTableIterInit(&iter, &(p->elementTypes));
5143 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5146 if (e->allocDefaultAtts != 0)
5147 ms->free_fcn(e->defaultAtts);
5149 hashTableDestroy(&(p->generalEntities));
5151 hashTableDestroy(&(p->paramEntities));
5152 #endif /* XML_DTD */
5153 hashTableDestroy(&(p->elementTypes));
5154 hashTableDestroy(&(p->attributeIds));
5155 hashTableDestroy(&(p->prefixes));
5156 poolDestroy(&(p->pool));
5158 poolDestroy(&(p->entityValuePool));
5159 #endif /* XML_DTD */
5161 ms->free_fcn(p->scaffIndex);
5162 ms->free_fcn(p->scaffold);
5167 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
5168 The new DTD has already been initialized.
5171 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
5173 HASH_TABLE_ITER iter;
5175 /* Copy the prefix table. */
5177 hashTableIterInit(&iter, &(oldDtd->prefixes));
5179 const XML_Char *name;
5180 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
5183 name = poolCopyString(&(newDtd->pool), oldP->name);
5186 if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
5190 hashTableIterInit(&iter, &(oldDtd->attributeIds));
5192 /* Copy the attribute id table. */
5196 const XML_Char *name;
5197 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
5201 /* Remember to allocate the scratch byte before the name. */
5202 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
5204 name = poolCopyString(&(newDtd->pool), oldA->name);
5208 newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
5209 sizeof(ATTRIBUTE_ID));
5212 newA->maybeTokenized = oldA->maybeTokenized;
5214 newA->xmlns = oldA->xmlns;
5215 if (oldA->prefix == &oldDtd->defaultPrefix)
5216 newA->prefix = &newDtd->defaultPrefix;
5218 newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
5219 oldA->prefix->name, 0);
5223 /* Copy the element type table. */
5225 hashTableIterInit(&iter, &(oldDtd->elementTypes));
5230 const XML_Char *name;
5231 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5234 name = poolCopyString(&(newDtd->pool), oldE->name);
5237 newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
5238 sizeof(ELEMENT_TYPE));
5241 if (oldE->nDefaultAtts) {
5242 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
5243 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
5244 if (!newE->defaultAtts) {
5250 newE->idAtt = (ATTRIBUTE_ID *)
5251 lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
5252 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
5254 newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
5255 oldE->prefix->name, 0);
5256 for (i = 0; i < newE->nDefaultAtts; i++) {
5257 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
5258 lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
5259 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
5260 if (oldE->defaultAtts[i].value) {
5261 newE->defaultAtts[i].value
5262 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
5263 if (!newE->defaultAtts[i].value)
5267 newE->defaultAtts[i].value = NULL;
5271 /* Copy the entity tables. */
5272 if (!copyEntityTable(&(newDtd->generalEntities),
5274 &(oldDtd->generalEntities)))
5278 if (!copyEntityTable(&(newDtd->paramEntities),
5280 &(oldDtd->paramEntities)))
5282 newDtd->paramEntityRead = oldDtd->paramEntityRead;
5283 #endif /* XML_DTD */
5285 newDtd->keepProcessing = oldDtd->keepProcessing;
5286 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
5287 newDtd->standalone = oldDtd->standalone;
5289 /* Don't want deep copying for scaffolding */
5290 newDtd->in_eldecl = oldDtd->in_eldecl;
5291 newDtd->scaffold = oldDtd->scaffold;
5292 newDtd->contentStringLen = oldDtd->contentStringLen;
5293 newDtd->scaffSize = oldDtd->scaffSize;
5294 newDtd->scaffLevel = oldDtd->scaffLevel;
5295 newDtd->scaffIndex = oldDtd->scaffIndex;
5301 copyEntityTable(HASH_TABLE *newTable,
5302 STRING_POOL *newPool,
5303 const HASH_TABLE *oldTable)
5305 HASH_TABLE_ITER iter;
5306 const XML_Char *cachedOldBase = NULL;
5307 const XML_Char *cachedNewBase = NULL;
5309 hashTableIterInit(&iter, oldTable);
5313 const XML_Char *name;
5314 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
5317 name = poolCopyString(newPool, oldE->name);
5320 newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
5323 if (oldE->systemId) {
5324 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
5327 newE->systemId = tem;
5329 if (oldE->base == cachedOldBase)
5330 newE->base = cachedNewBase;
5332 cachedOldBase = oldE->base;
5333 tem = poolCopyString(newPool, cachedOldBase);
5336 cachedNewBase = newE->base = tem;
5339 if (oldE->publicId) {
5340 tem = poolCopyString(newPool, oldE->publicId);
5343 newE->publicId = tem;
5347 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
5351 newE->textPtr = tem;
5352 newE->textLen = oldE->textLen;
5354 if (oldE->notation) {
5355 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
5358 newE->notation = tem;
5360 newE->is_param = oldE->is_param;
5361 newE->is_internal = oldE->is_internal;
5366 #define INIT_POWER 6
5368 static XML_Bool FASTCALL
5369 keyeq(KEY s1, KEY s2)
5371 for (; *s1 == *s2; s1++, s2++)
5377 static unsigned long FASTCALL
5380 unsigned long h = 0;
5382 h = CHAR_HASH(h, *s++);
5387 lookup(HASH_TABLE *table, KEY name, size_t createSize)
5390 if (table->size == 0) {
5394 table->power = INIT_POWER;
5395 /* table->size is a power of 2 */
5396 table->size = (size_t)1 << INIT_POWER;
5397 tsize = table->size * sizeof(NAMED *);
5398 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
5401 memset(table->v, 0, tsize);
5402 i = hash(name) & ((unsigned long)table->size - 1);
5405 unsigned long h = hash(name);
5406 unsigned long mask = (unsigned long)table->size - 1;
5407 unsigned char step = 0;
5409 while (table->v[i]) {
5410 if (keyeq(name, table->v[i]->name))
5413 step = PROBE_STEP(h, mask, table->power);
5414 i < step ? (i += table->size - step) : (i -= step);
5419 /* check for overflow (table is half full) */
5420 if (table->used >> (table->power - 1)) {
5421 unsigned char newPower = table->power + 1;
5422 size_t newSize = (size_t)1 << newPower;
5423 unsigned long newMask = (unsigned long)newSize - 1;
5424 size_t tsize = newSize * sizeof(NAMED *);
5425 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
5428 memset(newV, 0, tsize);
5429 for (i = 0; i < table->size; i++)
5431 unsigned long newHash = hash(table->v[i]->name);
5432 size_t j = newHash & newMask;
5436 step = PROBE_STEP(newHash, newMask, newPower);
5437 j < step ? (j += newSize - step) : (j -= step);
5439 newV[j] = table->v[i];
5441 table->mem->free_fcn(table->v);
5443 table->power = newPower;
5444 table->size = newSize;
5447 while (table->v[i]) {
5449 step = PROBE_STEP(h, newMask, newPower);
5450 i < step ? (i += newSize - step) : (i -= step);
5454 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
5457 memset(table->v[i], 0, createSize);
5458 table->v[i]->name = name;
5463 static void FASTCALL
5464 hashTableClear(HASH_TABLE *table)
5467 for (i = 0; i < table->size; i++) {
5468 table->mem->free_fcn(table->v[i]);
5474 static void FASTCALL
5475 hashTableDestroy(HASH_TABLE *table)
5478 for (i = 0; i < table->size; i++)
5479 table->mem->free_fcn(table->v[i]);
5480 table->mem->free_fcn(table->v);
5483 static void FASTCALL
5484 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
5493 static void FASTCALL
5494 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
5497 iter->end = iter->p + table->size;
5500 static NAMED * FASTCALL
5501 hashTableIterNext(HASH_TABLE_ITER *iter)
5503 while (iter->p != iter->end) {
5504 NAMED *tem = *(iter->p)++;
5511 static void FASTCALL
5512 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
5514 pool->blocks = NULL;
5515 pool->freeBlocks = NULL;
5522 static void FASTCALL
5523 poolClear(STRING_POOL *pool)
5525 if (!pool->freeBlocks)
5526 pool->freeBlocks = pool->blocks;
5528 BLOCK *p = pool->blocks;
5530 BLOCK *tem = p->next;
5531 p->next = pool->freeBlocks;
5532 pool->freeBlocks = p;
5536 pool->blocks = NULL;
5542 static void FASTCALL
5543 poolDestroy(STRING_POOL *pool)
5545 BLOCK *p = pool->blocks;
5547 BLOCK *tem = p->next;
5548 pool->mem->free_fcn(p);
5551 p = pool->freeBlocks;
5553 BLOCK *tem = p->next;
5554 pool->mem->free_fcn(p);
5560 poolAppend(STRING_POOL *pool, const ENCODING *enc,
5561 const char *ptr, const char *end)
5563 if (!pool->ptr && !poolGrow(pool))
5566 XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
5569 if (!poolGrow(pool))
5575 static const XML_Char * FASTCALL
5576 poolCopyString(STRING_POOL *pool, const XML_Char *s)
5579 if (!poolAppendChar(pool, *s))
5587 static const XML_Char *
5588 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
5590 if (!pool->ptr && !poolGrow(pool))
5592 for (; n > 0; --n, s++) {
5593 if (!poolAppendChar(pool, *s))
5601 static const XML_Char * FASTCALL
5602 poolAppendString(STRING_POOL *pool, const XML_Char *s)
5605 if (!poolAppendChar(pool, *s))
5613 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
5614 const char *ptr, const char *end)
5616 if (!poolAppend(pool, enc, ptr, end))
5618 if (pool->ptr == pool->end && !poolGrow(pool))
5624 static XML_Bool FASTCALL
5625 poolGrow(STRING_POOL *pool)
5627 if (pool->freeBlocks) {
5628 if (pool->start == 0) {
5629 pool->blocks = pool->freeBlocks;
5630 pool->freeBlocks = pool->freeBlocks->next;
5631 pool->blocks->next = NULL;
5632 pool->start = pool->blocks->s;
5633 pool->end = pool->start + pool->blocks->size;
5634 pool->ptr = pool->start;
5637 if (pool->end - pool->start < pool->freeBlocks->size) {
5638 BLOCK *tem = pool->freeBlocks->next;
5639 pool->freeBlocks->next = pool->blocks;
5640 pool->blocks = pool->freeBlocks;
5641 pool->freeBlocks = tem;
5642 memcpy(pool->blocks->s, pool->start,
5643 (pool->end - pool->start) * sizeof(XML_Char));
5644 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
5645 pool->start = pool->blocks->s;
5646 pool->end = pool->start + pool->blocks->size;
5650 if (pool->blocks && pool->start == pool->blocks->s) {
5651 int blockSize = (pool->end - pool->start)*2;
5652 pool->blocks = (BLOCK *)
5653 pool->mem->realloc_fcn(pool->blocks,
5655 + blockSize * sizeof(XML_Char)));
5656 if (pool->blocks == NULL)
5658 pool->blocks->size = blockSize;
5659 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
5660 pool->start = pool->blocks->s;
5661 pool->end = pool->start + blockSize;
5665 int blockSize = pool->end - pool->start;
5666 if (blockSize < INIT_BLOCK_SIZE)
5667 blockSize = INIT_BLOCK_SIZE;
5670 tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
5671 + blockSize * sizeof(XML_Char));
5674 tem->size = blockSize;
5675 tem->next = pool->blocks;
5677 if (pool->ptr != pool->start)
5678 memcpy(tem->s, pool->start,
5679 (pool->ptr - pool->start) * sizeof(XML_Char));
5680 pool->ptr = tem->s + (pool->ptr - pool->start);
5681 pool->start = tem->s;
5682 pool->end = tem->s + blockSize;
5688 nextScaffoldPart(XML_Parser parser)
5690 DTD * const dtd = _dtd; /* save one level of indirection */
5691 CONTENT_SCAFFOLD * me;
5694 if (!dtd->scaffIndex) {
5695 dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
5696 if (!dtd->scaffIndex)
5698 dtd->scaffIndex[0] = 0;
5701 if (dtd->scaffCount >= dtd->scaffSize) {
5702 CONTENT_SCAFFOLD *temp;
5703 if (dtd->scaffold) {
5704 temp = (CONTENT_SCAFFOLD *)
5705 REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
5708 dtd->scaffSize *= 2;
5711 temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
5712 * sizeof(CONTENT_SCAFFOLD));
5715 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
5717 dtd->scaffold = temp;
5719 next = dtd->scaffCount++;
5720 me = &dtd->scaffold[next];
5721 if (dtd->scaffLevel) {
5722 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
5723 if (parent->lastchild) {
5724 dtd->scaffold[parent->lastchild].nextsib = next;
5726 if (!parent->childcnt)
5727 parent->firstchild = next;
5728 parent->lastchild = next;
5731 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
5736 build_node(XML_Parser parser,
5739 XML_Content **contpos,
5742 DTD * const dtd = _dtd; /* save one level of indirection */
5743 dest->type = dtd->scaffold[src_node].type;
5744 dest->quant = dtd->scaffold[src_node].quant;
5745 if (dest->type == XML_CTYPE_NAME) {
5746 const XML_Char *src;
5747 dest->name = *strpos;
5748 src = dtd->scaffold[src_node].name;
5750 *(*strpos)++ = *src;
5755 dest->numchildren = 0;
5756 dest->children = NULL;
5761 dest->numchildren = dtd->scaffold[src_node].childcnt;
5762 dest->children = *contpos;
5763 *contpos += dest->numchildren;
5764 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
5765 i < dest->numchildren;
5766 i++, cn = dtd->scaffold[cn].nextsib) {
5767 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
5773 static XML_Content *
5774 build_model (XML_Parser parser)
5776 DTD * const dtd = _dtd; /* save one level of indirection */
5780 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
5781 + (dtd->contentStringLen * sizeof(XML_Char)));
5783 ret = (XML_Content *)MALLOC(allocsize);
5787 str = (XML_Char *) (&ret[dtd->scaffCount]);
5790 build_node(parser, 0, ret, &cpos, &str);
5794 static ELEMENT_TYPE *
5795 getElementType(XML_Parser parser,
5796 const ENCODING *enc,
5800 DTD * const dtd = _dtd; /* save one level of indirection */
5801 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
5806 ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
5809 if (ret->name != name)
5810 poolDiscard(&dtd->pool);
5812 poolFinish(&dtd->pool);
5813 if (!setElementTypePrefix(parser, ret))