--- /dev/null
+/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd\r
+ See the file COPYING for copying permission.\r
+*/\r
+\r
+#include <stddef.h>\r
+#include <string.h> /* memset(), memcpy() */\r
+#include <assert.h>\r
+#include <limits.h> /* UINT_MAX */\r
+#include <time.h> /* time() */\r
+\r
+#define XML_BUILDING_EXPAT 1\r
+\r
+#ifdef COMPILED_FROM_DSP\r
+#include "winconfig.h"\r
+#elif defined(MACOS_CLASSIC)\r
+#include "macconfig.h"\r
+#elif defined(__amigaos__)\r
+#include "amigaconfig.h"\r
+#elif defined(__WATCOMC__)\r
+#include "watcomconfig.h"\r
+#elif defined(HAVE_EXPAT_CONFIG_H)\r
+#include <expat_config.h>\r
+#endif /* ndef COMPILED_FROM_DSP */\r
+\r
+#include "ascii.h"\r
+#include "expat.h"\r
+\r
+#ifdef XML_UNICODE\r
+#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX\r
+#define XmlConvert XmlUtf16Convert\r
+#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding\r
+#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS\r
+#define XmlEncode XmlUtf16Encode\r
+/* Using pointer subtraction to convert to integer type. */\r
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))\r
+typedef unsigned short ICHAR;\r
+#else\r
+#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX\r
+#define XmlConvert XmlUtf8Convert\r
+#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding\r
+#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS\r
+#define XmlEncode XmlUtf8Encode\r
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)\r
+typedef char ICHAR;\r
+#endif\r
+\r
+\r
+#ifndef XML_NS\r
+\r
+#define XmlInitEncodingNS XmlInitEncoding\r
+#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding\r
+#undef XmlGetInternalEncodingNS\r
+#define XmlGetInternalEncodingNS XmlGetInternalEncoding\r
+#define XmlParseXmlDeclNS XmlParseXmlDecl\r
+\r
+#endif\r
+\r
+#ifdef XML_UNICODE\r
+\r
+#ifdef XML_UNICODE_WCHAR_T\r
+#define XML_T(x) (const wchar_t)x\r
+#define XML_L(x) L ## x\r
+#else\r
+#define XML_T(x) (const unsigned short)x\r
+#define XML_L(x) x\r
+#endif\r
+\r
+#else\r
+\r
+#define XML_T(x) x\r
+#define XML_L(x) x\r
+\r
+#endif\r
+\r
+/* Round up n to be a multiple of sz, where sz is a power of 2. */\r
+#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))\r
+\r
+/* Handle the case where memmove() doesn't exist. */\r
+#ifndef HAVE_MEMMOVE\r
+#ifdef HAVE_BCOPY\r
+#define memmove(d,s,l) bcopy((s),(d),(l))\r
+#else\r
+#error memmove does not exist on this platform, nor is a substitute available\r
+#endif /* HAVE_BCOPY */\r
+#endif /* HAVE_MEMMOVE */\r
+\r
+#include "internal.h"\r
+#include "xmltok.h"\r
+#include "xmlrole.h"\r
+\r
+typedef const XML_Char *KEY;\r
+\r
+typedef struct {\r
+ KEY name;\r
+} NAMED;\r
+\r
+typedef struct {\r
+ NAMED **v;\r
+ unsigned char power;\r
+ size_t size;\r
+ size_t used;\r
+ const XML_Memory_Handling_Suite *mem;\r
+} HASH_TABLE;\r
+\r
+/* Basic character hash algorithm, taken from Python's string hash:\r
+ h = h * 1000003 ^ character, the constant being a prime number.\r
+\r
+*/\r
+#ifdef XML_UNICODE\r
+#define CHAR_HASH(h, c) \\r
+ (((h) * 0xF4243) ^ (unsigned short)(c))\r
+#else\r
+#define CHAR_HASH(h, c) \\r
+ (((h) * 0xF4243) ^ (unsigned char)(c))\r
+#endif\r
+\r
+/* For probing (after a collision) we need a step size relative prime\r
+ to the hash table size, which is a power of 2. We use double-hashing,\r
+ since we can calculate a second hash value cheaply by taking those bits\r
+ of the first hash value that were discarded (masked out) when the table\r
+ index was calculated: index = hash & mask, where mask = table->size - 1.\r
+ We limit the maximum step size to table->size / 4 (mask >> 2) and make\r
+ it odd, since odd numbers are always relative prime to a power of 2.\r
+*/\r
+#define SECOND_HASH(hash, mask, power) \\r
+ ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))\r
+#define PROBE_STEP(hash, mask, power) \\r
+ ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))\r
+\r
+typedef struct {\r
+ NAMED **p;\r
+ NAMED **end;\r
+} HASH_TABLE_ITER;\r
+\r
+#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */\r
+#define INIT_DATA_BUF_SIZE 1024\r
+#define INIT_ATTS_SIZE 16\r
+#define INIT_ATTS_VERSION 0xFFFFFFFF\r
+#define INIT_BLOCK_SIZE 1024\r
+#define INIT_BUFFER_SIZE 1024\r
+\r
+#define EXPAND_SPARE 24\r
+\r
+typedef struct binding {\r
+ struct prefix *prefix;\r
+ struct binding *nextTagBinding;\r
+ struct binding *prevPrefixBinding;\r
+ const struct attribute_id *attId;\r
+ XML_Char *uri;\r
+ int uriLen;\r
+ int uriAlloc;\r
+} BINDING;\r
+\r
+typedef struct prefix {\r
+ const XML_Char *name;\r
+ BINDING *binding;\r
+} PREFIX;\r
+\r
+typedef struct {\r
+ const XML_Char *str;\r
+ const XML_Char *localPart;\r
+ const XML_Char *prefix;\r
+ int strLen;\r
+ int uriLen;\r
+ int prefixLen;\r
+} TAG_NAME;\r
+\r
+/* TAG represents an open element.\r
+ The name of the element is stored in both the document and API\r
+ encodings. The memory buffer 'buf' is a separately-allocated\r
+ memory area which stores the name. During the XML_Parse()/\r
+ XMLParseBuffer() when the element is open, the memory for the 'raw'\r
+ version of the name (in the document encoding) is shared with the\r
+ document buffer. If the element is open across calls to\r
+ XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to\r
+ contain the 'raw' name as well.\r
+\r
+ A parser re-uses these structures, maintaining a list of allocated\r
+ TAG objects in a free list.\r
+*/\r
+typedef struct tag {\r
+ struct tag *parent; /* parent of this element */\r
+ const char *rawName; /* tagName in the original encoding */\r
+ int rawNameLength;\r
+ TAG_NAME name; /* tagName in the API encoding */\r
+ char *buf; /* buffer for name components */\r
+ char *bufEnd; /* end of the buffer */\r
+ BINDING *bindings;\r
+} TAG;\r
+\r
+typedef struct {\r
+ const XML_Char *name;\r
+ const XML_Char *textPtr;\r
+ int textLen; /* length in XML_Chars */\r
+ int processed; /* # of processed bytes - when suspended */\r
+ const XML_Char *systemId;\r
+ const XML_Char *base;\r
+ const XML_Char *publicId;\r
+ const XML_Char *notation;\r
+ XML_Bool open;\r
+ XML_Bool is_param;\r
+ XML_Bool is_internal; /* true if declared in internal subset outside PE */\r
+} ENTITY;\r
+\r
+typedef struct {\r
+ enum XML_Content_Type type;\r
+ enum XML_Content_Quant quant;\r
+ const XML_Char * name;\r
+ int firstchild;\r
+ int lastchild;\r
+ int childcnt;\r
+ int nextsib;\r
+} CONTENT_SCAFFOLD;\r
+\r
+#define INIT_SCAFFOLD_ELEMENTS 32\r
+\r
+typedef struct block {\r
+ struct block *next;\r
+ int size;\r
+ XML_Char s[1];\r
+} BLOCK;\r
+\r
+typedef struct {\r
+ BLOCK *blocks;\r
+ BLOCK *freeBlocks;\r
+ const XML_Char *end;\r
+ XML_Char *ptr;\r
+ XML_Char *start;\r
+ const XML_Memory_Handling_Suite *mem;\r
+} STRING_POOL;\r
+\r
+/* The XML_Char before the name is used to determine whether\r
+ an attribute has been specified. */\r
+typedef struct attribute_id {\r
+ XML_Char *name;\r
+ PREFIX *prefix;\r
+ XML_Bool maybeTokenized;\r
+ XML_Bool xmlns;\r
+} ATTRIBUTE_ID;\r
+\r
+typedef struct {\r
+ const ATTRIBUTE_ID *id;\r
+ XML_Bool isCdata;\r
+ const XML_Char *value;\r
+} DEFAULT_ATTRIBUTE;\r
+\r
+typedef struct {\r
+ unsigned long version;\r
+ unsigned long hash;\r
+ const XML_Char *uriName;\r
+} NS_ATT;\r
+\r
+typedef struct {\r
+ const XML_Char *name;\r
+ PREFIX *prefix;\r
+ const ATTRIBUTE_ID *idAtt;\r
+ int nDefaultAtts;\r
+ int allocDefaultAtts;\r
+ DEFAULT_ATTRIBUTE *defaultAtts;\r
+} ELEMENT_TYPE;\r
+\r
+typedef struct {\r
+ HASH_TABLE generalEntities;\r
+ HASH_TABLE elementTypes;\r
+ HASH_TABLE attributeIds;\r
+ HASH_TABLE prefixes;\r
+ STRING_POOL pool;\r
+ STRING_POOL entityValuePool;\r
+ /* false once a parameter entity reference has been skipped */\r
+ XML_Bool keepProcessing;\r
+ /* true once an internal or external PE reference has been encountered;\r
+ this includes the reference to an external subset */\r
+ XML_Bool hasParamEntityRefs;\r
+ XML_Bool standalone;\r
+#ifdef XML_DTD\r
+ /* indicates if external PE has been read */\r
+ XML_Bool paramEntityRead;\r
+ HASH_TABLE paramEntities;\r
+#endif /* XML_DTD */\r
+ PREFIX defaultPrefix;\r
+ /* === scaffolding for building content model === */\r
+ XML_Bool in_eldecl;\r
+ CONTENT_SCAFFOLD *scaffold;\r
+ unsigned contentStringLen;\r
+ unsigned scaffSize;\r
+ unsigned scaffCount;\r
+ int scaffLevel;\r
+ int *scaffIndex;\r
+} DTD;\r
+\r
+typedef struct open_internal_entity {\r
+ const char *internalEventPtr;\r
+ const char *internalEventEndPtr;\r
+ struct open_internal_entity *next;\r
+ ENTITY *entity;\r
+ int startTagLevel;\r
+ XML_Bool betweenDecl; /* WFC: PE Between Declarations */\r
+} OPEN_INTERNAL_ENTITY;\r
+\r
+typedef enum XML_Error PTRCALL Processor(XML_Parser parser,\r
+ const char *start,\r
+ const char *end,\r
+ const char **endPtr);\r
+\r
+static Processor prologProcessor;\r
+static Processor prologInitProcessor;\r
+static Processor contentProcessor;\r
+static Processor cdataSectionProcessor;\r
+#ifdef XML_DTD\r
+static Processor ignoreSectionProcessor;\r
+static Processor externalParEntProcessor;\r
+static Processor externalParEntInitProcessor;\r
+static Processor entityValueProcessor;\r
+static Processor entityValueInitProcessor;\r
+#endif /* XML_DTD */\r
+static Processor epilogProcessor;\r
+static Processor errorProcessor;\r
+static Processor externalEntityInitProcessor;\r
+static Processor externalEntityInitProcessor2;\r
+static Processor externalEntityInitProcessor3;\r
+static Processor externalEntityContentProcessor;\r
+static Processor internalEntityProcessor;\r
+\r
+static enum XML_Error\r
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);\r
+static enum XML_Error\r
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity,\r
+ const char *s, const char *next);\r
+static enum XML_Error\r
+initializeEncoding(XML_Parser parser);\r
+static enum XML_Error\r
+doProlog(XML_Parser parser, const ENCODING *enc, const char *s,\r
+ const char *end, int tok, const char *next, const char **nextPtr,\r
+ XML_Bool haveMore);\r
+static enum XML_Error\r
+processInternalEntity(XML_Parser parser, ENTITY *entity,\r
+ XML_Bool betweenDecl);\r
+static enum XML_Error\r
+doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,\r
+ const char *start, const char *end, const char **endPtr,\r
+ XML_Bool haveMore);\r
+static enum XML_Error\r
+doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,\r
+ const char *end, const char **nextPtr, XML_Bool haveMore);\r
+#ifdef XML_DTD\r
+static enum XML_Error\r
+doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,\r
+ const char *end, const char **nextPtr, XML_Bool haveMore);\r
+#endif /* XML_DTD */\r
+\r
+static enum XML_Error\r
+storeAtts(XML_Parser parser, const ENCODING *, const char *s,\r
+ TAG_NAME *tagNamePtr, BINDING **bindingsPtr);\r
+static enum XML_Error\r
+addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,\r
+ const XML_Char *uri, BINDING **bindingsPtr);\r
+static int\r
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,\r
+ XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);\r
+static enum XML_Error\r
+storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,\r
+ const char *, const char *, STRING_POOL *);\r
+static enum XML_Error\r
+appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,\r
+ const char *, const char *, STRING_POOL *);\r
+static ATTRIBUTE_ID *\r
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,\r
+ const char *end);\r
+static int\r
+setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);\r
+static enum XML_Error\r
+storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,\r
+ const char *end);\r
+static int\r
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,\r
+ const char *start, const char *end);\r
+static int\r
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start,\r
+ const char *end);\r
+static void\r
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,\r
+ const char *end);\r
+\r
+static const XML_Char * getContext(XML_Parser parser);\r
+static XML_Bool\r
+setContext(XML_Parser parser, const XML_Char *context);\r
+\r
+static void FASTCALL normalizePublicId(XML_Char *s);\r
+\r
+static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);\r
+/* do not call if parentParser != NULL */\r
+static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);\r
+static void\r
+dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);\r
+static int\r
+dtdCopy(XML_Parser oldParser,\r
+ DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);\r
+static int\r
+copyEntityTable(XML_Parser oldParser,\r
+ HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);\r
+static NAMED *\r
+lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);\r
+static void FASTCALL\r
+hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);\r
+static void FASTCALL hashTableClear(HASH_TABLE *);\r
+static void FASTCALL hashTableDestroy(HASH_TABLE *);\r
+static void FASTCALL\r
+hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);\r
+static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);\r
+\r
+static void FASTCALL\r
+poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);\r
+static void FASTCALL poolClear(STRING_POOL *);\r
+static void FASTCALL poolDestroy(STRING_POOL *);\r
+static XML_Char *\r
+poolAppend(STRING_POOL *pool, const ENCODING *enc,\r
+ const char *ptr, const char *end);\r
+static XML_Char *\r
+poolStoreString(STRING_POOL *pool, const ENCODING *enc,\r
+ const char *ptr, const char *end);\r
+static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);\r
+static const XML_Char * FASTCALL\r
+poolCopyString(STRING_POOL *pool, const XML_Char *s);\r
+static const XML_Char *\r
+poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);\r
+static const XML_Char * FASTCALL\r
+poolAppendString(STRING_POOL *pool, const XML_Char *s);\r
+\r
+static int FASTCALL nextScaffoldPart(XML_Parser parser);\r
+static XML_Content * build_model(XML_Parser parser);\r
+static ELEMENT_TYPE *\r
+getElementType(XML_Parser parser, const ENCODING *enc,\r
+ const char *ptr, const char *end);\r
+\r
+static unsigned long generate_hash_secret_salt(void);\r
+static XML_Bool startParsing(XML_Parser parser);\r
+\r
+static XML_Parser\r
+parserCreate(const XML_Char *encodingName,\r
+ const XML_Memory_Handling_Suite *memsuite,\r
+ const XML_Char *nameSep,\r
+ DTD *dtd);\r
+\r
+static void\r
+parserInit(XML_Parser parser, const XML_Char *encodingName);\r
+\r
+#define poolStart(pool) ((pool)->start)\r
+#define poolEnd(pool) ((pool)->ptr)\r
+#define poolLength(pool) ((pool)->ptr - (pool)->start)\r
+#define poolChop(pool) ((void)--(pool->ptr))\r
+#define poolLastChar(pool) (((pool)->ptr)[-1])\r
+#define poolDiscard(pool) ((pool)->ptr = (pool)->start)\r
+#define poolFinish(pool) ((pool)->start = (pool)->ptr)\r
+#define poolAppendChar(pool, c) \\r
+ (((pool)->ptr == (pool)->end && !poolGrow(pool)) \\r
+ ? 0 \\r
+ : ((*((pool)->ptr)++ = c), 1))\r
+\r
+struct XML_ParserStruct {\r
+ /* The first member must be userData so that the XML_GetUserData\r
+ macro works. */\r
+ void *m_userData;\r
+ void *m_handlerArg;\r
+ char *m_buffer;\r
+ const XML_Memory_Handling_Suite m_mem;\r
+ /* first character to be parsed */\r
+ const char *m_bufferPtr;\r
+ /* past last character to be parsed */\r
+ char *m_bufferEnd;\r
+ /* allocated end of buffer */\r
+ const char *m_bufferLim;\r
+ XML_Index m_parseEndByteIndex;\r
+ const char *m_parseEndPtr;\r
+ XML_Char *m_dataBuf;\r
+ XML_Char *m_dataBufEnd;\r
+ XML_StartElementHandler m_startElementHandler;\r
+ XML_EndElementHandler m_endElementHandler;\r
+ XML_CharacterDataHandler m_characterDataHandler;\r
+ XML_ProcessingInstructionHandler m_processingInstructionHandler;\r
+ XML_CommentHandler m_commentHandler;\r
+ XML_StartCdataSectionHandler m_startCdataSectionHandler;\r
+ XML_EndCdataSectionHandler m_endCdataSectionHandler;\r
+ XML_DefaultHandler m_defaultHandler;\r
+ XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;\r
+ XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;\r
+ XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;\r
+ XML_NotationDeclHandler m_notationDeclHandler;\r
+ XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;\r
+ XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;\r
+ XML_NotStandaloneHandler m_notStandaloneHandler;\r
+ XML_ExternalEntityRefHandler m_externalEntityRefHandler;\r
+ XML_Parser m_externalEntityRefHandlerArg;\r
+ XML_SkippedEntityHandler m_skippedEntityHandler;\r
+ XML_UnknownEncodingHandler m_unknownEncodingHandler;\r
+ XML_ElementDeclHandler m_elementDeclHandler;\r
+ XML_AttlistDeclHandler m_attlistDeclHandler;\r
+ XML_EntityDeclHandler m_entityDeclHandler;\r
+ XML_XmlDeclHandler m_xmlDeclHandler;\r
+ const ENCODING *m_encoding;\r
+ INIT_ENCODING m_initEncoding;\r
+ const ENCODING *m_internalEncoding;\r
+ const XML_Char *m_protocolEncodingName;\r
+ XML_Bool m_ns;\r
+ XML_Bool m_ns_triplets;\r
+ void *m_unknownEncodingMem;\r
+ void *m_unknownEncodingData;\r
+ void *m_unknownEncodingHandlerData;\r
+ void (XMLCALL *m_unknownEncodingRelease)(void *);\r
+ PROLOG_STATE m_prologState;\r
+ Processor *m_processor;\r
+ enum XML_Error m_errorCode;\r
+ const char *m_eventPtr;\r
+ const char *m_eventEndPtr;\r
+ const char *m_positionPtr;\r
+ OPEN_INTERNAL_ENTITY *m_openInternalEntities;\r
+ OPEN_INTERNAL_ENTITY *m_freeInternalEntities;\r
+ XML_Bool m_defaultExpandInternalEntities;\r
+ int m_tagLevel;\r
+ ENTITY *m_declEntity;\r
+ const XML_Char *m_doctypeName;\r
+ const XML_Char *m_doctypeSysid;\r
+ const XML_Char *m_doctypePubid;\r
+ const XML_Char *m_declAttributeType;\r
+ const XML_Char *m_declNotationName;\r
+ const XML_Char *m_declNotationPublicId;\r
+ ELEMENT_TYPE *m_declElementType;\r
+ ATTRIBUTE_ID *m_declAttributeId;\r
+ XML_Bool m_declAttributeIsCdata;\r
+ XML_Bool m_declAttributeIsId;\r
+ DTD *m_dtd;\r
+ const XML_Char *m_curBase;\r
+ TAG *m_tagStack;\r
+ TAG *m_freeTagList;\r
+ BINDING *m_inheritedBindings;\r
+ BINDING *m_freeBindingList;\r
+ int m_attsSize;\r
+ int m_nSpecifiedAtts;\r
+ int m_idAttIndex;\r
+ ATTRIBUTE *m_atts;\r
+ NS_ATT *m_nsAtts;\r
+ unsigned long m_nsAttsVersion;\r
+ unsigned char m_nsAttsPower;\r
+#ifdef XML_ATTR_INFO\r
+ XML_AttrInfo *m_attInfo;\r
+#endif\r
+ POSITION m_position;\r
+ STRING_POOL m_tempPool;\r
+ STRING_POOL m_temp2Pool;\r
+ char *m_groupConnector;\r
+ unsigned int m_groupSize;\r
+ XML_Char m_namespaceSeparator;\r
+ XML_Parser m_parentParser;\r
+ XML_ParsingStatus m_parsingStatus;\r
+#ifdef XML_DTD\r
+ XML_Bool m_isParamEntity;\r
+ XML_Bool m_useForeignDTD;\r
+ enum XML_ParamEntityParsing m_paramEntityParsing;\r
+#endif\r
+ unsigned long m_hash_secret_salt;\r
+};\r
+\r
+#define MALLOC(s) (parser->m_mem.malloc_fcn((s)))\r
+#define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))\r
+#define FREE(p) (parser->m_mem.free_fcn((p)))\r
+\r
+#define userData (parser->m_userData)\r
+#define handlerArg (parser->m_handlerArg)\r
+#define startElementHandler (parser->m_startElementHandler)\r
+#define endElementHandler (parser->m_endElementHandler)\r
+#define characterDataHandler (parser->m_characterDataHandler)\r
+#define processingInstructionHandler \\r
+ (parser->m_processingInstructionHandler)\r
+#define commentHandler (parser->m_commentHandler)\r
+#define startCdataSectionHandler \\r
+ (parser->m_startCdataSectionHandler)\r
+#define endCdataSectionHandler (parser->m_endCdataSectionHandler)\r
+#define defaultHandler (parser->m_defaultHandler)\r
+#define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)\r
+#define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)\r
+#define unparsedEntityDeclHandler \\r
+ (parser->m_unparsedEntityDeclHandler)\r
+#define notationDeclHandler (parser->m_notationDeclHandler)\r
+#define startNamespaceDeclHandler \\r
+ (parser->m_startNamespaceDeclHandler)\r
+#define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)\r
+#define notStandaloneHandler (parser->m_notStandaloneHandler)\r
+#define externalEntityRefHandler \\r
+ (parser->m_externalEntityRefHandler)\r
+#define externalEntityRefHandlerArg \\r
+ (parser->m_externalEntityRefHandlerArg)\r
+#define internalEntityRefHandler \\r
+ (parser->m_internalEntityRefHandler)\r
+#define skippedEntityHandler (parser->m_skippedEntityHandler)\r
+#define unknownEncodingHandler (parser->m_unknownEncodingHandler)\r
+#define elementDeclHandler (parser->m_elementDeclHandler)\r
+#define attlistDeclHandler (parser->m_attlistDeclHandler)\r
+#define entityDeclHandler (parser->m_entityDeclHandler)\r
+#define xmlDeclHandler (parser->m_xmlDeclHandler)\r
+#define encoding (parser->m_encoding)\r
+#define initEncoding (parser->m_initEncoding)\r
+#define internalEncoding (parser->m_internalEncoding)\r
+#define unknownEncodingMem (parser->m_unknownEncodingMem)\r
+#define unknownEncodingData (parser->m_unknownEncodingData)\r
+#define unknownEncodingHandlerData \\r
+ (parser->m_unknownEncodingHandlerData)\r
+#define unknownEncodingRelease (parser->m_unknownEncodingRelease)\r
+#define protocolEncodingName (parser->m_protocolEncodingName)\r
+#define ns (parser->m_ns)\r
+#define ns_triplets (parser->m_ns_triplets)\r
+#define prologState (parser->m_prologState)\r
+#define processor (parser->m_processor)\r
+#define errorCode (parser->m_errorCode)\r
+#define eventPtr (parser->m_eventPtr)\r
+#define eventEndPtr (parser->m_eventEndPtr)\r
+#define positionPtr (parser->m_positionPtr)\r
+#define position (parser->m_position)\r
+#define openInternalEntities (parser->m_openInternalEntities)\r
+#define freeInternalEntities (parser->m_freeInternalEntities)\r
+#define defaultExpandInternalEntities \\r
+ (parser->m_defaultExpandInternalEntities)\r
+#define tagLevel (parser->m_tagLevel)\r
+#define buffer (parser->m_buffer)\r
+#define bufferPtr (parser->m_bufferPtr)\r
+#define bufferEnd (parser->m_bufferEnd)\r
+#define parseEndByteIndex (parser->m_parseEndByteIndex)\r
+#define parseEndPtr (parser->m_parseEndPtr)\r
+#define bufferLim (parser->m_bufferLim)\r
+#define dataBuf (parser->m_dataBuf)\r
+#define dataBufEnd (parser->m_dataBufEnd)\r
+#define _dtd (parser->m_dtd)\r
+#define curBase (parser->m_curBase)\r
+#define declEntity (parser->m_declEntity)\r
+#define doctypeName (parser->m_doctypeName)\r
+#define doctypeSysid (parser->m_doctypeSysid)\r
+#define doctypePubid (parser->m_doctypePubid)\r
+#define declAttributeType (parser->m_declAttributeType)\r
+#define declNotationName (parser->m_declNotationName)\r
+#define declNotationPublicId (parser->m_declNotationPublicId)\r
+#define declElementType (parser->m_declElementType)\r
+#define declAttributeId (parser->m_declAttributeId)\r
+#define declAttributeIsCdata (parser->m_declAttributeIsCdata)\r
+#define declAttributeIsId (parser->m_declAttributeIsId)\r
+#define freeTagList (parser->m_freeTagList)\r
+#define freeBindingList (parser->m_freeBindingList)\r
+#define inheritedBindings (parser->m_inheritedBindings)\r
+#define tagStack (parser->m_tagStack)\r
+#define atts (parser->m_atts)\r
+#define attsSize (parser->m_attsSize)\r
+#define nSpecifiedAtts (parser->m_nSpecifiedAtts)\r
+#define idAttIndex (parser->m_idAttIndex)\r
+#define nsAtts (parser->m_nsAtts)\r
+#define nsAttsVersion (parser->m_nsAttsVersion)\r
+#define nsAttsPower (parser->m_nsAttsPower)\r
+#define attInfo (parser->m_attInfo)\r
+#define tempPool (parser->m_tempPool)\r
+#define temp2Pool (parser->m_temp2Pool)\r
+#define groupConnector (parser->m_groupConnector)\r
+#define groupSize (parser->m_groupSize)\r
+#define namespaceSeparator (parser->m_namespaceSeparator)\r
+#define parentParser (parser->m_parentParser)\r
+#define ps_parsing (parser->m_parsingStatus.parsing)\r
+#define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)\r
+#ifdef XML_DTD\r
+#define isParamEntity (parser->m_isParamEntity)\r
+#define useForeignDTD (parser->m_useForeignDTD)\r
+#define paramEntityParsing (parser->m_paramEntityParsing)\r
+#endif /* XML_DTD */\r
+#define hash_secret_salt (parser->m_hash_secret_salt)\r
+\r
+XML_Parser XMLCALL\r
+XML_ParserCreate(const XML_Char *encodingName)\r
+{\r
+ return XML_ParserCreate_MM(encodingName, NULL, NULL);\r
+}\r
+\r
+XML_Parser XMLCALL\r
+XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)\r
+{\r
+ XML_Char tmp[2];\r
+ *tmp = nsSep;\r
+ return XML_ParserCreate_MM(encodingName, NULL, tmp);\r
+}\r
+\r
+static const XML_Char implicitContext[] = {\r
+ ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,\r
+ ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,\r
+ ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,\r
+ ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,\r
+ ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,\r
+ ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'\r
+};\r
+\r
+static unsigned long\r
+generate_hash_secret_salt(void)\r
+{\r
+ unsigned int seed = time(NULL) % UINT_MAX;\r
+ srand(seed);\r
+ return rand();\r
+}\r
+\r
+static XML_Bool /* only valid for root parser */\r
+startParsing(XML_Parser parser)\r
+{\r
+ /* hash functions must be initialized before setContext() is called */\r
+ if (hash_secret_salt == 0)\r
+ hash_secret_salt = generate_hash_secret_salt();\r
+ if (ns) {\r
+ /* implicit context only set for root parser, since child\r
+ parsers (i.e. external entity parsers) will inherit it\r
+ */\r
+ return setContext(parser, implicitContext);\r
+ }\r
+ return XML_TRUE;\r
+}\r
+\r
+XML_Parser XMLCALL\r
+XML_ParserCreate_MM(const XML_Char *encodingName,\r
+ const XML_Memory_Handling_Suite *memsuite,\r
+ const XML_Char *nameSep)\r
+{\r
+ return parserCreate(encodingName, memsuite, nameSep, NULL);\r
+}\r
+\r
+static XML_Parser\r
+parserCreate(const XML_Char *encodingName,\r
+ const XML_Memory_Handling_Suite *memsuite,\r
+ const XML_Char *nameSep,\r
+ DTD *dtd)\r
+{\r
+ XML_Parser parser;\r
+\r
+ if (memsuite) {\r
+ XML_Memory_Handling_Suite *mtemp;\r
+ parser = (XML_Parser)\r
+ memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));\r
+ if (parser != NULL) {\r
+ mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);\r
+ mtemp->malloc_fcn = memsuite->malloc_fcn;\r
+ mtemp->realloc_fcn = memsuite->realloc_fcn;\r
+ mtemp->free_fcn = memsuite->free_fcn;\r
+ }\r
+ }\r
+ else {\r
+ XML_Memory_Handling_Suite *mtemp;\r
+ parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));\r
+ if (parser != NULL) {\r
+ mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);\r
+ mtemp->malloc_fcn = malloc;\r
+ mtemp->realloc_fcn = realloc;\r
+ mtemp->free_fcn = free;\r
+ }\r
+ }\r
+\r
+ if (!parser)\r
+ return parser;\r
+\r
+ buffer = NULL;\r
+ bufferLim = NULL;\r
+\r
+ attsSize = INIT_ATTS_SIZE;\r
+ atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));\r
+ if (atts == NULL) {\r
+ FREE(parser);\r
+ return NULL;\r
+ }\r
+#ifdef XML_ATTR_INFO\r
+ attInfo = (XML_AttrInfo*)MALLOC(attsSize * sizeof(XML_AttrInfo));\r
+ if (attInfo == NULL) {\r
+ FREE(atts);\r
+ FREE(parser);\r
+ return NULL;\r
+ }\r
+#endif\r
+ dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));\r
+ if (dataBuf == NULL) {\r
+ FREE(atts);\r
+#ifdef XML_ATTR_INFO\r
+ FREE(attInfo);\r
+#endif\r
+ FREE(parser);\r
+ return NULL;\r
+ }\r
+ dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;\r
+\r
+ if (dtd)\r
+ _dtd = dtd;\r
+ else {\r
+ _dtd = dtdCreate(&parser->m_mem);\r
+ if (_dtd == NULL) {\r
+ FREE(dataBuf);\r
+ FREE(atts);\r
+#ifdef XML_ATTR_INFO\r
+ FREE(attInfo);\r
+#endif\r
+ FREE(parser);\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ freeBindingList = NULL;\r
+ freeTagList = NULL;\r
+ freeInternalEntities = NULL;\r
+\r
+ groupSize = 0;\r
+ groupConnector = NULL;\r
+\r
+ unknownEncodingHandler = NULL;\r
+ unknownEncodingHandlerData = NULL;\r
+\r
+ namespaceSeparator = ASCII_EXCL;\r
+ ns = XML_FALSE;\r
+ ns_triplets = XML_FALSE;\r
+\r
+ nsAtts = NULL;\r
+ nsAttsVersion = 0;\r
+ nsAttsPower = 0;\r
+\r
+ poolInit(&tempPool, &(parser->m_mem));\r
+ poolInit(&temp2Pool, &(parser->m_mem));\r
+ parserInit(parser, encodingName);\r
+\r
+ if (encodingName && !protocolEncodingName) {\r
+ XML_ParserFree(parser);\r
+ return NULL;\r
+ }\r
+\r
+ if (nameSep) {\r
+ ns = XML_TRUE;\r
+ internalEncoding = XmlGetInternalEncodingNS();\r
+ namespaceSeparator = *nameSep;\r
+ }\r
+ else {\r
+ internalEncoding = XmlGetInternalEncoding();\r
+ }\r
+\r
+ return parser;\r
+}\r
+\r
+static void\r
+parserInit(XML_Parser parser, const XML_Char *encodingName)\r
+{\r
+ processor = prologInitProcessor;\r
+ XmlPrologStateInit(&prologState);\r
+ protocolEncodingName = (encodingName != NULL\r
+ ? poolCopyString(&tempPool, encodingName)\r
+ : NULL);\r
+ curBase = NULL;\r
+ XmlInitEncoding(&initEncoding, &encoding, 0);\r
+ userData = NULL;\r
+ handlerArg = NULL;\r
+ startElementHandler = NULL;\r
+ endElementHandler = NULL;\r
+ characterDataHandler = NULL;\r
+ processingInstructionHandler = NULL;\r
+ commentHandler = NULL;\r
+ startCdataSectionHandler = NULL;\r
+ endCdataSectionHandler = NULL;\r
+ defaultHandler = NULL;\r
+ startDoctypeDeclHandler = NULL;\r
+ endDoctypeDeclHandler = NULL;\r
+ unparsedEntityDeclHandler = NULL;\r
+ notationDeclHandler = NULL;\r
+ startNamespaceDeclHandler = NULL;\r
+ endNamespaceDeclHandler = NULL;\r
+ notStandaloneHandler = NULL;\r
+ externalEntityRefHandler = NULL;\r
+ externalEntityRefHandlerArg = parser;\r
+ skippedEntityHandler = NULL;\r
+ elementDeclHandler = NULL;\r
+ attlistDeclHandler = NULL;\r
+ entityDeclHandler = NULL;\r
+ xmlDeclHandler = NULL;\r
+ bufferPtr = buffer;\r
+ bufferEnd = buffer;\r
+ parseEndByteIndex = 0;\r
+ parseEndPtr = NULL;\r
+ declElementType = NULL;\r
+ declAttributeId = NULL;\r
+ declEntity = NULL;\r
+ doctypeName = NULL;\r
+ doctypeSysid = NULL;\r
+ doctypePubid = NULL;\r
+ declAttributeType = NULL;\r
+ declNotationName = NULL;\r
+ declNotationPublicId = NULL;\r
+ declAttributeIsCdata = XML_FALSE;\r
+ declAttributeIsId = XML_FALSE;\r
+ memset(&position, 0, sizeof(POSITION));\r
+ errorCode = XML_ERROR_NONE;\r
+ eventPtr = NULL;\r
+ eventEndPtr = NULL;\r
+ positionPtr = NULL;\r
+ openInternalEntities = NULL;\r
+ defaultExpandInternalEntities = XML_TRUE;\r
+ tagLevel = 0;\r
+ tagStack = NULL;\r
+ inheritedBindings = NULL;\r
+ nSpecifiedAtts = 0;\r
+ unknownEncodingMem = NULL;\r
+ unknownEncodingRelease = NULL;\r
+ unknownEncodingData = NULL;\r
+ parentParser = NULL;\r
+ ps_parsing = XML_INITIALIZED;\r
+#ifdef XML_DTD\r
+ isParamEntity = XML_FALSE;\r
+ useForeignDTD = XML_FALSE;\r
+ paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;\r
+#endif\r
+ hash_secret_salt = 0;\r
+}\r
+\r
+/* moves list of bindings to freeBindingList */\r
+static void FASTCALL\r
+moveToFreeBindingList(XML_Parser parser, BINDING *bindings)\r
+{\r
+ while (bindings) {\r
+ BINDING *b = bindings;\r
+ bindings = bindings->nextTagBinding;\r
+ b->nextTagBinding = freeBindingList;\r
+ freeBindingList = b;\r
+ }\r
+}\r
+\r
+XML_Bool XMLCALL\r
+XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)\r
+{\r
+ TAG *tStk;\r
+ OPEN_INTERNAL_ENTITY *openEntityList;\r
+ if (parentParser)\r
+ return XML_FALSE;\r
+ /* move tagStack to freeTagList */\r
+ tStk = tagStack;\r
+ while (tStk) {\r
+ TAG *tag = tStk;\r
+ tStk = tStk->parent;\r
+ tag->parent = freeTagList;\r
+ moveToFreeBindingList(parser, tag->bindings);\r
+ tag->bindings = NULL;\r
+ freeTagList = tag;\r
+ }\r
+ /* move openInternalEntities to freeInternalEntities */\r
+ openEntityList = openInternalEntities;\r
+ while (openEntityList) {\r
+ OPEN_INTERNAL_ENTITY *openEntity = openEntityList;\r
+ openEntityList = openEntity->next;\r
+ openEntity->next = freeInternalEntities;\r
+ freeInternalEntities = openEntity;\r
+ }\r
+ moveToFreeBindingList(parser, inheritedBindings);\r
+ FREE(unknownEncodingMem);\r
+ if (unknownEncodingRelease)\r
+ unknownEncodingRelease(unknownEncodingData);\r
+ poolClear(&tempPool);\r
+ poolClear(&temp2Pool);\r
+ parserInit(parser, encodingName);\r
+ dtdReset(_dtd, &parser->m_mem);\r
+ return XML_TRUE;\r
+}\r
+\r
+enum XML_Status XMLCALL\r
+XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)\r
+{\r
+ /* Block after XML_Parse()/XML_ParseBuffer() has been called.\r
+ XXX There's no way for the caller to determine which of the\r
+ XXX possible error cases caused the XML_STATUS_ERROR return.\r
+ */\r
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)\r
+ return XML_STATUS_ERROR;\r
+ if (encodingName == NULL)\r
+ protocolEncodingName = NULL;\r
+ else {\r
+ protocolEncodingName = poolCopyString(&tempPool, encodingName);\r
+ if (!protocolEncodingName)\r
+ return XML_STATUS_ERROR;\r
+ }\r
+ return XML_STATUS_OK;\r
+}\r
+\r
+XML_Parser XMLCALL\r
+XML_ExternalEntityParserCreate(XML_Parser oldParser,\r
+ const XML_Char *context,\r
+ const XML_Char *encodingName)\r
+{\r
+ XML_Parser parser = oldParser;\r
+ DTD *newDtd = NULL;\r
+ DTD *oldDtd = _dtd;\r
+ XML_StartElementHandler oldStartElementHandler = startElementHandler;\r
+ XML_EndElementHandler oldEndElementHandler = endElementHandler;\r
+ XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;\r
+ XML_ProcessingInstructionHandler oldProcessingInstructionHandler\r
+ = processingInstructionHandler;\r
+ XML_CommentHandler oldCommentHandler = commentHandler;\r
+ XML_StartCdataSectionHandler oldStartCdataSectionHandler\r
+ = startCdataSectionHandler;\r
+ XML_EndCdataSectionHandler oldEndCdataSectionHandler\r
+ = endCdataSectionHandler;\r
+ XML_DefaultHandler oldDefaultHandler = defaultHandler;\r
+ XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler\r
+ = unparsedEntityDeclHandler;\r
+ XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;\r
+ XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler\r
+ = startNamespaceDeclHandler;\r
+ XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler\r
+ = endNamespaceDeclHandler;\r
+ XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;\r
+ XML_ExternalEntityRefHandler oldExternalEntityRefHandler\r
+ = externalEntityRefHandler;\r
+ XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;\r
+ XML_UnknownEncodingHandler oldUnknownEncodingHandler\r
+ = unknownEncodingHandler;\r
+ XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;\r
+ XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;\r
+ XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;\r
+ XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;\r
+ ELEMENT_TYPE * oldDeclElementType = declElementType;\r
+\r
+ void *oldUserData = userData;\r
+ void *oldHandlerArg = handlerArg;\r
+ XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;\r
+ XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;\r
+#ifdef XML_DTD\r
+ enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;\r
+ int oldInEntityValue = prologState.inEntityValue;\r
+#endif\r
+ XML_Bool oldns_triplets = ns_triplets;\r
+ /* Note that the new parser shares the same hash secret as the old\r
+ parser, so that dtdCopy and copyEntityTable can lookup values\r
+ from hash tables associated with either parser without us having\r
+ to worry which hash secrets each table has.\r
+ */\r
+ unsigned long oldhash_secret_salt = hash_secret_salt;\r
+\r
+#ifdef XML_DTD\r
+ if (!context)\r
+ newDtd = oldDtd;\r
+#endif /* XML_DTD */\r
+\r
+ /* Note that the magical uses of the pre-processor to make field\r
+ access look more like C++ require that `parser' be overwritten\r
+ here. This makes this function more painful to follow than it\r
+ would be otherwise.\r
+ */\r
+ if (ns) {\r
+ XML_Char tmp[2];\r
+ *tmp = namespaceSeparator;\r
+ parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);\r
+ }\r
+ else {\r
+ parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);\r
+ }\r
+\r
+ if (!parser)\r
+ return NULL;\r
+\r
+ startElementHandler = oldStartElementHandler;\r
+ endElementHandler = oldEndElementHandler;\r
+ characterDataHandler = oldCharacterDataHandler;\r
+ processingInstructionHandler = oldProcessingInstructionHandler;\r
+ commentHandler = oldCommentHandler;\r
+ startCdataSectionHandler = oldStartCdataSectionHandler;\r
+ endCdataSectionHandler = oldEndCdataSectionHandler;\r
+ defaultHandler = oldDefaultHandler;\r
+ unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;\r
+ notationDeclHandler = oldNotationDeclHandler;\r
+ startNamespaceDeclHandler = oldStartNamespaceDeclHandler;\r
+ endNamespaceDeclHandler = oldEndNamespaceDeclHandler;\r
+ notStandaloneHandler = oldNotStandaloneHandler;\r
+ externalEntityRefHandler = oldExternalEntityRefHandler;\r
+ skippedEntityHandler = oldSkippedEntityHandler;\r
+ unknownEncodingHandler = oldUnknownEncodingHandler;\r
+ elementDeclHandler = oldElementDeclHandler;\r
+ attlistDeclHandler = oldAttlistDeclHandler;\r
+ entityDeclHandler = oldEntityDeclHandler;\r
+ xmlDeclHandler = oldXmlDeclHandler;\r
+ declElementType = oldDeclElementType;\r
+ userData = oldUserData;\r
+ if (oldUserData == oldHandlerArg)\r
+ handlerArg = userData;\r
+ else\r
+ handlerArg = parser;\r
+ if (oldExternalEntityRefHandlerArg != oldParser)\r
+ externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;\r
+ defaultExpandInternalEntities = oldDefaultExpandInternalEntities;\r
+ ns_triplets = oldns_triplets;\r
+ hash_secret_salt = oldhash_secret_salt;\r
+ parentParser = oldParser;\r
+#ifdef XML_DTD\r
+ paramEntityParsing = oldParamEntityParsing;\r
+ prologState.inEntityValue = oldInEntityValue;\r
+ if (context) {\r
+#endif /* XML_DTD */\r
+ if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem)\r
+ || !setContext(parser, context)) {\r
+ XML_ParserFree(parser);\r
+ return NULL;\r
+ }\r
+ processor = externalEntityInitProcessor;\r
+#ifdef XML_DTD\r
+ }\r
+ else {\r
+ /* The DTD instance referenced by _dtd is shared between the document's\r
+ root parser and external PE parsers, therefore one does not need to\r
+ call setContext. In addition, one also *must* not call setContext,\r
+ because this would overwrite existing prefix->binding pointers in\r
+ _dtd with ones that get destroyed with the external PE parser.\r
+ This would leave those prefixes with dangling pointers.\r
+ */\r
+ isParamEntity = XML_TRUE;\r
+ XmlPrologStateInitExternalEntity(&prologState);\r
+ processor = externalParEntInitProcessor;\r
+ }\r
+#endif /* XML_DTD */\r
+ return parser;\r
+}\r
+\r
+static void FASTCALL\r
+destroyBindings(BINDING *bindings, XML_Parser parser)\r
+{\r
+ for (;;) {\r
+ BINDING *b = bindings;\r
+ if (!b)\r
+ break;\r
+ bindings = b->nextTagBinding;\r
+ FREE(b->uri);\r
+ FREE(b);\r
+ }\r
+}\r
+\r
+void XMLCALL\r
+XML_ParserFree(XML_Parser parser)\r
+{\r
+ TAG *tagList;\r
+ OPEN_INTERNAL_ENTITY *entityList;\r
+ if (parser == NULL)\r
+ return;\r
+ /* free tagStack and freeTagList */\r
+ tagList = tagStack;\r
+ for (;;) {\r
+ TAG *p;\r
+ if (tagList == NULL) {\r
+ if (freeTagList == NULL)\r
+ break;\r
+ tagList = freeTagList;\r
+ freeTagList = NULL;\r
+ }\r
+ p = tagList;\r
+ tagList = tagList->parent;\r
+ FREE(p->buf);\r
+ destroyBindings(p->bindings, parser);\r
+ FREE(p);\r
+ }\r
+ /* free openInternalEntities and freeInternalEntities */\r
+ entityList = openInternalEntities;\r
+ for (;;) {\r
+ OPEN_INTERNAL_ENTITY *openEntity;\r
+ if (entityList == NULL) {\r
+ if (freeInternalEntities == NULL)\r
+ break;\r
+ entityList = freeInternalEntities;\r
+ freeInternalEntities = NULL;\r
+ }\r
+ openEntity = entityList;\r
+ entityList = entityList->next;\r
+ FREE(openEntity);\r
+ }\r
+\r
+ destroyBindings(freeBindingList, parser);\r
+ destroyBindings(inheritedBindings, parser);\r
+ poolDestroy(&tempPool);\r
+ poolDestroy(&temp2Pool);\r
+#ifdef XML_DTD\r
+ /* external parameter entity parsers share the DTD structure\r
+ parser->m_dtd with the root parser, so we must not destroy it\r
+ */\r
+ if (!isParamEntity && _dtd)\r
+#else\r
+ if (_dtd)\r
+#endif /* XML_DTD */\r
+ dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);\r
+ FREE((void *)atts);\r
+#ifdef XML_ATTR_INFO\r
+ FREE((void *)attInfo);\r
+#endif\r
+ FREE(groupConnector);\r
+ FREE(buffer);\r
+ FREE(dataBuf);\r
+ FREE(nsAtts);\r
+ FREE(unknownEncodingMem);\r
+ if (unknownEncodingRelease)\r
+ unknownEncodingRelease(unknownEncodingData);\r
+ FREE(parser);\r
+}\r
+\r
+void XMLCALL\r
+XML_UseParserAsHandlerArg(XML_Parser parser)\r
+{\r
+ handlerArg = parser;\r
+}\r
+\r
+enum XML_Error XMLCALL\r
+XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)\r
+{\r
+#ifdef XML_DTD\r
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */\r
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)\r
+ return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;\r
+ useForeignDTD = useDTD;\r
+ return XML_ERROR_NONE;\r
+#else\r
+ return XML_ERROR_FEATURE_REQUIRES_XML_DTD;\r
+#endif\r
+}\r
+\r
+void XMLCALL\r
+XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)\r
+{\r
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */\r
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)\r
+ return;\r
+ ns_triplets = do_nst ? XML_TRUE : XML_FALSE;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetUserData(XML_Parser parser, void *p)\r
+{\r
+ if (handlerArg == userData)\r
+ handlerArg = userData = p;\r
+ else\r
+ userData = p;\r
+}\r
+\r
+enum XML_Status XMLCALL\r
+XML_SetBase(XML_Parser parser, const XML_Char *p)\r
+{\r
+ if (p) {\r
+ p = poolCopyString(&_dtd->pool, p);\r
+ if (!p)\r
+ return XML_STATUS_ERROR;\r
+ curBase = p;\r
+ }\r
+ else\r
+ curBase = NULL;\r
+ return XML_STATUS_OK;\r
+}\r
+\r
+const XML_Char * XMLCALL\r
+XML_GetBase(XML_Parser parser)\r
+{\r
+ return curBase;\r
+}\r
+\r
+int XMLCALL\r
+XML_GetSpecifiedAttributeCount(XML_Parser parser)\r
+{\r
+ return nSpecifiedAtts;\r
+}\r
+\r
+int XMLCALL\r
+XML_GetIdAttributeIndex(XML_Parser parser)\r
+{\r
+ return idAttIndex;\r
+}\r
+\r
+#ifdef XML_ATTR_INFO\r
+const XML_AttrInfo * XMLCALL\r
+XML_GetAttributeInfo(XML_Parser parser)\r
+{\r
+ return attInfo;\r
+}\r
+#endif\r
+\r
+void XMLCALL\r
+XML_SetElementHandler(XML_Parser parser,\r
+ XML_StartElementHandler start,\r
+ XML_EndElementHandler end)\r
+{\r
+ startElementHandler = start;\r
+ endElementHandler = end;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetStartElementHandler(XML_Parser parser,\r
+ XML_StartElementHandler start) {\r
+ startElementHandler = start;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetEndElementHandler(XML_Parser parser,\r
+ XML_EndElementHandler end) {\r
+ endElementHandler = end;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetCharacterDataHandler(XML_Parser parser,\r
+ XML_CharacterDataHandler handler)\r
+{\r
+ characterDataHandler = handler;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetProcessingInstructionHandler(XML_Parser parser,\r
+ XML_ProcessingInstructionHandler handler)\r
+{\r
+ processingInstructionHandler = handler;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetCommentHandler(XML_Parser parser,\r
+ XML_CommentHandler handler)\r
+{\r
+ commentHandler = handler;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetCdataSectionHandler(XML_Parser parser,\r
+ XML_StartCdataSectionHandler start,\r
+ XML_EndCdataSectionHandler end)\r
+{\r
+ startCdataSectionHandler = start;\r
+ endCdataSectionHandler = end;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetStartCdataSectionHandler(XML_Parser parser,\r
+ XML_StartCdataSectionHandler start) {\r
+ startCdataSectionHandler = start;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetEndCdataSectionHandler(XML_Parser parser,\r
+ XML_EndCdataSectionHandler end) {\r
+ endCdataSectionHandler = end;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetDefaultHandler(XML_Parser parser,\r
+ XML_DefaultHandler handler)\r
+{\r
+ defaultHandler = handler;\r
+ defaultExpandInternalEntities = XML_FALSE;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetDefaultHandlerExpand(XML_Parser parser,\r
+ XML_DefaultHandler handler)\r
+{\r
+ defaultHandler = handler;\r
+ defaultExpandInternalEntities = XML_TRUE;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetDoctypeDeclHandler(XML_Parser parser,\r
+ XML_StartDoctypeDeclHandler start,\r
+ XML_EndDoctypeDeclHandler end)\r
+{\r
+ startDoctypeDeclHandler = start;\r
+ endDoctypeDeclHandler = end;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetStartDoctypeDeclHandler(XML_Parser parser,\r
+ XML_StartDoctypeDeclHandler start) {\r
+ startDoctypeDeclHandler = start;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetEndDoctypeDeclHandler(XML_Parser parser,\r
+ XML_EndDoctypeDeclHandler end) {\r
+ endDoctypeDeclHandler = end;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetUnparsedEntityDeclHandler(XML_Parser parser,\r
+ XML_UnparsedEntityDeclHandler handler)\r
+{\r
+ unparsedEntityDeclHandler = handler;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetNotationDeclHandler(XML_Parser parser,\r
+ XML_NotationDeclHandler handler)\r
+{\r
+ notationDeclHandler = handler;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetNamespaceDeclHandler(XML_Parser parser,\r
+ XML_StartNamespaceDeclHandler start,\r
+ XML_EndNamespaceDeclHandler end)\r
+{\r
+ startNamespaceDeclHandler = start;\r
+ endNamespaceDeclHandler = end;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetStartNamespaceDeclHandler(XML_Parser parser,\r
+ XML_StartNamespaceDeclHandler start) {\r
+ startNamespaceDeclHandler = start;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetEndNamespaceDeclHandler(XML_Parser parser,\r
+ XML_EndNamespaceDeclHandler end) {\r
+ endNamespaceDeclHandler = end;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetNotStandaloneHandler(XML_Parser parser,\r
+ XML_NotStandaloneHandler handler)\r
+{\r
+ notStandaloneHandler = handler;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetExternalEntityRefHandler(XML_Parser parser,\r
+ XML_ExternalEntityRefHandler handler)\r
+{\r
+ externalEntityRefHandler = handler;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)\r
+{\r
+ if (arg)\r
+ externalEntityRefHandlerArg = (XML_Parser)arg;\r
+ else\r
+ externalEntityRefHandlerArg = parser;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetSkippedEntityHandler(XML_Parser parser,\r
+ XML_SkippedEntityHandler handler)\r
+{\r
+ skippedEntityHandler = handler;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetUnknownEncodingHandler(XML_Parser parser,\r
+ XML_UnknownEncodingHandler handler,\r
+ void *data)\r
+{\r
+ unknownEncodingHandler = handler;\r
+ unknownEncodingHandlerData = data;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetElementDeclHandler(XML_Parser parser,\r
+ XML_ElementDeclHandler eldecl)\r
+{\r
+ elementDeclHandler = eldecl;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetAttlistDeclHandler(XML_Parser parser,\r
+ XML_AttlistDeclHandler attdecl)\r
+{\r
+ attlistDeclHandler = attdecl;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetEntityDeclHandler(XML_Parser parser,\r
+ XML_EntityDeclHandler handler)\r
+{\r
+ entityDeclHandler = handler;\r
+}\r
+\r
+void XMLCALL\r
+XML_SetXmlDeclHandler(XML_Parser parser,\r
+ XML_XmlDeclHandler handler) {\r
+ xmlDeclHandler = handler;\r
+}\r
+\r
+int XMLCALL\r
+XML_SetParamEntityParsing(XML_Parser parser,\r
+ enum XML_ParamEntityParsing peParsing)\r
+{\r
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */\r
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)\r
+ return 0;\r
+#ifdef XML_DTD\r
+ paramEntityParsing = peParsing;\r
+ return 1;\r
+#else\r
+ return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;\r
+#endif\r
+}\r
+\r
+int XMLCALL\r
+XML_SetHashSalt(XML_Parser parser,\r
+ unsigned long hash_salt)\r
+{\r
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */\r
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)\r
+ return 0;\r
+ hash_secret_salt = hash_salt;\r
+ return 1;\r
+}\r
+\r
+enum XML_Status XMLCALL\r
+XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)\r
+{\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ errorCode = XML_ERROR_SUSPENDED;\r
+ return XML_STATUS_ERROR;\r
+ case XML_FINISHED:\r
+ errorCode = XML_ERROR_FINISHED;\r
+ return XML_STATUS_ERROR;\r
+ case XML_INITIALIZED:\r
+ if (parentParser == NULL && !startParsing(parser)) {\r
+ errorCode = XML_ERROR_NO_MEMORY;\r
+ return XML_STATUS_ERROR;\r
+ }\r
+ default:\r
+ ps_parsing = XML_PARSING;\r
+ }\r
+\r
+ if (len == 0) {\r
+ ps_finalBuffer = (XML_Bool)isFinal;\r
+ if (!isFinal)\r
+ return XML_STATUS_OK;\r
+ positionPtr = bufferPtr;\r
+ parseEndPtr = bufferEnd;\r
+\r
+ /* If data are left over from last buffer, and we now know that these\r
+ data are the final chunk of input, then we have to check them again\r
+ to detect errors based on that fact.\r
+ */\r
+ errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);\r
+\r
+ if (errorCode == XML_ERROR_NONE) {\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);\r
+ positionPtr = bufferPtr;\r
+ return XML_STATUS_SUSPENDED;\r
+ case XML_INITIALIZED:\r
+ case XML_PARSING:\r
+ ps_parsing = XML_FINISHED;\r
+ /* fall through */\r
+ default:\r
+ return XML_STATUS_OK;\r
+ }\r
+ }\r
+ eventEndPtr = eventPtr;\r
+ processor = errorProcessor;\r
+ return XML_STATUS_ERROR;\r
+ }\r
+#ifndef XML_CONTEXT_BYTES\r
+ else if (bufferPtr == bufferEnd) {\r
+ const char *end;\r
+ int nLeftOver;\r
+ enum XML_Error result;\r
+ parseEndByteIndex += len;\r
+ positionPtr = s;\r
+ ps_finalBuffer = (XML_Bool)isFinal;\r
+\r
+ errorCode = processor(parser, s, parseEndPtr = s + len, &end);\r
+\r
+ if (errorCode != XML_ERROR_NONE) {\r
+ eventEndPtr = eventPtr;\r
+ processor = errorProcessor;\r
+ return XML_STATUS_ERROR;\r
+ }\r
+ else {\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ result = XML_STATUS_SUSPENDED;\r
+ break;\r
+ case XML_INITIALIZED:\r
+ case XML_PARSING:\r
+ if (isFinal) {\r
+ ps_parsing = XML_FINISHED;\r
+ return XML_STATUS_OK;\r
+ }\r
+ /* fall through */\r
+ default:\r
+ result = XML_STATUS_OK;\r
+ }\r
+ }\r
+\r
+ XmlUpdatePosition(encoding, positionPtr, end, &position);\r
+ nLeftOver = s + len - end;\r
+ if (nLeftOver) {\r
+ if (buffer == NULL || nLeftOver > bufferLim - buffer) {\r
+ /* FIXME avoid integer overflow */\r
+ char *temp;\r
+ temp = (buffer == NULL\r
+ ? (char *)MALLOC(len * 2)\r
+ : (char *)REALLOC(buffer, len * 2));\r
+ if (temp == NULL) {\r
+ errorCode = XML_ERROR_NO_MEMORY;\r
+ eventPtr = eventEndPtr = NULL;\r
+ processor = errorProcessor;\r
+ return XML_STATUS_ERROR;\r
+ }\r
+ buffer = temp;\r
+ bufferLim = buffer + len * 2;\r
+ }\r
+ memcpy(buffer, end, nLeftOver);\r
+ }\r
+ bufferPtr = buffer;\r
+ bufferEnd = buffer + nLeftOver;\r
+ positionPtr = bufferPtr;\r
+ parseEndPtr = bufferEnd;\r
+ eventPtr = bufferPtr;\r
+ eventEndPtr = bufferPtr;\r
+ return result;\r
+ }\r
+#endif /* not defined XML_CONTEXT_BYTES */\r
+ else {\r
+ void *buff = XML_GetBuffer(parser, len);\r
+ if (buff == NULL)\r
+ return XML_STATUS_ERROR;\r
+ else {\r
+ memcpy(buff, s, len);\r
+ return XML_ParseBuffer(parser, len, isFinal);\r
+ }\r
+ }\r
+}\r
+\r
+enum XML_Status XMLCALL\r
+XML_ParseBuffer(XML_Parser parser, int len, int isFinal)\r
+{\r
+ const char *start;\r
+ enum XML_Status result = XML_STATUS_OK;\r
+\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ errorCode = XML_ERROR_SUSPENDED;\r
+ return XML_STATUS_ERROR;\r
+ case XML_FINISHED:\r
+ errorCode = XML_ERROR_FINISHED;\r
+ return XML_STATUS_ERROR;\r
+ case XML_INITIALIZED:\r
+ if (parentParser == NULL && !startParsing(parser)) {\r
+ errorCode = XML_ERROR_NO_MEMORY;\r
+ return XML_STATUS_ERROR;\r
+ }\r
+ default:\r
+ ps_parsing = XML_PARSING;\r
+ }\r
+\r
+ start = bufferPtr;\r
+ positionPtr = start;\r
+ bufferEnd += len;\r
+ parseEndPtr = bufferEnd;\r
+ parseEndByteIndex += len;\r
+ ps_finalBuffer = (XML_Bool)isFinal;\r
+\r
+ errorCode = processor(parser, start, parseEndPtr, &bufferPtr);\r
+\r
+ if (errorCode != XML_ERROR_NONE) {\r
+ eventEndPtr = eventPtr;\r
+ processor = errorProcessor;\r
+ return XML_STATUS_ERROR;\r
+ }\r
+ else {\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ result = XML_STATUS_SUSPENDED;\r
+ break;\r
+ case XML_INITIALIZED:\r
+ case XML_PARSING:\r
+ if (isFinal) {\r
+ ps_parsing = XML_FINISHED;\r
+ return result;\r
+ }\r
+ default: ; /* should not happen */\r
+ }\r
+ }\r
+\r
+ XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);\r
+ positionPtr = bufferPtr;\r
+ return result;\r
+}\r
+\r
+void * XMLCALL\r
+XML_GetBuffer(XML_Parser parser, int len)\r
+{\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ errorCode = XML_ERROR_SUSPENDED;\r
+ return NULL;\r
+ case XML_FINISHED:\r
+ errorCode = XML_ERROR_FINISHED;\r
+ return NULL;\r
+ default: ;\r
+ }\r
+\r
+ if (len > bufferLim - bufferEnd) {\r
+ /* FIXME avoid integer overflow */\r
+ int neededSize = len + (int)(bufferEnd - bufferPtr);\r
+#ifdef XML_CONTEXT_BYTES\r
+ int keep = (int)(bufferPtr - buffer);\r
+\r
+ if (keep > XML_CONTEXT_BYTES)\r
+ keep = XML_CONTEXT_BYTES;\r
+ neededSize += keep;\r
+#endif /* defined XML_CONTEXT_BYTES */\r
+ if (neededSize <= bufferLim - buffer) {\r
+#ifdef XML_CONTEXT_BYTES\r
+ if (keep < bufferPtr - buffer) {\r
+ int offset = (int)(bufferPtr - buffer) - keep;\r
+ memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);\r
+ bufferEnd -= offset;\r
+ bufferPtr -= offset;\r
+ }\r
+#else\r
+ memmove(buffer, bufferPtr, bufferEnd - bufferPtr);\r
+ bufferEnd = buffer + (bufferEnd - bufferPtr);\r
+ bufferPtr = buffer;\r
+#endif /* not defined XML_CONTEXT_BYTES */\r
+ }\r
+ else {\r
+ char *newBuf;\r
+ int bufferSize = (int)(bufferLim - bufferPtr);\r
+ if (bufferSize == 0)\r
+ bufferSize = INIT_BUFFER_SIZE;\r
+ do {\r
+ bufferSize *= 2;\r
+ } while (bufferSize < neededSize);\r
+ newBuf = (char *)MALLOC(bufferSize);\r
+ if (newBuf == 0) {\r
+ errorCode = XML_ERROR_NO_MEMORY;\r
+ return NULL;\r
+ }\r
+ bufferLim = newBuf + bufferSize;\r
+#ifdef XML_CONTEXT_BYTES\r
+ if (bufferPtr) {\r
+ int keep = (int)(bufferPtr - buffer);\r
+ if (keep > XML_CONTEXT_BYTES)\r
+ keep = XML_CONTEXT_BYTES;\r
+ memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);\r
+ FREE(buffer);\r
+ buffer = newBuf;\r
+ bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;\r
+ bufferPtr = buffer + keep;\r
+ }\r
+ else {\r
+ bufferEnd = newBuf + (bufferEnd - bufferPtr);\r
+ bufferPtr = buffer = newBuf;\r
+ }\r
+#else\r
+ if (bufferPtr) {\r
+ memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);\r
+ FREE(buffer);\r
+ }\r
+ bufferEnd = newBuf + (bufferEnd - bufferPtr);\r
+ bufferPtr = buffer = newBuf;\r
+#endif /* not defined XML_CONTEXT_BYTES */\r
+ }\r
+ eventPtr = eventEndPtr = NULL;\r
+ positionPtr = NULL;\r
+ }\r
+ return bufferEnd;\r
+}\r
+\r
+enum XML_Status XMLCALL\r
+XML_StopParser(XML_Parser parser, XML_Bool resumable)\r
+{\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ if (resumable) {\r
+ errorCode = XML_ERROR_SUSPENDED;\r
+ return XML_STATUS_ERROR;\r
+ }\r
+ ps_parsing = XML_FINISHED;\r
+ break;\r
+ case XML_FINISHED:\r
+ errorCode = XML_ERROR_FINISHED;\r
+ return XML_STATUS_ERROR;\r
+ default:\r
+ if (resumable) {\r
+#ifdef XML_DTD\r
+ if (isParamEntity) {\r
+ errorCode = XML_ERROR_SUSPEND_PE;\r
+ return XML_STATUS_ERROR;\r
+ }\r
+#endif\r
+ ps_parsing = XML_SUSPENDED;\r
+ }\r
+ else\r
+ ps_parsing = XML_FINISHED;\r
+ }\r
+ return XML_STATUS_OK;\r
+}\r
+\r
+enum XML_Status XMLCALL\r
+XML_ResumeParser(XML_Parser parser)\r
+{\r
+ enum XML_Status result = XML_STATUS_OK;\r
+\r
+ if (ps_parsing != XML_SUSPENDED) {\r
+ errorCode = XML_ERROR_NOT_SUSPENDED;\r
+ return XML_STATUS_ERROR;\r
+ }\r
+ ps_parsing = XML_PARSING;\r
+\r
+ errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);\r
+\r
+ if (errorCode != XML_ERROR_NONE) {\r
+ eventEndPtr = eventPtr;\r
+ processor = errorProcessor;\r
+ return XML_STATUS_ERROR;\r
+ }\r
+ else {\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ result = XML_STATUS_SUSPENDED;\r
+ break;\r
+ case XML_INITIALIZED:\r
+ case XML_PARSING:\r
+ if (ps_finalBuffer) {\r
+ ps_parsing = XML_FINISHED;\r
+ return result;\r
+ }\r
+ default: ;\r
+ }\r
+ }\r
+\r
+ XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);\r
+ positionPtr = bufferPtr;\r
+ return result;\r
+}\r
+\r
+void XMLCALL\r
+XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)\r
+{\r
+ assert(status != NULL);\r
+ *status = parser->m_parsingStatus;\r
+}\r
+\r
+enum XML_Error XMLCALL\r
+XML_GetErrorCode(XML_Parser parser)\r
+{\r
+ return errorCode;\r
+}\r
+\r
+XML_Index XMLCALL\r
+XML_GetCurrentByteIndex(XML_Parser parser)\r
+{\r
+ if (eventPtr)\r
+ return parseEndByteIndex - (parseEndPtr - eventPtr);\r
+ return -1;\r
+}\r
+\r
+int XMLCALL\r
+XML_GetCurrentByteCount(XML_Parser parser)\r
+{\r
+ if (eventEndPtr && eventPtr)\r
+ return (int)(eventEndPtr - eventPtr);\r
+ return 0;\r
+}\r
+\r
+const char * XMLCALL\r
+XML_GetInputContext(XML_Parser parser, int *offset, int *size)\r
+{\r
+#ifdef XML_CONTEXT_BYTES\r
+ if (eventPtr && buffer) {\r
+ *offset = (int)(eventPtr - buffer);\r
+ *size = (int)(bufferEnd - buffer);\r
+ return buffer;\r
+ }\r
+#endif /* defined XML_CONTEXT_BYTES */\r
+ return (char *) 0;\r
+}\r
+\r
+XML_Size XMLCALL\r
+XML_GetCurrentLineNumber(XML_Parser parser)\r
+{\r
+ if (eventPtr && eventPtr >= positionPtr) {\r
+ XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);\r
+ positionPtr = eventPtr;\r
+ }\r
+ return position.lineNumber + 1;\r
+}\r
+\r
+XML_Size XMLCALL\r
+XML_GetCurrentColumnNumber(XML_Parser parser)\r
+{\r
+ if (eventPtr && eventPtr >= positionPtr) {\r
+ XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);\r
+ positionPtr = eventPtr;\r
+ }\r
+ return position.columnNumber;\r
+}\r
+\r
+void XMLCALL\r
+XML_FreeContentModel(XML_Parser parser, XML_Content *model)\r
+{\r
+ FREE(model);\r
+}\r
+\r
+void * XMLCALL\r
+XML_MemMalloc(XML_Parser parser, size_t size)\r
+{\r
+ return MALLOC(size);\r
+}\r
+\r
+void * XMLCALL\r
+XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)\r
+{\r
+ return REALLOC(ptr, size);\r
+}\r
+\r
+void XMLCALL\r
+XML_MemFree(XML_Parser parser, void *ptr)\r
+{\r
+ FREE(ptr);\r
+}\r
+\r
+void XMLCALL\r
+XML_DefaultCurrent(XML_Parser parser)\r
+{\r
+ if (defaultHandler) {\r
+ if (openInternalEntities)\r
+ reportDefault(parser,\r
+ internalEncoding,\r
+ openInternalEntities->internalEventPtr,\r
+ openInternalEntities->internalEventEndPtr);\r
+ else\r
+ reportDefault(parser, encoding, eventPtr, eventEndPtr);\r
+ }\r
+}\r
+\r
+const XML_LChar * XMLCALL\r
+XML_ErrorString(enum XML_Error code)\r
+{\r
+ static const XML_LChar* const message[] = {\r
+ 0,\r
+ XML_L("out of memory"),\r
+ XML_L("syntax error"),\r
+ XML_L("no element found"),\r
+ XML_L("not well-formed (invalid token)"),\r
+ XML_L("unclosed token"),\r
+ XML_L("partial character"),\r
+ XML_L("mismatched tag"),\r
+ XML_L("duplicate attribute"),\r
+ XML_L("junk after document element"),\r
+ XML_L("illegal parameter entity reference"),\r
+ XML_L("undefined entity"),\r
+ XML_L("recursive entity reference"),\r
+ XML_L("asynchronous entity"),\r
+ XML_L("reference to invalid character number"),\r
+ XML_L("reference to binary entity"),\r
+ XML_L("reference to external entity in attribute"),\r
+ XML_L("XML or text declaration not at start of entity"),\r
+ XML_L("unknown encoding"),\r
+ XML_L("encoding specified in XML declaration is incorrect"),\r
+ XML_L("unclosed CDATA section"),\r
+ XML_L("error in processing external entity reference"),\r
+ XML_L("document is not standalone"),\r
+ XML_L("unexpected parser state - please send a bug report"),\r
+ XML_L("entity declared in parameter entity"),\r
+ XML_L("requested feature requires XML_DTD support in Expat"),\r
+ XML_L("cannot change setting once parsing has begun"),\r
+ XML_L("unbound prefix"),\r
+ XML_L("must not undeclare prefix"),\r
+ XML_L("incomplete markup in parameter entity"),\r
+ XML_L("XML declaration not well-formed"),\r
+ XML_L("text declaration not well-formed"),\r
+ XML_L("illegal character(s) in public id"),\r
+ XML_L("parser suspended"),\r
+ XML_L("parser not suspended"),\r
+ XML_L("parsing aborted"),\r
+ XML_L("parsing finished"),\r
+ XML_L("cannot suspend in external parameter entity"),\r
+ XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),\r
+ XML_L("reserved prefix (xmlns) must not be declared or undeclared"),\r
+ XML_L("prefix must not be bound to one of the reserved namespace names")\r
+ };\r
+ if (code > 0 && code < sizeof(message)/sizeof(message[0]))\r
+ return message[code];\r
+ return NULL;\r
+}\r
+\r
+const XML_LChar * XMLCALL\r
+XML_ExpatVersion(void) {\r
+\r
+ /* V1 is used to string-ize the version number. However, it would\r
+ string-ize the actual version macro *names* unless we get them\r
+ substituted before being passed to V1. CPP is defined to expand\r
+ a macro, then rescan for more expansions. Thus, we use V2 to expand\r
+ the version macros, then CPP will expand the resulting V1() macro\r
+ with the correct numerals. */\r
+ /* ### I'm assuming cpp is portable in this respect... */\r
+\r
+#define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)\r
+#define V2(a,b,c) XML_L("expat_")V1(a,b,c)\r
+\r
+ return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);\r
+\r
+#undef V1\r
+#undef V2\r
+}\r
+\r
+XML_Expat_Version XMLCALL\r
+XML_ExpatVersionInfo(void)\r
+{\r
+ XML_Expat_Version version;\r
+\r
+ version.major = XML_MAJOR_VERSION;\r
+ version.minor = XML_MINOR_VERSION;\r
+ version.micro = XML_MICRO_VERSION;\r
+\r
+ return version;\r
+}\r
+\r
+const XML_Feature * XMLCALL\r
+XML_GetFeatureList(void)\r
+{\r
+ static const XML_Feature features[] = {\r
+ {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),\r
+ sizeof(XML_Char)},\r
+ {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),\r
+ sizeof(XML_LChar)},\r
+#ifdef XML_UNICODE\r
+ {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},\r
+#endif\r
+#ifdef XML_UNICODE_WCHAR_T\r
+ {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},\r
+#endif\r
+#ifdef XML_DTD\r
+ {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},\r
+#endif\r
+#ifdef XML_CONTEXT_BYTES\r
+ {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),\r
+ XML_CONTEXT_BYTES},\r
+#endif\r
+#ifdef XML_MIN_SIZE\r
+ {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},\r
+#endif\r
+#ifdef XML_NS\r
+ {XML_FEATURE_NS, XML_L("XML_NS"), 0},\r
+#endif\r
+#ifdef XML_LARGE_SIZE\r
+ {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},\r
+#endif\r
+#ifdef XML_ATTR_INFO\r
+ {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},\r
+#endif\r
+ {XML_FEATURE_END, NULL, 0}\r
+ };\r
+\r
+ return features;\r
+}\r
+\r
+/* Initially tag->rawName always points into the parse buffer;\r
+ for those TAG instances opened while the current parse buffer was\r
+ processed, and not yet closed, we need to store tag->rawName in a more\r
+ permanent location, since the parse buffer is about to be discarded.\r
+*/\r
+static XML_Bool\r
+storeRawNames(XML_Parser parser)\r
+{\r
+ TAG *tag = tagStack;\r
+ while (tag) {\r
+ int bufSize;\r
+ int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);\r
+ char *rawNameBuf = tag->buf + nameLen;\r
+ /* Stop if already stored. Since tagStack is a stack, we can stop\r
+ at the first entry that has already been copied; everything\r
+ below it in the stack is already been accounted for in a\r
+ previous call to this function.\r
+ */\r
+ if (tag->rawName == rawNameBuf)\r
+ break;\r
+ /* For re-use purposes we need to ensure that the\r
+ size of tag->buf is a multiple of sizeof(XML_Char).\r
+ */\r
+ bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));\r
+ if (bufSize > tag->bufEnd - tag->buf) {\r
+ char *temp = (char *)REALLOC(tag->buf, bufSize);\r
+ if (temp == NULL)\r
+ return XML_FALSE;\r
+ /* if tag->name.str points to tag->buf (only when namespace\r
+ processing is off) then we have to update it\r
+ */\r
+ if (tag->name.str == (XML_Char *)tag->buf)\r
+ tag->name.str = (XML_Char *)temp;\r
+ /* if tag->name.localPart is set (when namespace processing is on)\r
+ then update it as well, since it will always point into tag->buf\r
+ */\r
+ if (tag->name.localPart)\r
+ tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -\r
+ (XML_Char *)tag->buf);\r
+ tag->buf = temp;\r
+ tag->bufEnd = temp + bufSize;\r
+ rawNameBuf = temp + nameLen;\r
+ }\r
+ memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);\r
+ tag->rawName = rawNameBuf;\r
+ tag = tag->parent;\r
+ }\r
+ return XML_TRUE;\r
+}\r
+\r
+static enum XML_Error PTRCALL\r
+contentProcessor(XML_Parser parser,\r
+ const char *start,\r
+ const char *end,\r
+ const char **endPtr)\r
+{\r
+ enum XML_Error result = doContent(parser, 0, encoding, start, end,\r
+ endPtr, (XML_Bool)!ps_finalBuffer);\r
+ if (result == XML_ERROR_NONE) {\r
+ if (!storeRawNames(parser))\r
+ return XML_ERROR_NO_MEMORY;\r
+ }\r
+ return result;\r
+}\r
+\r
+static enum XML_Error PTRCALL\r
+externalEntityInitProcessor(XML_Parser parser,\r
+ const char *start,\r
+ const char *end,\r
+ const char **endPtr)\r
+{\r
+ enum XML_Error result = initializeEncoding(parser);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ processor = externalEntityInitProcessor2;\r
+ return externalEntityInitProcessor2(parser, start, end, endPtr);\r
+}\r
+\r
+static enum XML_Error PTRCALL\r
+externalEntityInitProcessor2(XML_Parser parser,\r
+ const char *start,\r
+ const char *end,\r
+ const char **endPtr)\r
+{\r
+ const char *next = start; /* XmlContentTok doesn't always set the last arg */\r
+ int tok = XmlContentTok(encoding, start, end, &next);\r
+ switch (tok) {\r
+ case XML_TOK_BOM:\r
+ /* If we are at the end of the buffer, this would cause the next stage,\r
+ i.e. externalEntityInitProcessor3, to pass control directly to\r
+ doContent (by detecting XML_TOK_NONE) without processing any xml text\r
+ declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.\r
+ */\r
+ if (next == end && !ps_finalBuffer) {\r
+ *endPtr = next;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ start = next;\r
+ break;\r
+ case XML_TOK_PARTIAL:\r
+ if (!ps_finalBuffer) {\r
+ *endPtr = start;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ eventPtr = start;\r
+ return XML_ERROR_UNCLOSED_TOKEN;\r
+ case XML_TOK_PARTIAL_CHAR:\r
+ if (!ps_finalBuffer) {\r
+ *endPtr = start;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ eventPtr = start;\r
+ return XML_ERROR_PARTIAL_CHAR;\r
+ }\r
+ processor = externalEntityInitProcessor3;\r
+ return externalEntityInitProcessor3(parser, start, end, endPtr);\r
+}\r
+\r
+static enum XML_Error PTRCALL\r
+externalEntityInitProcessor3(XML_Parser parser,\r
+ const char *start,\r
+ const char *end,\r
+ const char **endPtr)\r
+{\r
+ int tok;\r
+ const char *next = start; /* XmlContentTok doesn't always set the last arg */\r
+ eventPtr = start;\r
+ tok = XmlContentTok(encoding, start, end, &next);\r
+ eventEndPtr = next;\r
+\r
+ switch (tok) {\r
+ case XML_TOK_XML_DECL:\r
+ {\r
+ enum XML_Error result;\r
+ result = processXmlDecl(parser, 1, start, next);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ *endPtr = next;\r
+ return XML_ERROR_NONE;\r
+ case XML_FINISHED:\r
+ return XML_ERROR_ABORTED;\r
+ default:\r
+ start = next;\r
+ }\r
+ }\r
+ break;\r
+ case XML_TOK_PARTIAL:\r
+ if (!ps_finalBuffer) {\r
+ *endPtr = start;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ return XML_ERROR_UNCLOSED_TOKEN;\r
+ case XML_TOK_PARTIAL_CHAR:\r
+ if (!ps_finalBuffer) {\r
+ *endPtr = start;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ return XML_ERROR_PARTIAL_CHAR;\r
+ }\r
+ processor = externalEntityContentProcessor;\r
+ tagLevel = 1;\r
+ return externalEntityContentProcessor(parser, start, end, endPtr);\r
+}\r
+\r
+static enum XML_Error PTRCALL\r
+externalEntityContentProcessor(XML_Parser parser,\r
+ const char *start,\r
+ const char *end,\r
+ const char **endPtr)\r
+{\r
+ enum XML_Error result = doContent(parser, 1, encoding, start, end,\r
+ endPtr, (XML_Bool)!ps_finalBuffer);\r
+ if (result == XML_ERROR_NONE) {\r
+ if (!storeRawNames(parser))\r
+ return XML_ERROR_NO_MEMORY;\r
+ }\r
+ return result;\r
+}\r
+\r
+static enum XML_Error\r
+doContent(XML_Parser parser,\r
+ int startTagLevel,\r
+ const ENCODING *enc,\r
+ const char *s,\r
+ const char *end,\r
+ const char **nextPtr,\r
+ XML_Bool haveMore)\r
+{\r
+ /* save one level of indirection */\r
+ DTD * const dtd = _dtd;\r
+\r
+ const char **eventPP;\r
+ const char **eventEndPP;\r
+ if (enc == encoding) {\r
+ eventPP = &eventPtr;\r
+ eventEndPP = &eventEndPtr;\r
+ }\r
+ else {\r
+ eventPP = &(openInternalEntities->internalEventPtr);\r
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);\r
+ }\r
+ *eventPP = s;\r
+\r
+ for (;;) {\r
+ const char *next = s; /* XmlContentTok doesn't always set the last arg */\r
+ int tok = XmlContentTok(enc, s, end, &next);\r
+ *eventEndPP = next;\r
+ switch (tok) {\r
+ case XML_TOK_TRAILING_CR:\r
+ if (haveMore) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ *eventEndPP = end;\r
+ if (characterDataHandler) {\r
+ XML_Char c = 0xA;\r
+ characterDataHandler(handlerArg, &c, 1);\r
+ }\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, end);\r
+ /* We are at the end of the final buffer, should we check for\r
+ XML_SUSPENDED, XML_FINISHED?\r
+ */\r
+ if (startTagLevel == 0)\r
+ return XML_ERROR_NO_ELEMENTS;\r
+ if (tagLevel != startTagLevel)\r
+ return XML_ERROR_ASYNC_ENTITY;\r
+ *nextPtr = end;\r
+ return XML_ERROR_NONE;\r
+ case XML_TOK_NONE:\r
+ if (haveMore) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ if (startTagLevel > 0) {\r
+ if (tagLevel != startTagLevel)\r
+ return XML_ERROR_ASYNC_ENTITY;\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ return XML_ERROR_NO_ELEMENTS;\r
+ case XML_TOK_INVALID:\r
+ *eventPP = next;\r
+ return XML_ERROR_INVALID_TOKEN;\r
+ case XML_TOK_PARTIAL:\r
+ if (haveMore) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ return XML_ERROR_UNCLOSED_TOKEN;\r
+ case XML_TOK_PARTIAL_CHAR:\r
+ if (haveMore) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ return XML_ERROR_PARTIAL_CHAR;\r
+ case XML_TOK_ENTITY_REF:\r
+ {\r
+ const XML_Char *name;\r
+ ENTITY *entity;\r
+ XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,\r
+ s + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (ch) {\r
+ if (characterDataHandler)\r
+ characterDataHandler(handlerArg, &ch, 1);\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ break;\r
+ }\r
+ name = poolStoreString(&dtd->pool, enc,\r
+ s + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (!name)\r
+ return XML_ERROR_NO_MEMORY;\r
+ entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);\r
+ poolDiscard(&dtd->pool);\r
+ /* First, determine if a check for an existing declaration is needed;\r
+ if yes, check that the entity exists, and that it is internal,\r
+ otherwise call the skipped entity or default handler.\r
+ */\r
+ if (!dtd->hasParamEntityRefs || dtd->standalone) {\r
+ if (!entity)\r
+ return XML_ERROR_UNDEFINED_ENTITY;\r
+ else if (!entity->is_internal)\r
+ return XML_ERROR_ENTITY_DECLARED_IN_PE;\r
+ }\r
+ else if (!entity) {\r
+ if (skippedEntityHandler)\r
+ skippedEntityHandler(handlerArg, name, 0);\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ break;\r
+ }\r
+ if (entity->open)\r
+ return XML_ERROR_RECURSIVE_ENTITY_REF;\r
+ if (entity->notation)\r
+ return XML_ERROR_BINARY_ENTITY_REF;\r
+ if (entity->textPtr) {\r
+ enum XML_Error result;\r
+ if (!defaultExpandInternalEntities) {\r
+ if (skippedEntityHandler)\r
+ skippedEntityHandler(handlerArg, entity->name, 0);\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ break;\r
+ }\r
+ result = processInternalEntity(parser, entity, XML_FALSE);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ }\r
+ else if (externalEntityRefHandler) {\r
+ const XML_Char *context;\r
+ entity->open = XML_TRUE;\r
+ context = getContext(parser);\r
+ entity->open = XML_FALSE;\r
+ if (!context)\r
+ return XML_ERROR_NO_MEMORY;\r
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,\r
+ context,\r
+ entity->base,\r
+ entity->systemId,\r
+ entity->publicId))\r
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;\r
+ poolDiscard(&tempPool);\r
+ }\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ break;\r
+ }\r
+ case XML_TOK_START_TAG_NO_ATTS:\r
+ /* fall through */\r
+ case XML_TOK_START_TAG_WITH_ATTS:\r
+ {\r
+ TAG *tag;\r
+ enum XML_Error result;\r
+ XML_Char *toPtr;\r
+ if (freeTagList) {\r
+ tag = freeTagList;\r
+ freeTagList = freeTagList->parent;\r
+ }\r
+ else {\r
+ tag = (TAG *)MALLOC(sizeof(TAG));\r
+ if (!tag)\r
+ return XML_ERROR_NO_MEMORY;\r
+ tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);\r
+ if (!tag->buf) {\r
+ FREE(tag);\r
+ return XML_ERROR_NO_MEMORY;\r
+ }\r
+ tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;\r
+ }\r
+ tag->bindings = NULL;\r
+ tag->parent = tagStack;\r
+ tagStack = tag;\r
+ tag->name.localPart = NULL;\r
+ tag->name.prefix = NULL;\r
+ tag->rawName = s + enc->minBytesPerChar;\r
+ tag->rawNameLength = XmlNameLength(enc, tag->rawName);\r
+ ++tagLevel;\r
+ {\r
+ const char *rawNameEnd = tag->rawName + tag->rawNameLength;\r
+ const char *fromPtr = tag->rawName;\r
+ toPtr = (XML_Char *)tag->buf;\r
+ for (;;) {\r
+ int bufSize;\r
+ int convLen;\r
+ XmlConvert(enc,\r
+ &fromPtr, rawNameEnd,\r
+ (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);\r
+ convLen = (int)(toPtr - (XML_Char *)tag->buf);\r
+ if (fromPtr == rawNameEnd) {\r
+ tag->name.strLen = convLen;\r
+ break;\r
+ }\r
+ bufSize = (int)(tag->bufEnd - tag->buf) << 1;\r
+ {\r
+ char *temp = (char *)REALLOC(tag->buf, bufSize);\r
+ if (temp == NULL)\r
+ return XML_ERROR_NO_MEMORY;\r
+ tag->buf = temp;\r
+ tag->bufEnd = temp + bufSize;\r
+ toPtr = (XML_Char *)temp + convLen;\r
+ }\r
+ }\r
+ }\r
+ tag->name.str = (XML_Char *)tag->buf;\r
+ *toPtr = XML_T('\0');\r
+ result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));\r
+ if (result)\r
+ return result;\r
+ if (startElementHandler)\r
+ startElementHandler(handlerArg, tag->name.str,\r
+ (const XML_Char **)atts);\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ poolClear(&tempPool);\r
+ break;\r
+ }\r
+ case XML_TOK_EMPTY_ELEMENT_NO_ATTS:\r
+ /* fall through */\r
+ case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:\r
+ {\r
+ const char *rawName = s + enc->minBytesPerChar;\r
+ enum XML_Error result;\r
+ BINDING *bindings = NULL;\r
+ XML_Bool noElmHandlers = XML_TRUE;\r
+ TAG_NAME name;\r
+ name.str = poolStoreString(&tempPool, enc, rawName,\r
+ rawName + XmlNameLength(enc, rawName));\r
+ if (!name.str)\r
+ return XML_ERROR_NO_MEMORY;\r
+ poolFinish(&tempPool);\r
+ result = storeAtts(parser, enc, s, &name, &bindings);\r
+ if (result)\r
+ return result;\r
+ poolFinish(&tempPool);\r
+ if (startElementHandler) {\r
+ startElementHandler(handlerArg, name.str, (const XML_Char **)atts);\r
+ noElmHandlers = XML_FALSE;\r
+ }\r
+ if (endElementHandler) {\r
+ if (startElementHandler)\r
+ *eventPP = *eventEndPP;\r
+ endElementHandler(handlerArg, name.str);\r
+ noElmHandlers = XML_FALSE;\r
+ }\r
+ if (noElmHandlers && defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ poolClear(&tempPool);\r
+ while (bindings) {\r
+ BINDING *b = bindings;\r
+ if (endNamespaceDeclHandler)\r
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);\r
+ bindings = bindings->nextTagBinding;\r
+ b->nextTagBinding = freeBindingList;\r
+ freeBindingList = b;\r
+ b->prefix->binding = b->prevPrefixBinding;\r
+ }\r
+ }\r
+ if (tagLevel == 0)\r
+ return epilogProcessor(parser, next, end, nextPtr);\r
+ break;\r
+ case XML_TOK_END_TAG:\r
+ if (tagLevel == startTagLevel)\r
+ return XML_ERROR_ASYNC_ENTITY;\r
+ else {\r
+ int len;\r
+ const char *rawName;\r
+ TAG *tag = tagStack;\r
+ tagStack = tag->parent;\r
+ tag->parent = freeTagList;\r
+ freeTagList = tag;\r
+ rawName = s + enc->minBytesPerChar*2;\r
+ len = XmlNameLength(enc, rawName);\r
+ if (len != tag->rawNameLength\r
+ || memcmp(tag->rawName, rawName, len) != 0) {\r
+ *eventPP = rawName;\r
+ return XML_ERROR_TAG_MISMATCH;\r
+ }\r
+ --tagLevel;\r
+ if (endElementHandler) {\r
+ const XML_Char *localPart;\r
+ const XML_Char *prefix;\r
+ XML_Char *uri;\r
+ localPart = tag->name.localPart;\r
+ if (ns && localPart) {\r
+ /* localPart and prefix may have been overwritten in\r
+ tag->name.str, since this points to the binding->uri\r
+ buffer which gets re-used; so we have to add them again\r
+ */\r
+ uri = (XML_Char *)tag->name.str + tag->name.uriLen;\r
+ /* don't need to check for space - already done in storeAtts() */\r
+ while (*localPart) *uri++ = *localPart++;\r
+ prefix = (XML_Char *)tag->name.prefix;\r
+ if (ns_triplets && prefix) {\r
+ *uri++ = namespaceSeparator;\r
+ while (*prefix) *uri++ = *prefix++;\r
+ }\r
+ *uri = XML_T('\0');\r
+ }\r
+ endElementHandler(handlerArg, tag->name.str);\r
+ }\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ while (tag->bindings) {\r
+ BINDING *b = tag->bindings;\r
+ if (endNamespaceDeclHandler)\r
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);\r
+ tag->bindings = tag->bindings->nextTagBinding;\r
+ b->nextTagBinding = freeBindingList;\r
+ freeBindingList = b;\r
+ b->prefix->binding = b->prevPrefixBinding;\r
+ }\r
+ if (tagLevel == 0)\r
+ return epilogProcessor(parser, next, end, nextPtr);\r
+ }\r
+ break;\r
+ case XML_TOK_CHAR_REF:\r
+ {\r
+ int n = XmlCharRefNumber(enc, s);\r
+ if (n < 0)\r
+ return XML_ERROR_BAD_CHAR_REF;\r
+ if (characterDataHandler) {\r
+ XML_Char buf[XML_ENCODE_MAX];\r
+ characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));\r
+ }\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ }\r
+ break;\r
+ case XML_TOK_XML_DECL:\r
+ return XML_ERROR_MISPLACED_XML_PI;\r
+ case XML_TOK_DATA_NEWLINE:\r
+ if (characterDataHandler) {\r
+ XML_Char c = 0xA;\r
+ characterDataHandler(handlerArg, &c, 1);\r
+ }\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ break;\r
+ case XML_TOK_CDATA_SECT_OPEN:\r
+ {\r
+ enum XML_Error result;\r
+ if (startCdataSectionHandler)\r
+ startCdataSectionHandler(handlerArg);\r
+#if 0\r
+ /* Suppose you doing a transformation on a document that involves\r
+ changing only the character data. You set up a defaultHandler\r
+ and a characterDataHandler. The defaultHandler simply copies\r
+ characters through. The characterDataHandler does the\r
+ transformation and writes the characters out escaping them as\r
+ necessary. This case will fail to work if we leave out the\r
+ following two lines (because & and < inside CDATA sections will\r
+ be incorrectly escaped).\r
+\r
+ However, now we have a start/endCdataSectionHandler, so it seems\r
+ easier to let the user deal with this.\r
+ */\r
+ else if (characterDataHandler)\r
+ characterDataHandler(handlerArg, dataBuf, 0);\r
+#endif\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ else if (!next) {\r
+ processor = cdataSectionProcessor;\r
+ return result;\r
+ }\r
+ }\r
+ break;\r
+ case XML_TOK_TRAILING_RSQB:\r
+ if (haveMore) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ if (characterDataHandler) {\r
+ if (MUST_CONVERT(enc, s)) {\r
+ ICHAR *dataPtr = (ICHAR *)dataBuf;\r
+ XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);\r
+ characterDataHandler(handlerArg, dataBuf,\r
+ (int)(dataPtr - (ICHAR *)dataBuf));\r
+ }\r
+ else\r
+ characterDataHandler(handlerArg,\r
+ (XML_Char *)s,\r
+ (int)((XML_Char *)end - (XML_Char *)s));\r
+ }\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, end);\r
+ /* We are at the end of the final buffer, should we check for\r
+ XML_SUSPENDED, XML_FINISHED?\r
+ */\r
+ if (startTagLevel == 0) {\r
+ *eventPP = end;\r
+ return XML_ERROR_NO_ELEMENTS;\r
+ }\r
+ if (tagLevel != startTagLevel) {\r
+ *eventPP = end;\r
+ return XML_ERROR_ASYNC_ENTITY;\r
+ }\r
+ *nextPtr = end;\r
+ return XML_ERROR_NONE;\r
+ case XML_TOK_DATA_CHARS:\r
+ {\r
+ XML_CharacterDataHandler charDataHandler = characterDataHandler;\r
+ if (charDataHandler) {\r
+ if (MUST_CONVERT(enc, s)) {\r
+ for (;;) {\r
+ ICHAR *dataPtr = (ICHAR *)dataBuf;\r
+ XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);\r
+ *eventEndPP = s;\r
+ charDataHandler(handlerArg, dataBuf,\r
+ (int)(dataPtr - (ICHAR *)dataBuf));\r
+ if (s == next)\r
+ break;\r
+ *eventPP = s;\r
+ }\r
+ }\r
+ else\r
+ charDataHandler(handlerArg,\r
+ (XML_Char *)s,\r
+ (int)((XML_Char *)next - (XML_Char *)s));\r
+ }\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ }\r
+ break;\r
+ case XML_TOK_PI:\r
+ if (!reportProcessingInstruction(parser, enc, s, next))\r
+ return XML_ERROR_NO_MEMORY;\r
+ break;\r
+ case XML_TOK_COMMENT:\r
+ if (!reportComment(parser, enc, s, next))\r
+ return XML_ERROR_NO_MEMORY;\r
+ break;\r
+ default:\r
+ if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ break;\r
+ }\r
+ *eventPP = s = next;\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ *nextPtr = next;\r
+ return XML_ERROR_NONE;\r
+ case XML_FINISHED:\r
+ return XML_ERROR_ABORTED;\r
+ default: ;\r
+ }\r
+ }\r
+ /* not reached */\r
+}\r
+\r
+/* Precondition: all arguments must be non-NULL;\r
+ Purpose:\r
+ - normalize attributes\r
+ - check attributes for well-formedness\r
+ - generate namespace aware attribute names (URI, prefix)\r
+ - build list of attributes for startElementHandler\r
+ - default attributes\r
+ - process namespace declarations (check and report them)\r
+ - generate namespace aware element name (URI, prefix)\r
+*/\r
+static enum XML_Error\r
+storeAtts(XML_Parser parser, const ENCODING *enc,\r
+ const char *attStr, TAG_NAME *tagNamePtr,\r
+ BINDING **bindingsPtr)\r
+{\r
+ DTD * const dtd = _dtd; /* save one level of indirection */\r
+ ELEMENT_TYPE *elementType;\r
+ int nDefaultAtts;\r
+ const XML_Char **appAtts; /* the attribute list for the application */\r
+ int attIndex = 0;\r
+ int prefixLen;\r
+ int i;\r
+ int n;\r
+ XML_Char *uri;\r
+ int nPrefixes = 0;\r
+ BINDING *binding;\r
+ const XML_Char *localPart;\r
+\r
+ /* lookup the element type name */\r
+ elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);\r
+ if (!elementType) {\r
+ const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);\r
+ if (!name)\r
+ return XML_ERROR_NO_MEMORY;\r
+ elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,\r
+ sizeof(ELEMENT_TYPE));\r
+ if (!elementType)\r
+ return XML_ERROR_NO_MEMORY;\r
+ if (ns && !setElementTypePrefix(parser, elementType))\r
+ return XML_ERROR_NO_MEMORY;\r
+ }\r
+ nDefaultAtts = elementType->nDefaultAtts;\r
+\r
+ /* get the attributes from the tokenizer */\r
+ n = XmlGetAttributes(enc, attStr, attsSize, atts);\r
+ if (n + nDefaultAtts > attsSize) {\r
+ int oldAttsSize = attsSize;\r
+ ATTRIBUTE *temp;\r
+#ifdef XML_ATTR_INFO\r
+ XML_AttrInfo *temp2;\r
+#endif\r
+ attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;\r
+ temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));\r
+ if (temp == NULL)\r
+ return XML_ERROR_NO_MEMORY;\r
+ atts = temp;\r
+#ifdef XML_ATTR_INFO\r
+ temp2 = (XML_AttrInfo *)REALLOC((void *)attInfo, attsSize * sizeof(XML_AttrInfo));\r
+ if (temp2 == NULL)\r
+ return XML_ERROR_NO_MEMORY;\r
+ attInfo = temp2;\r
+#endif\r
+ if (n > oldAttsSize)\r
+ XmlGetAttributes(enc, attStr, n, atts);\r
+ }\r
+\r
+ appAtts = (const XML_Char **)atts;\r
+ for (i = 0; i < n; i++) {\r
+ ATTRIBUTE *currAtt = &atts[i];\r
+#ifdef XML_ATTR_INFO\r
+ XML_AttrInfo *currAttInfo = &attInfo[i];\r
+#endif\r
+ /* add the name and value to the attribute list */\r
+ ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,\r
+ currAtt->name\r
+ + XmlNameLength(enc, currAtt->name));\r
+ if (!attId)\r
+ return XML_ERROR_NO_MEMORY;\r
+#ifdef XML_ATTR_INFO\r
+ currAttInfo->nameStart = parseEndByteIndex - (parseEndPtr - currAtt->name);\r
+ currAttInfo->nameEnd = currAttInfo->nameStart +\r
+ XmlNameLength(enc, currAtt->name);\r
+ currAttInfo->valueStart = parseEndByteIndex -\r
+ (parseEndPtr - currAtt->valuePtr);\r
+ currAttInfo->valueEnd = parseEndByteIndex - (parseEndPtr - currAtt->valueEnd);\r
+#endif\r
+ /* Detect duplicate attributes by their QNames. This does not work when\r
+ namespace processing is turned on and different prefixes for the same\r
+ namespace are used. For this case we have a check further down.\r
+ */\r
+ if ((attId->name)[-1]) {\r
+ if (enc == encoding)\r
+ eventPtr = atts[i].name;\r
+ return XML_ERROR_DUPLICATE_ATTRIBUTE;\r
+ }\r
+ (attId->name)[-1] = 1;\r
+ appAtts[attIndex++] = attId->name;\r
+ if (!atts[i].normalized) {\r
+ enum XML_Error result;\r
+ XML_Bool isCdata = XML_TRUE;\r
+\r
+ /* figure out whether declared as other than CDATA */\r
+ if (attId->maybeTokenized) {\r
+ int j;\r
+ for (j = 0; j < nDefaultAtts; j++) {\r
+ if (attId == elementType->defaultAtts[j].id) {\r
+ isCdata = elementType->defaultAtts[j].isCdata;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* normalize the attribute value */\r
+ result = storeAttributeValue(parser, enc, isCdata,\r
+ atts[i].valuePtr, atts[i].valueEnd,\r
+ &tempPool);\r
+ if (result)\r
+ return result;\r
+ appAtts[attIndex] = poolStart(&tempPool);\r
+ poolFinish(&tempPool);\r
+ }\r
+ else {\r
+ /* the value did not need normalizing */\r
+ appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,\r
+ atts[i].valueEnd);\r
+ if (appAtts[attIndex] == 0)\r
+ return XML_ERROR_NO_MEMORY;\r
+ poolFinish(&tempPool);\r
+ }\r
+ /* handle prefixed attribute names */\r
+ if (attId->prefix) {\r
+ if (attId->xmlns) {\r
+ /* deal with namespace declarations here */\r
+ enum XML_Error result = addBinding(parser, attId->prefix, attId,\r
+ appAtts[attIndex], bindingsPtr);\r
+ if (result)\r
+ return result;\r
+ --attIndex;\r
+ }\r
+ else {\r
+ /* deal with other prefixed names later */\r
+ attIndex++;\r
+ nPrefixes++;\r
+ (attId->name)[-1] = 2;\r
+ }\r
+ }\r
+ else\r
+ attIndex++;\r
+ }\r
+\r
+ /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */\r
+ nSpecifiedAtts = attIndex;\r
+ if (elementType->idAtt && (elementType->idAtt->name)[-1]) {\r
+ for (i = 0; i < attIndex; i += 2)\r
+ if (appAtts[i] == elementType->idAtt->name) {\r
+ idAttIndex = i;\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ idAttIndex = -1;\r
+\r
+ /* do attribute defaulting */\r
+ for (i = 0; i < nDefaultAtts; i++) {\r
+ const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;\r
+ if (!(da->id->name)[-1] && da->value) {\r
+ if (da->id->prefix) {\r
+ if (da->id->xmlns) {\r
+ enum XML_Error result = addBinding(parser, da->id->prefix, da->id,\r
+ da->value, bindingsPtr);\r
+ if (result)\r
+ return result;\r
+ }\r
+ else {\r
+ (da->id->name)[-1] = 2;\r
+ nPrefixes++;\r
+ appAtts[attIndex++] = da->id->name;\r
+ appAtts[attIndex++] = da->value;\r
+ }\r
+ }\r
+ else {\r
+ (da->id->name)[-1] = 1;\r
+ appAtts[attIndex++] = da->id->name;\r
+ appAtts[attIndex++] = da->value;\r
+ }\r
+ }\r
+ }\r
+ appAtts[attIndex] = 0;\r
+\r
+ /* expand prefixed attribute names, check for duplicates,\r
+ and clear flags that say whether attributes were specified */\r
+ i = 0;\r
+ if (nPrefixes) {\r
+ int j; /* hash table index */\r
+ unsigned long version = nsAttsVersion;\r
+ int nsAttsSize = (int)1 << nsAttsPower;\r
+ /* size of hash table must be at least 2 * (# of prefixed attributes) */\r
+ if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */\r
+ NS_ATT *temp;\r
+ /* hash table size must also be a power of 2 and >= 8 */\r
+ while (nPrefixes >> nsAttsPower++);\r
+ if (nsAttsPower < 3)\r
+ nsAttsPower = 3;\r
+ nsAttsSize = (int)1 << nsAttsPower;\r
+ temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));\r
+ if (!temp)\r
+ return XML_ERROR_NO_MEMORY;\r
+ nsAtts = temp;\r
+ version = 0; /* force re-initialization of nsAtts hash table */\r
+ }\r
+ /* using a version flag saves us from initializing nsAtts every time */\r
+ if (!version) { /* initialize version flags when version wraps around */\r
+ version = INIT_ATTS_VERSION;\r
+ for (j = nsAttsSize; j != 0; )\r
+ nsAtts[--j].version = version;\r
+ }\r
+ nsAttsVersion = --version;\r
+\r
+ /* expand prefixed names and check for duplicates */\r
+ for (; i < attIndex; i += 2) {\r
+ const XML_Char *s = appAtts[i];\r
+ if (s[-1] == 2) { /* prefixed */\r
+ ATTRIBUTE_ID *id;\r
+ const BINDING *b;\r
+ unsigned long uriHash = hash_secret_salt;\r
+ ((XML_Char *)s)[-1] = 0; /* clear flag */\r
+ id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);\r
+ b = id->prefix->binding;\r
+ if (!b)\r
+ return XML_ERROR_UNBOUND_PREFIX;\r
+\r
+ /* as we expand the name we also calculate its hash value */\r
+ for (j = 0; j < b->uriLen; j++) {\r
+ const XML_Char c = b->uri[j];\r
+ if (!poolAppendChar(&tempPool, c))\r
+ return XML_ERROR_NO_MEMORY;\r
+ uriHash = CHAR_HASH(uriHash, c);\r
+ }\r
+ while (*s++ != XML_T(ASCII_COLON))\r
+ ;\r
+ do { /* copies null terminator */\r
+ const XML_Char c = *s;\r
+ if (!poolAppendChar(&tempPool, *s))\r
+ return XML_ERROR_NO_MEMORY;\r
+ uriHash = CHAR_HASH(uriHash, c);\r
+ } while (*s++);\r
+\r
+ { /* Check hash table for duplicate of expanded name (uriName).\r
+ Derived from code in lookup(parser, HASH_TABLE *table, ...).\r
+ */\r
+ unsigned char step = 0;\r
+ unsigned long mask = nsAttsSize - 1;\r
+ j = uriHash & mask; /* index into hash table */\r
+ while (nsAtts[j].version == version) {\r
+ /* for speed we compare stored hash values first */\r
+ if (uriHash == nsAtts[j].hash) {\r
+ const XML_Char *s1 = poolStart(&tempPool);\r
+ const XML_Char *s2 = nsAtts[j].uriName;\r
+ /* s1 is null terminated, but not s2 */\r
+ for (; *s1 == *s2 && *s1 != 0; s1++, s2++);\r
+ if (*s1 == 0)\r
+ return XML_ERROR_DUPLICATE_ATTRIBUTE;\r
+ }\r
+ if (!step)\r
+ step = PROBE_STEP(uriHash, mask, nsAttsPower);\r
+ j < step ? (j += nsAttsSize - step) : (j -= step);\r
+ }\r
+ }\r
+\r
+ if (ns_triplets) { /* append namespace separator and prefix */\r
+ tempPool.ptr[-1] = namespaceSeparator;\r
+ s = b->prefix->name;\r
+ do {\r
+ if (!poolAppendChar(&tempPool, *s))\r
+ return XML_ERROR_NO_MEMORY;\r
+ } while (*s++);\r
+ }\r
+\r
+ /* store expanded name in attribute list */\r
+ s = poolStart(&tempPool);\r
+ poolFinish(&tempPool);\r
+ appAtts[i] = s;\r
+\r
+ /* fill empty slot with new version, uriName and hash value */\r
+ nsAtts[j].version = version;\r
+ nsAtts[j].hash = uriHash;\r
+ nsAtts[j].uriName = s;\r
+\r
+ if (!--nPrefixes) {\r
+ i += 2;\r
+ break;\r
+ }\r
+ }\r
+ else /* not prefixed */\r
+ ((XML_Char *)s)[-1] = 0; /* clear flag */\r
+ }\r
+ }\r
+ /* clear flags for the remaining attributes */\r
+ for (; i < attIndex; i += 2)\r
+ ((XML_Char *)(appAtts[i]))[-1] = 0;\r
+ for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)\r
+ binding->attId->name[-1] = 0;\r
+\r
+ if (!ns)\r
+ return XML_ERROR_NONE;\r
+\r
+ /* expand the element type name */\r
+ if (elementType->prefix) {\r
+ binding = elementType->prefix->binding;\r
+ if (!binding)\r
+ return XML_ERROR_UNBOUND_PREFIX;\r
+ localPart = tagNamePtr->str;\r
+ while (*localPart++ != XML_T(ASCII_COLON))\r
+ ;\r
+ }\r
+ else if (dtd->defaultPrefix.binding) {\r
+ binding = dtd->defaultPrefix.binding;\r
+ localPart = tagNamePtr->str;\r
+ }\r
+ else\r
+ return XML_ERROR_NONE;\r
+ prefixLen = 0;\r
+ if (ns_triplets && binding->prefix->name) {\r
+ for (; binding->prefix->name[prefixLen++];)\r
+ ; /* prefixLen includes null terminator */\r
+ }\r
+ tagNamePtr->localPart = localPart;\r
+ tagNamePtr->uriLen = binding->uriLen;\r
+ tagNamePtr->prefix = binding->prefix->name;\r
+ tagNamePtr->prefixLen = prefixLen;\r
+ for (i = 0; localPart[i++];)\r
+ ; /* i includes null terminator */\r
+ n = i + binding->uriLen + prefixLen;\r
+ if (n > binding->uriAlloc) {\r
+ TAG *p;\r
+ uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));\r
+ if (!uri)\r
+ return XML_ERROR_NO_MEMORY;\r
+ binding->uriAlloc = n + EXPAND_SPARE;\r
+ memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));\r
+ for (p = tagStack; p; p = p->parent)\r
+ if (p->name.str == binding->uri)\r
+ p->name.str = uri;\r
+ FREE(binding->uri);\r
+ binding->uri = uri;\r
+ }\r
+ /* if namespaceSeparator != '\0' then uri includes it already */\r
+ uri = binding->uri + binding->uriLen;\r
+ memcpy(uri, localPart, i * sizeof(XML_Char));\r
+ /* we always have a namespace separator between localPart and prefix */\r
+ if (prefixLen) {\r
+ uri += i - 1;\r
+ *uri = namespaceSeparator; /* replace null terminator */\r
+ memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));\r
+ }\r
+ tagNamePtr->str = binding->uri;\r
+ return XML_ERROR_NONE;\r
+}\r
+\r
+/* addBinding() overwrites the value of prefix->binding without checking.\r
+ Therefore one must keep track of the old value outside of addBinding().\r
+*/\r
+static enum XML_Error\r
+addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,\r
+ const XML_Char *uri, BINDING **bindingsPtr)\r
+{\r
+ static const XML_Char xmlNamespace[] = {\r
+ ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,\r
+ ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,\r
+ ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,\r
+ ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,\r
+ ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,\r
+ ASCII_e, '\0'\r
+ };\r
+ static const int xmlLen =\r
+ (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;\r
+ static const XML_Char xmlnsNamespace[] = {\r
+ ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,\r
+ ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,\r
+ ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,\r
+ ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,\r
+ ASCII_SLASH, '\0'\r
+ };\r
+ static const int xmlnsLen =\r
+ (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;\r
+\r
+ XML_Bool mustBeXML = XML_FALSE;\r
+ XML_Bool isXML = XML_TRUE;\r
+ XML_Bool isXMLNS = XML_TRUE;\r
+\r
+ BINDING *b;\r
+ int len;\r
+\r
+ /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */\r
+ if (*uri == XML_T('\0') && prefix->name)\r
+ return XML_ERROR_UNDECLARING_PREFIX;\r
+\r
+ if (prefix->name\r
+ && prefix->name[0] == XML_T(ASCII_x)\r
+ && prefix->name[1] == XML_T(ASCII_m)\r
+ && prefix->name[2] == XML_T(ASCII_l)) {\r
+\r
+ /* Not allowed to bind xmlns */\r
+ if (prefix->name[3] == XML_T(ASCII_n)\r
+ && prefix->name[4] == XML_T(ASCII_s)\r
+ && prefix->name[5] == XML_T('\0'))\r
+ return XML_ERROR_RESERVED_PREFIX_XMLNS;\r
+\r
+ if (prefix->name[3] == XML_T('\0'))\r
+ mustBeXML = XML_TRUE;\r
+ }\r
+\r
+ for (len = 0; uri[len]; len++) {\r
+ if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))\r
+ isXML = XML_FALSE;\r
+\r
+ if (!mustBeXML && isXMLNS\r
+ && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))\r
+ isXMLNS = XML_FALSE;\r
+ }\r
+ isXML = isXML && len == xmlLen;\r
+ isXMLNS = isXMLNS && len == xmlnsLen;\r
+\r
+ if (mustBeXML != isXML)\r
+ return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML\r
+ : XML_ERROR_RESERVED_NAMESPACE_URI;\r
+\r
+ if (isXMLNS)\r
+ return XML_ERROR_RESERVED_NAMESPACE_URI;\r
+\r
+ if (namespaceSeparator)\r
+ len++;\r
+ if (freeBindingList) {\r
+ b = freeBindingList;\r
+ if (len > b->uriAlloc) {\r
+ XML_Char *temp = (XML_Char *)REALLOC(b->uri,\r
+ sizeof(XML_Char) * (len + EXPAND_SPARE));\r
+ if (temp == NULL)\r
+ return XML_ERROR_NO_MEMORY;\r
+ b->uri = temp;\r
+ b->uriAlloc = len + EXPAND_SPARE;\r
+ }\r
+ freeBindingList = b->nextTagBinding;\r
+ }\r
+ else {\r
+ b = (BINDING *)MALLOC(sizeof(BINDING));\r
+ if (!b)\r
+ return XML_ERROR_NO_MEMORY;\r
+ b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));\r
+ if (!b->uri) {\r
+ FREE(b);\r
+ return XML_ERROR_NO_MEMORY;\r
+ }\r
+ b->uriAlloc = len + EXPAND_SPARE;\r
+ }\r
+ b->uriLen = len;\r
+ memcpy(b->uri, uri, len * sizeof(XML_Char));\r
+ if (namespaceSeparator)\r
+ b->uri[len - 1] = namespaceSeparator;\r
+ b->prefix = prefix;\r
+ b->attId = attId;\r
+ b->prevPrefixBinding = prefix->binding;\r
+ /* NULL binding when default namespace undeclared */\r
+ if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)\r
+ prefix->binding = NULL;\r
+ else\r
+ prefix->binding = b;\r
+ b->nextTagBinding = *bindingsPtr;\r
+ *bindingsPtr = b;\r
+ /* if attId == NULL then we are not starting a namespace scope */\r
+ if (attId && startNamespaceDeclHandler)\r
+ startNamespaceDeclHandler(handlerArg, prefix->name,\r
+ prefix->binding ? uri : 0);\r
+ return XML_ERROR_NONE;\r
+}\r
+\r
+/* The idea here is to avoid using stack for each CDATA section when\r
+ the whole file is parsed with one call.\r
+*/\r
+static enum XML_Error PTRCALL\r
+cdataSectionProcessor(XML_Parser parser,\r
+ const char *start,\r
+ const char *end,\r
+ const char **endPtr)\r
+{\r
+ enum XML_Error result = doCdataSection(parser, encoding, &start, end,\r
+ endPtr, (XML_Bool)!ps_finalBuffer);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ if (start) {\r
+ if (parentParser) { /* we are parsing an external entity */\r
+ processor = externalEntityContentProcessor;\r
+ return externalEntityContentProcessor(parser, start, end, endPtr);\r
+ }\r
+ else {\r
+ processor = contentProcessor;\r
+ return contentProcessor(parser, start, end, endPtr);\r
+ }\r
+ }\r
+ return result;\r
+}\r
+\r
+/* startPtr gets set to non-null if the section is closed, and to null if\r
+ the section is not yet closed.\r
+*/\r
+static enum XML_Error\r
+doCdataSection(XML_Parser parser,\r
+ const ENCODING *enc,\r
+ const char **startPtr,\r
+ const char *end,\r
+ const char **nextPtr,\r
+ XML_Bool haveMore)\r
+{\r
+ const char *s = *startPtr;\r
+ const char **eventPP;\r
+ const char **eventEndPP;\r
+ if (enc == encoding) {\r
+ eventPP = &eventPtr;\r
+ *eventPP = s;\r
+ eventEndPP = &eventEndPtr;\r
+ }\r
+ else {\r
+ eventPP = &(openInternalEntities->internalEventPtr);\r
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);\r
+ }\r
+ *eventPP = s;\r
+ *startPtr = NULL;\r
+\r
+ for (;;) {\r
+ const char *next;\r
+ int tok = XmlCdataSectionTok(enc, s, end, &next);\r
+ *eventEndPP = next;\r
+ switch (tok) {\r
+ case XML_TOK_CDATA_SECT_CLOSE:\r
+ if (endCdataSectionHandler)\r
+ endCdataSectionHandler(handlerArg);\r
+#if 0\r
+ /* see comment under XML_TOK_CDATA_SECT_OPEN */\r
+ else if (characterDataHandler)\r
+ characterDataHandler(handlerArg, dataBuf, 0);\r
+#endif\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ *startPtr = next;\r
+ *nextPtr = next;\r
+ if (ps_parsing == XML_FINISHED)\r
+ return XML_ERROR_ABORTED;\r
+ else\r
+ return XML_ERROR_NONE;\r
+ case XML_TOK_DATA_NEWLINE:\r
+ if (characterDataHandler) {\r
+ XML_Char c = 0xA;\r
+ characterDataHandler(handlerArg, &c, 1);\r
+ }\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ break;\r
+ case XML_TOK_DATA_CHARS:\r
+ {\r
+ XML_CharacterDataHandler charDataHandler = characterDataHandler;\r
+ if (charDataHandler) {\r
+ if (MUST_CONVERT(enc, s)) {\r
+ for (;;) {\r
+ ICHAR *dataPtr = (ICHAR *)dataBuf;\r
+ XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);\r
+ *eventEndPP = next;\r
+ charDataHandler(handlerArg, dataBuf,\r
+ (int)(dataPtr - (ICHAR *)dataBuf));\r
+ if (s == next)\r
+ break;\r
+ *eventPP = s;\r
+ }\r
+ }\r
+ else\r
+ charDataHandler(handlerArg,\r
+ (XML_Char *)s,\r
+ (int)((XML_Char *)next - (XML_Char *)s));\r
+ }\r
+ else if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ }\r
+ break;\r
+ case XML_TOK_INVALID:\r
+ *eventPP = next;\r
+ return XML_ERROR_INVALID_TOKEN;\r
+ case XML_TOK_PARTIAL_CHAR:\r
+ if (haveMore) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ return XML_ERROR_PARTIAL_CHAR;\r
+ case XML_TOK_PARTIAL:\r
+ case XML_TOK_NONE:\r
+ if (haveMore) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ return XML_ERROR_UNCLOSED_CDATA_SECTION;\r
+ default:\r
+ *eventPP = next;\r
+ return XML_ERROR_UNEXPECTED_STATE;\r
+ }\r
+\r
+ *eventPP = s = next;\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ *nextPtr = next;\r
+ return XML_ERROR_NONE;\r
+ case XML_FINISHED:\r
+ return XML_ERROR_ABORTED;\r
+ default: ;\r
+ }\r
+ }\r
+ /* not reached */\r
+}\r
+\r
+#ifdef XML_DTD\r
+\r
+/* The idea here is to avoid using stack for each IGNORE section when\r
+ the whole file is parsed with one call.\r
+*/\r
+static enum XML_Error PTRCALL\r
+ignoreSectionProcessor(XML_Parser parser,\r
+ const char *start,\r
+ const char *end,\r
+ const char **endPtr)\r
+{\r
+ enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,\r
+ endPtr, (XML_Bool)!ps_finalBuffer);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ if (start) {\r
+ processor = prologProcessor;\r
+ return prologProcessor(parser, start, end, endPtr);\r
+ }\r
+ return result;\r
+}\r
+\r
+/* startPtr gets set to non-null is the section is closed, and to null\r
+ if the section is not yet closed.\r
+*/\r
+static enum XML_Error\r
+doIgnoreSection(XML_Parser parser,\r
+ const ENCODING *enc,\r
+ const char **startPtr,\r
+ const char *end,\r
+ const char **nextPtr,\r
+ XML_Bool haveMore)\r
+{\r
+ const char *next;\r
+ int tok;\r
+ const char *s = *startPtr;\r
+ const char **eventPP;\r
+ const char **eventEndPP;\r
+ if (enc == encoding) {\r
+ eventPP = &eventPtr;\r
+ *eventPP = s;\r
+ eventEndPP = &eventEndPtr;\r
+ }\r
+ else {\r
+ eventPP = &(openInternalEntities->internalEventPtr);\r
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);\r
+ }\r
+ *eventPP = s;\r
+ *startPtr = NULL;\r
+ tok = XmlIgnoreSectionTok(enc, s, end, &next);\r
+ *eventEndPP = next;\r
+ switch (tok) {\r
+ case XML_TOK_IGNORE_SECT:\r
+ if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ *startPtr = next;\r
+ *nextPtr = next;\r
+ if (ps_parsing == XML_FINISHED)\r
+ return XML_ERROR_ABORTED;\r
+ else\r
+ return XML_ERROR_NONE;\r
+ case XML_TOK_INVALID:\r
+ *eventPP = next;\r
+ return XML_ERROR_INVALID_TOKEN;\r
+ case XML_TOK_PARTIAL_CHAR:\r
+ if (haveMore) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ return XML_ERROR_PARTIAL_CHAR;\r
+ case XML_TOK_PARTIAL:\r
+ case XML_TOK_NONE:\r
+ if (haveMore) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */\r
+ default:\r
+ *eventPP = next;\r
+ return XML_ERROR_UNEXPECTED_STATE;\r
+ }\r
+ /* not reached */\r
+}\r
+\r
+#endif /* XML_DTD */\r
+\r
+static enum XML_Error\r
+initializeEncoding(XML_Parser parser)\r
+{\r
+ const char *s;\r
+#ifdef XML_UNICODE\r
+ char encodingBuf[128];\r
+ if (!protocolEncodingName)\r
+ s = NULL;\r
+ else {\r
+ int i;\r
+ for (i = 0; protocolEncodingName[i]; i++) {\r
+ if (i == sizeof(encodingBuf) - 1\r
+ || (protocolEncodingName[i] & ~0x7f) != 0) {\r
+ encodingBuf[0] = '\0';\r
+ break;\r
+ }\r
+ encodingBuf[i] = (char)protocolEncodingName[i];\r
+ }\r
+ encodingBuf[i] = '\0';\r
+ s = encodingBuf;\r
+ }\r
+#else\r
+ s = protocolEncodingName;\r
+#endif\r
+ if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))\r
+ return XML_ERROR_NONE;\r
+ return handleUnknownEncoding(parser, protocolEncodingName);\r
+}\r
+\r
+static enum XML_Error\r
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity,\r
+ const char *s, const char *next)\r
+{\r
+ const char *encodingName = NULL;\r
+ const XML_Char *storedEncName = NULL;\r
+ const ENCODING *newEncoding = NULL;\r
+ const char *version = NULL;\r
+ const char *versionend;\r
+ const XML_Char *storedversion = NULL;\r
+ int standalone = -1;\r
+ if (!(ns\r
+ ? XmlParseXmlDeclNS\r
+ : XmlParseXmlDecl)(isGeneralTextEntity,\r
+ encoding,\r
+ s,\r
+ next,\r
+ &eventPtr,\r
+ &version,\r
+ &versionend,\r
+ &encodingName,\r
+ &newEncoding,\r
+ &standalone)) {\r
+ if (isGeneralTextEntity)\r
+ return XML_ERROR_TEXT_DECL;\r
+ else\r
+ return XML_ERROR_XML_DECL;\r
+ }\r
+ if (!isGeneralTextEntity && standalone == 1) {\r
+ _dtd->standalone = XML_TRUE;\r
+#ifdef XML_DTD\r
+ if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)\r
+ paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;\r
+#endif /* XML_DTD */\r
+ }\r
+ if (xmlDeclHandler) {\r
+ if (encodingName != NULL) {\r
+ storedEncName = poolStoreString(&temp2Pool,\r
+ encoding,\r
+ encodingName,\r
+ encodingName\r
+ + XmlNameLength(encoding, encodingName));\r
+ if (!storedEncName)\r
+ return XML_ERROR_NO_MEMORY;\r
+ poolFinish(&temp2Pool);\r
+ }\r
+ if (version) {\r
+ storedversion = poolStoreString(&temp2Pool,\r
+ encoding,\r
+ version,\r
+ versionend - encoding->minBytesPerChar);\r
+ if (!storedversion)\r
+ return XML_ERROR_NO_MEMORY;\r
+ }\r
+ xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);\r
+ }\r
+ else if (defaultHandler)\r
+ reportDefault(parser, encoding, s, next);\r
+ if (protocolEncodingName == NULL) {\r
+ if (newEncoding) {\r
+ if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {\r
+ eventPtr = encodingName;\r
+ return XML_ERROR_INCORRECT_ENCODING;\r
+ }\r
+ encoding = newEncoding;\r
+ }\r
+ else if (encodingName) {\r
+ enum XML_Error result;\r
+ if (!storedEncName) {\r
+ storedEncName = poolStoreString(\r
+ &temp2Pool, encoding, encodingName,\r
+ encodingName + XmlNameLength(encoding, encodingName));\r
+ if (!storedEncName)\r
+ return XML_ERROR_NO_MEMORY;\r
+ }\r
+ result = handleUnknownEncoding(parser, storedEncName);\r
+ poolClear(&temp2Pool);\r
+ if (result == XML_ERROR_UNKNOWN_ENCODING)\r
+ eventPtr = encodingName;\r
+ return result;\r
+ }\r
+ }\r
+\r
+ if (storedEncName || storedversion)\r
+ poolClear(&temp2Pool);\r
+\r
+ return XML_ERROR_NONE;\r
+}\r
+\r
+static enum XML_Error\r
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)\r
+{\r
+ if (unknownEncodingHandler) {\r
+ XML_Encoding info;\r
+ int i;\r
+ for (i = 0; i < 256; i++)\r
+ info.map[i] = -1;\r
+ info.convert = NULL;\r
+ info.data = NULL;\r
+ info.release = NULL;\r
+ if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,\r
+ &info)) {\r
+ ENCODING *enc;\r
+ unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());\r
+ if (!unknownEncodingMem) {\r
+ if (info.release)\r
+ info.release(info.data);\r
+ return XML_ERROR_NO_MEMORY;\r
+ }\r
+ enc = (ns\r
+ ? XmlInitUnknownEncodingNS\r
+ : XmlInitUnknownEncoding)(unknownEncodingMem,\r
+ info.map,\r
+ info.convert,\r
+ info.data);\r
+ if (enc) {\r
+ unknownEncodingData = info.data;\r
+ unknownEncodingRelease = info.release;\r
+ encoding = enc;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ }\r
+ if (info.release != NULL)\r
+ info.release(info.data);\r
+ }\r
+ return XML_ERROR_UNKNOWN_ENCODING;\r
+}\r
+\r
+static enum XML_Error PTRCALL\r
+prologInitProcessor(XML_Parser parser,\r
+ const char *s,\r
+ const char *end,\r
+ const char **nextPtr)\r
+{\r
+ enum XML_Error result = initializeEncoding(parser);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ processor = prologProcessor;\r
+ return prologProcessor(parser, s, end, nextPtr);\r
+}\r
+\r
+#ifdef XML_DTD\r
+\r
+static enum XML_Error PTRCALL\r
+externalParEntInitProcessor(XML_Parser parser,\r
+ const char *s,\r
+ const char *end,\r
+ const char **nextPtr)\r
+{\r
+ enum XML_Error result = initializeEncoding(parser);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+\r
+ /* we know now that XML_Parse(Buffer) has been called,\r
+ so we consider the external parameter entity read */\r
+ _dtd->paramEntityRead = XML_TRUE;\r
+\r
+ if (prologState.inEntityValue) {\r
+ processor = entityValueInitProcessor;\r
+ return entityValueInitProcessor(parser, s, end, nextPtr);\r
+ }\r
+ else {\r
+ processor = externalParEntProcessor;\r
+ return externalParEntProcessor(parser, s, end, nextPtr);\r
+ }\r
+}\r
+\r
+static enum XML_Error PTRCALL\r
+entityValueInitProcessor(XML_Parser parser,\r
+ const char *s,\r
+ const char *end,\r
+ const char **nextPtr)\r
+{\r
+ int tok;\r
+ const char *start = s;\r
+ const char *next = start;\r
+ eventPtr = start;\r
+\r
+ for (;;) {\r
+ tok = XmlPrologTok(encoding, start, end, &next);\r
+ eventEndPtr = next;\r
+ if (tok <= 0) {\r
+ if (!ps_finalBuffer && tok != XML_TOK_INVALID) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ switch (tok) {\r
+ case XML_TOK_INVALID:\r
+ return XML_ERROR_INVALID_TOKEN;\r
+ case XML_TOK_PARTIAL:\r
+ return XML_ERROR_UNCLOSED_TOKEN;\r
+ case XML_TOK_PARTIAL_CHAR:\r
+ return XML_ERROR_PARTIAL_CHAR;\r
+ case XML_TOK_NONE: /* start == end */\r
+ default:\r
+ break;\r
+ }\r
+ /* found end of entity value - can store it now */\r
+ return storeEntityValue(parser, encoding, s, end);\r
+ }\r
+ else if (tok == XML_TOK_XML_DECL) {\r
+ enum XML_Error result;\r
+ result = processXmlDecl(parser, 0, start, next);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ *nextPtr = next;\r
+ return XML_ERROR_NONE;\r
+ case XML_FINISHED:\r
+ return XML_ERROR_ABORTED;\r
+ default:\r
+ *nextPtr = next;\r
+ }\r
+ /* stop scanning for text declaration - we found one */\r
+ processor = entityValueProcessor;\r
+ return entityValueProcessor(parser, next, end, nextPtr);\r
+ }\r
+ /* If we are at the end of the buffer, this would cause XmlPrologTok to\r
+ return XML_TOK_NONE on the next call, which would then cause the\r
+ function to exit with *nextPtr set to s - that is what we want for other\r
+ tokens, but not for the BOM - we would rather like to skip it;\r
+ then, when this routine is entered the next time, XmlPrologTok will\r
+ return XML_TOK_INVALID, since the BOM is still in the buffer\r
+ */\r
+ else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {\r
+ *nextPtr = next;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ start = next;\r
+ eventPtr = start;\r
+ }\r
+}\r
+\r
+static enum XML_Error PTRCALL\r
+externalParEntProcessor(XML_Parser parser,\r
+ const char *s,\r
+ const char *end,\r
+ const char **nextPtr)\r
+{\r
+ const char *next = s;\r
+ int tok;\r
+\r
+ tok = XmlPrologTok(encoding, s, end, &next);\r
+ if (tok <= 0) {\r
+ if (!ps_finalBuffer && tok != XML_TOK_INVALID) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ switch (tok) {\r
+ case XML_TOK_INVALID:\r
+ return XML_ERROR_INVALID_TOKEN;\r
+ case XML_TOK_PARTIAL:\r
+ return XML_ERROR_UNCLOSED_TOKEN;\r
+ case XML_TOK_PARTIAL_CHAR:\r
+ return XML_ERROR_PARTIAL_CHAR;\r
+ case XML_TOK_NONE: /* start == end */\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.\r
+ However, when parsing an external subset, doProlog will not accept a BOM\r
+ as valid, and report a syntax error, so we have to skip the BOM\r
+ */\r
+ else if (tok == XML_TOK_BOM) {\r
+ s = next;\r
+ tok = XmlPrologTok(encoding, s, end, &next);\r
+ }\r
+\r
+ processor = prologProcessor;\r
+ return doProlog(parser, encoding, s, end, tok, next,\r
+ nextPtr, (XML_Bool)!ps_finalBuffer);\r
+}\r
+\r
+static enum XML_Error PTRCALL\r
+entityValueProcessor(XML_Parser parser,\r
+ const char *s,\r
+ const char *end,\r
+ const char **nextPtr)\r
+{\r
+ const char *start = s;\r
+ const char *next = s;\r
+ const ENCODING *enc = encoding;\r
+ int tok;\r
+\r
+ for (;;) {\r
+ tok = XmlPrologTok(enc, start, end, &next);\r
+ if (tok <= 0) {\r
+ if (!ps_finalBuffer && tok != XML_TOK_INVALID) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ switch (tok) {\r
+ case XML_TOK_INVALID:\r
+ return XML_ERROR_INVALID_TOKEN;\r
+ case XML_TOK_PARTIAL:\r
+ return XML_ERROR_UNCLOSED_TOKEN;\r
+ case XML_TOK_PARTIAL_CHAR:\r
+ return XML_ERROR_PARTIAL_CHAR;\r
+ case XML_TOK_NONE: /* start == end */\r
+ default:\r
+ break;\r
+ }\r
+ /* found end of entity value - can store it now */\r
+ return storeEntityValue(parser, enc, s, end);\r
+ }\r
+ start = next;\r
+ }\r
+}\r
+\r
+#endif /* XML_DTD */\r
+\r
+static enum XML_Error PTRCALL\r
+prologProcessor(XML_Parser parser,\r
+ const char *s,\r
+ const char *end,\r
+ const char **nextPtr)\r
+{\r
+ const char *next = s;\r
+ int tok = XmlPrologTok(encoding, s, end, &next);\r
+ return doProlog(parser, encoding, s, end, tok, next,\r
+ nextPtr, (XML_Bool)!ps_finalBuffer);\r
+}\r
+\r
+static enum XML_Error\r
+doProlog(XML_Parser parser,\r
+ const ENCODING *enc,\r
+ const char *s,\r
+ const char *end,\r
+ int tok,\r
+ const char *next,\r
+ const char **nextPtr,\r
+ XML_Bool haveMore)\r
+{\r
+#ifdef XML_DTD\r
+ static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };\r
+#endif /* XML_DTD */\r
+ static const XML_Char atypeCDATA[] =\r
+ { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };\r
+ static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };\r
+ static const XML_Char atypeIDREF[] =\r
+ { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };\r
+ static const XML_Char atypeIDREFS[] =\r
+ { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };\r
+ static const XML_Char atypeENTITY[] =\r
+ { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };\r
+ static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,\r
+ ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };\r
+ static const XML_Char atypeNMTOKEN[] = {\r
+ ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };\r
+ static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,\r
+ ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };\r
+ static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,\r
+ ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };\r
+ static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };\r
+ static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };\r
+\r
+ /* save one level of indirection */\r
+ DTD * const dtd = _dtd;\r
+\r
+ const char **eventPP;\r
+ const char **eventEndPP;\r
+ enum XML_Content_Quant quant;\r
+\r
+ if (enc == encoding) {\r
+ eventPP = &eventPtr;\r
+ eventEndPP = &eventEndPtr;\r
+ }\r
+ else {\r
+ eventPP = &(openInternalEntities->internalEventPtr);\r
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);\r
+ }\r
+\r
+ for (;;) {\r
+ int role;\r
+ XML_Bool handleDefault = XML_TRUE;\r
+ *eventPP = s;\r
+ *eventEndPP = next;\r
+ if (tok <= 0) {\r
+ if (haveMore && tok != XML_TOK_INVALID) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ switch (tok) {\r
+ case XML_TOK_INVALID:\r
+ *eventPP = next;\r
+ return XML_ERROR_INVALID_TOKEN;\r
+ case XML_TOK_PARTIAL:\r
+ return XML_ERROR_UNCLOSED_TOKEN;\r
+ case XML_TOK_PARTIAL_CHAR:\r
+ return XML_ERROR_PARTIAL_CHAR;\r
+ case -XML_TOK_PROLOG_S:\r
+ tok = -tok;\r
+ break;\r
+ case XML_TOK_NONE:\r
+#ifdef XML_DTD\r
+ /* for internal PE NOT referenced between declarations */\r
+ if (enc != encoding && !openInternalEntities->betweenDecl) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ /* WFC: PE Between Declarations - must check that PE contains\r
+ complete markup, not only for external PEs, but also for\r
+ internal PEs if the reference occurs between declarations.\r
+ */\r
+ if (isParamEntity || enc != encoding) {\r
+ if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)\r
+ == XML_ROLE_ERROR)\r
+ return XML_ERROR_INCOMPLETE_PE;\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+#endif /* XML_DTD */\r
+ return XML_ERROR_NO_ELEMENTS;\r
+ default:\r
+ tok = -tok;\r
+ next = end;\r
+ break;\r
+ }\r
+ }\r
+ role = XmlTokenRole(&prologState, tok, s, next, enc);\r
+ switch (role) {\r
+ case XML_ROLE_XML_DECL:\r
+ {\r
+ enum XML_Error result = processXmlDecl(parser, 0, s, next);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ enc = encoding;\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+ case XML_ROLE_DOCTYPE_NAME:\r
+ if (startDoctypeDeclHandler) {\r
+ doctypeName = poolStoreString(&tempPool, enc, s, next);\r
+ if (!doctypeName)\r
+ return XML_ERROR_NO_MEMORY;\r
+ poolFinish(&tempPool);\r
+ doctypePubid = NULL;\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ doctypeSysid = NULL; /* always initialize to NULL */\r
+ break;\r
+ case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:\r
+ if (startDoctypeDeclHandler) {\r
+ startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,\r
+ doctypePubid, 1);\r
+ doctypeName = NULL;\r
+ poolClear(&tempPool);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+#ifdef XML_DTD\r
+ case XML_ROLE_TEXT_DECL:\r
+ {\r
+ enum XML_Error result = processXmlDecl(parser, 1, s, next);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ enc = encoding;\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+#endif /* XML_DTD */\r
+ case XML_ROLE_DOCTYPE_PUBLIC_ID:\r
+#ifdef XML_DTD\r
+ useForeignDTD = XML_FALSE;\r
+ declEntity = (ENTITY *)lookup(parser,\r
+ &dtd->paramEntities,\r
+ externalSubsetName,\r
+ sizeof(ENTITY));\r
+ if (!declEntity)\r
+ return XML_ERROR_NO_MEMORY;\r
+#endif /* XML_DTD */\r
+ dtd->hasParamEntityRefs = XML_TRUE;\r
+ if (startDoctypeDeclHandler) {\r
+ XML_Char *pubId;\r
+ if (!XmlIsPublicId(enc, s, next, eventPP))\r
+ return XML_ERROR_PUBLICID;\r
+ pubId = poolStoreString(&tempPool, enc,\r
+ s + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (!pubId)\r
+ return XML_ERROR_NO_MEMORY;\r
+ normalizePublicId(pubId);\r
+ poolFinish(&tempPool);\r
+ doctypePubid = pubId;\r
+ handleDefault = XML_FALSE;\r
+ goto alreadyChecked;\r
+ }\r
+ /* fall through */\r
+ case XML_ROLE_ENTITY_PUBLIC_ID:\r
+ if (!XmlIsPublicId(enc, s, next, eventPP))\r
+ return XML_ERROR_PUBLICID;\r
+ alreadyChecked:\r
+ if (dtd->keepProcessing && declEntity) {\r
+ XML_Char *tem = poolStoreString(&dtd->pool,\r
+ enc,\r
+ s + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (!tem)\r
+ return XML_ERROR_NO_MEMORY;\r
+ normalizePublicId(tem);\r
+ declEntity->publicId = tem;\r
+ poolFinish(&dtd->pool);\r
+ if (entityDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+ case XML_ROLE_DOCTYPE_CLOSE:\r
+ if (doctypeName) {\r
+ startDoctypeDeclHandler(handlerArg, doctypeName,\r
+ doctypeSysid, doctypePubid, 0);\r
+ poolClear(&tempPool);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ /* doctypeSysid will be non-NULL in the case of a previous\r
+ XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler\r
+ was not set, indicating an external subset\r
+ */\r
+#ifdef XML_DTD\r
+ if (doctypeSysid || useForeignDTD) {\r
+ XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;\r
+ dtd->hasParamEntityRefs = XML_TRUE;\r
+ if (paramEntityParsing && externalEntityRefHandler) {\r
+ ENTITY *entity = (ENTITY *)lookup(parser,\r
+ &dtd->paramEntities,\r
+ externalSubsetName,\r
+ sizeof(ENTITY));\r
+ if (!entity)\r
+ return XML_ERROR_NO_MEMORY;\r
+ if (useForeignDTD)\r
+ entity->base = curBase;\r
+ dtd->paramEntityRead = XML_FALSE;\r
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,\r
+ 0,\r
+ entity->base,\r
+ entity->systemId,\r
+ entity->publicId))\r
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;\r
+ if (dtd->paramEntityRead) {\r
+ if (!dtd->standalone &&\r
+ notStandaloneHandler &&\r
+ !notStandaloneHandler(handlerArg))\r
+ return XML_ERROR_NOT_STANDALONE;\r
+ }\r
+ /* if we didn't read the foreign DTD then this means that there\r
+ is no external subset and we must reset dtd->hasParamEntityRefs\r
+ */\r
+ else if (!doctypeSysid)\r
+ dtd->hasParamEntityRefs = hadParamEntityRefs;\r
+ /* end of DTD - no need to update dtd->keepProcessing */\r
+ }\r
+ useForeignDTD = XML_FALSE;\r
+ }\r
+#endif /* XML_DTD */\r
+ if (endDoctypeDeclHandler) {\r
+ endDoctypeDeclHandler(handlerArg);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+ case XML_ROLE_INSTANCE_START:\r
+#ifdef XML_DTD\r
+ /* if there is no DOCTYPE declaration then now is the\r
+ last chance to read the foreign DTD\r
+ */\r
+ if (useForeignDTD) {\r
+ XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;\r
+ dtd->hasParamEntityRefs = XML_TRUE;\r
+ if (paramEntityParsing && externalEntityRefHandler) {\r
+ ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,\r
+ externalSubsetName,\r
+ sizeof(ENTITY));\r
+ if (!entity)\r
+ return XML_ERROR_NO_MEMORY;\r
+ entity->base = curBase;\r
+ dtd->paramEntityRead = XML_FALSE;\r
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,\r
+ 0,\r
+ entity->base,\r
+ entity->systemId,\r
+ entity->publicId))\r
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;\r
+ if (dtd->paramEntityRead) {\r
+ if (!dtd->standalone &&\r
+ notStandaloneHandler &&\r
+ !notStandaloneHandler(handlerArg))\r
+ return XML_ERROR_NOT_STANDALONE;\r
+ }\r
+ /* if we didn't read the foreign DTD then this means that there\r
+ is no external subset and we must reset dtd->hasParamEntityRefs\r
+ */\r
+ else\r
+ dtd->hasParamEntityRefs = hadParamEntityRefs;\r
+ /* end of DTD - no need to update dtd->keepProcessing */\r
+ }\r
+ }\r
+#endif /* XML_DTD */\r
+ processor = contentProcessor;\r
+ return contentProcessor(parser, s, end, nextPtr);\r
+ case XML_ROLE_ATTLIST_ELEMENT_NAME:\r
+ declElementType = getElementType(parser, enc, s, next);\r
+ if (!declElementType)\r
+ return XML_ERROR_NO_MEMORY;\r
+ goto checkAttListDeclHandler;\r
+ case XML_ROLE_ATTRIBUTE_NAME:\r
+ declAttributeId = getAttributeId(parser, enc, s, next);\r
+ if (!declAttributeId)\r
+ return XML_ERROR_NO_MEMORY;\r
+ declAttributeIsCdata = XML_FALSE;\r
+ declAttributeType = NULL;\r
+ declAttributeIsId = XML_FALSE;\r
+ goto checkAttListDeclHandler;\r
+ case XML_ROLE_ATTRIBUTE_TYPE_CDATA:\r
+ declAttributeIsCdata = XML_TRUE;\r
+ declAttributeType = atypeCDATA;\r
+ goto checkAttListDeclHandler;\r
+ case XML_ROLE_ATTRIBUTE_TYPE_ID:\r
+ declAttributeIsId = XML_TRUE;\r
+ declAttributeType = atypeID;\r
+ goto checkAttListDeclHandler;\r
+ case XML_ROLE_ATTRIBUTE_TYPE_IDREF:\r
+ declAttributeType = atypeIDREF;\r
+ goto checkAttListDeclHandler;\r
+ case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:\r
+ declAttributeType = atypeIDREFS;\r
+ goto checkAttListDeclHandler;\r
+ case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:\r
+ declAttributeType = atypeENTITY;\r
+ goto checkAttListDeclHandler;\r
+ case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:\r
+ declAttributeType = atypeENTITIES;\r
+ goto checkAttListDeclHandler;\r
+ case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:\r
+ declAttributeType = atypeNMTOKEN;\r
+ goto checkAttListDeclHandler;\r
+ case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:\r
+ declAttributeType = atypeNMTOKENS;\r
+ checkAttListDeclHandler:\r
+ if (dtd->keepProcessing && attlistDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ break;\r
+ case XML_ROLE_ATTRIBUTE_ENUM_VALUE:\r
+ case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:\r
+ if (dtd->keepProcessing && attlistDeclHandler) {\r
+ const XML_Char *prefix;\r
+ if (declAttributeType) {\r
+ prefix = enumValueSep;\r
+ }\r
+ else {\r
+ prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE\r
+ ? notationPrefix\r
+ : enumValueStart);\r
+ }\r
+ if (!poolAppendString(&tempPool, prefix))\r
+ return XML_ERROR_NO_MEMORY;\r
+ if (!poolAppend(&tempPool, enc, s, next))\r
+ return XML_ERROR_NO_MEMORY;\r
+ declAttributeType = tempPool.start;\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+ case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:\r
+ case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:\r
+ if (dtd->keepProcessing) {\r
+ if (!defineAttribute(declElementType, declAttributeId,\r
+ declAttributeIsCdata, declAttributeIsId,\r
+ 0, parser))\r
+ return XML_ERROR_NO_MEMORY;\r
+ if (attlistDeclHandler && declAttributeType) {\r
+ if (*declAttributeType == XML_T(ASCII_LPAREN)\r
+ || (*declAttributeType == XML_T(ASCII_N)\r
+ && declAttributeType[1] == XML_T(ASCII_O))) {\r
+ /* Enumerated or Notation type */\r
+ if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))\r
+ || !poolAppendChar(&tempPool, XML_T('\0')))\r
+ return XML_ERROR_NO_MEMORY;\r
+ declAttributeType = tempPool.start;\r
+ poolFinish(&tempPool);\r
+ }\r
+ *eventEndPP = s;\r
+ attlistDeclHandler(handlerArg, declElementType->name,\r
+ declAttributeId->name, declAttributeType,\r
+ 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);\r
+ poolClear(&tempPool);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ }\r
+ break;\r
+ case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:\r
+ case XML_ROLE_FIXED_ATTRIBUTE_VALUE:\r
+ if (dtd->keepProcessing) {\r
+ const XML_Char *attVal;\r
+ enum XML_Error result =\r
+ storeAttributeValue(parser, enc, declAttributeIsCdata,\r
+ s + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar,\r
+ &dtd->pool);\r
+ if (result)\r
+ return result;\r
+ attVal = poolStart(&dtd->pool);\r
+ poolFinish(&dtd->pool);\r
+ /* ID attributes aren't allowed to have a default */\r
+ if (!defineAttribute(declElementType, declAttributeId,\r
+ declAttributeIsCdata, XML_FALSE, attVal, parser))\r
+ return XML_ERROR_NO_MEMORY;\r
+ if (attlistDeclHandler && declAttributeType) {\r
+ if (*declAttributeType == XML_T(ASCII_LPAREN)\r
+ || (*declAttributeType == XML_T(ASCII_N)\r
+ && declAttributeType[1] == XML_T(ASCII_O))) {\r
+ /* Enumerated or Notation type */\r
+ if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))\r
+ || !poolAppendChar(&tempPool, XML_T('\0')))\r
+ return XML_ERROR_NO_MEMORY;\r
+ declAttributeType = tempPool.start;\r
+ poolFinish(&tempPool);\r
+ }\r
+ *eventEndPP = s;\r
+ attlistDeclHandler(handlerArg, declElementType->name,\r
+ declAttributeId->name, declAttributeType,\r
+ attVal,\r
+ role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);\r
+ poolClear(&tempPool);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ }\r
+ break;\r
+ case XML_ROLE_ENTITY_VALUE:\r
+ if (dtd->keepProcessing) {\r
+ enum XML_Error result = storeEntityValue(parser, enc,\r
+ s + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (declEntity) {\r
+ declEntity->textPtr = poolStart(&dtd->entityValuePool);\r
+ declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));\r
+ poolFinish(&dtd->entityValuePool);\r
+ if (entityDeclHandler) {\r
+ *eventEndPP = s;\r
+ entityDeclHandler(handlerArg,\r
+ declEntity->name,\r
+ declEntity->is_param,\r
+ declEntity->textPtr,\r
+ declEntity->textLen,\r
+ curBase, 0, 0, 0);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ }\r
+ else\r
+ poolDiscard(&dtd->entityValuePool);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ }\r
+ break;\r
+ case XML_ROLE_DOCTYPE_SYSTEM_ID:\r
+#ifdef XML_DTD\r
+ useForeignDTD = XML_FALSE;\r
+#endif /* XML_DTD */\r
+ dtd->hasParamEntityRefs = XML_TRUE;\r
+ if (startDoctypeDeclHandler) {\r
+ doctypeSysid = poolStoreString(&tempPool, enc,\r
+ s + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (doctypeSysid == NULL)\r
+ return XML_ERROR_NO_MEMORY;\r
+ poolFinish(&tempPool);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+#ifdef XML_DTD\r
+ else\r
+ /* use externalSubsetName to make doctypeSysid non-NULL\r
+ for the case where no startDoctypeDeclHandler is set */\r
+ doctypeSysid = externalSubsetName;\r
+#endif /* XML_DTD */\r
+ if (!dtd->standalone\r
+#ifdef XML_DTD\r
+ && !paramEntityParsing\r
+#endif /* XML_DTD */\r
+ && notStandaloneHandler\r
+ && !notStandaloneHandler(handlerArg))\r
+ return XML_ERROR_NOT_STANDALONE;\r
+#ifndef XML_DTD\r
+ break;\r
+#else /* XML_DTD */\r
+ if (!declEntity) {\r
+ declEntity = (ENTITY *)lookup(parser,\r
+ &dtd->paramEntities,\r
+ externalSubsetName,\r
+ sizeof(ENTITY));\r
+ if (!declEntity)\r
+ return XML_ERROR_NO_MEMORY;\r
+ declEntity->publicId = NULL;\r
+ }\r
+ /* fall through */\r
+#endif /* XML_DTD */\r
+ case XML_ROLE_ENTITY_SYSTEM_ID:\r
+ if (dtd->keepProcessing && declEntity) {\r
+ declEntity->systemId = poolStoreString(&dtd->pool, enc,\r
+ s + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (!declEntity->systemId)\r
+ return XML_ERROR_NO_MEMORY;\r
+ declEntity->base = curBase;\r
+ poolFinish(&dtd->pool);\r
+ if (entityDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+ case XML_ROLE_ENTITY_COMPLETE:\r
+ if (dtd->keepProcessing && declEntity && entityDeclHandler) {\r
+ *eventEndPP = s;\r
+ entityDeclHandler(handlerArg,\r
+ declEntity->name,\r
+ declEntity->is_param,\r
+ 0,0,\r
+ declEntity->base,\r
+ declEntity->systemId,\r
+ declEntity->publicId,\r
+ 0);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+ case XML_ROLE_ENTITY_NOTATION_NAME:\r
+ if (dtd->keepProcessing && declEntity) {\r
+ declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);\r
+ if (!declEntity->notation)\r
+ return XML_ERROR_NO_MEMORY;\r
+ poolFinish(&dtd->pool);\r
+ if (unparsedEntityDeclHandler) {\r
+ *eventEndPP = s;\r
+ unparsedEntityDeclHandler(handlerArg,\r
+ declEntity->name,\r
+ declEntity->base,\r
+ declEntity->systemId,\r
+ declEntity->publicId,\r
+ declEntity->notation);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ else if (entityDeclHandler) {\r
+ *eventEndPP = s;\r
+ entityDeclHandler(handlerArg,\r
+ declEntity->name,\r
+ 0,0,0,\r
+ declEntity->base,\r
+ declEntity->systemId,\r
+ declEntity->publicId,\r
+ declEntity->notation);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ }\r
+ break;\r
+ case XML_ROLE_GENERAL_ENTITY_NAME:\r
+ {\r
+ if (XmlPredefinedEntityName(enc, s, next)) {\r
+ declEntity = NULL;\r
+ break;\r
+ }\r
+ if (dtd->keepProcessing) {\r
+ const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);\r
+ if (!name)\r
+ return XML_ERROR_NO_MEMORY;\r
+ declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,\r
+ sizeof(ENTITY));\r
+ if (!declEntity)\r
+ return XML_ERROR_NO_MEMORY;\r
+ if (declEntity->name != name) {\r
+ poolDiscard(&dtd->pool);\r
+ declEntity = NULL;\r
+ }\r
+ else {\r
+ poolFinish(&dtd->pool);\r
+ declEntity->publicId = NULL;\r
+ declEntity->is_param = XML_FALSE;\r
+ /* if we have a parent parser or are reading an internal parameter\r
+ entity, then the entity declaration is not considered "internal"\r
+ */\r
+ declEntity->is_internal = !(parentParser || openInternalEntities);\r
+ if (entityDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ }\r
+ else {\r
+ poolDiscard(&dtd->pool);\r
+ declEntity = NULL;\r
+ }\r
+ }\r
+ break;\r
+ case XML_ROLE_PARAM_ENTITY_NAME:\r
+#ifdef XML_DTD\r
+ if (dtd->keepProcessing) {\r
+ const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);\r
+ if (!name)\r
+ return XML_ERROR_NO_MEMORY;\r
+ declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,\r
+ name, sizeof(ENTITY));\r
+ if (!declEntity)\r
+ return XML_ERROR_NO_MEMORY;\r
+ if (declEntity->name != name) {\r
+ poolDiscard(&dtd->pool);\r
+ declEntity = NULL;\r
+ }\r
+ else {\r
+ poolFinish(&dtd->pool);\r
+ declEntity->publicId = NULL;\r
+ declEntity->is_param = XML_TRUE;\r
+ /* if we have a parent parser or are reading an internal parameter\r
+ entity, then the entity declaration is not considered "internal"\r
+ */\r
+ declEntity->is_internal = !(parentParser || openInternalEntities);\r
+ if (entityDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ }\r
+ else {\r
+ poolDiscard(&dtd->pool);\r
+ declEntity = NULL;\r
+ }\r
+#else /* not XML_DTD */\r
+ declEntity = NULL;\r
+#endif /* XML_DTD */\r
+ break;\r
+ case XML_ROLE_NOTATION_NAME:\r
+ declNotationPublicId = NULL;\r
+ declNotationName = NULL;\r
+ if (notationDeclHandler) {\r
+ declNotationName = poolStoreString(&tempPool, enc, s, next);\r
+ if (!declNotationName)\r
+ return XML_ERROR_NO_MEMORY;\r
+ poolFinish(&tempPool);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+ case XML_ROLE_NOTATION_PUBLIC_ID:\r
+ if (!XmlIsPublicId(enc, s, next, eventPP))\r
+ return XML_ERROR_PUBLICID;\r
+ if (declNotationName) { /* means notationDeclHandler != NULL */\r
+ XML_Char *tem = poolStoreString(&tempPool,\r
+ enc,\r
+ s + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (!tem)\r
+ return XML_ERROR_NO_MEMORY;\r
+ normalizePublicId(tem);\r
+ declNotationPublicId = tem;\r
+ poolFinish(&tempPool);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+ case XML_ROLE_NOTATION_SYSTEM_ID:\r
+ if (declNotationName && notationDeclHandler) {\r
+ const XML_Char *systemId\r
+ = poolStoreString(&tempPool, enc,\r
+ s + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (!systemId)\r
+ return XML_ERROR_NO_MEMORY;\r
+ *eventEndPP = s;\r
+ notationDeclHandler(handlerArg,\r
+ declNotationName,\r
+ curBase,\r
+ systemId,\r
+ declNotationPublicId);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ poolClear(&tempPool);\r
+ break;\r
+ case XML_ROLE_NOTATION_NO_SYSTEM_ID:\r
+ if (declNotationPublicId && notationDeclHandler) {\r
+ *eventEndPP = s;\r
+ notationDeclHandler(handlerArg,\r
+ declNotationName,\r
+ curBase,\r
+ 0,\r
+ declNotationPublicId);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ poolClear(&tempPool);\r
+ break;\r
+ case XML_ROLE_ERROR:\r
+ switch (tok) {\r
+ case XML_TOK_PARAM_ENTITY_REF:\r
+ /* PE references in internal subset are\r
+ not allowed within declarations. */\r
+ return XML_ERROR_PARAM_ENTITY_REF;\r
+ case XML_TOK_XML_DECL:\r
+ return XML_ERROR_MISPLACED_XML_PI;\r
+ default:\r
+ return XML_ERROR_SYNTAX;\r
+ }\r
+#ifdef XML_DTD\r
+ case XML_ROLE_IGNORE_SECT:\r
+ {\r
+ enum XML_Error result;\r
+ if (defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+ handleDefault = XML_FALSE;\r
+ result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ else if (!next) {\r
+ processor = ignoreSectionProcessor;\r
+ return result;\r
+ }\r
+ }\r
+ break;\r
+#endif /* XML_DTD */\r
+ case XML_ROLE_GROUP_OPEN:\r
+ if (prologState.level >= groupSize) {\r
+ if (groupSize) {\r
+ char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);\r
+ if (temp == NULL)\r
+ return XML_ERROR_NO_MEMORY;\r
+ groupConnector = temp;\r
+ if (dtd->scaffIndex) {\r
+ int *temp = (int *)REALLOC(dtd->scaffIndex,\r
+ groupSize * sizeof(int));\r
+ if (temp == NULL)\r
+ return XML_ERROR_NO_MEMORY;\r
+ dtd->scaffIndex = temp;\r
+ }\r
+ }\r
+ else {\r
+ groupConnector = (char *)MALLOC(groupSize = 32);\r
+ if (!groupConnector)\r
+ return XML_ERROR_NO_MEMORY;\r
+ }\r
+ }\r
+ groupConnector[prologState.level] = 0;\r
+ if (dtd->in_eldecl) {\r
+ int myindex = nextScaffoldPart(parser);\r
+ if (myindex < 0)\r
+ return XML_ERROR_NO_MEMORY;\r
+ dtd->scaffIndex[dtd->scaffLevel] = myindex;\r
+ dtd->scaffLevel++;\r
+ dtd->scaffold[myindex].type = XML_CTYPE_SEQ;\r
+ if (elementDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+ case XML_ROLE_GROUP_SEQUENCE:\r
+ if (groupConnector[prologState.level] == ASCII_PIPE)\r
+ return XML_ERROR_SYNTAX;\r
+ groupConnector[prologState.level] = ASCII_COMMA;\r
+ if (dtd->in_eldecl && elementDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ break;\r
+ case XML_ROLE_GROUP_CHOICE:\r
+ if (groupConnector[prologState.level] == ASCII_COMMA)\r
+ return XML_ERROR_SYNTAX;\r
+ if (dtd->in_eldecl\r
+ && !groupConnector[prologState.level]\r
+ && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type\r
+ != XML_CTYPE_MIXED)\r
+ ) {\r
+ dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type\r
+ = XML_CTYPE_CHOICE;\r
+ if (elementDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ groupConnector[prologState.level] = ASCII_PIPE;\r
+ break;\r
+ case XML_ROLE_PARAM_ENTITY_REF:\r
+#ifdef XML_DTD\r
+ case XML_ROLE_INNER_PARAM_ENTITY_REF:\r
+ dtd->hasParamEntityRefs = XML_TRUE;\r
+ if (!paramEntityParsing)\r
+ dtd->keepProcessing = dtd->standalone;\r
+ else {\r
+ const XML_Char *name;\r
+ ENTITY *entity;\r
+ name = poolStoreString(&dtd->pool, enc,\r
+ s + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (!name)\r
+ return XML_ERROR_NO_MEMORY;\r
+ entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);\r
+ poolDiscard(&dtd->pool);\r
+ /* first, determine if a check for an existing declaration is needed;\r
+ if yes, check that the entity exists, and that it is internal,\r
+ otherwise call the skipped entity handler\r
+ */\r
+ if (prologState.documentEntity &&\r
+ (dtd->standalone\r
+ ? !openInternalEntities\r
+ : !dtd->hasParamEntityRefs)) {\r
+ if (!entity)\r
+ return XML_ERROR_UNDEFINED_ENTITY;\r
+ else if (!entity->is_internal)\r
+ return XML_ERROR_ENTITY_DECLARED_IN_PE;\r
+ }\r
+ else if (!entity) {\r
+ dtd->keepProcessing = dtd->standalone;\r
+ /* cannot report skipped entities in declarations */\r
+ if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {\r
+ skippedEntityHandler(handlerArg, name, 1);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+ }\r
+ if (entity->open)\r
+ return XML_ERROR_RECURSIVE_ENTITY_REF;\r
+ if (entity->textPtr) {\r
+ enum XML_Error result;\r
+ XML_Bool betweenDecl =\r
+ (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);\r
+ result = processInternalEntity(parser, entity, betweenDecl);\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ handleDefault = XML_FALSE;\r
+ break;\r
+ }\r
+ if (externalEntityRefHandler) {\r
+ dtd->paramEntityRead = XML_FALSE;\r
+ entity->open = XML_TRUE;\r
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,\r
+ 0,\r
+ entity->base,\r
+ entity->systemId,\r
+ entity->publicId)) {\r
+ entity->open = XML_FALSE;\r
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;\r
+ }\r
+ entity->open = XML_FALSE;\r
+ handleDefault = XML_FALSE;\r
+ if (!dtd->paramEntityRead) {\r
+ dtd->keepProcessing = dtd->standalone;\r
+ break;\r
+ }\r
+ }\r
+ else {\r
+ dtd->keepProcessing = dtd->standalone;\r
+ break;\r
+ }\r
+ }\r
+#endif /* XML_DTD */\r
+ if (!dtd->standalone &&\r
+ notStandaloneHandler &&\r
+ !notStandaloneHandler(handlerArg))\r
+ return XML_ERROR_NOT_STANDALONE;\r
+ break;\r
+\r
+ /* Element declaration stuff */\r
+\r
+ case XML_ROLE_ELEMENT_NAME:\r
+ if (elementDeclHandler) {\r
+ declElementType = getElementType(parser, enc, s, next);\r
+ if (!declElementType)\r
+ return XML_ERROR_NO_MEMORY;\r
+ dtd->scaffLevel = 0;\r
+ dtd->scaffCount = 0;\r
+ dtd->in_eldecl = XML_TRUE;\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+\r
+ case XML_ROLE_CONTENT_ANY:\r
+ case XML_ROLE_CONTENT_EMPTY:\r
+ if (dtd->in_eldecl) {\r
+ if (elementDeclHandler) {\r
+ XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));\r
+ if (!content)\r
+ return XML_ERROR_NO_MEMORY;\r
+ content->quant = XML_CQUANT_NONE;\r
+ content->name = NULL;\r
+ content->numchildren = 0;\r
+ content->children = NULL;\r
+ content->type = ((role == XML_ROLE_CONTENT_ANY) ?\r
+ XML_CTYPE_ANY :\r
+ XML_CTYPE_EMPTY);\r
+ *eventEndPP = s;\r
+ elementDeclHandler(handlerArg, declElementType->name, content);\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ dtd->in_eldecl = XML_FALSE;\r
+ }\r
+ break;\r
+\r
+ case XML_ROLE_CONTENT_PCDATA:\r
+ if (dtd->in_eldecl) {\r
+ dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type\r
+ = XML_CTYPE_MIXED;\r
+ if (elementDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+\r
+ case XML_ROLE_CONTENT_ELEMENT:\r
+ quant = XML_CQUANT_NONE;\r
+ goto elementContent;\r
+ case XML_ROLE_CONTENT_ELEMENT_OPT:\r
+ quant = XML_CQUANT_OPT;\r
+ goto elementContent;\r
+ case XML_ROLE_CONTENT_ELEMENT_REP:\r
+ quant = XML_CQUANT_REP;\r
+ goto elementContent;\r
+ case XML_ROLE_CONTENT_ELEMENT_PLUS:\r
+ quant = XML_CQUANT_PLUS;\r
+ elementContent:\r
+ if (dtd->in_eldecl) {\r
+ ELEMENT_TYPE *el;\r
+ const XML_Char *name;\r
+ int nameLen;\r
+ const char *nxt = (quant == XML_CQUANT_NONE\r
+ ? next\r
+ : next - enc->minBytesPerChar);\r
+ int myindex = nextScaffoldPart(parser);\r
+ if (myindex < 0)\r
+ return XML_ERROR_NO_MEMORY;\r
+ dtd->scaffold[myindex].type = XML_CTYPE_NAME;\r
+ dtd->scaffold[myindex].quant = quant;\r
+ el = getElementType(parser, enc, s, nxt);\r
+ if (!el)\r
+ return XML_ERROR_NO_MEMORY;\r
+ name = el->name;\r
+ dtd->scaffold[myindex].name = name;\r
+ nameLen = 0;\r
+ for (; name[nameLen++]; );\r
+ dtd->contentStringLen += nameLen;\r
+ if (elementDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ }\r
+ break;\r
+\r
+ case XML_ROLE_GROUP_CLOSE:\r
+ quant = XML_CQUANT_NONE;\r
+ goto closeGroup;\r
+ case XML_ROLE_GROUP_CLOSE_OPT:\r
+ quant = XML_CQUANT_OPT;\r
+ goto closeGroup;\r
+ case XML_ROLE_GROUP_CLOSE_REP:\r
+ quant = XML_CQUANT_REP;\r
+ goto closeGroup;\r
+ case XML_ROLE_GROUP_CLOSE_PLUS:\r
+ quant = XML_CQUANT_PLUS;\r
+ closeGroup:\r
+ if (dtd->in_eldecl) {\r
+ if (elementDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ dtd->scaffLevel--;\r
+ dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;\r
+ if (dtd->scaffLevel == 0) {\r
+ if (!handleDefault) {\r
+ XML_Content *model = build_model(parser);\r
+ if (!model)\r
+ return XML_ERROR_NO_MEMORY;\r
+ *eventEndPP = s;\r
+ elementDeclHandler(handlerArg, declElementType->name, model);\r
+ }\r
+ dtd->in_eldecl = XML_FALSE;\r
+ dtd->contentStringLen = 0;\r
+ }\r
+ }\r
+ break;\r
+ /* End element declaration stuff */\r
+\r
+ case XML_ROLE_PI:\r
+ if (!reportProcessingInstruction(parser, enc, s, next))\r
+ return XML_ERROR_NO_MEMORY;\r
+ handleDefault = XML_FALSE;\r
+ break;\r
+ case XML_ROLE_COMMENT:\r
+ if (!reportComment(parser, enc, s, next))\r
+ return XML_ERROR_NO_MEMORY;\r
+ handleDefault = XML_FALSE;\r
+ break;\r
+ case XML_ROLE_NONE:\r
+ switch (tok) {\r
+ case XML_TOK_BOM:\r
+ handleDefault = XML_FALSE;\r
+ break;\r
+ }\r
+ break;\r
+ case XML_ROLE_DOCTYPE_NONE:\r
+ if (startDoctypeDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ break;\r
+ case XML_ROLE_ENTITY_NONE:\r
+ if (dtd->keepProcessing && entityDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ break;\r
+ case XML_ROLE_NOTATION_NONE:\r
+ if (notationDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ break;\r
+ case XML_ROLE_ATTLIST_NONE:\r
+ if (dtd->keepProcessing && attlistDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ break;\r
+ case XML_ROLE_ELEMENT_NONE:\r
+ if (elementDeclHandler)\r
+ handleDefault = XML_FALSE;\r
+ break;\r
+ } /* end of big switch */\r
+\r
+ if (handleDefault && defaultHandler)\r
+ reportDefault(parser, enc, s, next);\r
+\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ *nextPtr = next;\r
+ return XML_ERROR_NONE;\r
+ case XML_FINISHED:\r
+ return XML_ERROR_ABORTED;\r
+ default:\r
+ s = next;\r
+ tok = XmlPrologTok(enc, s, end, &next);\r
+ }\r
+ }\r
+ /* not reached */\r
+}\r
+\r
+static enum XML_Error PTRCALL\r
+epilogProcessor(XML_Parser parser,\r
+ const char *s,\r
+ const char *end,\r
+ const char **nextPtr)\r
+{\r
+ processor = epilogProcessor;\r
+ eventPtr = s;\r
+ for (;;) {\r
+ const char *next = NULL;\r
+ int tok = XmlPrologTok(encoding, s, end, &next);\r
+ eventEndPtr = next;\r
+ switch (tok) {\r
+ /* report partial linebreak - it might be the last token */\r
+ case -XML_TOK_PROLOG_S:\r
+ if (defaultHandler) {\r
+ reportDefault(parser, encoding, s, next);\r
+ if (ps_parsing == XML_FINISHED)\r
+ return XML_ERROR_ABORTED;\r
+ }\r
+ *nextPtr = next;\r
+ return XML_ERROR_NONE;\r
+ case XML_TOK_NONE:\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ case XML_TOK_PROLOG_S:\r
+ if (defaultHandler)\r
+ reportDefault(parser, encoding, s, next);\r
+ break;\r
+ case XML_TOK_PI:\r
+ if (!reportProcessingInstruction(parser, encoding, s, next))\r
+ return XML_ERROR_NO_MEMORY;\r
+ break;\r
+ case XML_TOK_COMMENT:\r
+ if (!reportComment(parser, encoding, s, next))\r
+ return XML_ERROR_NO_MEMORY;\r
+ break;\r
+ case XML_TOK_INVALID:\r
+ eventPtr = next;\r
+ return XML_ERROR_INVALID_TOKEN;\r
+ case XML_TOK_PARTIAL:\r
+ if (!ps_finalBuffer) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ return XML_ERROR_UNCLOSED_TOKEN;\r
+ case XML_TOK_PARTIAL_CHAR:\r
+ if (!ps_finalBuffer) {\r
+ *nextPtr = s;\r
+ return XML_ERROR_NONE;\r
+ }\r
+ return XML_ERROR_PARTIAL_CHAR;\r
+ default:\r
+ return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;\r
+ }\r
+ eventPtr = s = next;\r
+ switch (ps_parsing) {\r
+ case XML_SUSPENDED:\r
+ *nextPtr = next;\r
+ return XML_ERROR_NONE;\r
+ case XML_FINISHED:\r
+ return XML_ERROR_ABORTED;\r
+ default: ;\r
+ }\r
+ }\r
+}\r
+\r
+static enum XML_Error\r
+processInternalEntity(XML_Parser parser, ENTITY *entity,\r
+ XML_Bool betweenDecl)\r
+{\r
+ const char *textStart, *textEnd;\r
+ const char *next;\r
+ enum XML_Error result;\r
+ OPEN_INTERNAL_ENTITY *openEntity;\r
+\r
+ if (freeInternalEntities) {\r
+ openEntity = freeInternalEntities;\r
+ freeInternalEntities = openEntity->next;\r
+ }\r
+ else {\r
+ openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));\r
+ if (!openEntity)\r
+ return XML_ERROR_NO_MEMORY;\r
+ }\r
+ entity->open = XML_TRUE;\r
+ entity->processed = 0;\r
+ openEntity->next = openInternalEntities;\r
+ openInternalEntities = openEntity;\r
+ openEntity->entity = entity;\r
+ openEntity->startTagLevel = tagLevel;\r
+ openEntity->betweenDecl = betweenDecl;\r
+ openEntity->internalEventPtr = NULL;\r
+ openEntity->internalEventEndPtr = NULL;\r
+ textStart = (char *)entity->textPtr;\r
+ textEnd = (char *)(entity->textPtr + entity->textLen);\r
+\r
+#ifdef XML_DTD\r
+ if (entity->is_param) {\r
+ int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);\r
+ result = doProlog(parser, internalEncoding, textStart, textEnd, tok,\r
+ next, &next, XML_FALSE);\r
+ }\r
+ else\r
+#endif /* XML_DTD */\r
+ result = doContent(parser, tagLevel, internalEncoding, textStart,\r
+ textEnd, &next, XML_FALSE);\r
+\r
+ if (result == XML_ERROR_NONE) {\r
+ if (textEnd != next && ps_parsing == XML_SUSPENDED) {\r
+ entity->processed = (int)(next - textStart);\r
+ processor = internalEntityProcessor;\r
+ }\r
+ else {\r
+ entity->open = XML_FALSE;\r
+ openInternalEntities = openEntity->next;\r
+ /* put openEntity back in list of free instances */\r
+ openEntity->next = freeInternalEntities;\r
+ freeInternalEntities = openEntity;\r
+ }\r
+ }\r
+ return result;\r
+}\r
+\r
+static enum XML_Error PTRCALL\r
+internalEntityProcessor(XML_Parser parser,\r
+ const char *s,\r
+ const char *end,\r
+ const char **nextPtr)\r
+{\r
+ ENTITY *entity;\r
+ const char *textStart, *textEnd;\r
+ const char *next;\r
+ enum XML_Error result;\r
+ OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;\r
+ if (!openEntity)\r
+ return XML_ERROR_UNEXPECTED_STATE;\r
+\r
+ entity = openEntity->entity;\r
+ textStart = ((char *)entity->textPtr) + entity->processed;\r
+ textEnd = (char *)(entity->textPtr + entity->textLen);\r
+\r
+#ifdef XML_DTD\r
+ if (entity->is_param) {\r
+ int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);\r
+ result = doProlog(parser, internalEncoding, textStart, textEnd, tok,\r
+ next, &next, XML_FALSE);\r
+ }\r
+ else\r
+#endif /* XML_DTD */\r
+ result = doContent(parser, openEntity->startTagLevel, internalEncoding,\r
+ textStart, textEnd, &next, XML_FALSE);\r
+\r
+ if (result != XML_ERROR_NONE)\r
+ return result;\r
+ else if (textEnd != next && ps_parsing == XML_SUSPENDED) {\r
+ entity->processed = (int)(next - (char *)entity->textPtr);\r
+ return result;\r
+ }\r
+ else {\r
+ entity->open = XML_FALSE;\r
+ openInternalEntities = openEntity->next;\r
+ /* put openEntity back in list of free instances */\r
+ openEntity->next = freeInternalEntities;\r
+ freeInternalEntities = openEntity;\r
+ }\r
+\r
+#ifdef XML_DTD\r
+ if (entity->is_param) {\r
+ int tok;\r
+ processor = prologProcessor;\r
+ tok = XmlPrologTok(encoding, s, end, &next);\r
+ return doProlog(parser, encoding, s, end, tok, next, nextPtr,\r
+ (XML_Bool)!ps_finalBuffer);\r
+ }\r
+ else\r
+#endif /* XML_DTD */\r
+ {\r
+ processor = contentProcessor;\r
+ /* see externalEntityContentProcessor vs contentProcessor */\r
+ return doContent(parser, parentParser ? 1 : 0, encoding, s, end,\r
+ nextPtr, (XML_Bool)!ps_finalBuffer);\r
+ }\r
+}\r
+\r
+static enum XML_Error PTRCALL\r
+errorProcessor(XML_Parser parser,\r
+ const char *s,\r
+ const char *end,\r
+ const char **nextPtr)\r
+{\r
+ return errorCode;\r
+}\r
+\r
+static enum XML_Error\r
+storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,\r
+ const char *ptr, const char *end,\r
+ STRING_POOL *pool)\r
+{\r
+ enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,\r
+ end, pool);\r
+ if (result)\r
+ return result;\r
+ if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)\r
+ poolChop(pool);\r
+ if (!poolAppendChar(pool, XML_T('\0')))\r
+ return XML_ERROR_NO_MEMORY;\r
+ return XML_ERROR_NONE;\r
+}\r
+\r
+static enum XML_Error\r
+appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,\r
+ const char *ptr, const char *end,\r
+ STRING_POOL *pool)\r
+{\r
+ DTD * const dtd = _dtd; /* save one level of indirection */\r
+ for (;;) {\r
+ const char *next;\r
+ int tok = XmlAttributeValueTok(enc, ptr, end, &next);\r
+ switch (tok) {\r
+ case XML_TOK_NONE:\r
+ return XML_ERROR_NONE;\r
+ case XML_TOK_INVALID:\r
+ if (enc == encoding)\r
+ eventPtr = next;\r
+ return XML_ERROR_INVALID_TOKEN;\r
+ case XML_TOK_PARTIAL:\r
+ if (enc == encoding)\r
+ eventPtr = ptr;\r
+ return XML_ERROR_INVALID_TOKEN;\r
+ case XML_TOK_CHAR_REF:\r
+ {\r
+ XML_Char buf[XML_ENCODE_MAX];\r
+ int i;\r
+ int n = XmlCharRefNumber(enc, ptr);\r
+ if (n < 0) {\r
+ if (enc == encoding)\r
+ eventPtr = ptr;\r
+ return XML_ERROR_BAD_CHAR_REF;\r
+ }\r
+ if (!isCdata\r
+ && n == 0x20 /* space */\r
+ && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))\r
+ break;\r
+ n = XmlEncode(n, (ICHAR *)buf);\r
+ if (!n) {\r
+ if (enc == encoding)\r
+ eventPtr = ptr;\r
+ return XML_ERROR_BAD_CHAR_REF;\r
+ }\r
+ for (i = 0; i < n; i++) {\r
+ if (!poolAppendChar(pool, buf[i]))\r
+ return XML_ERROR_NO_MEMORY;\r
+ }\r
+ }\r
+ break;\r
+ case XML_TOK_DATA_CHARS:\r
+ if (!poolAppend(pool, enc, ptr, next))\r
+ return XML_ERROR_NO_MEMORY;\r
+ break;\r
+ case XML_TOK_TRAILING_CR:\r
+ next = ptr + enc->minBytesPerChar;\r
+ /* fall through */\r
+ case XML_TOK_ATTRIBUTE_VALUE_S:\r
+ case XML_TOK_DATA_NEWLINE:\r
+ if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))\r
+ break;\r
+ if (!poolAppendChar(pool, 0x20))\r
+ return XML_ERROR_NO_MEMORY;\r
+ break;\r
+ case XML_TOK_ENTITY_REF:\r
+ {\r
+ const XML_Char *name;\r
+ ENTITY *entity;\r
+ char checkEntityDecl;\r
+ XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,\r
+ ptr + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (ch) {\r
+ if (!poolAppendChar(pool, ch))\r
+ return XML_ERROR_NO_MEMORY;\r
+ break;\r
+ }\r
+ name = poolStoreString(&temp2Pool, enc,\r
+ ptr + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (!name)\r
+ return XML_ERROR_NO_MEMORY;\r
+ entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);\r
+ poolDiscard(&temp2Pool);\r
+ /* First, determine if a check for an existing declaration is needed;\r
+ if yes, check that the entity exists, and that it is internal.\r
+ */\r
+ if (pool == &dtd->pool) /* are we called from prolog? */\r
+ checkEntityDecl =\r
+#ifdef XML_DTD\r
+ prologState.documentEntity &&\r
+#endif /* XML_DTD */\r
+ (dtd->standalone\r
+ ? !openInternalEntities\r
+ : !dtd->hasParamEntityRefs);\r
+ else /* if (pool == &tempPool): we are called from content */\r
+ checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;\r
+ if (checkEntityDecl) {\r
+ if (!entity)\r
+ return XML_ERROR_UNDEFINED_ENTITY;\r
+ else if (!entity->is_internal)\r
+ return XML_ERROR_ENTITY_DECLARED_IN_PE;\r
+ }\r
+ else if (!entity) {\r
+ /* Cannot report skipped entity here - see comments on\r
+ skippedEntityHandler.\r
+ if (skippedEntityHandler)\r
+ skippedEntityHandler(handlerArg, name, 0);\r
+ */\r
+ /* Cannot call the default handler because this would be\r
+ out of sync with the call to the startElementHandler.\r
+ if ((pool == &tempPool) && defaultHandler)\r
+ reportDefault(parser, enc, ptr, next);\r
+ */\r
+ break;\r
+ }\r
+ if (entity->open) {\r
+ if (enc == encoding)\r
+ eventPtr = ptr;\r
+ return XML_ERROR_RECURSIVE_ENTITY_REF;\r
+ }\r
+ if (entity->notation) {\r
+ if (enc == encoding)\r
+ eventPtr = ptr;\r
+ return XML_ERROR_BINARY_ENTITY_REF;\r
+ }\r
+ if (!entity->textPtr) {\r
+ if (enc == encoding)\r
+ eventPtr = ptr;\r
+ return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;\r
+ }\r
+ else {\r
+ enum XML_Error result;\r
+ const XML_Char *textEnd = entity->textPtr + entity->textLen;\r
+ entity->open = XML_TRUE;\r
+ result = appendAttributeValue(parser, internalEncoding, isCdata,\r
+ (char *)entity->textPtr,\r
+ (char *)textEnd, pool);\r
+ entity->open = XML_FALSE;\r
+ if (result)\r
+ return result;\r
+ }\r
+ }\r
+ break;\r
+ default:\r
+ if (enc == encoding)\r
+ eventPtr = ptr;\r
+ return XML_ERROR_UNEXPECTED_STATE;\r
+ }\r
+ ptr = next;\r
+ }\r
+ /* not reached */\r
+}\r
+\r
+static enum XML_Error\r
+storeEntityValue(XML_Parser parser,\r
+ const ENCODING *enc,\r
+ const char *entityTextPtr,\r
+ const char *entityTextEnd)\r
+{\r
+ DTD * const dtd = _dtd; /* save one level of indirection */\r
+ STRING_POOL *pool = &(dtd->entityValuePool);\r
+ enum XML_Error result = XML_ERROR_NONE;\r
+#ifdef XML_DTD\r
+ int oldInEntityValue = prologState.inEntityValue;\r
+ prologState.inEntityValue = 1;\r
+#endif /* XML_DTD */\r
+ /* never return Null for the value argument in EntityDeclHandler,\r
+ since this would indicate an external entity; therefore we\r
+ have to make sure that entityValuePool.start is not null */\r
+ if (!pool->blocks) {\r
+ if (!poolGrow(pool))\r
+ return XML_ERROR_NO_MEMORY;\r
+ }\r
+\r
+ for (;;) {\r
+ const char *next;\r
+ int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);\r
+ switch (tok) {\r
+ case XML_TOK_PARAM_ENTITY_REF:\r
+#ifdef XML_DTD\r
+ if (isParamEntity || enc != encoding) {\r
+ const XML_Char *name;\r
+ ENTITY *entity;\r
+ name = poolStoreString(&tempPool, enc,\r
+ entityTextPtr + enc->minBytesPerChar,\r
+ next - enc->minBytesPerChar);\r
+ if (!name) {\r
+ result = XML_ERROR_NO_MEMORY;\r
+ goto endEntityValue;\r
+ }\r
+ entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);\r
+ poolDiscard(&tempPool);\r
+ if (!entity) {\r
+ /* not a well-formedness error - see XML 1.0: WFC Entity Declared */\r
+ /* cannot report skipped entity here - see comments on\r
+ skippedEntityHandler\r
+ if (skippedEntityHandler)\r
+ skippedEntityHandler(handlerArg, name, 0);\r
+ */\r
+ dtd->keepProcessing = dtd->standalone;\r
+ goto endEntityValue;\r
+ }\r
+ if (entity->open) {\r
+ if (enc == encoding)\r
+ eventPtr = entityTextPtr;\r
+ result = XML_ERROR_RECURSIVE_ENTITY_REF;\r
+ goto endEntityValue;\r
+ }\r
+ if (entity->systemId) {\r
+ if (externalEntityRefHandler) {\r
+ dtd->paramEntityRead = XML_FALSE;\r
+ entity->open = XML_TRUE;\r
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,\r
+ 0,\r
+ entity->base,\r
+ entity->systemId,\r
+ entity->publicId)) {\r
+ entity->open = XML_FALSE;\r
+ result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;\r
+ goto endEntityValue;\r
+ }\r
+ entity->open = XML_FALSE;\r
+ if (!dtd->paramEntityRead)\r
+ dtd->keepProcessing = dtd->standalone;\r
+ }\r
+ else\r
+ dtd->keepProcessing = dtd->standalone;\r
+ }\r
+ else {\r
+ entity->open = XML_TRUE;\r
+ result = storeEntityValue(parser,\r
+ internalEncoding,\r
+ (char *)entity->textPtr,\r
+ (char *)(entity->textPtr\r
+ + entity->textLen));\r
+ entity->open = XML_FALSE;\r
+ if (result)\r
+ goto endEntityValue;\r
+ }\r
+ break;\r
+ }\r
+#endif /* XML_DTD */\r
+ /* In the internal subset, PE references are not legal\r
+ within markup declarations, e.g entity values in this case. */\r
+ eventPtr = entityTextPtr;\r
+ result = XML_ERROR_PARAM_ENTITY_REF;\r
+ goto endEntityValue;\r
+ case XML_TOK_NONE:\r
+ result = XML_ERROR_NONE;\r
+ goto endEntityValue;\r
+ case XML_TOK_ENTITY_REF:\r
+ case XML_TOK_DATA_CHARS:\r
+ if (!poolAppend(pool, enc, entityTextPtr, next)) {\r
+ result = XML_ERROR_NO_MEMORY;\r
+ goto endEntityValue;\r
+ }\r
+ break;\r
+ case XML_TOK_TRAILING_CR:\r
+ next = entityTextPtr + enc->minBytesPerChar;\r
+ /* fall through */\r
+ case XML_TOK_DATA_NEWLINE:\r
+ if (pool->end == pool->ptr && !poolGrow(pool)) {\r
+ result = XML_ERROR_NO_MEMORY;\r
+ goto endEntityValue;\r
+ }\r
+ *(pool->ptr)++ = 0xA;\r
+ break;\r
+ case XML_TOK_CHAR_REF:\r
+ {\r
+ XML_Char buf[XML_ENCODE_MAX];\r
+ int i;\r
+ int n = XmlCharRefNumber(enc, entityTextPtr);\r
+ if (n < 0) {\r
+ if (enc == encoding)\r
+ eventPtr = entityTextPtr;\r
+ result = XML_ERROR_BAD_CHAR_REF;\r
+ goto endEntityValue;\r
+ }\r
+ n = XmlEncode(n, (ICHAR *)buf);\r
+ if (!n) {\r
+ if (enc == encoding)\r
+ eventPtr = entityTextPtr;\r
+ result = XML_ERROR_BAD_CHAR_REF;\r
+ goto endEntityValue;\r
+ }\r
+ for (i = 0; i < n; i++) {\r
+ if (pool->end == pool->ptr && !poolGrow(pool)) {\r
+ result = XML_ERROR_NO_MEMORY;\r
+ goto endEntityValue;\r
+ }\r
+ *(pool->ptr)++ = buf[i];\r
+ }\r
+ }\r
+ break;\r
+ case XML_TOK_PARTIAL:\r
+ if (enc == encoding)\r
+ eventPtr = entityTextPtr;\r
+ result = XML_ERROR_INVALID_TOKEN;\r
+ goto endEntityValue;\r
+ case XML_TOK_INVALID:\r
+ if (enc == encoding)\r
+ eventPtr = next;\r
+ result = XML_ERROR_INVALID_TOKEN;\r
+ goto endEntityValue;\r
+ default:\r
+ if (enc == encoding)\r
+ eventPtr = entityTextPtr;\r
+ result = XML_ERROR_UNEXPECTED_STATE;\r
+ goto endEntityValue;\r
+ }\r
+ entityTextPtr = next;\r
+ }\r
+endEntityValue:\r
+#ifdef XML_DTD\r
+ prologState.inEntityValue = oldInEntityValue;\r
+#endif /* XML_DTD */\r
+ return result;\r
+}\r
+\r
+static void FASTCALL\r
+normalizeLines(XML_Char *s)\r
+{\r
+ XML_Char *p;\r
+ for (;; s++) {\r
+ if (*s == XML_T('\0'))\r
+ return;\r
+ if (*s == 0xD)\r
+ break;\r
+ }\r
+ p = s;\r
+ do {\r
+ if (*s == 0xD) {\r
+ *p++ = 0xA;\r
+ if (*++s == 0xA)\r
+ s++;\r
+ }\r
+ else\r
+ *p++ = *s++;\r
+ } while (*s);\r
+ *p = XML_T('\0');\r
+}\r
+\r
+static int\r
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,\r
+ const char *start, const char *end)\r
+{\r
+ const XML_Char *target;\r
+ XML_Char *data;\r
+ const char *tem;\r
+ if (!processingInstructionHandler) {\r
+ if (defaultHandler)\r
+ reportDefault(parser, enc, start, end);\r
+ return 1;\r
+ }\r
+ start += enc->minBytesPerChar * 2;\r
+ tem = start + XmlNameLength(enc, start);\r
+ target = poolStoreString(&tempPool, enc, start, tem);\r
+ if (!target)\r
+ return 0;\r
+ poolFinish(&tempPool);\r
+ data = poolStoreString(&tempPool, enc,\r
+ XmlSkipS(enc, tem),\r
+ end - enc->minBytesPerChar*2);\r
+ if (!data)\r
+ return 0;\r
+ normalizeLines(data);\r
+ processingInstructionHandler(handlerArg, target, data);\r
+ poolClear(&tempPool);\r
+ return 1;\r
+}\r
+\r
+static int\r
+reportComment(XML_Parser parser, const ENCODING *enc,\r
+ const char *start, const char *end)\r
+{\r
+ XML_Char *data;\r
+ if (!commentHandler) {\r
+ if (defaultHandler)\r
+ reportDefault(parser, enc, start, end);\r
+ return 1;\r
+ }\r
+ data = poolStoreString(&tempPool,\r
+ enc,\r
+ start + enc->minBytesPerChar * 4,\r
+ end - enc->minBytesPerChar * 3);\r
+ if (!data)\r
+ return 0;\r
+ normalizeLines(data);\r
+ commentHandler(handlerArg, data);\r
+ poolClear(&tempPool);\r
+ return 1;\r
+}\r
+\r
+static void\r
+reportDefault(XML_Parser parser, const ENCODING *enc,\r
+ const char *s, const char *end)\r
+{\r
+ if (MUST_CONVERT(enc, s)) {\r
+ const char **eventPP;\r
+ const char **eventEndPP;\r
+ if (enc == encoding) {\r
+ eventPP = &eventPtr;\r
+ eventEndPP = &eventEndPtr;\r
+ }\r
+ else {\r
+ eventPP = &(openInternalEntities->internalEventPtr);\r
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);\r
+ }\r
+ do {\r
+ ICHAR *dataPtr = (ICHAR *)dataBuf;\r
+ XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);\r
+ *eventEndPP = s;\r
+ defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));\r
+ *eventPP = s;\r
+ } while (s != end);\r
+ }\r
+ else\r
+ defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));\r
+}\r
+\r
+\r
+static int\r
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,\r
+ XML_Bool isId, const XML_Char *value, XML_Parser parser)\r
+{\r
+ DEFAULT_ATTRIBUTE *att;\r
+ if (value || isId) {\r
+ /* The handling of default attributes gets messed up if we have\r
+ a default which duplicates a non-default. */\r
+ int i;\r
+ for (i = 0; i < type->nDefaultAtts; i++)\r
+ if (attId == type->defaultAtts[i].id)\r
+ return 1;\r
+ if (isId && !type->idAtt && !attId->xmlns)\r
+ type->idAtt = attId;\r
+ }\r
+ if (type->nDefaultAtts == type->allocDefaultAtts) {\r
+ if (type->allocDefaultAtts == 0) {\r
+ type->allocDefaultAtts = 8;\r
+ type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts\r
+ * sizeof(DEFAULT_ATTRIBUTE));\r
+ if (!type->defaultAtts)\r
+ return 0;\r
+ }\r
+ else {\r
+ DEFAULT_ATTRIBUTE *temp;\r
+ int count = type->allocDefaultAtts * 2;\r
+ temp = (DEFAULT_ATTRIBUTE *)\r
+ REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));\r
+ if (temp == NULL)\r
+ return 0;\r
+ type->allocDefaultAtts = count;\r
+ type->defaultAtts = temp;\r
+ }\r
+ }\r
+ att = type->defaultAtts + type->nDefaultAtts;\r
+ att->id = attId;\r
+ att->value = value;\r
+ att->isCdata = isCdata;\r
+ if (!isCdata)\r
+ attId->maybeTokenized = XML_TRUE;\r
+ type->nDefaultAtts += 1;\r
+ return 1;\r
+}\r
+\r
+static int\r
+setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)\r
+{\r
+ DTD * const dtd = _dtd; /* save one level of indirection */\r
+ const XML_Char *name;\r
+ for (name = elementType->name; *name; name++) {\r
+ if (*name == XML_T(ASCII_COLON)) {\r
+ PREFIX *prefix;\r
+ const XML_Char *s;\r
+ for (s = elementType->name; s != name; s++) {\r
+ if (!poolAppendChar(&dtd->pool, *s))\r
+ return 0;\r
+ }\r
+ if (!poolAppendChar(&dtd->pool, XML_T('\0')))\r
+ return 0;\r
+ prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),\r
+ sizeof(PREFIX));\r
+ if (!prefix)\r
+ return 0;\r
+ if (prefix->name == poolStart(&dtd->pool))\r
+ poolFinish(&dtd->pool);\r
+ else\r
+ poolDiscard(&dtd->pool);\r
+ elementType->prefix = prefix;\r
+\r
+ }\r
+ }\r
+ return 1;\r
+}\r
+\r
+static ATTRIBUTE_ID *\r
+getAttributeId(XML_Parser parser, const ENCODING *enc,\r
+ const char *start, const char *end)\r
+{\r
+ DTD * const dtd = _dtd; /* save one level of indirection */\r
+ ATTRIBUTE_ID *id;\r
+ const XML_Char *name;\r
+ if (!poolAppendChar(&dtd->pool, XML_T('\0')))\r
+ return NULL;\r
+ name = poolStoreString(&dtd->pool, enc, start, end);\r
+ if (!name)\r
+ return NULL;\r
+ /* skip quotation mark - its storage will be re-used (like in name[-1]) */\r
+ ++name;\r
+ id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));\r
+ if (!id)\r
+ return NULL;\r
+ if (id->name != name)\r
+ poolDiscard(&dtd->pool);\r
+ else {\r
+ poolFinish(&dtd->pool);\r
+ if (!ns)\r
+ ;\r
+ else if (name[0] == XML_T(ASCII_x)\r
+ && name[1] == XML_T(ASCII_m)\r
+ && name[2] == XML_T(ASCII_l)\r
+ && name[3] == XML_T(ASCII_n)\r
+ && name[4] == XML_T(ASCII_s)\r
+ && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {\r
+ if (name[5] == XML_T('\0'))\r
+ id->prefix = &dtd->defaultPrefix;\r
+ else\r
+ id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));\r
+ id->xmlns = XML_TRUE;\r
+ }\r
+ else {\r
+ int i;\r
+ for (i = 0; name[i]; i++) {\r
+ /* attributes without prefix are *not* in the default namespace */\r
+ if (name[i] == XML_T(ASCII_COLON)) {\r
+ int j;\r
+ for (j = 0; j < i; j++) {\r
+ if (!poolAppendChar(&dtd->pool, name[j]))\r
+ return NULL;\r
+ }\r
+ if (!poolAppendChar(&dtd->pool, XML_T('\0')))\r
+ return NULL;\r
+ id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),\r
+ sizeof(PREFIX));\r
+ if (id->prefix->name == poolStart(&dtd->pool))\r
+ poolFinish(&dtd->pool);\r
+ else\r
+ poolDiscard(&dtd->pool);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return id;\r
+}\r
+\r
+#define CONTEXT_SEP XML_T(ASCII_FF)\r
+\r
+static const XML_Char *\r
+getContext(XML_Parser parser)\r
+{\r
+ DTD * const dtd = _dtd; /* save one level of indirection */\r
+ HASH_TABLE_ITER iter;\r
+ XML_Bool needSep = XML_FALSE;\r
+\r
+ if (dtd->defaultPrefix.binding) {\r
+ int i;\r
+ int len;\r
+ if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))\r
+ return NULL;\r
+ len = dtd->defaultPrefix.binding->uriLen;\r
+ if (namespaceSeparator)\r
+ len--;\r
+ for (i = 0; i < len; i++)\r
+ if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))\r
+ return NULL;\r
+ needSep = XML_TRUE;\r
+ }\r
+\r
+ hashTableIterInit(&iter, &(dtd->prefixes));\r
+ for (;;) {\r
+ int i;\r
+ int len;\r
+ const XML_Char *s;\r
+ PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);\r
+ if (!prefix)\r
+ break;\r
+ if (!prefix->binding)\r
+ continue;\r
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))\r
+ return NULL;\r
+ for (s = prefix->name; *s; s++)\r
+ if (!poolAppendChar(&tempPool, *s))\r
+ return NULL;\r
+ if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))\r
+ return NULL;\r
+ len = prefix->binding->uriLen;\r
+ if (namespaceSeparator)\r
+ len--;\r
+ for (i = 0; i < len; i++)\r
+ if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))\r
+ return NULL;\r
+ needSep = XML_TRUE;\r
+ }\r
+\r
+\r
+ hashTableIterInit(&iter, &(dtd->generalEntities));\r
+ for (;;) {\r
+ const XML_Char *s;\r
+ ENTITY *e = (ENTITY *)hashTableIterNext(&iter);\r
+ if (!e)\r
+ break;\r
+ if (!e->open)\r
+ continue;\r
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))\r
+ return NULL;\r
+ for (s = e->name; *s; s++)\r
+ if (!poolAppendChar(&tempPool, *s))\r
+ return 0;\r
+ needSep = XML_TRUE;\r
+ }\r
+\r
+ if (!poolAppendChar(&tempPool, XML_T('\0')))\r
+ return NULL;\r
+ return tempPool.start;\r
+}\r
+\r
+static XML_Bool\r
+setContext(XML_Parser parser, const XML_Char *context)\r
+{\r
+ DTD * const dtd = _dtd; /* save one level of indirection */\r
+ const XML_Char *s = context;\r
+\r
+ while (*context != XML_T('\0')) {\r
+ if (*s == CONTEXT_SEP || *s == XML_T('\0')) {\r
+ ENTITY *e;\r
+ if (!poolAppendChar(&tempPool, XML_T('\0')))\r
+ return XML_FALSE;\r
+ e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0);\r
+ if (e)\r
+ e->open = XML_TRUE;\r
+ if (*s != XML_T('\0'))\r
+ s++;\r
+ context = s;\r
+ poolDiscard(&tempPool);\r
+ }\r
+ else if (*s == XML_T(ASCII_EQUALS)) {\r
+ PREFIX *prefix;\r
+ if (poolLength(&tempPool) == 0)\r
+ prefix = &dtd->defaultPrefix;\r
+ else {\r
+ if (!poolAppendChar(&tempPool, XML_T('\0')))\r
+ return XML_FALSE;\r
+ prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool),\r
+ sizeof(PREFIX));\r
+ if (!prefix)\r
+ return XML_FALSE;\r
+ if (prefix->name == poolStart(&tempPool)) {\r
+ prefix->name = poolCopyString(&dtd->pool, prefix->name);\r
+ if (!prefix->name)\r
+ return XML_FALSE;\r
+ }\r
+ poolDiscard(&tempPool);\r
+ }\r
+ for (context = s + 1;\r
+ *context != CONTEXT_SEP && *context != XML_T('\0');\r
+ context++)\r
+ if (!poolAppendChar(&tempPool, *context))\r
+ return XML_FALSE;\r
+ if (!poolAppendChar(&tempPool, XML_T('\0')))\r
+ return XML_FALSE;\r
+ if (addBinding(parser, prefix, NULL, poolStart(&tempPool),\r
+ &inheritedBindings) != XML_ERROR_NONE)\r
+ return XML_FALSE;\r
+ poolDiscard(&tempPool);\r
+ if (*context != XML_T('\0'))\r
+ ++context;\r
+ s = context;\r
+ }\r
+ else {\r
+ if (!poolAppendChar(&tempPool, *s))\r
+ return XML_FALSE;\r
+ s++;\r
+ }\r
+ }\r
+ return XML_TRUE;\r
+}\r
+\r
+static void FASTCALL\r
+normalizePublicId(XML_Char *publicId)\r
+{\r
+ XML_Char *p = publicId;\r
+ XML_Char *s;\r
+ for (s = publicId; *s; s++) {\r
+ switch (*s) {\r
+ case 0x20:\r
+ case 0xD:\r
+ case 0xA:\r
+ if (p != publicId && p[-1] != 0x20)\r
+ *p++ = 0x20;\r
+ break;\r
+ default:\r
+ *p++ = *s;\r
+ }\r
+ }\r
+ if (p != publicId && p[-1] == 0x20)\r
+ --p;\r
+ *p = XML_T('\0');\r
+}\r
+\r
+static DTD *\r
+dtdCreate(const XML_Memory_Handling_Suite *ms)\r
+{\r
+ DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));\r
+ if (p == NULL)\r
+ return p;\r
+ poolInit(&(p->pool), ms);\r
+ poolInit(&(p->entityValuePool), ms);\r
+ hashTableInit(&(p->generalEntities), ms);\r
+ hashTableInit(&(p->elementTypes), ms);\r
+ hashTableInit(&(p->attributeIds), ms);\r
+ hashTableInit(&(p->prefixes), ms);\r
+#ifdef XML_DTD\r
+ p->paramEntityRead = XML_FALSE;\r
+ hashTableInit(&(p->paramEntities), ms);\r
+#endif /* XML_DTD */\r
+ p->defaultPrefix.name = NULL;\r
+ p->defaultPrefix.binding = NULL;\r
+\r
+ p->in_eldecl = XML_FALSE;\r
+ p->scaffIndex = NULL;\r
+ p->scaffold = NULL;\r
+ p->scaffLevel = 0;\r
+ p->scaffSize = 0;\r
+ p->scaffCount = 0;\r
+ p->contentStringLen = 0;\r
+\r
+ p->keepProcessing = XML_TRUE;\r
+ p->hasParamEntityRefs = XML_FALSE;\r
+ p->standalone = XML_FALSE;\r
+ return p;\r
+}\r
+\r
+static void\r
+dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)\r
+{\r
+ HASH_TABLE_ITER iter;\r
+ hashTableIterInit(&iter, &(p->elementTypes));\r
+ for (;;) {\r
+ ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);\r
+ if (!e)\r
+ break;\r
+ if (e->allocDefaultAtts != 0)\r
+ ms->free_fcn(e->defaultAtts);\r
+ }\r
+ hashTableClear(&(p->generalEntities));\r
+#ifdef XML_DTD\r
+ p->paramEntityRead = XML_FALSE;\r
+ hashTableClear(&(p->paramEntities));\r
+#endif /* XML_DTD */\r
+ hashTableClear(&(p->elementTypes));\r
+ hashTableClear(&(p->attributeIds));\r
+ hashTableClear(&(p->prefixes));\r
+ poolClear(&(p->pool));\r
+ poolClear(&(p->entityValuePool));\r
+ p->defaultPrefix.name = NULL;\r
+ p->defaultPrefix.binding = NULL;\r
+\r
+ p->in_eldecl = XML_FALSE;\r
+\r
+ ms->free_fcn(p->scaffIndex);\r
+ p->scaffIndex = NULL;\r
+ ms->free_fcn(p->scaffold);\r
+ p->scaffold = NULL;\r
+\r
+ p->scaffLevel = 0;\r
+ p->scaffSize = 0;\r
+ p->scaffCount = 0;\r
+ p->contentStringLen = 0;\r
+\r
+ p->keepProcessing = XML_TRUE;\r
+ p->hasParamEntityRefs = XML_FALSE;\r
+ p->standalone = XML_FALSE;\r
+}\r
+\r
+static void\r
+dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)\r
+{\r
+ HASH_TABLE_ITER iter;\r
+ hashTableIterInit(&iter, &(p->elementTypes));\r
+ for (;;) {\r
+ ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);\r
+ if (!e)\r
+ break;\r
+ if (e->allocDefaultAtts != 0)\r
+ ms->free_fcn(e->defaultAtts);\r
+ }\r
+ hashTableDestroy(&(p->generalEntities));\r
+#ifdef XML_DTD\r
+ hashTableDestroy(&(p->paramEntities));\r
+#endif /* XML_DTD */\r
+ hashTableDestroy(&(p->elementTypes));\r
+ hashTableDestroy(&(p->attributeIds));\r
+ hashTableDestroy(&(p->prefixes));\r
+ poolDestroy(&(p->pool));\r
+ poolDestroy(&(p->entityValuePool));\r
+ if (isDocEntity) {\r
+ ms->free_fcn(p->scaffIndex);\r
+ ms->free_fcn(p->scaffold);\r
+ }\r
+ ms->free_fcn(p);\r
+}\r
+\r
+/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.\r
+ The new DTD has already been initialized.\r
+*/\r
+static int\r
+dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)\r
+{\r
+ HASH_TABLE_ITER iter;\r
+\r
+ /* Copy the prefix table. */\r
+\r
+ hashTableIterInit(&iter, &(oldDtd->prefixes));\r
+ for (;;) {\r
+ const XML_Char *name;\r
+ const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);\r
+ if (!oldP)\r
+ break;\r
+ name = poolCopyString(&(newDtd->pool), oldP->name);\r
+ if (!name)\r
+ return 0;\r
+ if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))\r
+ return 0;\r
+ }\r
+\r
+ hashTableIterInit(&iter, &(oldDtd->attributeIds));\r
+\r
+ /* Copy the attribute id table. */\r
+\r
+ for (;;) {\r
+ ATTRIBUTE_ID *newA;\r
+ const XML_Char *name;\r
+ const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);\r
+\r
+ if (!oldA)\r
+ break;\r
+ /* Remember to allocate the scratch byte before the name. */\r
+ if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))\r
+ return 0;\r
+ name = poolCopyString(&(newDtd->pool), oldA->name);\r
+ if (!name)\r
+ return 0;\r
+ ++name;\r
+ newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,\r
+ sizeof(ATTRIBUTE_ID));\r
+ if (!newA)\r
+ return 0;\r
+ newA->maybeTokenized = oldA->maybeTokenized;\r
+ if (oldA->prefix) {\r
+ newA->xmlns = oldA->xmlns;\r
+ if (oldA->prefix == &oldDtd->defaultPrefix)\r
+ newA->prefix = &newDtd->defaultPrefix;\r
+ else\r
+ newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),\r
+ oldA->prefix->name, 0);\r
+ }\r
+ }\r
+\r
+ /* Copy the element type table. */\r
+\r
+ hashTableIterInit(&iter, &(oldDtd->elementTypes));\r
+\r
+ for (;;) {\r
+ int i;\r
+ ELEMENT_TYPE *newE;\r
+ const XML_Char *name;\r
+ const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);\r
+ if (!oldE)\r
+ break;\r
+ name = poolCopyString(&(newDtd->pool), oldE->name);\r
+ if (!name)\r
+ return 0;\r
+ newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,\r
+ sizeof(ELEMENT_TYPE));\r
+ if (!newE)\r
+ return 0;\r
+ if (oldE->nDefaultAtts) {\r
+ newE->defaultAtts = (DEFAULT_ATTRIBUTE *)\r
+ ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));\r
+ if (!newE->defaultAtts) {\r
+ ms->free_fcn(newE);\r
+ return 0;\r
+ }\r
+ }\r
+ if (oldE->idAtt)\r
+ newE->idAtt = (ATTRIBUTE_ID *)\r
+ lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);\r
+ newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;\r
+ if (oldE->prefix)\r
+ newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),\r
+ oldE->prefix->name, 0);\r
+ for (i = 0; i < newE->nDefaultAtts; i++) {\r
+ newE->defaultAtts[i].id = (ATTRIBUTE_ID *)\r
+ lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);\r
+ newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;\r
+ if (oldE->defaultAtts[i].value) {\r
+ newE->defaultAtts[i].value\r
+ = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);\r
+ if (!newE->defaultAtts[i].value)\r
+ return 0;\r
+ }\r
+ else\r
+ newE->defaultAtts[i].value = NULL;\r
+ }\r
+ }\r
+\r
+ /* Copy the entity tables. */\r
+ if (!copyEntityTable(oldParser,\r
+ &(newDtd->generalEntities),\r
+ &(newDtd->pool),\r
+ &(oldDtd->generalEntities)))\r
+ return 0;\r
+\r
+#ifdef XML_DTD\r
+ if (!copyEntityTable(oldParser,\r
+ &(newDtd->paramEntities),\r
+ &(newDtd->pool),\r
+ &(oldDtd->paramEntities)))\r
+ return 0;\r
+ newDtd->paramEntityRead = oldDtd->paramEntityRead;\r
+#endif /* XML_DTD */\r
+\r
+ newDtd->keepProcessing = oldDtd->keepProcessing;\r
+ newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;\r
+ newDtd->standalone = oldDtd->standalone;\r
+\r
+ /* Don't want deep copying for scaffolding */\r
+ newDtd->in_eldecl = oldDtd->in_eldecl;\r
+ newDtd->scaffold = oldDtd->scaffold;\r
+ newDtd->contentStringLen = oldDtd->contentStringLen;\r
+ newDtd->scaffSize = oldDtd->scaffSize;\r
+ newDtd->scaffLevel = oldDtd->scaffLevel;\r
+ newDtd->scaffIndex = oldDtd->scaffIndex;\r
+\r
+ return 1;\r
+} /* End dtdCopy */\r
+\r
+static int\r
+copyEntityTable(XML_Parser oldParser,\r
+ HASH_TABLE *newTable,\r
+ STRING_POOL *newPool,\r
+ const HASH_TABLE *oldTable)\r
+{\r
+ HASH_TABLE_ITER iter;\r
+ const XML_Char *cachedOldBase = NULL;\r
+ const XML_Char *cachedNewBase = NULL;\r
+\r
+ hashTableIterInit(&iter, oldTable);\r
+\r
+ for (;;) {\r
+ ENTITY *newE;\r
+ const XML_Char *name;\r
+ const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);\r
+ if (!oldE)\r
+ break;\r
+ name = poolCopyString(newPool, oldE->name);\r
+ if (!name)\r
+ return 0;\r
+ newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));\r
+ if (!newE)\r
+ return 0;\r
+ if (oldE->systemId) {\r
+ const XML_Char *tem = poolCopyString(newPool, oldE->systemId);\r
+ if (!tem)\r
+ return 0;\r
+ newE->systemId = tem;\r
+ if (oldE->base) {\r
+ if (oldE->base == cachedOldBase)\r
+ newE->base = cachedNewBase;\r
+ else {\r
+ cachedOldBase = oldE->base;\r
+ tem = poolCopyString(newPool, cachedOldBase);\r
+ if (!tem)\r
+ return 0;\r
+ cachedNewBase = newE->base = tem;\r
+ }\r
+ }\r
+ if (oldE->publicId) {\r
+ tem = poolCopyString(newPool, oldE->publicId);\r
+ if (!tem)\r
+ return 0;\r
+ newE->publicId = tem;\r
+ }\r
+ }\r
+ else {\r
+ const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,\r
+ oldE->textLen);\r
+ if (!tem)\r
+ return 0;\r
+ newE->textPtr = tem;\r
+ newE->textLen = oldE->textLen;\r
+ }\r
+ if (oldE->notation) {\r
+ const XML_Char *tem = poolCopyString(newPool, oldE->notation);\r
+ if (!tem)\r
+ return 0;\r
+ newE->notation = tem;\r
+ }\r
+ newE->is_param = oldE->is_param;\r
+ newE->is_internal = oldE->is_internal;\r
+ }\r
+ return 1;\r
+}\r
+\r
+#define INIT_POWER 6\r
+\r
+static XML_Bool FASTCALL\r
+keyeq(KEY s1, KEY s2)\r
+{\r
+ for (; *s1 == *s2; s1++, s2++)\r
+ if (*s1 == 0)\r
+ return XML_TRUE;\r
+ return XML_FALSE;\r
+}\r
+\r
+static unsigned long FASTCALL\r
+hash(XML_Parser parser, KEY s)\r
+{\r
+ unsigned long h = hash_secret_salt;\r
+ while (*s)\r
+ h = CHAR_HASH(h, *s++);\r
+ return h;\r
+}\r
+\r
+static NAMED *\r
+lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)\r
+{\r
+ size_t i;\r
+ if (table->size == 0) {\r
+ size_t tsize;\r
+ if (!createSize)\r
+ return NULL;\r
+ table->power = INIT_POWER;\r
+ /* table->size is a power of 2 */\r
+ table->size = (size_t)1 << INIT_POWER;\r
+ tsize = table->size * sizeof(NAMED *);\r
+ table->v = (NAMED **)table->mem->malloc_fcn(tsize);\r
+ if (!table->v) {\r
+ table->size = 0;\r
+ return NULL;\r
+ }\r
+ memset(table->v, 0, tsize);\r
+ i = hash(parser, name) & ((unsigned long)table->size - 1);\r
+ }\r
+ else {\r
+ unsigned long h = hash(parser, name);\r
+ unsigned long mask = (unsigned long)table->size - 1;\r
+ unsigned char step = 0;\r
+ i = h & mask;\r
+ while (table->v[i]) {\r
+ if (keyeq(name, table->v[i]->name))\r
+ return table->v[i];\r
+ if (!step)\r
+ step = PROBE_STEP(h, mask, table->power);\r
+ i < step ? (i += table->size - step) : (i -= step);\r
+ }\r
+ if (!createSize)\r
+ return NULL;\r
+\r
+ /* check for overflow (table is half full) */\r
+ if (table->used >> (table->power - 1)) {\r
+ unsigned char newPower = table->power + 1;\r
+ size_t newSize = (size_t)1 << newPower;\r
+ unsigned long newMask = (unsigned long)newSize - 1;\r
+ size_t tsize = newSize * sizeof(NAMED *);\r
+ NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);\r
+ if (!newV)\r
+ return NULL;\r
+ memset(newV, 0, tsize);\r
+ for (i = 0; i < table->size; i++)\r
+ if (table->v[i]) {\r
+ unsigned long newHash = hash(parser, table->v[i]->name);\r
+ size_t j = newHash & newMask;\r
+ step = 0;\r
+ while (newV[j]) {\r
+ if (!step)\r
+ step = PROBE_STEP(newHash, newMask, newPower);\r
+ j < step ? (j += newSize - step) : (j -= step);\r
+ }\r
+ newV[j] = table->v[i];\r
+ }\r
+ table->mem->free_fcn(table->v);\r
+ table->v = newV;\r
+ table->power = newPower;\r
+ table->size = newSize;\r
+ i = h & newMask;\r
+ step = 0;\r
+ while (table->v[i]) {\r
+ if (!step)\r
+ step = PROBE_STEP(h, newMask, newPower);\r
+ i < step ? (i += newSize - step) : (i -= step);\r
+ }\r
+ }\r
+ }\r
+ table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);\r
+ if (!table->v[i])\r
+ return NULL;\r
+ memset(table->v[i], 0, createSize);\r
+ table->v[i]->name = name;\r
+ (table->used)++;\r
+ return table->v[i];\r
+}\r
+\r
+static void FASTCALL\r
+hashTableClear(HASH_TABLE *table)\r
+{\r
+ size_t i;\r
+ for (i = 0; i < table->size; i++) {\r
+ table->mem->free_fcn(table->v[i]);\r
+ table->v[i] = NULL;\r
+ }\r
+ table->used = 0;\r
+}\r
+\r
+static void FASTCALL\r
+hashTableDestroy(HASH_TABLE *table)\r
+{\r
+ size_t i;\r
+ for (i = 0; i < table->size; i++)\r
+ table->mem->free_fcn(table->v[i]);\r
+ table->mem->free_fcn(table->v);\r
+}\r
+\r
+static void FASTCALL\r
+hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)\r
+{\r
+ p->power = 0;\r
+ p->size = 0;\r
+ p->used = 0;\r
+ p->v = NULL;\r
+ p->mem = ms;\r
+}\r
+\r
+static void FASTCALL\r
+hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)\r
+{\r
+ iter->p = table->v;\r
+ iter->end = iter->p + table->size;\r
+}\r
+\r
+static NAMED * FASTCALL\r
+hashTableIterNext(HASH_TABLE_ITER *iter)\r
+{\r
+ while (iter->p != iter->end) {\r
+ NAMED *tem = *(iter->p)++;\r
+ if (tem)\r
+ return tem;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+static void FASTCALL\r
+poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)\r
+{\r
+ pool->blocks = NULL;\r
+ pool->freeBlocks = NULL;\r
+ pool->start = NULL;\r
+ pool->ptr = NULL;\r
+ pool->end = NULL;\r
+ pool->mem = ms;\r
+}\r
+\r
+static void FASTCALL\r
+poolClear(STRING_POOL *pool)\r
+{\r
+ if (!pool->freeBlocks)\r
+ pool->freeBlocks = pool->blocks;\r
+ else {\r
+ BLOCK *p = pool->blocks;\r
+ while (p) {\r
+ BLOCK *tem = p->next;\r
+ p->next = pool->freeBlocks;\r
+ pool->freeBlocks = p;\r
+ p = tem;\r
+ }\r
+ }\r
+ pool->blocks = NULL;\r
+ pool->start = NULL;\r
+ pool->ptr = NULL;\r
+ pool->end = NULL;\r
+}\r
+\r
+static void FASTCALL\r
+poolDestroy(STRING_POOL *pool)\r
+{\r
+ BLOCK *p = pool->blocks;\r
+ while (p) {\r
+ BLOCK *tem = p->next;\r
+ pool->mem->free_fcn(p);\r
+ p = tem;\r
+ }\r
+ p = pool->freeBlocks;\r
+ while (p) {\r
+ BLOCK *tem = p->next;\r
+ pool->mem->free_fcn(p);\r
+ p = tem;\r
+ }\r
+}\r
+\r
+static XML_Char *\r
+poolAppend(STRING_POOL *pool, const ENCODING *enc,\r
+ const char *ptr, const char *end)\r
+{\r
+ if (!pool->ptr && !poolGrow(pool))\r
+ return NULL;\r
+ for (;;) {\r
+ XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);\r
+ if (ptr == end)\r
+ break;\r
+ if (!poolGrow(pool))\r
+ return NULL;\r
+ }\r
+ return pool->start;\r
+}\r
+\r
+static const XML_Char * FASTCALL\r
+poolCopyString(STRING_POOL *pool, const XML_Char *s)\r
+{\r
+ do {\r
+ if (!poolAppendChar(pool, *s))\r
+ return NULL;\r
+ } while (*s++);\r
+ s = pool->start;\r
+ poolFinish(pool);\r
+ return s;\r
+}\r
+\r
+static const XML_Char *\r
+poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)\r
+{\r
+ if (!pool->ptr && !poolGrow(pool))\r
+ return NULL;\r
+ for (; n > 0; --n, s++) {\r
+ if (!poolAppendChar(pool, *s))\r
+ return NULL;\r
+ }\r
+ s = pool->start;\r
+ poolFinish(pool);\r
+ return s;\r
+}\r
+\r
+static const XML_Char * FASTCALL\r
+poolAppendString(STRING_POOL *pool, const XML_Char *s)\r
+{\r
+ while (*s) {\r
+ if (!poolAppendChar(pool, *s))\r
+ return NULL;\r
+ s++;\r
+ }\r
+ return pool->start;\r
+}\r
+\r
+static XML_Char *\r
+poolStoreString(STRING_POOL *pool, const ENCODING *enc,\r
+ const char *ptr, const char *end)\r
+{\r
+ if (!poolAppend(pool, enc, ptr, end))\r
+ return NULL;\r
+ if (pool->ptr == pool->end && !poolGrow(pool))\r
+ return NULL;\r
+ *(pool->ptr)++ = 0;\r
+ return pool->start;\r
+}\r
+\r
+static XML_Bool FASTCALL\r
+poolGrow(STRING_POOL *pool)\r
+{\r
+ if (pool->freeBlocks) {\r
+ if (pool->start == 0) {\r
+ pool->blocks = pool->freeBlocks;\r
+ pool->freeBlocks = pool->freeBlocks->next;\r
+ pool->blocks->next = NULL;\r
+ pool->start = pool->blocks->s;\r
+ pool->end = pool->start + pool->blocks->size;\r
+ pool->ptr = pool->start;\r
+ return XML_TRUE;\r
+ }\r
+ if (pool->end - pool->start < pool->freeBlocks->size) {\r
+ BLOCK *tem = pool->freeBlocks->next;\r
+ pool->freeBlocks->next = pool->blocks;\r
+ pool->blocks = pool->freeBlocks;\r
+ pool->freeBlocks = tem;\r
+ memcpy(pool->blocks->s, pool->start,\r
+ (pool->end - pool->start) * sizeof(XML_Char));\r
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);\r
+ pool->start = pool->blocks->s;\r
+ pool->end = pool->start + pool->blocks->size;\r
+ return XML_TRUE;\r
+ }\r
+ }\r
+ if (pool->blocks && pool->start == pool->blocks->s) {\r
+ int blockSize = (int)(pool->end - pool->start)*2;\r
+ BLOCK *temp = (BLOCK *)\r
+ pool->mem->realloc_fcn(pool->blocks,\r
+ (offsetof(BLOCK, s)\r
+ + blockSize * sizeof(XML_Char)));\r
+ if (temp == NULL)\r
+ return XML_FALSE;\r
+ pool->blocks = temp;\r
+ pool->blocks->size = blockSize;\r
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);\r
+ pool->start = pool->blocks->s;\r
+ pool->end = pool->start + blockSize;\r
+ }\r
+ else {\r
+ BLOCK *tem;\r
+ int blockSize = (int)(pool->end - pool->start);\r
+ if (blockSize < INIT_BLOCK_SIZE)\r
+ blockSize = INIT_BLOCK_SIZE;\r
+ else\r
+ blockSize *= 2;\r
+ tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)\r
+ + blockSize * sizeof(XML_Char));\r
+ if (!tem)\r
+ return XML_FALSE;\r
+ tem->size = blockSize;\r
+ tem->next = pool->blocks;\r
+ pool->blocks = tem;\r
+ if (pool->ptr != pool->start)\r
+ memcpy(tem->s, pool->start,\r
+ (pool->ptr - pool->start) * sizeof(XML_Char));\r
+ pool->ptr = tem->s + (pool->ptr - pool->start);\r
+ pool->start = tem->s;\r
+ pool->end = tem->s + blockSize;\r
+ }\r
+ return XML_TRUE;\r
+}\r
+\r
+static int FASTCALL\r
+nextScaffoldPart(XML_Parser parser)\r
+{\r
+ DTD * const dtd = _dtd; /* save one level of indirection */\r
+ CONTENT_SCAFFOLD * me;\r
+ int next;\r
+\r
+ if (!dtd->scaffIndex) {\r
+ dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));\r
+ if (!dtd->scaffIndex)\r
+ return -1;\r
+ dtd->scaffIndex[0] = 0;\r
+ }\r
+\r
+ if (dtd->scaffCount >= dtd->scaffSize) {\r
+ CONTENT_SCAFFOLD *temp;\r
+ if (dtd->scaffold) {\r
+ temp = (CONTENT_SCAFFOLD *)\r
+ REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));\r
+ if (temp == NULL)\r
+ return -1;\r
+ dtd->scaffSize *= 2;\r
+ }\r
+ else {\r
+ temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS\r
+ * sizeof(CONTENT_SCAFFOLD));\r
+ if (temp == NULL)\r
+ return -1;\r
+ dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;\r
+ }\r
+ dtd->scaffold = temp;\r
+ }\r
+ next = dtd->scaffCount++;\r
+ me = &dtd->scaffold[next];\r
+ if (dtd->scaffLevel) {\r
+ CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];\r
+ if (parent->lastchild) {\r
+ dtd->scaffold[parent->lastchild].nextsib = next;\r
+ }\r
+ if (!parent->childcnt)\r
+ parent->firstchild = next;\r
+ parent->lastchild = next;\r
+ parent->childcnt++;\r
+ }\r
+ me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;\r
+ return next;\r
+}\r
+\r
+static void\r
+build_node(XML_Parser parser,\r
+ int src_node,\r
+ XML_Content *dest,\r
+ XML_Content **contpos,\r
+ XML_Char **strpos)\r
+{\r
+ DTD * const dtd = _dtd; /* save one level of indirection */\r
+ dest->type = dtd->scaffold[src_node].type;\r
+ dest->quant = dtd->scaffold[src_node].quant;\r
+ if (dest->type == XML_CTYPE_NAME) {\r
+ const XML_Char *src;\r
+ dest->name = *strpos;\r
+ src = dtd->scaffold[src_node].name;\r
+ for (;;) {\r
+ *(*strpos)++ = *src;\r
+ if (!*src)\r
+ break;\r
+ src++;\r
+ }\r
+ dest->numchildren = 0;\r
+ dest->children = NULL;\r
+ }\r
+ else {\r
+ unsigned int i;\r
+ int cn;\r
+ dest->numchildren = dtd->scaffold[src_node].childcnt;\r
+ dest->children = *contpos;\r
+ *contpos += dest->numchildren;\r
+ for (i = 0, cn = dtd->scaffold[src_node].firstchild;\r
+ i < dest->numchildren;\r
+ i++, cn = dtd->scaffold[cn].nextsib) {\r
+ build_node(parser, cn, &(dest->children[i]), contpos, strpos);\r
+ }\r
+ dest->name = NULL;\r
+ }\r
+}\r
+\r
+static XML_Content *\r
+build_model (XML_Parser parser)\r
+{\r
+ DTD * const dtd = _dtd; /* save one level of indirection */\r
+ XML_Content *ret;\r
+ XML_Content *cpos;\r
+ XML_Char * str;\r
+ int allocsize = (dtd->scaffCount * sizeof(XML_Content)\r
+ + (dtd->contentStringLen * sizeof(XML_Char)));\r
+\r
+ ret = (XML_Content *)MALLOC(allocsize);\r
+ if (!ret)\r
+ return NULL;\r
+\r
+ str = (XML_Char *) (&ret[dtd->scaffCount]);\r
+ cpos = &ret[1];\r
+\r
+ build_node(parser, 0, ret, &cpos, &str);\r
+ return ret;\r
+}\r
+\r
+static ELEMENT_TYPE *\r
+getElementType(XML_Parser parser,\r
+ const ENCODING *enc,\r
+ const char *ptr,\r
+ const char *end)\r
+{\r
+ DTD * const dtd = _dtd; /* save one level of indirection */\r
+ const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);\r
+ ELEMENT_TYPE *ret;\r
+\r
+ if (!name)\r
+ return NULL;\r
+ ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));\r
+ if (!ret)\r
+ return NULL;\r
+ if (ret->name != name)\r
+ poolDiscard(&dtd->pool);\r
+ else {\r
+ poolFinish(&dtd->pool);\r
+ if (!setElementTypePrefix(parser, ret))\r
+ return NULL;\r
+ }\r
+ return ret;\r
+}\r