This source file includes following definitions.
- XML_ParserCreate
- XML_ParserCreateNS
- generate_hash_secret_salt
- startParsing
- XML_ParserCreate_MM
- parserCreate
- parserInit
- moveToFreeBindingList
- XML_ParserReset
- XML_SetEncoding
- XML_ExternalEntityParserCreate
- destroyBindings
- XML_ParserFree
- XML_UseParserAsHandlerArg
- XML_UseForeignDTD
- XML_SetReturnNSTriplet
- XML_SetUserData
- XML_SetBase
- XML_GetBase
- XML_GetSpecifiedAttributeCount
- XML_GetIdAttributeIndex
- XML_GetAttributeInfo
- XML_SetElementHandler
- XML_SetStartElementHandler
- XML_SetEndElementHandler
- XML_SetCharacterDataHandler
- XML_SetProcessingInstructionHandler
- XML_SetCommentHandler
- XML_SetCdataSectionHandler
- XML_SetStartCdataSectionHandler
- XML_SetEndCdataSectionHandler
- XML_SetDefaultHandler
- XML_SetDefaultHandlerExpand
- XML_SetDoctypeDeclHandler
- XML_SetStartDoctypeDeclHandler
- XML_SetEndDoctypeDeclHandler
- XML_SetUnparsedEntityDeclHandler
- XML_SetNotationDeclHandler
- XML_SetNamespaceDeclHandler
- XML_SetStartNamespaceDeclHandler
- XML_SetEndNamespaceDeclHandler
- XML_SetNotStandaloneHandler
- XML_SetExternalEntityRefHandler
- XML_SetExternalEntityRefHandlerArg
- XML_SetSkippedEntityHandler
- XML_SetUnknownEncodingHandler
- XML_SetElementDeclHandler
- XML_SetAttlistDeclHandler
- XML_SetEntityDeclHandler
- XML_SetXmlDeclHandler
- XML_SetParamEntityParsing
- XML_SetHashSalt
- XML_Parse
- XML_ParseBuffer
- XML_GetBuffer
- XML_StopParser
- XML_ResumeParser
- XML_GetParsingStatus
- XML_GetErrorCode
- XML_GetCurrentByteIndex
- XML_GetCurrentByteCount
- XML_GetInputContext
- XML_GetCurrentLineNumber
- XML_GetCurrentColumnNumber
- XML_FreeContentModel
- XML_MemMalloc
- XML_MemRealloc
- XML_MemFree
- XML_DefaultCurrent
- XML_ErrorString
- XML_ExpatVersion
- XML_ExpatVersionInfo
- XML_GetFeatureList
- storeRawNames
- contentProcessor
- externalEntityInitProcessor
- externalEntityInitProcessor2
- externalEntityInitProcessor3
- externalEntityContentProcessor
- doContent
- storeAtts
- addBinding
- cdataSectionProcessor
- doCdataSection
- ignoreSectionProcessor
- doIgnoreSection
- initializeEncoding
- processXmlDecl
- handleUnknownEncoding
- prologInitProcessor
- externalParEntInitProcessor
- entityValueInitProcessor
- externalParEntProcessor
- entityValueProcessor
- prologProcessor
- doProlog
- epilogProcessor
- processInternalEntity
- internalEntityProcessor
- errorProcessor
- storeAttributeValue
- appendAttributeValue
- storeEntityValue
- normalizeLines
- reportProcessingInstruction
- reportComment
- reportDefault
- defineAttribute
- setElementTypePrefix
- getAttributeId
- getContext
- setContext
- normalizePublicId
- dtdCreate
- dtdReset
- dtdDestroy
- dtdCopy
- copyEntityTable
- keyeq
- hash
- lookup
- hashTableClear
- hashTableDestroy
- hashTableInit
- hashTableIterInit
- hashTableIterNext
- poolInit
- poolClear
- poolDestroy
- poolAppend
- poolCopyString
- poolCopyStringN
- poolAppendString
- poolStoreString
- poolGrow
- nextScaffoldPart
- build_node
- build_model
- getElementType
#include <stddef.h>
#include <string.h>
#include <assert.h>
#include <limits.h>
#include <time.h>
#define XML_BUILDING_EXPAT 1
#ifdef COMPILED_FROM_DSP
#include "winconfig.h"
#elif defined(MACOS_CLASSIC)
#include "macconfig.h"
#elif defined(__amigaos__)
#include "amigaconfig.h"
#elif defined(__WATCOMC__)
#include "watcomconfig.h"
#elif defined(HAVE_EXPAT_CONFIG_H)
#include <expat_config.h>
#endif
#include "ascii.h"
#include "expat.h"
#ifdef XML_UNICODE
#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
#define XmlConvert XmlUtf16Convert
#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
#define XmlEncode XmlUtf16Encode
#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
typedef unsigned short ICHAR;
#else
#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
#define XmlConvert XmlUtf8Convert
#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
#define XmlEncode XmlUtf8Encode
#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
typedef char ICHAR;
#endif
#ifndef XML_NS
#define XmlInitEncodingNS XmlInitEncoding
#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
#undef XmlGetInternalEncodingNS
#define XmlGetInternalEncodingNS XmlGetInternalEncoding
#define XmlParseXmlDeclNS XmlParseXmlDecl
#endif
#ifdef XML_UNICODE
#ifdef XML_UNICODE_WCHAR_T
#define XML_T(x) (const wchar_t)x
#define XML_L(x) L ## x
#else
#define XML_T(x) (const unsigned short)x
#define XML_L(x) x
#endif
#else
#define XML_T(x) x
#define XML_L(x) x
#endif
#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
#ifndef HAVE_MEMMOVE
#ifdef HAVE_BCOPY
#define memmove(d,s,l) bcopy((s),(d),(l))
#else
#error memmove does not exist on this platform, nor is a substitute available
#endif
#endif
#include "internal.h"
#include "xmltok.h"
#include "xmlrole.h"
typedef const XML_Char *KEY;
typedef struct {
KEY name;
} NAMED;
typedef struct {
NAMED **v;
unsigned char power;
size_t size;
size_t used;
const XML_Memory_Handling_Suite *mem;
} HASH_TABLE;
#ifdef XML_UNICODE
#define CHAR_HASH(h, c) \
(((h) * 0xF4243) ^ (unsigned short)(c))
#else
#define CHAR_HASH(h, c) \
(((h) * 0xF4243) ^ (unsigned char)(c))
#endif
#define SECOND_HASH(hash, mask, power) \
((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
#define PROBE_STEP(hash, mask, power) \
((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
typedef struct {
NAMED **p;
NAMED **end;
} HASH_TABLE_ITER;
#define INIT_TAG_BUF_SIZE 32
#define INIT_DATA_BUF_SIZE 1024
#define INIT_ATTS_SIZE 16
#define INIT_ATTS_VERSION 0xFFFFFFFF
#define INIT_BLOCK_SIZE 1024
#define INIT_BUFFER_SIZE 1024
#define EXPAND_SPARE 24
typedef struct binding {
struct prefix *prefix;
struct binding *nextTagBinding;
struct binding *prevPrefixBinding;
const struct attribute_id *attId;
XML_Char *uri;
int uriLen;
int uriAlloc;
} BINDING;
typedef struct prefix {
const XML_Char *name;
BINDING *binding;
} PREFIX;
typedef struct {
const XML_Char *str;
const XML_Char *localPart;
const XML_Char *prefix;
int strLen;
int uriLen;
int prefixLen;
} TAG_NAME;
typedef struct tag {
struct tag *parent;
const char *rawName;
int rawNameLength;
TAG_NAME name;
char *buf;
char *bufEnd;
BINDING *bindings;
} TAG;
typedef struct {
const XML_Char *name;
const XML_Char *textPtr;
int textLen;
int processed;
const XML_Char *systemId;
const XML_Char *base;
const XML_Char *publicId;
const XML_Char *notation;
XML_Bool open;
XML_Bool is_param;
XML_Bool is_internal;
} ENTITY;
typedef struct {
enum XML_Content_Type type;
enum XML_Content_Quant quant;
const XML_Char * name;
int firstchild;
int lastchild;
int childcnt;
int nextsib;
} CONTENT_SCAFFOLD;
#define INIT_SCAFFOLD_ELEMENTS 32
typedef struct block {
struct block *next;
int size;
XML_Char s[1];
} BLOCK;
typedef struct {
BLOCK *blocks;
BLOCK *freeBlocks;
const XML_Char *end;
XML_Char *ptr;
XML_Char *start;
const XML_Memory_Handling_Suite *mem;
} STRING_POOL;
typedef struct attribute_id {
XML_Char *name;
PREFIX *prefix;
XML_Bool maybeTokenized;
XML_Bool xmlns;
} ATTRIBUTE_ID;
typedef struct {
const ATTRIBUTE_ID *id;
XML_Bool isCdata;
const XML_Char *value;
} DEFAULT_ATTRIBUTE;
typedef struct {
unsigned long version;
unsigned long hash;
const XML_Char *uriName;
} NS_ATT;
typedef struct {
const XML_Char *name;
PREFIX *prefix;
const ATTRIBUTE_ID *idAtt;
int nDefaultAtts;
int allocDefaultAtts;
DEFAULT_ATTRIBUTE *defaultAtts;
} ELEMENT_TYPE;
typedef struct {
HASH_TABLE generalEntities;
HASH_TABLE elementTypes;
HASH_TABLE attributeIds;
HASH_TABLE prefixes;
STRING_POOL pool;
STRING_POOL entityValuePool;
XML_Bool keepProcessing;
XML_Bool hasParamEntityRefs;
XML_Bool standalone;
#ifdef XML_DTD
XML_Bool paramEntityRead;
HASH_TABLE paramEntities;
#endif
PREFIX defaultPrefix;
XML_Bool in_eldecl;
CONTENT_SCAFFOLD *scaffold;
unsigned contentStringLen;
unsigned scaffSize;
unsigned scaffCount;
int scaffLevel;
int *scaffIndex;
} DTD;
typedef struct open_internal_entity {
const char *internalEventPtr;
const char *internalEventEndPtr;
struct open_internal_entity *next;
ENTITY *entity;
int startTagLevel;
XML_Bool betweenDecl;
} OPEN_INTERNAL_ENTITY;
typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
const char *start,
const char *end,
const char **endPtr);
static Processor prologProcessor;
static Processor prologInitProcessor;
static Processor contentProcessor;
static Processor cdataSectionProcessor;
#ifdef XML_DTD
static Processor ignoreSectionProcessor;
static Processor externalParEntProcessor;
static Processor externalParEntInitProcessor;
static Processor entityValueProcessor;
static Processor entityValueInitProcessor;
#endif
static Processor epilogProcessor;
static Processor errorProcessor;
static Processor externalEntityInitProcessor;
static Processor externalEntityInitProcessor2;
static Processor externalEntityInitProcessor3;
static Processor externalEntityContentProcessor;
static Processor internalEntityProcessor;
static enum XML_Error
handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
static enum XML_Error
processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
const char *s, const char *next);
static enum XML_Error
initializeEncoding(XML_Parser parser);
static enum XML_Error
doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
const char *end, int tok, const char *next, const char **nextPtr,
XML_Bool haveMore);
static enum XML_Error
processInternalEntity(XML_Parser parser, ENTITY *entity,
XML_Bool betweenDecl);
static enum XML_Error
doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
const char *start, const char *end, const char **endPtr,
XML_Bool haveMore);
static enum XML_Error
doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
const char *end, const char **nextPtr, XML_Bool haveMore);
#ifdef XML_DTD
static enum XML_Error
doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
const char *end, const char **nextPtr, XML_Bool haveMore);
#endif
static enum XML_Error
storeAtts(XML_Parser parser, const ENCODING *, const char *s,
TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
static enum XML_Error
addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
const XML_Char *uri, BINDING **bindingsPtr);
static int
defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
static enum XML_Error
storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
const char *, const char *, STRING_POOL *);
static enum XML_Error
appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
const char *, const char *, STRING_POOL *);
static ATTRIBUTE_ID *
getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
const char *end);
static int
setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
static enum XML_Error
storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
const char *end);
static int
reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end);
static int
reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
const char *end);
static void
reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
const char *end);
static const XML_Char * getContext(XML_Parser parser);
static XML_Bool
setContext(XML_Parser parser, const XML_Char *context);
static void FASTCALL normalizePublicId(XML_Char *s);
static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
static void
dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
static int
dtdCopy(XML_Parser oldParser,
DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
static int
copyEntityTable(XML_Parser oldParser,
HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
static NAMED *
lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
static void FASTCALL
hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
static void FASTCALL hashTableClear(HASH_TABLE *);
static void FASTCALL hashTableDestroy(HASH_TABLE *);
static void FASTCALL
hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
static void FASTCALL
poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
static void FASTCALL poolClear(STRING_POOL *);
static void FASTCALL poolDestroy(STRING_POOL *);
static XML_Char *
poolAppend(STRING_POOL *pool, const ENCODING *enc,
const char *ptr, const char *end);
static XML_Char *
poolStoreString(STRING_POOL *pool, const ENCODING *enc,
const char *ptr, const char *end);
static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
static const XML_Char * FASTCALL
poolCopyString(STRING_POOL *pool, const XML_Char *s);
static const XML_Char *
poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
static const XML_Char * FASTCALL
poolAppendString(STRING_POOL *pool, const XML_Char *s);
static int FASTCALL nextScaffoldPart(XML_Parser parser);
static XML_Content * build_model(XML_Parser parser);
static ELEMENT_TYPE *
getElementType(XML_Parser parser, const ENCODING *enc,
const char *ptr, const char *end);
static unsigned long generate_hash_secret_salt(void);
static XML_Bool startParsing(XML_Parser parser);
static XML_Parser
parserCreate(const XML_Char *encodingName,
const XML_Memory_Handling_Suite *memsuite,
const XML_Char *nameSep,
DTD *dtd);
static void
parserInit(XML_Parser parser, const XML_Char *encodingName);
#define poolStart(pool) ((pool)->start)
#define poolEnd(pool) ((pool)->ptr)
#define poolLength(pool) ((pool)->ptr - (pool)->start)
#define poolChop(pool) ((void)--(pool->ptr))
#define poolLastChar(pool) (((pool)->ptr)[-1])
#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
#define poolFinish(pool) ((pool)->start = (pool)->ptr)
#define poolAppendChar(pool, c) \
(((pool)->ptr == (pool)->end && !poolGrow(pool)) \
? 0 \
: ((*((pool)->ptr)++ = c), 1))
struct XML_ParserStruct {
void *m_userData;
void *m_handlerArg;
char *m_buffer;
const XML_Memory_Handling_Suite m_mem;
const char *m_bufferPtr;
char *m_bufferEnd;
const char *m_bufferLim;
XML_Index m_parseEndByteIndex;
const char *m_parseEndPtr;
XML_Char *m_dataBuf;
XML_Char *m_dataBufEnd;
XML_StartElementHandler m_startElementHandler;
XML_EndElementHandler m_endElementHandler;
XML_CharacterDataHandler m_characterDataHandler;
XML_ProcessingInstructionHandler m_processingInstructionHandler;
XML_CommentHandler m_commentHandler;
XML_StartCdataSectionHandler m_startCdataSectionHandler;
XML_EndCdataSectionHandler m_endCdataSectionHandler;
XML_DefaultHandler m_defaultHandler;
XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
XML_NotationDeclHandler m_notationDeclHandler;
XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
XML_NotStandaloneHandler m_notStandaloneHandler;
XML_ExternalEntityRefHandler m_externalEntityRefHandler;
XML_Parser m_externalEntityRefHandlerArg;
XML_SkippedEntityHandler m_skippedEntityHandler;
XML_UnknownEncodingHandler m_unknownEncodingHandler;
XML_ElementDeclHandler m_elementDeclHandler;
XML_AttlistDeclHandler m_attlistDeclHandler;
XML_EntityDeclHandler m_entityDeclHandler;
XML_XmlDeclHandler m_xmlDeclHandler;
const ENCODING *m_encoding;
INIT_ENCODING m_initEncoding;
const ENCODING *m_internalEncoding;
const XML_Char *m_protocolEncodingName;
XML_Bool m_ns;
XML_Bool m_ns_triplets;
void *m_unknownEncodingMem;
void *m_unknownEncodingData;
void *m_unknownEncodingHandlerData;
void (XMLCALL *m_unknownEncodingRelease)(void *);
PROLOG_STATE m_prologState;
Processor *m_processor;
enum XML_Error m_errorCode;
const char *m_eventPtr;
const char *m_eventEndPtr;
const char *m_positionPtr;
OPEN_INTERNAL_ENTITY *m_openInternalEntities;
OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
XML_Bool m_defaultExpandInternalEntities;
int m_tagLevel;
ENTITY *m_declEntity;
const XML_Char *m_doctypeName;
const XML_Char *m_doctypeSysid;
const XML_Char *m_doctypePubid;
const XML_Char *m_declAttributeType;
const XML_Char *m_declNotationName;
const XML_Char *m_declNotationPublicId;
ELEMENT_TYPE *m_declElementType;
ATTRIBUTE_ID *m_declAttributeId;
XML_Bool m_declAttributeIsCdata;
XML_Bool m_declAttributeIsId;
DTD *m_dtd;
const XML_Char *m_curBase;
TAG *m_tagStack;
TAG *m_freeTagList;
BINDING *m_inheritedBindings;
BINDING *m_freeBindingList;
int m_attsSize;
int m_nSpecifiedAtts;
int m_idAttIndex;
ATTRIBUTE *m_atts;
NS_ATT *m_nsAtts;
unsigned long m_nsAttsVersion;
unsigned char m_nsAttsPower;
#ifdef XML_ATTR_INFO
XML_AttrInfo *m_attInfo;
#endif
POSITION m_position;
STRING_POOL m_tempPool;
STRING_POOL m_temp2Pool;
char *m_groupConnector;
unsigned int m_groupSize;
XML_Char m_namespaceSeparator;
XML_Parser m_parentParser;
XML_ParsingStatus m_parsingStatus;
#ifdef XML_DTD
XML_Bool m_isParamEntity;
XML_Bool m_useForeignDTD;
enum XML_ParamEntityParsing m_paramEntityParsing;
#endif
unsigned long m_hash_secret_salt;
};
#define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
#define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
#define FREE(p) (parser->m_mem.free_fcn((p)))
#define userData (parser->m_userData)
#define handlerArg (parser->m_handlerArg)
#define startElementHandler (parser->m_startElementHandler)
#define endElementHandler (parser->m_endElementHandler)
#define characterDataHandler (parser->m_characterDataHandler)
#define processingInstructionHandler \
(parser->m_processingInstructionHandler)
#define commentHandler (parser->m_commentHandler)
#define startCdataSectionHandler \
(parser->m_startCdataSectionHandler)
#define endCdataSectionHandler (parser->m_endCdataSectionHandler)
#define defaultHandler (parser->m_defaultHandler)
#define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
#define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
#define unparsedEntityDeclHandler \
(parser->m_unparsedEntityDeclHandler)
#define notationDeclHandler (parser->m_notationDeclHandler)
#define startNamespaceDeclHandler \
(parser->m_startNamespaceDeclHandler)
#define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
#define notStandaloneHandler (parser->m_notStandaloneHandler)
#define externalEntityRefHandler \
(parser->m_externalEntityRefHandler)
#define externalEntityRefHandlerArg \
(parser->m_externalEntityRefHandlerArg)
#define internalEntityRefHandler \
(parser->m_internalEntityRefHandler)
#define skippedEntityHandler (parser->m_skippedEntityHandler)
#define unknownEncodingHandler (parser->m_unknownEncodingHandler)
#define elementDeclHandler (parser->m_elementDeclHandler)
#define attlistDeclHandler (parser->m_attlistDeclHandler)
#define entityDeclHandler (parser->m_entityDeclHandler)
#define xmlDeclHandler (parser->m_xmlDeclHandler)
#define encoding (parser->m_encoding)
#define initEncoding (parser->m_initEncoding)
#define internalEncoding (parser->m_internalEncoding)
#define unknownEncodingMem (parser->m_unknownEncodingMem)
#define unknownEncodingData (parser->m_unknownEncodingData)
#define unknownEncodingHandlerData \
(parser->m_unknownEncodingHandlerData)
#define unknownEncodingRelease (parser->m_unknownEncodingRelease)
#define protocolEncodingName (parser->m_protocolEncodingName)
#define ns (parser->m_ns)
#define ns_triplets (parser->m_ns_triplets)
#define prologState (parser->m_prologState)
#define processor (parser->m_processor)
#define errorCode (parser->m_errorCode)
#define eventPtr (parser->m_eventPtr)
#define eventEndPtr (parser->m_eventEndPtr)
#define positionPtr (parser->m_positionPtr)
#define position (parser->m_position)
#define openInternalEntities (parser->m_openInternalEntities)
#define freeInternalEntities (parser->m_freeInternalEntities)
#define defaultExpandInternalEntities \
(parser->m_defaultExpandInternalEntities)
#define tagLevel (parser->m_tagLevel)
#define buffer (parser->m_buffer)
#define bufferPtr (parser->m_bufferPtr)
#define bufferEnd (parser->m_bufferEnd)
#define parseEndByteIndex (parser->m_parseEndByteIndex)
#define parseEndPtr (parser->m_parseEndPtr)
#define bufferLim (parser->m_bufferLim)
#define dataBuf (parser->m_dataBuf)
#define dataBufEnd (parser->m_dataBufEnd)
#define _dtd (parser->m_dtd)
#define curBase (parser->m_curBase)
#define declEntity (parser->m_declEntity)
#define doctypeName (parser->m_doctypeName)
#define doctypeSysid (parser->m_doctypeSysid)
#define doctypePubid (parser->m_doctypePubid)
#define declAttributeType (parser->m_declAttributeType)
#define declNotationName (parser->m_declNotationName)
#define declNotationPublicId (parser->m_declNotationPublicId)
#define declElementType (parser->m_declElementType)
#define declAttributeId (parser->m_declAttributeId)
#define declAttributeIsCdata (parser->m_declAttributeIsCdata)
#define declAttributeIsId (parser->m_declAttributeIsId)
#define freeTagList (parser->m_freeTagList)
#define freeBindingList (parser->m_freeBindingList)
#define inheritedBindings (parser->m_inheritedBindings)
#define tagStack (parser->m_tagStack)
#define atts (parser->m_atts)
#define attsSize (parser->m_attsSize)
#define nSpecifiedAtts (parser->m_nSpecifiedAtts)
#define idAttIndex (parser->m_idAttIndex)
#define nsAtts (parser->m_nsAtts)
#define nsAttsVersion (parser->m_nsAttsVersion)
#define nsAttsPower (parser->m_nsAttsPower)
#define attInfo (parser->m_attInfo)
#define tempPool (parser->m_tempPool)
#define temp2Pool (parser->m_temp2Pool)
#define groupConnector (parser->m_groupConnector)
#define groupSize (parser->m_groupSize)
#define namespaceSeparator (parser->m_namespaceSeparator)
#define parentParser (parser->m_parentParser)
#define ps_parsing (parser->m_parsingStatus.parsing)
#define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
#ifdef XML_DTD
#define isParamEntity (parser->m_isParamEntity)
#define useForeignDTD (parser->m_useForeignDTD)
#define paramEntityParsing (parser->m_paramEntityParsing)
#endif
#define hash_secret_salt (parser->m_hash_secret_salt)
XML_Parser XMLCALL
XML_ParserCreate(const XML_Char *encodingName)
{
return XML_ParserCreate_MM(encodingName, NULL, NULL);
}
XML_Parser XMLCALL
XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
{
XML_Char tmp[2];
*tmp = nsSep;
return XML_ParserCreate_MM(encodingName, NULL, tmp);
}
static const XML_Char implicitContext[] = {
ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
};
static unsigned long
generate_hash_secret_salt(void)
{
unsigned int seed = time(NULL) % UINT_MAX;
srand(seed);
return rand();
}
static XML_Bool
startParsing(XML_Parser parser)
{
if (hash_secret_salt == 0)
hash_secret_salt = generate_hash_secret_salt();
if (ns) {
return setContext(parser, implicitContext);
}
return XML_TRUE;
}
XML_Parser XMLCALL
XML_ParserCreate_MM(const XML_Char *encodingName,
const XML_Memory_Handling_Suite *memsuite,
const XML_Char *nameSep)
{
return parserCreate(encodingName, memsuite, nameSep, NULL);
}
static XML_Parser
parserCreate(const XML_Char *encodingName,
const XML_Memory_Handling_Suite *memsuite,
const XML_Char *nameSep,
DTD *dtd)
{
XML_Parser parser;
if (memsuite) {
XML_Memory_Handling_Suite *mtemp;
parser = (XML_Parser)
memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
if (parser != NULL) {
mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
mtemp->malloc_fcn = memsuite->malloc_fcn;
mtemp->realloc_fcn = memsuite->realloc_fcn;
mtemp->free_fcn = memsuite->free_fcn;
}
}
else {
XML_Memory_Handling_Suite *mtemp;
parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
if (parser != NULL) {
mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
mtemp->malloc_fcn = malloc;
mtemp->realloc_fcn = realloc;
mtemp->free_fcn = free;
}
}
if (!parser)
return parser;
buffer = NULL;
bufferLim = NULL;
attsSize = INIT_ATTS_SIZE;
atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
if (atts == NULL) {
FREE(parser);
return NULL;
}
#ifdef XML_ATTR_INFO
attInfo = (XML_AttrInfo*)MALLOC(attsSize * sizeof(XML_AttrInfo));
if (attInfo == NULL) {
FREE(atts);
FREE(parser);
return NULL;
}
#endif
dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
if (dataBuf == NULL) {
FREE(atts);
#ifdef XML_ATTR_INFO
FREE(attInfo);
#endif
FREE(parser);
return NULL;
}
dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
if (dtd)
_dtd = dtd;
else {
_dtd = dtdCreate(&parser->m_mem);
if (_dtd == NULL) {
FREE(dataBuf);
FREE(atts);
#ifdef XML_ATTR_INFO
FREE(attInfo);
#endif
FREE(parser);
return NULL;
}
}
freeBindingList = NULL;
freeTagList = NULL;
freeInternalEntities = NULL;
groupSize = 0;
groupConnector = NULL;
unknownEncodingHandler = NULL;
unknownEncodingHandlerData = NULL;
namespaceSeparator = ASCII_EXCL;
ns = XML_FALSE;
ns_triplets = XML_FALSE;
nsAtts = NULL;
nsAttsVersion = 0;
nsAttsPower = 0;
poolInit(&tempPool, &(parser->m_mem));
poolInit(&temp2Pool, &(parser->m_mem));
parserInit(parser, encodingName);
if (encodingName && !protocolEncodingName) {
XML_ParserFree(parser);
return NULL;
}
if (nameSep) {
ns = XML_TRUE;
internalEncoding = XmlGetInternalEncodingNS();
namespaceSeparator = *nameSep;
}
else {
internalEncoding = XmlGetInternalEncoding();
}
return parser;
}
static void
parserInit(XML_Parser parser, const XML_Char *encodingName)
{
processor = prologInitProcessor;
XmlPrologStateInit(&prologState);
protocolEncodingName = (encodingName != NULL
? poolCopyString(&tempPool, encodingName)
: NULL);
curBase = NULL;
XmlInitEncoding(&initEncoding, &encoding, 0);
userData = NULL;
handlerArg = NULL;
startElementHandler = NULL;
endElementHandler = NULL;
characterDataHandler = NULL;
processingInstructionHandler = NULL;
commentHandler = NULL;
startCdataSectionHandler = NULL;
endCdataSectionHandler = NULL;
defaultHandler = NULL;
startDoctypeDeclHandler = NULL;
endDoctypeDeclHandler = NULL;
unparsedEntityDeclHandler = NULL;
notationDeclHandler = NULL;
startNamespaceDeclHandler = NULL;
endNamespaceDeclHandler = NULL;
notStandaloneHandler = NULL;
externalEntityRefHandler = NULL;
externalEntityRefHandlerArg = parser;
skippedEntityHandler = NULL;
elementDeclHandler = NULL;
attlistDeclHandler = NULL;
entityDeclHandler = NULL;
xmlDeclHandler = NULL;
bufferPtr = buffer;
bufferEnd = buffer;
parseEndByteIndex = 0;
parseEndPtr = NULL;
declElementType = NULL;
declAttributeId = NULL;
declEntity = NULL;
doctypeName = NULL;
doctypeSysid = NULL;
doctypePubid = NULL;
declAttributeType = NULL;
declNotationName = NULL;
declNotationPublicId = NULL;
declAttributeIsCdata = XML_FALSE;
declAttributeIsId = XML_FALSE;
memset(&position, 0, sizeof(POSITION));
errorCode = XML_ERROR_NONE;
eventPtr = NULL;
eventEndPtr = NULL;
positionPtr = NULL;
openInternalEntities = NULL;
defaultExpandInternalEntities = XML_TRUE;
tagLevel = 0;
tagStack = NULL;
inheritedBindings = NULL;
nSpecifiedAtts = 0;
unknownEncodingMem = NULL;
unknownEncodingRelease = NULL;
unknownEncodingData = NULL;
parentParser = NULL;
ps_parsing = XML_INITIALIZED;
#ifdef XML_DTD
isParamEntity = XML_FALSE;
useForeignDTD = XML_FALSE;
paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
#endif
hash_secret_salt = 0;
}
static void FASTCALL
moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
{
while (bindings) {
BINDING *b = bindings;
bindings = bindings->nextTagBinding;
b->nextTagBinding = freeBindingList;
freeBindingList = b;
}
}
XML_Bool XMLCALL
XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
{
TAG *tStk;
OPEN_INTERNAL_ENTITY *openEntityList;
if (parentParser)
return XML_FALSE;
tStk = tagStack;
while (tStk) {
TAG *tag = tStk;
tStk = tStk->parent;
tag->parent = freeTagList;
moveToFreeBindingList(parser, tag->bindings);
tag->bindings = NULL;
freeTagList = tag;
}
openEntityList = openInternalEntities;
while (openEntityList) {
OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
openEntityList = openEntity->next;
openEntity->next = freeInternalEntities;
freeInternalEntities = openEntity;
}
moveToFreeBindingList(parser, inheritedBindings);
FREE(unknownEncodingMem);
if (unknownEncodingRelease)
unknownEncodingRelease(unknownEncodingData);
poolClear(&tempPool);
poolClear(&temp2Pool);
parserInit(parser, encodingName);
dtdReset(_dtd, &parser->m_mem);
return XML_TRUE;
}
enum XML_Status XMLCALL
XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
{
if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
return XML_STATUS_ERROR;
if (encodingName == NULL)
protocolEncodingName = NULL;
else {
protocolEncodingName = poolCopyString(&tempPool, encodingName);
if (!protocolEncodingName)
return XML_STATUS_ERROR;
}
return XML_STATUS_OK;
}
XML_Parser XMLCALL
XML_ExternalEntityParserCreate(XML_Parser oldParser,
const XML_Char *context,
const XML_Char *encodingName)
{
XML_Parser parser = oldParser;
DTD *newDtd = NULL;
DTD *oldDtd = _dtd;
XML_StartElementHandler oldStartElementHandler = startElementHandler;
XML_EndElementHandler oldEndElementHandler = endElementHandler;
XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
XML_ProcessingInstructionHandler oldProcessingInstructionHandler
= processingInstructionHandler;
XML_CommentHandler oldCommentHandler = commentHandler;
XML_StartCdataSectionHandler oldStartCdataSectionHandler
= startCdataSectionHandler;
XML_EndCdataSectionHandler oldEndCdataSectionHandler
= endCdataSectionHandler;
XML_DefaultHandler oldDefaultHandler = defaultHandler;
XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
= unparsedEntityDeclHandler;
XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
= startNamespaceDeclHandler;
XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
= endNamespaceDeclHandler;
XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
XML_ExternalEntityRefHandler oldExternalEntityRefHandler
= externalEntityRefHandler;
XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
XML_UnknownEncodingHandler oldUnknownEncodingHandler
= unknownEncodingHandler;
XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
ELEMENT_TYPE * oldDeclElementType = declElementType;
void *oldUserData = userData;
void *oldHandlerArg = handlerArg;
XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
#ifdef XML_DTD
enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
int oldInEntityValue = prologState.inEntityValue;
#endif
XML_Bool oldns_triplets = ns_triplets;
unsigned long oldhash_secret_salt = hash_secret_salt;
#ifdef XML_DTD
if (!context)
newDtd = oldDtd;
#endif
if (ns) {
XML_Char tmp[2];
*tmp = namespaceSeparator;
parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
}
else {
parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
}
if (!parser)
return NULL;
startElementHandler = oldStartElementHandler;
endElementHandler = oldEndElementHandler;
characterDataHandler = oldCharacterDataHandler;
processingInstructionHandler = oldProcessingInstructionHandler;
commentHandler = oldCommentHandler;
startCdataSectionHandler = oldStartCdataSectionHandler;
endCdataSectionHandler = oldEndCdataSectionHandler;
defaultHandler = oldDefaultHandler;
unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
notationDeclHandler = oldNotationDeclHandler;
startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
notStandaloneHandler = oldNotStandaloneHandler;
externalEntityRefHandler = oldExternalEntityRefHandler;
skippedEntityHandler = oldSkippedEntityHandler;
unknownEncodingHandler = oldUnknownEncodingHandler;
elementDeclHandler = oldElementDeclHandler;
attlistDeclHandler = oldAttlistDeclHandler;
entityDeclHandler = oldEntityDeclHandler;
xmlDeclHandler = oldXmlDeclHandler;
declElementType = oldDeclElementType;
userData = oldUserData;
if (oldUserData == oldHandlerArg)
handlerArg = userData;
else
handlerArg = parser;
if (oldExternalEntityRefHandlerArg != oldParser)
externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
ns_triplets = oldns_triplets;
hash_secret_salt = oldhash_secret_salt;
parentParser = oldParser;
#ifdef XML_DTD
paramEntityParsing = oldParamEntityParsing;
prologState.inEntityValue = oldInEntityValue;
if (context) {
#endif
if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem)
|| !setContext(parser, context)) {
XML_ParserFree(parser);
return NULL;
}
processor = externalEntityInitProcessor;
#ifdef XML_DTD
}
else {
isParamEntity = XML_TRUE;
XmlPrologStateInitExternalEntity(&prologState);
processor = externalParEntInitProcessor;
}
#endif
return parser;
}
static void FASTCALL
destroyBindings(BINDING *bindings, XML_Parser parser)
{
for (;;) {
BINDING *b = bindings;
if (!b)
break;
bindings = b->nextTagBinding;
FREE(b->uri);
FREE(b);
}
}
void XMLCALL
XML_ParserFree(XML_Parser parser)
{
TAG *tagList;
OPEN_INTERNAL_ENTITY *entityList;
if (parser == NULL)
return;
tagList = tagStack;
for (;;) {
TAG *p;
if (tagList == NULL) {
if (freeTagList == NULL)
break;
tagList = freeTagList;
freeTagList = NULL;
}
p = tagList;
tagList = tagList->parent;
FREE(p->buf);
destroyBindings(p->bindings, parser);
FREE(p);
}
entityList = openInternalEntities;
for (;;) {
OPEN_INTERNAL_ENTITY *openEntity;
if (entityList == NULL) {
if (freeInternalEntities == NULL)
break;
entityList = freeInternalEntities;
freeInternalEntities = NULL;
}
openEntity = entityList;
entityList = entityList->next;
FREE(openEntity);
}
destroyBindings(freeBindingList, parser);
destroyBindings(inheritedBindings, parser);
poolDestroy(&tempPool);
poolDestroy(&temp2Pool);
#ifdef XML_DTD
if (!isParamEntity && _dtd)
#else
if (_dtd)
#endif
dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
FREE((void *)atts);
#ifdef XML_ATTR_INFO
FREE((void *)attInfo);
#endif
FREE(groupConnector);
FREE(buffer);
FREE(dataBuf);
FREE(nsAtts);
FREE(unknownEncodingMem);
if (unknownEncodingRelease)
unknownEncodingRelease(unknownEncodingData);
FREE(parser);
}
void XMLCALL
XML_UseParserAsHandlerArg(XML_Parser parser)
{
handlerArg = parser;
}
enum XML_Error XMLCALL
XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
{
#ifdef XML_DTD
if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
useForeignDTD = useDTD;
return XML_ERROR_NONE;
#else
return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
#endif
}
void XMLCALL
XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
{
if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
return;
ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
}
void XMLCALL
XML_SetUserData(XML_Parser parser, void *p)
{
if (handlerArg == userData)
handlerArg = userData = p;
else
userData = p;
}
enum XML_Status XMLCALL
XML_SetBase(XML_Parser parser, const XML_Char *p)
{
if (p) {
p = poolCopyString(&_dtd->pool, p);
if (!p)
return XML_STATUS_ERROR;
curBase = p;
}
else
curBase = NULL;
return XML_STATUS_OK;
}
const XML_Char * XMLCALL
XML_GetBase(XML_Parser parser)
{
return curBase;
}
int XMLCALL
XML_GetSpecifiedAttributeCount(XML_Parser parser)
{
return nSpecifiedAtts;
}
int XMLCALL
XML_GetIdAttributeIndex(XML_Parser parser)
{
return idAttIndex;
}
#ifdef XML_ATTR_INFO
const XML_AttrInfo * XMLCALL
XML_GetAttributeInfo(XML_Parser parser)
{
return attInfo;
}
#endif
void XMLCALL
XML_SetElementHandler(XML_Parser parser,
XML_StartElementHandler start,
XML_EndElementHandler end)
{
startElementHandler = start;
endElementHandler = end;
}
void XMLCALL
XML_SetStartElementHandler(XML_Parser parser,
XML_StartElementHandler start) {
startElementHandler = start;
}
void XMLCALL
XML_SetEndElementHandler(XML_Parser parser,
XML_EndElementHandler end) {
endElementHandler = end;
}
void XMLCALL
XML_SetCharacterDataHandler(XML_Parser parser,
XML_CharacterDataHandler handler)
{
characterDataHandler = handler;
}
void XMLCALL
XML_SetProcessingInstructionHandler(XML_Parser parser,
XML_ProcessingInstructionHandler handler)
{
processingInstructionHandler = handler;
}
void XMLCALL
XML_SetCommentHandler(XML_Parser parser,
XML_CommentHandler handler)
{
commentHandler = handler;
}
void XMLCALL
XML_SetCdataSectionHandler(XML_Parser parser,
XML_StartCdataSectionHandler start,
XML_EndCdataSectionHandler end)
{
startCdataSectionHandler = start;
endCdataSectionHandler = end;
}
void XMLCALL
XML_SetStartCdataSectionHandler(XML_Parser parser,
XML_StartCdataSectionHandler start) {
startCdataSectionHandler = start;
}
void XMLCALL
XML_SetEndCdataSectionHandler(XML_Parser parser,
XML_EndCdataSectionHandler end) {
endCdataSectionHandler = end;
}
void XMLCALL
XML_SetDefaultHandler(XML_Parser parser,
XML_DefaultHandler handler)
{
defaultHandler = handler;
defaultExpandInternalEntities = XML_FALSE;
}
void XMLCALL
XML_SetDefaultHandlerExpand(XML_Parser parser,
XML_DefaultHandler handler)
{
defaultHandler = handler;
defaultExpandInternalEntities = XML_TRUE;
}
void XMLCALL
XML_SetDoctypeDeclHandler(XML_Parser parser,
XML_StartDoctypeDeclHandler start,
XML_EndDoctypeDeclHandler end)
{
startDoctypeDeclHandler = start;
endDoctypeDeclHandler = end;
}
void XMLCALL
XML_SetStartDoctypeDeclHandler(XML_Parser parser,
XML_StartDoctypeDeclHandler start) {
startDoctypeDeclHandler = start;
}
void XMLCALL
XML_SetEndDoctypeDeclHandler(XML_Parser parser,
XML_EndDoctypeDeclHandler end) {
endDoctypeDeclHandler = end;
}
void XMLCALL
XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
XML_UnparsedEntityDeclHandler handler)
{
unparsedEntityDeclHandler = handler;
}
void XMLCALL
XML_SetNotationDeclHandler(XML_Parser parser,
XML_NotationDeclHandler handler)
{
notationDeclHandler = handler;
}
void XMLCALL
XML_SetNamespaceDeclHandler(XML_Parser parser,
XML_StartNamespaceDeclHandler start,
XML_EndNamespaceDeclHandler end)
{
startNamespaceDeclHandler = start;
endNamespaceDeclHandler = end;
}
void XMLCALL
XML_SetStartNamespaceDeclHandler(XML_Parser parser,
XML_StartNamespaceDeclHandler start) {
startNamespaceDeclHandler = start;
}
void XMLCALL
XML_SetEndNamespaceDeclHandler(XML_Parser parser,
XML_EndNamespaceDeclHandler end) {
endNamespaceDeclHandler = end;
}
void XMLCALL
XML_SetNotStandaloneHandler(XML_Parser parser,
XML_NotStandaloneHandler handler)
{
notStandaloneHandler = handler;
}
void XMLCALL
XML_SetExternalEntityRefHandler(XML_Parser parser,
XML_ExternalEntityRefHandler handler)
{
externalEntityRefHandler = handler;
}
void XMLCALL
XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
{
if (arg)
externalEntityRefHandlerArg = (XML_Parser)arg;
else
externalEntityRefHandlerArg = parser;
}
void XMLCALL
XML_SetSkippedEntityHandler(XML_Parser parser,
XML_SkippedEntityHandler handler)
{
skippedEntityHandler = handler;
}
void XMLCALL
XML_SetUnknownEncodingHandler(XML_Parser parser,
XML_UnknownEncodingHandler handler,
void *data)
{
unknownEncodingHandler = handler;
unknownEncodingHandlerData = data;
}
void XMLCALL
XML_SetElementDeclHandler(XML_Parser parser,
XML_ElementDeclHandler eldecl)
{
elementDeclHandler = eldecl;
}
void XMLCALL
XML_SetAttlistDeclHandler(XML_Parser parser,
XML_AttlistDeclHandler attdecl)
{
attlistDeclHandler = attdecl;
}
void XMLCALL
XML_SetEntityDeclHandler(XML_Parser parser,
XML_EntityDeclHandler handler)
{
entityDeclHandler = handler;
}
void XMLCALL
XML_SetXmlDeclHandler(XML_Parser parser,
XML_XmlDeclHandler handler) {
xmlDeclHandler = handler;
}
int XMLCALL
XML_SetParamEntityParsing(XML_Parser parser,
enum XML_ParamEntityParsing peParsing)
{
if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
return 0;
#ifdef XML_DTD
paramEntityParsing = peParsing;
return 1;
#else
return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
#endif
}
int XMLCALL
XML_SetHashSalt(XML_Parser parser,
unsigned long hash_salt)
{
if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
return 0;
hash_secret_salt = hash_salt;
return 1;
}
enum XML_Status XMLCALL
XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
{
switch (ps_parsing) {
case XML_SUSPENDED:
errorCode = XML_ERROR_SUSPENDED;
return XML_STATUS_ERROR;
case XML_FINISHED:
errorCode = XML_ERROR_FINISHED;
return XML_STATUS_ERROR;
case XML_INITIALIZED:
if (parentParser == NULL && !startParsing(parser)) {
errorCode = XML_ERROR_NO_MEMORY;
return XML_STATUS_ERROR;
}
default:
ps_parsing = XML_PARSING;
}
if (len == 0) {
ps_finalBuffer = (XML_Bool)isFinal;
if (!isFinal)
return XML_STATUS_OK;
positionPtr = bufferPtr;
parseEndPtr = bufferEnd;
errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
if (errorCode == XML_ERROR_NONE) {
switch (ps_parsing) {
case XML_SUSPENDED:
XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
positionPtr = bufferPtr;
return XML_STATUS_SUSPENDED;
case XML_INITIALIZED:
case XML_PARSING:
ps_parsing = XML_FINISHED;
default:
return XML_STATUS_OK;
}
}
eventEndPtr = eventPtr;
processor = errorProcessor;
return XML_STATUS_ERROR;
}
#ifndef XML_CONTEXT_BYTES
else if (bufferPtr == bufferEnd) {
const char *end;
int nLeftOver;
enum XML_Error result;
parseEndByteIndex += len;
positionPtr = s;
ps_finalBuffer = (XML_Bool)isFinal;
errorCode = processor(parser, s, parseEndPtr = s + len, &end);
if (errorCode != XML_ERROR_NONE) {
eventEndPtr = eventPtr;
processor = errorProcessor;
return XML_STATUS_ERROR;
}
else {
switch (ps_parsing) {
case XML_SUSPENDED:
result = XML_STATUS_SUSPENDED;
break;
case XML_INITIALIZED:
case XML_PARSING:
if (isFinal) {
ps_parsing = XML_FINISHED;
return XML_STATUS_OK;
}
default:
result = XML_STATUS_OK;
}
}
XmlUpdatePosition(encoding, positionPtr, end, &position);
nLeftOver = s + len - end;
if (nLeftOver) {
if (buffer == NULL || nLeftOver > bufferLim - buffer) {
char *temp;
temp = (buffer == NULL
? (char *)MALLOC(len * 2)
: (char *)REALLOC(buffer, len * 2));
if (temp == NULL) {
errorCode = XML_ERROR_NO_MEMORY;
eventPtr = eventEndPtr = NULL;
processor = errorProcessor;
return XML_STATUS_ERROR;
}
buffer = temp;
bufferLim = buffer + len * 2;
}
memcpy(buffer, end, nLeftOver);
}
bufferPtr = buffer;
bufferEnd = buffer + nLeftOver;
positionPtr = bufferPtr;
parseEndPtr = bufferEnd;
eventPtr = bufferPtr;
eventEndPtr = bufferPtr;
return result;
}
#endif
else {
void *buff = XML_GetBuffer(parser, len);
if (buff == NULL)
return XML_STATUS_ERROR;
else {
memcpy(buff, s, len);
return XML_ParseBuffer(parser, len, isFinal);
}
}
}
enum XML_Status XMLCALL
XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
{
const char *start;
enum XML_Status result = XML_STATUS_OK;
switch (ps_parsing) {
case XML_SUSPENDED:
errorCode = XML_ERROR_SUSPENDED;
return XML_STATUS_ERROR;
case XML_FINISHED:
errorCode = XML_ERROR_FINISHED;
return XML_STATUS_ERROR;
case XML_INITIALIZED:
if (parentParser == NULL && !startParsing(parser)) {
errorCode = XML_ERROR_NO_MEMORY;
return XML_STATUS_ERROR;
}
default:
ps_parsing = XML_PARSING;
}
start = bufferPtr;
positionPtr = start;
bufferEnd += len;
parseEndPtr = bufferEnd;
parseEndByteIndex += len;
ps_finalBuffer = (XML_Bool)isFinal;
errorCode = processor(parser, start, parseEndPtr, &bufferPtr);
if (errorCode != XML_ERROR_NONE) {
eventEndPtr = eventPtr;
processor = errorProcessor;
return XML_STATUS_ERROR;
}
else {
switch (ps_parsing) {
case XML_SUSPENDED:
result = XML_STATUS_SUSPENDED;
break;
case XML_INITIALIZED:
case XML_PARSING:
if (isFinal) {
ps_parsing = XML_FINISHED;
return result;
}
default: ;
}
}
XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
positionPtr = bufferPtr;
return result;
}
void * XMLCALL
XML_GetBuffer(XML_Parser parser, int len)
{
switch (ps_parsing) {
case XML_SUSPENDED:
errorCode = XML_ERROR_SUSPENDED;
return NULL;
case XML_FINISHED:
errorCode = XML_ERROR_FINISHED;
return NULL;
default: ;
}
if (len > bufferLim - bufferEnd) {
int neededSize = len + (int)(bufferEnd - bufferPtr);
#ifdef XML_CONTEXT_BYTES
int keep = (int)(bufferPtr - buffer);
if (keep > XML_CONTEXT_BYTES)
keep = XML_CONTEXT_BYTES;
neededSize += keep;
#endif
if (neededSize <= bufferLim - buffer) {
#ifdef XML_CONTEXT_BYTES
if (keep < bufferPtr - buffer) {
int offset = (int)(bufferPtr - buffer) - keep;
memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
bufferEnd -= offset;
bufferPtr -= offset;
}
#else
memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
bufferEnd = buffer + (bufferEnd - bufferPtr);
bufferPtr = buffer;
#endif
}
else {
char *newBuf;
int bufferSize = (int)(bufferLim - bufferPtr);
if (bufferSize == 0)
bufferSize = INIT_BUFFER_SIZE;
do {
bufferSize *= 2;
} while (bufferSize < neededSize);
newBuf = (char *)MALLOC(bufferSize);
if (newBuf == 0) {
errorCode = XML_ERROR_NO_MEMORY;
return NULL;
}
bufferLim = newBuf + bufferSize;
#ifdef XML_CONTEXT_BYTES
if (bufferPtr) {
int keep = (int)(bufferPtr - buffer);
if (keep > XML_CONTEXT_BYTES)
keep = XML_CONTEXT_BYTES;
memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
FREE(buffer);
buffer = newBuf;
bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
bufferPtr = buffer + keep;
}
else {
bufferEnd = newBuf + (bufferEnd - bufferPtr);
bufferPtr = buffer = newBuf;
}
#else
if (bufferPtr) {
memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
FREE(buffer);
}
bufferEnd = newBuf + (bufferEnd - bufferPtr);
bufferPtr = buffer = newBuf;
#endif
}
eventPtr = eventEndPtr = NULL;
positionPtr = NULL;
}
return bufferEnd;
}
enum XML_Status XMLCALL
XML_StopParser(XML_Parser parser, XML_Bool resumable)
{
switch (ps_parsing) {
case XML_SUSPENDED:
if (resumable) {
errorCode = XML_ERROR_SUSPENDED;
return XML_STATUS_ERROR;
}
ps_parsing = XML_FINISHED;
break;
case XML_FINISHED:
errorCode = XML_ERROR_FINISHED;
return XML_STATUS_ERROR;
default:
if (resumable) {
#ifdef XML_DTD
if (isParamEntity) {
errorCode = XML_ERROR_SUSPEND_PE;
return XML_STATUS_ERROR;
}
#endif
ps_parsing = XML_SUSPENDED;
}
else
ps_parsing = XML_FINISHED;
}
return XML_STATUS_OK;
}
enum XML_Status XMLCALL
XML_ResumeParser(XML_Parser parser)
{
enum XML_Status result = XML_STATUS_OK;
if (ps_parsing != XML_SUSPENDED) {
errorCode = XML_ERROR_NOT_SUSPENDED;
return XML_STATUS_ERROR;
}
ps_parsing = XML_PARSING;
errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
if (errorCode != XML_ERROR_NONE) {
eventEndPtr = eventPtr;
processor = errorProcessor;
return XML_STATUS_ERROR;
}
else {
switch (ps_parsing) {
case XML_SUSPENDED:
result = XML_STATUS_SUSPENDED;
break;
case XML_INITIALIZED:
case XML_PARSING:
if (ps_finalBuffer) {
ps_parsing = XML_FINISHED;
return result;
}
default: ;
}
}
XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
positionPtr = bufferPtr;
return result;
}
void XMLCALL
XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
{
assert(status != NULL);
*status = parser->m_parsingStatus;
}
enum XML_Error XMLCALL
XML_GetErrorCode(XML_Parser parser)
{
return errorCode;
}
XML_Index XMLCALL
XML_GetCurrentByteIndex(XML_Parser parser)
{
if (eventPtr)
return parseEndByteIndex - (parseEndPtr - eventPtr);
return -1;
}
int XMLCALL
XML_GetCurrentByteCount(XML_Parser parser)
{
if (eventEndPtr && eventPtr)
return (int)(eventEndPtr - eventPtr);
return 0;
}
const char * XMLCALL
XML_GetInputContext(XML_Parser parser, int *offset, int *size)
{
#ifdef XML_CONTEXT_BYTES
if (eventPtr && buffer) {
*offset = (int)(eventPtr - buffer);
*size = (int)(bufferEnd - buffer);
return buffer;
}
#endif
return (char *) 0;
}
XML_Size XMLCALL
XML_GetCurrentLineNumber(XML_Parser parser)
{
if (eventPtr && eventPtr >= positionPtr) {
XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
positionPtr = eventPtr;
}
return position.lineNumber + 1;
}
XML_Size XMLCALL
XML_GetCurrentColumnNumber(XML_Parser parser)
{
if (eventPtr && eventPtr >= positionPtr) {
XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
positionPtr = eventPtr;
}
return position.columnNumber;
}
void XMLCALL
XML_FreeContentModel(XML_Parser parser, XML_Content *model)
{
FREE(model);
}
void * XMLCALL
XML_MemMalloc(XML_Parser parser, size_t size)
{
return MALLOC(size);
}
void * XMLCALL
XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
{
return REALLOC(ptr, size);
}
void XMLCALL
XML_MemFree(XML_Parser parser, void *ptr)
{
FREE(ptr);
}
void XMLCALL
XML_DefaultCurrent(XML_Parser parser)
{
if (defaultHandler) {
if (openInternalEntities)
reportDefault(parser,
internalEncoding,
openInternalEntities->internalEventPtr,
openInternalEntities->internalEventEndPtr);
else
reportDefault(parser, encoding, eventPtr, eventEndPtr);
}
}
const XML_LChar * XMLCALL
XML_ErrorString(enum XML_Error code)
{
static const XML_LChar* const message[] = {
0,
XML_L("out of memory"),
XML_L("syntax error"),
XML_L("no element found"),
XML_L("not well-formed (invalid token)"),
XML_L("unclosed token"),
XML_L("partial character"),
XML_L("mismatched tag"),
XML_L("duplicate attribute"),
XML_L("junk after document element"),
XML_L("illegal parameter entity reference"),
XML_L("undefined entity"),
XML_L("recursive entity reference"),
XML_L("asynchronous entity"),
XML_L("reference to invalid character number"),
XML_L("reference to binary entity"),
XML_L("reference to external entity in attribute"),
XML_L("XML or text declaration not at start of entity"),
XML_L("unknown encoding"),
XML_L("encoding specified in XML declaration is incorrect"),
XML_L("unclosed CDATA section"),
XML_L("error in processing external entity reference"),
XML_L("document is not standalone"),
XML_L("unexpected parser state - please send a bug report"),
XML_L("entity declared in parameter entity"),
XML_L("requested feature requires XML_DTD support in Expat"),
XML_L("cannot change setting once parsing has begun"),
XML_L("unbound prefix"),
XML_L("must not undeclare prefix"),
XML_L("incomplete markup in parameter entity"),
XML_L("XML declaration not well-formed"),
XML_L("text declaration not well-formed"),
XML_L("illegal character(s) in public id"),
XML_L("parser suspended"),
XML_L("parser not suspended"),
XML_L("parsing aborted"),
XML_L("parsing finished"),
XML_L("cannot suspend in external parameter entity"),
XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
XML_L("prefix must not be bound to one of the reserved namespace names")
};
if (code > 0 && code < sizeof(message)/sizeof(message[0]))
return message[code];
return NULL;
}
const XML_LChar * XMLCALL
XML_ExpatVersion(void) {
#define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
#define V2(a,b,c) XML_L("expat_")V1(a,b,c)
return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
#undef V1
#undef V2
}
XML_Expat_Version XMLCALL
XML_ExpatVersionInfo(void)
{
XML_Expat_Version version;
version.major = XML_MAJOR_VERSION;
version.minor = XML_MINOR_VERSION;
version.micro = XML_MICRO_VERSION;
return version;
}
const XML_Feature * XMLCALL
XML_GetFeatureList(void)
{
static const XML_Feature features[] = {
{XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
sizeof(XML_Char)},
{XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
sizeof(XML_LChar)},
#ifdef XML_UNICODE
{XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
#endif
#ifdef XML_UNICODE_WCHAR_T
{XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
#endif
#ifdef XML_DTD
{XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
#endif
#ifdef XML_CONTEXT_BYTES
{XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
XML_CONTEXT_BYTES},
#endif
#ifdef XML_MIN_SIZE
{XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
#endif
#ifdef XML_NS
{XML_FEATURE_NS, XML_L("XML_NS"), 0},
#endif
#ifdef XML_LARGE_SIZE
{XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
#endif
#ifdef XML_ATTR_INFO
{XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
#endif
{XML_FEATURE_END, NULL, 0}
};
return features;
}
static XML_Bool
storeRawNames(XML_Parser parser)
{
TAG *tag = tagStack;
while (tag) {
int bufSize;
int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
char *rawNameBuf = tag->buf + nameLen;
if (tag->rawName == rawNameBuf)
break;
bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
if (bufSize > tag->bufEnd - tag->buf) {
char *temp = (char *)REALLOC(tag->buf, bufSize);
if (temp == NULL)
return XML_FALSE;
if (tag->name.str == (XML_Char *)tag->buf)
tag->name.str = (XML_Char *)temp;
if (tag->name.localPart)
tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
(XML_Char *)tag->buf);
tag->buf = temp;
tag->bufEnd = temp + bufSize;
rawNameBuf = temp + nameLen;
}
memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
tag->rawName = rawNameBuf;
tag = tag->parent;
}
return XML_TRUE;
}
static enum XML_Error PTRCALL
contentProcessor(XML_Parser parser,
const char *start,
const char *end,
const char **endPtr)
{
enum XML_Error result = doContent(parser, 0, encoding, start, end,
endPtr, (XML_Bool)!ps_finalBuffer);
if (result == XML_ERROR_NONE) {
if (!storeRawNames(parser))
return XML_ERROR_NO_MEMORY;
}
return result;
}
static enum XML_Error PTRCALL
externalEntityInitProcessor(XML_Parser parser,
const char *start,
const char *end,
const char **endPtr)
{
enum XML_Error result = initializeEncoding(parser);
if (result != XML_ERROR_NONE)
return result;
processor = externalEntityInitProcessor2;
return externalEntityInitProcessor2(parser, start, end, endPtr);
}
static enum XML_Error PTRCALL
externalEntityInitProcessor2(XML_Parser parser,
const char *start,
const char *end,
const char **endPtr)
{
const char *next = start;
int tok = XmlContentTok(encoding, start, end, &next);
switch (tok) {
case XML_TOK_BOM:
if (next == end && !ps_finalBuffer) {
*endPtr = next;
return XML_ERROR_NONE;
}
start = next;
break;
case XML_TOK_PARTIAL:
if (!ps_finalBuffer) {
*endPtr = start;
return XML_ERROR_NONE;
}
eventPtr = start;
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
if (!ps_finalBuffer) {
*endPtr = start;
return XML_ERROR_NONE;
}
eventPtr = start;
return XML_ERROR_PARTIAL_CHAR;
}
processor = externalEntityInitProcessor3;
return externalEntityInitProcessor3(parser, start, end, endPtr);
}
static enum XML_Error PTRCALL
externalEntityInitProcessor3(XML_Parser parser,
const char *start,
const char *end,
const char **endPtr)
{
int tok;
const char *next = start;
eventPtr = start;
tok = XmlContentTok(encoding, start, end, &next);
eventEndPtr = next;
switch (tok) {
case XML_TOK_XML_DECL:
{
enum XML_Error result;
result = processXmlDecl(parser, 1, start, next);
if (result != XML_ERROR_NONE)
return result;
switch (ps_parsing) {
case XML_SUSPENDED:
*endPtr = next;
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
default:
start = next;
}
}
break;
case XML_TOK_PARTIAL:
if (!ps_finalBuffer) {
*endPtr = start;
return XML_ERROR_NONE;
}
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
if (!ps_finalBuffer) {
*endPtr = start;
return XML_ERROR_NONE;
}
return XML_ERROR_PARTIAL_CHAR;
}
processor = externalEntityContentProcessor;
tagLevel = 1;
return externalEntityContentProcessor(parser, start, end, endPtr);
}
static enum XML_Error PTRCALL
externalEntityContentProcessor(XML_Parser parser,
const char *start,
const char *end,
const char **endPtr)
{
enum XML_Error result = doContent(parser, 1, encoding, start, end,
endPtr, (XML_Bool)!ps_finalBuffer);
if (result == XML_ERROR_NONE) {
if (!storeRawNames(parser))
return XML_ERROR_NO_MEMORY;
}
return result;
}
static enum XML_Error
doContent(XML_Parser parser,
int startTagLevel,
const ENCODING *enc,
const char *s,
const char *end,
const char **nextPtr,
XML_Bool haveMore)
{
DTD * const dtd = _dtd;
const char **eventPP;
const char **eventEndPP;
if (enc == encoding) {
eventPP = &eventPtr;
eventEndPP = &eventEndPtr;
}
else {
eventPP = &(openInternalEntities->internalEventPtr);
eventEndPP = &(openInternalEntities->internalEventEndPtr);
}
*eventPP = s;
for (;;) {
const char *next = s;
int tok = XmlContentTok(enc, s, end, &next);
*eventEndPP = next;
switch (tok) {
case XML_TOK_TRAILING_CR:
if (haveMore) {
*nextPtr = s;
return XML_ERROR_NONE;
}
*eventEndPP = end;
if (characterDataHandler) {
XML_Char c = 0xA;
characterDataHandler(handlerArg, &c, 1);
}
else if (defaultHandler)
reportDefault(parser, enc, s, end);
if (startTagLevel == 0)
return XML_ERROR_NO_ELEMENTS;
if (tagLevel != startTagLevel)
return XML_ERROR_ASYNC_ENTITY;
*nextPtr = end;
return XML_ERROR_NONE;
case XML_TOK_NONE:
if (haveMore) {
*nextPtr = s;
return XML_ERROR_NONE;
}
if (startTagLevel > 0) {
if (tagLevel != startTagLevel)
return XML_ERROR_ASYNC_ENTITY;
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_NO_ELEMENTS;
case XML_TOK_INVALID:
*eventPP = next;
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_PARTIAL:
if (haveMore) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
if (haveMore) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_PARTIAL_CHAR;
case XML_TOK_ENTITY_REF:
{
const XML_Char *name;
ENTITY *entity;
XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (ch) {
if (characterDataHandler)
characterDataHandler(handlerArg, &ch, 1);
else if (defaultHandler)
reportDefault(parser, enc, s, next);
break;
}
name = poolStoreString(&dtd->pool, enc,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (!name)
return XML_ERROR_NO_MEMORY;
entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
poolDiscard(&dtd->pool);
if (!dtd->hasParamEntityRefs || dtd->standalone) {
if (!entity)
return XML_ERROR_UNDEFINED_ENTITY;
else if (!entity->is_internal)
return XML_ERROR_ENTITY_DECLARED_IN_PE;
}
else if (!entity) {
if (skippedEntityHandler)
skippedEntityHandler(handlerArg, name, 0);
else if (defaultHandler)
reportDefault(parser, enc, s, next);
break;
}
if (entity->open)
return XML_ERROR_RECURSIVE_ENTITY_REF;
if (entity->notation)
return XML_ERROR_BINARY_ENTITY_REF;
if (entity->textPtr) {
enum XML_Error result;
if (!defaultExpandInternalEntities) {
if (skippedEntityHandler)
skippedEntityHandler(handlerArg, entity->name, 0);
else if (defaultHandler)
reportDefault(parser, enc, s, next);
break;
}
result = processInternalEntity(parser, entity, XML_FALSE);
if (result != XML_ERROR_NONE)
return result;
}
else if (externalEntityRefHandler) {
const XML_Char *context;
entity->open = XML_TRUE;
context = getContext(parser);
entity->open = XML_FALSE;
if (!context)
return XML_ERROR_NO_MEMORY;
if (!externalEntityRefHandler(externalEntityRefHandlerArg,
context,
entity->base,
entity->systemId,
entity->publicId))
return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
poolDiscard(&tempPool);
}
else if (defaultHandler)
reportDefault(parser, enc, s, next);
break;
}
case XML_TOK_START_TAG_NO_ATTS:
case XML_TOK_START_TAG_WITH_ATTS:
{
TAG *tag;
enum XML_Error result;
XML_Char *toPtr;
if (freeTagList) {
tag = freeTagList;
freeTagList = freeTagList->parent;
}
else {
tag = (TAG *)MALLOC(sizeof(TAG));
if (!tag)
return XML_ERROR_NO_MEMORY;
tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
if (!tag->buf) {
FREE(tag);
return XML_ERROR_NO_MEMORY;
}
tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
}
tag->bindings = NULL;
tag->parent = tagStack;
tagStack = tag;
tag->name.localPart = NULL;
tag->name.prefix = NULL;
tag->rawName = s + enc->minBytesPerChar;
tag->rawNameLength = XmlNameLength(enc, tag->rawName);
++tagLevel;
{
const char *rawNameEnd = tag->rawName + tag->rawNameLength;
const char *fromPtr = tag->rawName;
toPtr = (XML_Char *)tag->buf;
for (;;) {
int bufSize;
int convLen;
XmlConvert(enc,
&fromPtr, rawNameEnd,
(ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
convLen = (int)(toPtr - (XML_Char *)tag->buf);
if (fromPtr == rawNameEnd) {
tag->name.strLen = convLen;
break;
}
bufSize = (int)(tag->bufEnd - tag->buf) << 1;
{
char *temp = (char *)REALLOC(tag->buf, bufSize);
if (temp == NULL)
return XML_ERROR_NO_MEMORY;
tag->buf = temp;
tag->bufEnd = temp + bufSize;
toPtr = (XML_Char *)temp + convLen;
}
}
}
tag->name.str = (XML_Char *)tag->buf;
*toPtr = XML_T('\0');
result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
if (result)
return result;
if (startElementHandler)
startElementHandler(handlerArg, tag->name.str,
(const XML_Char **)atts);
else if (defaultHandler)
reportDefault(parser, enc, s, next);
poolClear(&tempPool);
break;
}
case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
{
const char *rawName = s + enc->minBytesPerChar;
enum XML_Error result;
BINDING *bindings = NULL;
XML_Bool noElmHandlers = XML_TRUE;
TAG_NAME name;
name.str = poolStoreString(&tempPool, enc, rawName,
rawName + XmlNameLength(enc, rawName));
if (!name.str)
return XML_ERROR_NO_MEMORY;
poolFinish(&tempPool);
result = storeAtts(parser, enc, s, &name, &bindings);
if (result)
return result;
poolFinish(&tempPool);
if (startElementHandler) {
startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
noElmHandlers = XML_FALSE;
}
if (endElementHandler) {
if (startElementHandler)
*eventPP = *eventEndPP;
endElementHandler(handlerArg, name.str);
noElmHandlers = XML_FALSE;
}
if (noElmHandlers && defaultHandler)
reportDefault(parser, enc, s, next);
poolClear(&tempPool);
while (bindings) {
BINDING *b = bindings;
if (endNamespaceDeclHandler)
endNamespaceDeclHandler(handlerArg, b->prefix->name);
bindings = bindings->nextTagBinding;
b->nextTagBinding = freeBindingList;
freeBindingList = b;
b->prefix->binding = b->prevPrefixBinding;
}
}
if (tagLevel == 0)
return epilogProcessor(parser, next, end, nextPtr);
break;
case XML_TOK_END_TAG:
if (tagLevel == startTagLevel)
return XML_ERROR_ASYNC_ENTITY;
else {
int len;
const char *rawName;
TAG *tag = tagStack;
tagStack = tag->parent;
tag->parent = freeTagList;
freeTagList = tag;
rawName = s + enc->minBytesPerChar*2;
len = XmlNameLength(enc, rawName);
if (len != tag->rawNameLength
|| memcmp(tag->rawName, rawName, len) != 0) {
*eventPP = rawName;
return XML_ERROR_TAG_MISMATCH;
}
--tagLevel;
if (endElementHandler) {
const XML_Char *localPart;
const XML_Char *prefix;
XML_Char *uri;
localPart = tag->name.localPart;
if (ns && localPart) {
uri = (XML_Char *)tag->name.str + tag->name.uriLen;
while (*localPart) *uri++ = *localPart++;
prefix = (XML_Char *)tag->name.prefix;
if (ns_triplets && prefix) {
*uri++ = namespaceSeparator;
while (*prefix) *uri++ = *prefix++;
}
*uri = XML_T('\0');
}
endElementHandler(handlerArg, tag->name.str);
}
else if (defaultHandler)
reportDefault(parser, enc, s, next);
while (tag->bindings) {
BINDING *b = tag->bindings;
if (endNamespaceDeclHandler)
endNamespaceDeclHandler(handlerArg, b->prefix->name);
tag->bindings = tag->bindings->nextTagBinding;
b->nextTagBinding = freeBindingList;
freeBindingList = b;
b->prefix->binding = b->prevPrefixBinding;
}
if (tagLevel == 0)
return epilogProcessor(parser, next, end, nextPtr);
}
break;
case XML_TOK_CHAR_REF:
{
int n = XmlCharRefNumber(enc, s);
if (n < 0)
return XML_ERROR_BAD_CHAR_REF;
if (characterDataHandler) {
XML_Char buf[XML_ENCODE_MAX];
characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
}
else if (defaultHandler)
reportDefault(parser, enc, s, next);
}
break;
case XML_TOK_XML_DECL:
return XML_ERROR_MISPLACED_XML_PI;
case XML_TOK_DATA_NEWLINE:
if (characterDataHandler) {
XML_Char c = 0xA;
characterDataHandler(handlerArg, &c, 1);
}
else if (defaultHandler)
reportDefault(parser, enc, s, next);
break;
case XML_TOK_CDATA_SECT_OPEN:
{
enum XML_Error result;
if (startCdataSectionHandler)
startCdataSectionHandler(handlerArg);
#if 0
else if (characterDataHandler)
characterDataHandler(handlerArg, dataBuf, 0);
#endif
else if (defaultHandler)
reportDefault(parser, enc, s, next);
result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
if (result != XML_ERROR_NONE)
return result;
else if (!next) {
processor = cdataSectionProcessor;
return result;
}
}
break;
case XML_TOK_TRAILING_RSQB:
if (haveMore) {
*nextPtr = s;
return XML_ERROR_NONE;
}
if (characterDataHandler) {
if (MUST_CONVERT(enc, s)) {
ICHAR *dataPtr = (ICHAR *)dataBuf;
XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
characterDataHandler(handlerArg, dataBuf,
(int)(dataPtr - (ICHAR *)dataBuf));
}
else
characterDataHandler(handlerArg,
(XML_Char *)s,
(int)((XML_Char *)end - (XML_Char *)s));
}
else if (defaultHandler)
reportDefault(parser, enc, s, end);
if (startTagLevel == 0) {
*eventPP = end;
return XML_ERROR_NO_ELEMENTS;
}
if (tagLevel != startTagLevel) {
*eventPP = end;
return XML_ERROR_ASYNC_ENTITY;
}
*nextPtr = end;
return XML_ERROR_NONE;
case XML_TOK_DATA_CHARS:
{
XML_CharacterDataHandler charDataHandler = characterDataHandler;
if (charDataHandler) {
if (MUST_CONVERT(enc, s)) {
for (;;) {
ICHAR *dataPtr = (ICHAR *)dataBuf;
XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
*eventEndPP = s;
charDataHandler(handlerArg, dataBuf,
(int)(dataPtr - (ICHAR *)dataBuf));
if (s == next)
break;
*eventPP = s;
}
}
else
charDataHandler(handlerArg,
(XML_Char *)s,
(int)((XML_Char *)next - (XML_Char *)s));
}
else if (defaultHandler)
reportDefault(parser, enc, s, next);
}
break;
case XML_TOK_PI:
if (!reportProcessingInstruction(parser, enc, s, next))
return XML_ERROR_NO_MEMORY;
break;
case XML_TOK_COMMENT:
if (!reportComment(parser, enc, s, next))
return XML_ERROR_NO_MEMORY;
break;
default:
if (defaultHandler)
reportDefault(parser, enc, s, next);
break;
}
*eventPP = s = next;
switch (ps_parsing) {
case XML_SUSPENDED:
*nextPtr = next;
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
default: ;
}
}
}
static enum XML_Error
storeAtts(XML_Parser parser, const ENCODING *enc,
const char *attStr, TAG_NAME *tagNamePtr,
BINDING **bindingsPtr)
{
DTD * const dtd = _dtd;
ELEMENT_TYPE *elementType;
int nDefaultAtts;
const XML_Char **appAtts;
int attIndex = 0;
int prefixLen;
int i;
int n;
XML_Char *uri;
int nPrefixes = 0;
BINDING *binding;
const XML_Char *localPart;
elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
if (!elementType) {
const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
if (!name)
return XML_ERROR_NO_MEMORY;
elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
sizeof(ELEMENT_TYPE));
if (!elementType)
return XML_ERROR_NO_MEMORY;
if (ns && !setElementTypePrefix(parser, elementType))
return XML_ERROR_NO_MEMORY;
}
nDefaultAtts = elementType->nDefaultAtts;
n = XmlGetAttributes(enc, attStr, attsSize, atts);
if (n + nDefaultAtts > attsSize) {
int oldAttsSize = attsSize;
ATTRIBUTE *temp;
#ifdef XML_ATTR_INFO
XML_AttrInfo *temp2;
#endif
attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
if (temp == NULL)
return XML_ERROR_NO_MEMORY;
atts = temp;
#ifdef XML_ATTR_INFO
temp2 = (XML_AttrInfo *)REALLOC((void *)attInfo, attsSize * sizeof(XML_AttrInfo));
if (temp2 == NULL)
return XML_ERROR_NO_MEMORY;
attInfo = temp2;
#endif
if (n > oldAttsSize)
XmlGetAttributes(enc, attStr, n, atts);
}
appAtts = (const XML_Char **)atts;
for (i = 0; i < n; i++) {
ATTRIBUTE *currAtt = &atts[i];
#ifdef XML_ATTR_INFO
XML_AttrInfo *currAttInfo = &attInfo[i];
#endif
ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
currAtt->name
+ XmlNameLength(enc, currAtt->name));
if (!attId)
return XML_ERROR_NO_MEMORY;
#ifdef XML_ATTR_INFO
currAttInfo->nameStart = parseEndByteIndex - (parseEndPtr - currAtt->name);
currAttInfo->nameEnd = currAttInfo->nameStart +
XmlNameLength(enc, currAtt->name);
currAttInfo->valueStart = parseEndByteIndex -
(parseEndPtr - currAtt->valuePtr);
currAttInfo->valueEnd = parseEndByteIndex - (parseEndPtr - currAtt->valueEnd);
#endif
if ((attId->name)[-1]) {
if (enc == encoding)
eventPtr = atts[i].name;
return XML_ERROR_DUPLICATE_ATTRIBUTE;
}
(attId->name)[-1] = 1;
appAtts[attIndex++] = attId->name;
if (!atts[i].normalized) {
enum XML_Error result;
XML_Bool isCdata = XML_TRUE;
if (attId->maybeTokenized) {
int j;
for (j = 0; j < nDefaultAtts; j++) {
if (attId == elementType->defaultAtts[j].id) {
isCdata = elementType->defaultAtts[j].isCdata;
break;
}
}
}
result = storeAttributeValue(parser, enc, isCdata,
atts[i].valuePtr, atts[i].valueEnd,
&tempPool);
if (result)
return result;
appAtts[attIndex] = poolStart(&tempPool);
poolFinish(&tempPool);
}
else {
appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
atts[i].valueEnd);
if (appAtts[attIndex] == 0)
return XML_ERROR_NO_MEMORY;
poolFinish(&tempPool);
}
if (attId->prefix) {
if (attId->xmlns) {
enum XML_Error result = addBinding(parser, attId->prefix, attId,
appAtts[attIndex], bindingsPtr);
if (result)
return result;
--attIndex;
}
else {
attIndex++;
nPrefixes++;
(attId->name)[-1] = 2;
}
}
else
attIndex++;
}
nSpecifiedAtts = attIndex;
if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
for (i = 0; i < attIndex; i += 2)
if (appAtts[i] == elementType->idAtt->name) {
idAttIndex = i;
break;
}
}
else
idAttIndex = -1;
for (i = 0; i < nDefaultAtts; i++) {
const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
if (!(da->id->name)[-1] && da->value) {
if (da->id->prefix) {
if (da->id->xmlns) {
enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
da->value, bindingsPtr);
if (result)
return result;
}
else {
(da->id->name)[-1] = 2;
nPrefixes++;
appAtts[attIndex++] = da->id->name;
appAtts[attIndex++] = da->value;
}
}
else {
(da->id->name)[-1] = 1;
appAtts[attIndex++] = da->id->name;
appAtts[attIndex++] = da->value;
}
}
}
appAtts[attIndex] = 0;
i = 0;
if (nPrefixes) {
int j;
unsigned long version = nsAttsVersion;
int nsAttsSize = (int)1 << nsAttsPower;
if ((nPrefixes << 1) >> nsAttsPower) {
NS_ATT *temp;
while (nPrefixes >> nsAttsPower++);
if (nsAttsPower < 3)
nsAttsPower = 3;
nsAttsSize = (int)1 << nsAttsPower;
temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
if (!temp)
return XML_ERROR_NO_MEMORY;
nsAtts = temp;
version = 0;
}
if (!version) {
version = INIT_ATTS_VERSION;
for (j = nsAttsSize; j != 0; )
nsAtts[--j].version = version;
}
nsAttsVersion = --version;
for (; i < attIndex; i += 2) {
const XML_Char *s = appAtts[i];
if (s[-1] == 2) {
ATTRIBUTE_ID *id;
const BINDING *b;
unsigned long uriHash = hash_secret_salt;
((XML_Char *)s)[-1] = 0;
id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
b = id->prefix->binding;
if (!b)
return XML_ERROR_UNBOUND_PREFIX;
for (j = 0; j < b->uriLen; j++) {
const XML_Char c = b->uri[j];
if (!poolAppendChar(&tempPool, c))
return XML_ERROR_NO_MEMORY;
uriHash = CHAR_HASH(uriHash, c);
}
while (*s++ != XML_T(ASCII_COLON))
;
do {
const XML_Char c = *s;
if (!poolAppendChar(&tempPool, *s))
return XML_ERROR_NO_MEMORY;
uriHash = CHAR_HASH(uriHash, c);
} while (*s++);
{
unsigned char step = 0;
unsigned long mask = nsAttsSize - 1;
j = uriHash & mask;
while (nsAtts[j].version == version) {
if (uriHash == nsAtts[j].hash) {
const XML_Char *s1 = poolStart(&tempPool);
const XML_Char *s2 = nsAtts[j].uriName;
for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
if (*s1 == 0)
return XML_ERROR_DUPLICATE_ATTRIBUTE;
}
if (!step)
step = PROBE_STEP(uriHash, mask, nsAttsPower);
j < step ? (j += nsAttsSize - step) : (j -= step);
}
}
if (ns_triplets) {
tempPool.ptr[-1] = namespaceSeparator;
s = b->prefix->name;
do {
if (!poolAppendChar(&tempPool, *s))
return XML_ERROR_NO_MEMORY;
} while (*s++);
}
s = poolStart(&tempPool);
poolFinish(&tempPool);
appAtts[i] = s;
nsAtts[j].version = version;
nsAtts[j].hash = uriHash;
nsAtts[j].uriName = s;
if (!--nPrefixes) {
i += 2;
break;
}
}
else
((XML_Char *)s)[-1] = 0;
}
}
for (; i < attIndex; i += 2)
((XML_Char *)(appAtts[i]))[-1] = 0;
for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
binding->attId->name[-1] = 0;
if (!ns)
return XML_ERROR_NONE;
if (elementType->prefix) {
binding = elementType->prefix->binding;
if (!binding)
return XML_ERROR_UNBOUND_PREFIX;
localPart = tagNamePtr->str;
while (*localPart++ != XML_T(ASCII_COLON))
;
}
else if (dtd->defaultPrefix.binding) {
binding = dtd->defaultPrefix.binding;
localPart = tagNamePtr->str;
}
else
return XML_ERROR_NONE;
prefixLen = 0;
if (ns_triplets && binding->prefix->name) {
for (; binding->prefix->name[prefixLen++];)
;
}
tagNamePtr->localPart = localPart;
tagNamePtr->uriLen = binding->uriLen;
tagNamePtr->prefix = binding->prefix->name;
tagNamePtr->prefixLen = prefixLen;
for (i = 0; localPart[i++];)
;
n = i + binding->uriLen + prefixLen;
if (n > binding->uriAlloc) {
TAG *p;
uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
if (!uri)
return XML_ERROR_NO_MEMORY;
binding->uriAlloc = n + EXPAND_SPARE;
memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
for (p = tagStack; p; p = p->parent)
if (p->name.str == binding->uri)
p->name.str = uri;
FREE(binding->uri);
binding->uri = uri;
}
uri = binding->uri + binding->uriLen;
memcpy(uri, localPart, i * sizeof(XML_Char));
if (prefixLen) {
uri += i - 1;
*uri = namespaceSeparator;
memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
}
tagNamePtr->str = binding->uri;
return XML_ERROR_NONE;
}
static enum XML_Error
addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
const XML_Char *uri, BINDING **bindingsPtr)
{
static const XML_Char xmlNamespace[] = {
ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
ASCII_e, '\0'
};
static const int xmlLen =
(int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
static const XML_Char xmlnsNamespace[] = {
ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
ASCII_SLASH, '\0'
};
static const int xmlnsLen =
(int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
XML_Bool mustBeXML = XML_FALSE;
XML_Bool isXML = XML_TRUE;
XML_Bool isXMLNS = XML_TRUE;
BINDING *b;
int len;
if (*uri == XML_T('\0') && prefix->name)
return XML_ERROR_UNDECLARING_PREFIX;
if (prefix->name
&& prefix->name[0] == XML_T(ASCII_x)
&& prefix->name[1] == XML_T(ASCII_m)
&& prefix->name[2] == XML_T(ASCII_l)) {
if (prefix->name[3] == XML_T(ASCII_n)
&& prefix->name[4] == XML_T(ASCII_s)
&& prefix->name[5] == XML_T('\0'))
return XML_ERROR_RESERVED_PREFIX_XMLNS;
if (prefix->name[3] == XML_T('\0'))
mustBeXML = XML_TRUE;
}
for (len = 0; uri[len]; len++) {
if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
isXML = XML_FALSE;
if (!mustBeXML && isXMLNS
&& (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
isXMLNS = XML_FALSE;
}
isXML = isXML && len == xmlLen;
isXMLNS = isXMLNS && len == xmlnsLen;
if (mustBeXML != isXML)
return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
: XML_ERROR_RESERVED_NAMESPACE_URI;
if (isXMLNS)
return XML_ERROR_RESERVED_NAMESPACE_URI;
if (namespaceSeparator)
len++;
if (freeBindingList) {
b = freeBindingList;
if (len > b->uriAlloc) {
XML_Char *temp = (XML_Char *)REALLOC(b->uri,
sizeof(XML_Char) * (len + EXPAND_SPARE));
if (temp == NULL)
return XML_ERROR_NO_MEMORY;
b->uri = temp;
b->uriAlloc = len + EXPAND_SPARE;
}
freeBindingList = b->nextTagBinding;
}
else {
b = (BINDING *)MALLOC(sizeof(BINDING));
if (!b)
return XML_ERROR_NO_MEMORY;
b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
if (!b->uri) {
FREE(b);
return XML_ERROR_NO_MEMORY;
}
b->uriAlloc = len + EXPAND_SPARE;
}
b->uriLen = len;
memcpy(b->uri, uri, len * sizeof(XML_Char));
if (namespaceSeparator)
b->uri[len - 1] = namespaceSeparator;
b->prefix = prefix;
b->attId = attId;
b->prevPrefixBinding = prefix->binding;
if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
prefix->binding = NULL;
else
prefix->binding = b;
b->nextTagBinding = *bindingsPtr;
*bindingsPtr = b;
if (attId && startNamespaceDeclHandler)
startNamespaceDeclHandler(handlerArg, prefix->name,
prefix->binding ? uri : 0);
return XML_ERROR_NONE;
}
static enum XML_Error PTRCALL
cdataSectionProcessor(XML_Parser parser,
const char *start,
const char *end,
const char **endPtr)
{
enum XML_Error result = doCdataSection(parser, encoding, &start, end,
endPtr, (XML_Bool)!ps_finalBuffer);
if (result != XML_ERROR_NONE)
return result;
if (start) {
if (parentParser) {
processor = externalEntityContentProcessor;
return externalEntityContentProcessor(parser, start, end, endPtr);
}
else {
processor = contentProcessor;
return contentProcessor(parser, start, end, endPtr);
}
}
return result;
}
static enum XML_Error
doCdataSection(XML_Parser parser,
const ENCODING *enc,
const char **startPtr,
const char *end,
const char **nextPtr,
XML_Bool haveMore)
{
const char *s = *startPtr;
const char **eventPP;
const char **eventEndPP;
if (enc == encoding) {
eventPP = &eventPtr;
*eventPP = s;
eventEndPP = &eventEndPtr;
}
else {
eventPP = &(openInternalEntities->internalEventPtr);
eventEndPP = &(openInternalEntities->internalEventEndPtr);
}
*eventPP = s;
*startPtr = NULL;
for (;;) {
const char *next;
int tok = XmlCdataSectionTok(enc, s, end, &next);
*eventEndPP = next;
switch (tok) {
case XML_TOK_CDATA_SECT_CLOSE:
if (endCdataSectionHandler)
endCdataSectionHandler(handlerArg);
#if 0
else if (characterDataHandler)
characterDataHandler(handlerArg, dataBuf, 0);
#endif
else if (defaultHandler)
reportDefault(parser, enc, s, next);
*startPtr = next;
*nextPtr = next;
if (ps_parsing == XML_FINISHED)
return XML_ERROR_ABORTED;
else
return XML_ERROR_NONE;
case XML_TOK_DATA_NEWLINE:
if (characterDataHandler) {
XML_Char c = 0xA;
characterDataHandler(handlerArg, &c, 1);
}
else if (defaultHandler)
reportDefault(parser, enc, s, next);
break;
case XML_TOK_DATA_CHARS:
{
XML_CharacterDataHandler charDataHandler = characterDataHandler;
if (charDataHandler) {
if (MUST_CONVERT(enc, s)) {
for (;;) {
ICHAR *dataPtr = (ICHAR *)dataBuf;
XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
*eventEndPP = next;
charDataHandler(handlerArg, dataBuf,
(int)(dataPtr - (ICHAR *)dataBuf));
if (s == next)
break;
*eventPP = s;
}
}
else
charDataHandler(handlerArg,
(XML_Char *)s,
(int)((XML_Char *)next - (XML_Char *)s));
}
else if (defaultHandler)
reportDefault(parser, enc, s, next);
}
break;
case XML_TOK_INVALID:
*eventPP = next;
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_PARTIAL_CHAR:
if (haveMore) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_PARTIAL_CHAR;
case XML_TOK_PARTIAL:
case XML_TOK_NONE:
if (haveMore) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_UNCLOSED_CDATA_SECTION;
default:
*eventPP = next;
return XML_ERROR_UNEXPECTED_STATE;
}
*eventPP = s = next;
switch (ps_parsing) {
case XML_SUSPENDED:
*nextPtr = next;
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
default: ;
}
}
}
#ifdef XML_DTD
static enum XML_Error PTRCALL
ignoreSectionProcessor(XML_Parser parser,
const char *start,
const char *end,
const char **endPtr)
{
enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
endPtr, (XML_Bool)!ps_finalBuffer);
if (result != XML_ERROR_NONE)
return result;
if (start) {
processor = prologProcessor;
return prologProcessor(parser, start, end, endPtr);
}
return result;
}
static enum XML_Error
doIgnoreSection(XML_Parser parser,
const ENCODING *enc,
const char **startPtr,
const char *end,
const char **nextPtr,
XML_Bool haveMore)
{
const char *next;
int tok;
const char *s = *startPtr;
const char **eventPP;
const char **eventEndPP;
if (enc == encoding) {
eventPP = &eventPtr;
*eventPP = s;
eventEndPP = &eventEndPtr;
}
else {
eventPP = &(openInternalEntities->internalEventPtr);
eventEndPP = &(openInternalEntities->internalEventEndPtr);
}
*eventPP = s;
*startPtr = NULL;
tok = XmlIgnoreSectionTok(enc, s, end, &next);
*eventEndPP = next;
switch (tok) {
case XML_TOK_IGNORE_SECT:
if (defaultHandler)
reportDefault(parser, enc, s, next);
*startPtr = next;
*nextPtr = next;
if (ps_parsing == XML_FINISHED)
return XML_ERROR_ABORTED;
else
return XML_ERROR_NONE;
case XML_TOK_INVALID:
*eventPP = next;
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_PARTIAL_CHAR:
if (haveMore) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_PARTIAL_CHAR;
case XML_TOK_PARTIAL:
case XML_TOK_NONE:
if (haveMore) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_SYNTAX;
default:
*eventPP = next;
return XML_ERROR_UNEXPECTED_STATE;
}
}
#endif
static enum XML_Error
initializeEncoding(XML_Parser parser)
{
const char *s;
#ifdef XML_UNICODE
char encodingBuf[128];
if (!protocolEncodingName)
s = NULL;
else {
int i;
for (i = 0; protocolEncodingName[i]; i++) {
if (i == sizeof(encodingBuf) - 1
|| (protocolEncodingName[i] & ~0x7f) != 0) {
encodingBuf[0] = '\0';
break;
}
encodingBuf[i] = (char)protocolEncodingName[i];
}
encodingBuf[i] = '\0';
s = encodingBuf;
}
#else
s = protocolEncodingName;
#endif
if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
return XML_ERROR_NONE;
return handleUnknownEncoding(parser, protocolEncodingName);
}
static enum XML_Error
processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
const char *s, const char *next)
{
const char *encodingName = NULL;
const XML_Char *storedEncName = NULL;
const ENCODING *newEncoding = NULL;
const char *version = NULL;
const char *versionend;
const XML_Char *storedversion = NULL;
int standalone = -1;
if (!(ns
? XmlParseXmlDeclNS
: XmlParseXmlDecl)(isGeneralTextEntity,
encoding,
s,
next,
&eventPtr,
&version,
&versionend,
&encodingName,
&newEncoding,
&standalone)) {
if (isGeneralTextEntity)
return XML_ERROR_TEXT_DECL;
else
return XML_ERROR_XML_DECL;
}
if (!isGeneralTextEntity && standalone == 1) {
_dtd->standalone = XML_TRUE;
#ifdef XML_DTD
if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
#endif
}
if (xmlDeclHandler) {
if (encodingName != NULL) {
storedEncName = poolStoreString(&temp2Pool,
encoding,
encodingName,
encodingName
+ XmlNameLength(encoding, encodingName));
if (!storedEncName)
return XML_ERROR_NO_MEMORY;
poolFinish(&temp2Pool);
}
if (version) {
storedversion = poolStoreString(&temp2Pool,
encoding,
version,
versionend - encoding->minBytesPerChar);
if (!storedversion)
return XML_ERROR_NO_MEMORY;
}
xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
}
else if (defaultHandler)
reportDefault(parser, encoding, s, next);
if (protocolEncodingName == NULL) {
if (newEncoding) {
if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
eventPtr = encodingName;
return XML_ERROR_INCORRECT_ENCODING;
}
encoding = newEncoding;
}
else if (encodingName) {
enum XML_Error result;
if (!storedEncName) {
storedEncName = poolStoreString(
&temp2Pool, encoding, encodingName,
encodingName + XmlNameLength(encoding, encodingName));
if (!storedEncName)
return XML_ERROR_NO_MEMORY;
}
result = handleUnknownEncoding(parser, storedEncName);
poolClear(&temp2Pool);
if (result == XML_ERROR_UNKNOWN_ENCODING)
eventPtr = encodingName;
return result;
}
}
if (storedEncName || storedversion)
poolClear(&temp2Pool);
return XML_ERROR_NONE;
}
static enum XML_Error
handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
{
if (unknownEncodingHandler) {
XML_Encoding info;
int i;
for (i = 0; i < 256; i++)
info.map[i] = -1;
info.convert = NULL;
info.data = NULL;
info.release = NULL;
if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
&info)) {
ENCODING *enc;
unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
if (!unknownEncodingMem) {
if (info.release)
info.release(info.data);
return XML_ERROR_NO_MEMORY;
}
enc = (ns
? XmlInitUnknownEncodingNS
: XmlInitUnknownEncoding)(unknownEncodingMem,
info.map,
info.convert,
info.data);
if (enc) {
unknownEncodingData = info.data;
unknownEncodingRelease = info.release;
encoding = enc;
return XML_ERROR_NONE;
}
}
if (info.release != NULL)
info.release(info.data);
}
return XML_ERROR_UNKNOWN_ENCODING;
}
static enum XML_Error PTRCALL
prologInitProcessor(XML_Parser parser,
const char *s,
const char *end,
const char **nextPtr)
{
enum XML_Error result = initializeEncoding(parser);
if (result != XML_ERROR_NONE)
return result;
processor = prologProcessor;
return prologProcessor(parser, s, end, nextPtr);
}
#ifdef XML_DTD
static enum XML_Error PTRCALL
externalParEntInitProcessor(XML_Parser parser,
const char *s,
const char *end,
const char **nextPtr)
{
enum XML_Error result = initializeEncoding(parser);
if (result != XML_ERROR_NONE)
return result;
_dtd->paramEntityRead = XML_TRUE;
if (prologState.inEntityValue) {
processor = entityValueInitProcessor;
return entityValueInitProcessor(parser, s, end, nextPtr);
}
else {
processor = externalParEntProcessor;
return externalParEntProcessor(parser, s, end, nextPtr);
}
}
static enum XML_Error PTRCALL
entityValueInitProcessor(XML_Parser parser,
const char *s,
const char *end,
const char **nextPtr)
{
int tok;
const char *start = s;
const char *next = start;
eventPtr = start;
for (;;) {
tok = XmlPrologTok(encoding, start, end, &next);
eventEndPtr = next;
if (tok <= 0) {
if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
*nextPtr = s;
return XML_ERROR_NONE;
}
switch (tok) {
case XML_TOK_INVALID:
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_PARTIAL:
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
return XML_ERROR_PARTIAL_CHAR;
case XML_TOK_NONE:
default:
break;
}
return storeEntityValue(parser, encoding, s, end);
}
else if (tok == XML_TOK_XML_DECL) {
enum XML_Error result;
result = processXmlDecl(parser, 0, start, next);
if (result != XML_ERROR_NONE)
return result;
switch (ps_parsing) {
case XML_SUSPENDED:
*nextPtr = next;
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
default:
*nextPtr = next;
}
processor = entityValueProcessor;
return entityValueProcessor(parser, next, end, nextPtr);
}
else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
*nextPtr = next;
return XML_ERROR_NONE;
}
start = next;
eventPtr = start;
}
}
static enum XML_Error PTRCALL
externalParEntProcessor(XML_Parser parser,
const char *s,
const char *end,
const char **nextPtr)
{
const char *next = s;
int tok;
tok = XmlPrologTok(encoding, s, end, &next);
if (tok <= 0) {
if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
*nextPtr = s;
return XML_ERROR_NONE;
}
switch (tok) {
case XML_TOK_INVALID:
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_PARTIAL:
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
return XML_ERROR_PARTIAL_CHAR;
case XML_TOK_NONE:
default:
break;
}
}
else if (tok == XML_TOK_BOM) {
s = next;
tok = XmlPrologTok(encoding, s, end, &next);
}
processor = prologProcessor;
return doProlog(parser, encoding, s, end, tok, next,
nextPtr, (XML_Bool)!ps_finalBuffer);
}
static enum XML_Error PTRCALL
entityValueProcessor(XML_Parser parser,
const char *s,
const char *end,
const char **nextPtr)
{
const char *start = s;
const char *next = s;
const ENCODING *enc = encoding;
int tok;
for (;;) {
tok = XmlPrologTok(enc, start, end, &next);
if (tok <= 0) {
if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
*nextPtr = s;
return XML_ERROR_NONE;
}
switch (tok) {
case XML_TOK_INVALID:
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_PARTIAL:
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
return XML_ERROR_PARTIAL_CHAR;
case XML_TOK_NONE:
default:
break;
}
return storeEntityValue(parser, enc, s, end);
}
start = next;
}
}
#endif
static enum XML_Error PTRCALL
prologProcessor(XML_Parser parser,
const char *s,
const char *end,
const char **nextPtr)
{
const char *next = s;
int tok = XmlPrologTok(encoding, s, end, &next);
return doProlog(parser, encoding, s, end, tok, next,
nextPtr, (XML_Bool)!ps_finalBuffer);
}
static enum XML_Error
doProlog(XML_Parser parser,
const ENCODING *enc,
const char *s,
const char *end,
int tok,
const char *next,
const char **nextPtr,
XML_Bool haveMore)
{
#ifdef XML_DTD
static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
#endif
static const XML_Char atypeCDATA[] =
{ ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
static const XML_Char atypeIDREF[] =
{ ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
static const XML_Char atypeIDREFS[] =
{ ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
static const XML_Char atypeENTITY[] =
{ ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
static const XML_Char atypeNMTOKEN[] = {
ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
DTD * const dtd = _dtd;
const char **eventPP;
const char **eventEndPP;
enum XML_Content_Quant quant;
if (enc == encoding) {
eventPP = &eventPtr;
eventEndPP = &eventEndPtr;
}
else {
eventPP = &(openInternalEntities->internalEventPtr);
eventEndPP = &(openInternalEntities->internalEventEndPtr);
}
for (;;) {
int role;
XML_Bool handleDefault = XML_TRUE;
*eventPP = s;
*eventEndPP = next;
if (tok <= 0) {
if (haveMore && tok != XML_TOK_INVALID) {
*nextPtr = s;
return XML_ERROR_NONE;
}
switch (tok) {
case XML_TOK_INVALID:
*eventPP = next;
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_PARTIAL:
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
return XML_ERROR_PARTIAL_CHAR;
case -XML_TOK_PROLOG_S:
tok = -tok;
break;
case XML_TOK_NONE:
#ifdef XML_DTD
if (enc != encoding && !openInternalEntities->betweenDecl) {
*nextPtr = s;
return XML_ERROR_NONE;
}
if (isParamEntity || enc != encoding) {
if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
== XML_ROLE_ERROR)
return XML_ERROR_INCOMPLETE_PE;
*nextPtr = s;
return XML_ERROR_NONE;
}
#endif
return XML_ERROR_NO_ELEMENTS;
default:
tok = -tok;
next = end;
break;
}
}
role = XmlTokenRole(&prologState, tok, s, next, enc);
switch (role) {
case XML_ROLE_XML_DECL:
{
enum XML_Error result = processXmlDecl(parser, 0, s, next);
if (result != XML_ERROR_NONE)
return result;
enc = encoding;
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_DOCTYPE_NAME:
if (startDoctypeDeclHandler) {
doctypeName = poolStoreString(&tempPool, enc, s, next);
if (!doctypeName)
return XML_ERROR_NO_MEMORY;
poolFinish(&tempPool);
doctypePubid = NULL;
handleDefault = XML_FALSE;
}
doctypeSysid = NULL;
break;
case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
if (startDoctypeDeclHandler) {
startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
doctypePubid, 1);
doctypeName = NULL;
poolClear(&tempPool);
handleDefault = XML_FALSE;
}
break;
#ifdef XML_DTD
case XML_ROLE_TEXT_DECL:
{
enum XML_Error result = processXmlDecl(parser, 1, s, next);
if (result != XML_ERROR_NONE)
return result;
enc = encoding;
handleDefault = XML_FALSE;
}
break;
#endif
case XML_ROLE_DOCTYPE_PUBLIC_ID:
#ifdef XML_DTD
useForeignDTD = XML_FALSE;
declEntity = (ENTITY *)lookup(parser,
&dtd->paramEntities,
externalSubsetName,
sizeof(ENTITY));
if (!declEntity)
return XML_ERROR_NO_MEMORY;
#endif
dtd->hasParamEntityRefs = XML_TRUE;
if (startDoctypeDeclHandler) {
XML_Char *pubId;
if (!XmlIsPublicId(enc, s, next, eventPP))
return XML_ERROR_PUBLICID;
pubId = poolStoreString(&tempPool, enc,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (!pubId)
return XML_ERROR_NO_MEMORY;
normalizePublicId(pubId);
poolFinish(&tempPool);
doctypePubid = pubId;
handleDefault = XML_FALSE;
goto alreadyChecked;
}
case XML_ROLE_ENTITY_PUBLIC_ID:
if (!XmlIsPublicId(enc, s, next, eventPP))
return XML_ERROR_PUBLICID;
alreadyChecked:
if (dtd->keepProcessing && declEntity) {
XML_Char *tem = poolStoreString(&dtd->pool,
enc,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (!tem)
return XML_ERROR_NO_MEMORY;
normalizePublicId(tem);
declEntity->publicId = tem;
poolFinish(&dtd->pool);
if (entityDeclHandler)
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_DOCTYPE_CLOSE:
if (doctypeName) {
startDoctypeDeclHandler(handlerArg, doctypeName,
doctypeSysid, doctypePubid, 0);
poolClear(&tempPool);
handleDefault = XML_FALSE;
}
#ifdef XML_DTD
if (doctypeSysid || useForeignDTD) {
XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
dtd->hasParamEntityRefs = XML_TRUE;
if (paramEntityParsing && externalEntityRefHandler) {
ENTITY *entity = (ENTITY *)lookup(parser,
&dtd->paramEntities,
externalSubsetName,
sizeof(ENTITY));
if (!entity)
return XML_ERROR_NO_MEMORY;
if (useForeignDTD)
entity->base = curBase;
dtd->paramEntityRead = XML_FALSE;
if (!externalEntityRefHandler(externalEntityRefHandlerArg,
0,
entity->base,
entity->systemId,
entity->publicId))
return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
if (dtd->paramEntityRead) {
if (!dtd->standalone &&
notStandaloneHandler &&
!notStandaloneHandler(handlerArg))
return XML_ERROR_NOT_STANDALONE;
}
else if (!doctypeSysid)
dtd->hasParamEntityRefs = hadParamEntityRefs;
}
useForeignDTD = XML_FALSE;
}
#endif
if (endDoctypeDeclHandler) {
endDoctypeDeclHandler(handlerArg);
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_INSTANCE_START:
#ifdef XML_DTD
if (useForeignDTD) {
XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
dtd->hasParamEntityRefs = XML_TRUE;
if (paramEntityParsing && externalEntityRefHandler) {
ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
externalSubsetName,
sizeof(ENTITY));
if (!entity)
return XML_ERROR_NO_MEMORY;
entity->base = curBase;
dtd->paramEntityRead = XML_FALSE;
if (!externalEntityRefHandler(externalEntityRefHandlerArg,
0,
entity->base,
entity->systemId,
entity->publicId))
return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
if (dtd->paramEntityRead) {
if (!dtd->standalone &&
notStandaloneHandler &&
!notStandaloneHandler(handlerArg))
return XML_ERROR_NOT_STANDALONE;
}
else
dtd->hasParamEntityRefs = hadParamEntityRefs;
}
}
#endif
processor = contentProcessor;
return contentProcessor(parser, s, end, nextPtr);
case XML_ROLE_ATTLIST_ELEMENT_NAME:
declElementType = getElementType(parser, enc, s, next);
if (!declElementType)
return XML_ERROR_NO_MEMORY;
goto checkAttListDeclHandler;
case XML_ROLE_ATTRIBUTE_NAME:
declAttributeId = getAttributeId(parser, enc, s, next);
if (!declAttributeId)
return XML_ERROR_NO_MEMORY;
declAttributeIsCdata = XML_FALSE;
declAttributeType = NULL;
declAttributeIsId = XML_FALSE;
goto checkAttListDeclHandler;
case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
declAttributeIsCdata = XML_TRUE;
declAttributeType = atypeCDATA;
goto checkAttListDeclHandler;
case XML_ROLE_ATTRIBUTE_TYPE_ID:
declAttributeIsId = XML_TRUE;
declAttributeType = atypeID;
goto checkAttListDeclHandler;
case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
declAttributeType = atypeIDREF;
goto checkAttListDeclHandler;
case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
declAttributeType = atypeIDREFS;
goto checkAttListDeclHandler;
case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
declAttributeType = atypeENTITY;
goto checkAttListDeclHandler;
case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
declAttributeType = atypeENTITIES;
goto checkAttListDeclHandler;
case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
declAttributeType = atypeNMTOKEN;
goto checkAttListDeclHandler;
case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
declAttributeType = atypeNMTOKENS;
checkAttListDeclHandler:
if (dtd->keepProcessing && attlistDeclHandler)
handleDefault = XML_FALSE;
break;
case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
if (dtd->keepProcessing && attlistDeclHandler) {
const XML_Char *prefix;
if (declAttributeType) {
prefix = enumValueSep;
}
else {
prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
? notationPrefix
: enumValueStart);
}
if (!poolAppendString(&tempPool, prefix))
return XML_ERROR_NO_MEMORY;
if (!poolAppend(&tempPool, enc, s, next))
return XML_ERROR_NO_MEMORY;
declAttributeType = tempPool.start;
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
if (dtd->keepProcessing) {
if (!defineAttribute(declElementType, declAttributeId,
declAttributeIsCdata, declAttributeIsId,
0, parser))
return XML_ERROR_NO_MEMORY;
if (attlistDeclHandler && declAttributeType) {
if (*declAttributeType == XML_T(ASCII_LPAREN)
|| (*declAttributeType == XML_T(ASCII_N)
&& declAttributeType[1] == XML_T(ASCII_O))) {
if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
|| !poolAppendChar(&tempPool, XML_T('\0')))
return XML_ERROR_NO_MEMORY;
declAttributeType = tempPool.start;
poolFinish(&tempPool);
}
*eventEndPP = s;
attlistDeclHandler(handlerArg, declElementType->name,
declAttributeId->name, declAttributeType,
0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
poolClear(&tempPool);
handleDefault = XML_FALSE;
}
}
break;
case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
if (dtd->keepProcessing) {
const XML_Char *attVal;
enum XML_Error result =
storeAttributeValue(parser, enc, declAttributeIsCdata,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar,
&dtd->pool);
if (result)
return result;
attVal = poolStart(&dtd->pool);
poolFinish(&dtd->pool);
if (!defineAttribute(declElementType, declAttributeId,
declAttributeIsCdata, XML_FALSE, attVal, parser))
return XML_ERROR_NO_MEMORY;
if (attlistDeclHandler && declAttributeType) {
if (*declAttributeType == XML_T(ASCII_LPAREN)
|| (*declAttributeType == XML_T(ASCII_N)
&& declAttributeType[1] == XML_T(ASCII_O))) {
if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
|| !poolAppendChar(&tempPool, XML_T('\0')))
return XML_ERROR_NO_MEMORY;
declAttributeType = tempPool.start;
poolFinish(&tempPool);
}
*eventEndPP = s;
attlistDeclHandler(handlerArg, declElementType->name,
declAttributeId->name, declAttributeType,
attVal,
role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
poolClear(&tempPool);
handleDefault = XML_FALSE;
}
}
break;
case XML_ROLE_ENTITY_VALUE:
if (dtd->keepProcessing) {
enum XML_Error result = storeEntityValue(parser, enc,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (declEntity) {
declEntity->textPtr = poolStart(&dtd->entityValuePool);
declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
poolFinish(&dtd->entityValuePool);
if (entityDeclHandler) {
*eventEndPP = s;
entityDeclHandler(handlerArg,
declEntity->name,
declEntity->is_param,
declEntity->textPtr,
declEntity->textLen,
curBase, 0, 0, 0);
handleDefault = XML_FALSE;
}
}
else
poolDiscard(&dtd->entityValuePool);
if (result != XML_ERROR_NONE)
return result;
}
break;
case XML_ROLE_DOCTYPE_SYSTEM_ID:
#ifdef XML_DTD
useForeignDTD = XML_FALSE;
#endif
dtd->hasParamEntityRefs = XML_TRUE;
if (startDoctypeDeclHandler) {
doctypeSysid = poolStoreString(&tempPool, enc,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (doctypeSysid == NULL)
return XML_ERROR_NO_MEMORY;
poolFinish(&tempPool);
handleDefault = XML_FALSE;
}
#ifdef XML_DTD
else
doctypeSysid = externalSubsetName;
#endif
if (!dtd->standalone
#ifdef XML_DTD
&& !paramEntityParsing
#endif
&& notStandaloneHandler
&& !notStandaloneHandler(handlerArg))
return XML_ERROR_NOT_STANDALONE;
#ifndef XML_DTD
break;
#else
if (!declEntity) {
declEntity = (ENTITY *)lookup(parser,
&dtd->paramEntities,
externalSubsetName,
sizeof(ENTITY));
if (!declEntity)
return XML_ERROR_NO_MEMORY;
declEntity->publicId = NULL;
}
#endif
case XML_ROLE_ENTITY_SYSTEM_ID:
if (dtd->keepProcessing && declEntity) {
declEntity->systemId = poolStoreString(&dtd->pool, enc,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (!declEntity->systemId)
return XML_ERROR_NO_MEMORY;
declEntity->base = curBase;
poolFinish(&dtd->pool);
if (entityDeclHandler)
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_ENTITY_COMPLETE:
if (dtd->keepProcessing && declEntity && entityDeclHandler) {
*eventEndPP = s;
entityDeclHandler(handlerArg,
declEntity->name,
declEntity->is_param,
0,0,
declEntity->base,
declEntity->systemId,
declEntity->publicId,
0);
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_ENTITY_NOTATION_NAME:
if (dtd->keepProcessing && declEntity) {
declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
if (!declEntity->notation)
return XML_ERROR_NO_MEMORY;
poolFinish(&dtd->pool);
if (unparsedEntityDeclHandler) {
*eventEndPP = s;
unparsedEntityDeclHandler(handlerArg,
declEntity->name,
declEntity->base,
declEntity->systemId,
declEntity->publicId,
declEntity->notation);
handleDefault = XML_FALSE;
}
else if (entityDeclHandler) {
*eventEndPP = s;
entityDeclHandler(handlerArg,
declEntity->name,
0,0,0,
declEntity->base,
declEntity->systemId,
declEntity->publicId,
declEntity->notation);
handleDefault = XML_FALSE;
}
}
break;
case XML_ROLE_GENERAL_ENTITY_NAME:
{
if (XmlPredefinedEntityName(enc, s, next)) {
declEntity = NULL;
break;
}
if (dtd->keepProcessing) {
const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
if (!name)
return XML_ERROR_NO_MEMORY;
declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
sizeof(ENTITY));
if (!declEntity)
return XML_ERROR_NO_MEMORY;
if (declEntity->name != name) {
poolDiscard(&dtd->pool);
declEntity = NULL;
}
else {
poolFinish(&dtd->pool);
declEntity->publicId = NULL;
declEntity->is_param = XML_FALSE;
declEntity->is_internal = !(parentParser || openInternalEntities);
if (entityDeclHandler)
handleDefault = XML_FALSE;
}
}
else {
poolDiscard(&dtd->pool);
declEntity = NULL;
}
}
break;
case XML_ROLE_PARAM_ENTITY_NAME:
#ifdef XML_DTD
if (dtd->keepProcessing) {
const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
if (!name)
return XML_ERROR_NO_MEMORY;
declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
name, sizeof(ENTITY));
if (!declEntity)
return XML_ERROR_NO_MEMORY;
if (declEntity->name != name) {
poolDiscard(&dtd->pool);
declEntity = NULL;
}
else {
poolFinish(&dtd->pool);
declEntity->publicId = NULL;
declEntity->is_param = XML_TRUE;
declEntity->is_internal = !(parentParser || openInternalEntities);
if (entityDeclHandler)
handleDefault = XML_FALSE;
}
}
else {
poolDiscard(&dtd->pool);
declEntity = NULL;
}
#else
declEntity = NULL;
#endif
break;
case XML_ROLE_NOTATION_NAME:
declNotationPublicId = NULL;
declNotationName = NULL;
if (notationDeclHandler) {
declNotationName = poolStoreString(&tempPool, enc, s, next);
if (!declNotationName)
return XML_ERROR_NO_MEMORY;
poolFinish(&tempPool);
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_NOTATION_PUBLIC_ID:
if (!XmlIsPublicId(enc, s, next, eventPP))
return XML_ERROR_PUBLICID;
if (declNotationName) {
XML_Char *tem = poolStoreString(&tempPool,
enc,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (!tem)
return XML_ERROR_NO_MEMORY;
normalizePublicId(tem);
declNotationPublicId = tem;
poolFinish(&tempPool);
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_NOTATION_SYSTEM_ID:
if (declNotationName && notationDeclHandler) {
const XML_Char *systemId
= poolStoreString(&tempPool, enc,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (!systemId)
return XML_ERROR_NO_MEMORY;
*eventEndPP = s;
notationDeclHandler(handlerArg,
declNotationName,
curBase,
systemId,
declNotationPublicId);
handleDefault = XML_FALSE;
}
poolClear(&tempPool);
break;
case XML_ROLE_NOTATION_NO_SYSTEM_ID:
if (declNotationPublicId && notationDeclHandler) {
*eventEndPP = s;
notationDeclHandler(handlerArg,
declNotationName,
curBase,
0,
declNotationPublicId);
handleDefault = XML_FALSE;
}
poolClear(&tempPool);
break;
case XML_ROLE_ERROR:
switch (tok) {
case XML_TOK_PARAM_ENTITY_REF:
return XML_ERROR_PARAM_ENTITY_REF;
case XML_TOK_XML_DECL:
return XML_ERROR_MISPLACED_XML_PI;
default:
return XML_ERROR_SYNTAX;
}
#ifdef XML_DTD
case XML_ROLE_IGNORE_SECT:
{
enum XML_Error result;
if (defaultHandler)
reportDefault(parser, enc, s, next);
handleDefault = XML_FALSE;
result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
if (result != XML_ERROR_NONE)
return result;
else if (!next) {
processor = ignoreSectionProcessor;
return result;
}
}
break;
#endif
case XML_ROLE_GROUP_OPEN:
if (prologState.level >= groupSize) {
if (groupSize) {
char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
if (temp == NULL)
return XML_ERROR_NO_MEMORY;
groupConnector = temp;
if (dtd->scaffIndex) {
int *temp = (int *)REALLOC(dtd->scaffIndex,
groupSize * sizeof(int));
if (temp == NULL)
return XML_ERROR_NO_MEMORY;
dtd->scaffIndex = temp;
}
}
else {
groupConnector = (char *)MALLOC(groupSize = 32);
if (!groupConnector)
return XML_ERROR_NO_MEMORY;
}
}
groupConnector[prologState.level] = 0;
if (dtd->in_eldecl) {
int myindex = nextScaffoldPart(parser);
if (myindex < 0)
return XML_ERROR_NO_MEMORY;
dtd->scaffIndex[dtd->scaffLevel] = myindex;
dtd->scaffLevel++;
dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
if (elementDeclHandler)
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_GROUP_SEQUENCE:
if (groupConnector[prologState.level] == ASCII_PIPE)
return XML_ERROR_SYNTAX;
groupConnector[prologState.level] = ASCII_COMMA;
if (dtd->in_eldecl && elementDeclHandler)
handleDefault = XML_FALSE;
break;
case XML_ROLE_GROUP_CHOICE:
if (groupConnector[prologState.level] == ASCII_COMMA)
return XML_ERROR_SYNTAX;
if (dtd->in_eldecl
&& !groupConnector[prologState.level]
&& (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
!= XML_CTYPE_MIXED)
) {
dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
= XML_CTYPE_CHOICE;
if (elementDeclHandler)
handleDefault = XML_FALSE;
}
groupConnector[prologState.level] = ASCII_PIPE;
break;
case XML_ROLE_PARAM_ENTITY_REF:
#ifdef XML_DTD
case XML_ROLE_INNER_PARAM_ENTITY_REF:
dtd->hasParamEntityRefs = XML_TRUE;
if (!paramEntityParsing)
dtd->keepProcessing = dtd->standalone;
else {
const XML_Char *name;
ENTITY *entity;
name = poolStoreString(&dtd->pool, enc,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (!name)
return XML_ERROR_NO_MEMORY;
entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
poolDiscard(&dtd->pool);
if (prologState.documentEntity &&
(dtd->standalone
? !openInternalEntities
: !dtd->hasParamEntityRefs)) {
if (!entity)
return XML_ERROR_UNDEFINED_ENTITY;
else if (!entity->is_internal)
return XML_ERROR_ENTITY_DECLARED_IN_PE;
}
else if (!entity) {
dtd->keepProcessing = dtd->standalone;
if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
skippedEntityHandler(handlerArg, name, 1);
handleDefault = XML_FALSE;
}
break;
}
if (entity->open)
return XML_ERROR_RECURSIVE_ENTITY_REF;
if (entity->textPtr) {
enum XML_Error result;
XML_Bool betweenDecl =
(role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
result = processInternalEntity(parser, entity, betweenDecl);
if (result != XML_ERROR_NONE)
return result;
handleDefault = XML_FALSE;
break;
}
if (externalEntityRefHandler) {
dtd->paramEntityRead = XML_FALSE;
entity->open = XML_TRUE;
if (!externalEntityRefHandler(externalEntityRefHandlerArg,
0,
entity->base,
entity->systemId,
entity->publicId)) {
entity->open = XML_FALSE;
return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
}
entity->open = XML_FALSE;
handleDefault = XML_FALSE;
if (!dtd->paramEntityRead) {
dtd->keepProcessing = dtd->standalone;
break;
}
}
else {
dtd->keepProcessing = dtd->standalone;
break;
}
}
#endif
if (!dtd->standalone &&
notStandaloneHandler &&
!notStandaloneHandler(handlerArg))
return XML_ERROR_NOT_STANDALONE;
break;
case XML_ROLE_ELEMENT_NAME:
if (elementDeclHandler) {
declElementType = getElementType(parser, enc, s, next);
if (!declElementType)
return XML_ERROR_NO_MEMORY;
dtd->scaffLevel = 0;
dtd->scaffCount = 0;
dtd->in_eldecl = XML_TRUE;
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_CONTENT_ANY:
case XML_ROLE_CONTENT_EMPTY:
if (dtd->in_eldecl) {
if (elementDeclHandler) {
XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
if (!content)
return XML_ERROR_NO_MEMORY;
content->quant = XML_CQUANT_NONE;
content->name = NULL;
content->numchildren = 0;
content->children = NULL;
content->type = ((role == XML_ROLE_CONTENT_ANY) ?
XML_CTYPE_ANY :
XML_CTYPE_EMPTY);
*eventEndPP = s;
elementDeclHandler(handlerArg, declElementType->name, content);
handleDefault = XML_FALSE;
}
dtd->in_eldecl = XML_FALSE;
}
break;
case XML_ROLE_CONTENT_PCDATA:
if (dtd->in_eldecl) {
dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
= XML_CTYPE_MIXED;
if (elementDeclHandler)
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_CONTENT_ELEMENT:
quant = XML_CQUANT_NONE;
goto elementContent;
case XML_ROLE_CONTENT_ELEMENT_OPT:
quant = XML_CQUANT_OPT;
goto elementContent;
case XML_ROLE_CONTENT_ELEMENT_REP:
quant = XML_CQUANT_REP;
goto elementContent;
case XML_ROLE_CONTENT_ELEMENT_PLUS:
quant = XML_CQUANT_PLUS;
elementContent:
if (dtd->in_eldecl) {
ELEMENT_TYPE *el;
const XML_Char *name;
int nameLen;
const char *nxt = (quant == XML_CQUANT_NONE
? next
: next - enc->minBytesPerChar);
int myindex = nextScaffoldPart(parser);
if (myindex < 0)
return XML_ERROR_NO_MEMORY;
dtd->scaffold[myindex].type = XML_CTYPE_NAME;
dtd->scaffold[myindex].quant = quant;
el = getElementType(parser, enc, s, nxt);
if (!el)
return XML_ERROR_NO_MEMORY;
name = el->name;
dtd->scaffold[myindex].name = name;
nameLen = 0;
for (; name[nameLen++]; );
dtd->contentStringLen += nameLen;
if (elementDeclHandler)
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_GROUP_CLOSE:
quant = XML_CQUANT_NONE;
goto closeGroup;
case XML_ROLE_GROUP_CLOSE_OPT:
quant = XML_CQUANT_OPT;
goto closeGroup;
case XML_ROLE_GROUP_CLOSE_REP:
quant = XML_CQUANT_REP;
goto closeGroup;
case XML_ROLE_GROUP_CLOSE_PLUS:
quant = XML_CQUANT_PLUS;
closeGroup:
if (dtd->in_eldecl) {
if (elementDeclHandler)
handleDefault = XML_FALSE;
dtd->scaffLevel--;
dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
if (dtd->scaffLevel == 0) {
if (!handleDefault) {
XML_Content *model = build_model(parser);
if (!model)
return XML_ERROR_NO_MEMORY;
*eventEndPP = s;
elementDeclHandler(handlerArg, declElementType->name, model);
}
dtd->in_eldecl = XML_FALSE;
dtd->contentStringLen = 0;
}
}
break;
case XML_ROLE_PI:
if (!reportProcessingInstruction(parser, enc, s, next))
return XML_ERROR_NO_MEMORY;
handleDefault = XML_FALSE;
break;
case XML_ROLE_COMMENT:
if (!reportComment(parser, enc, s, next))
return XML_ERROR_NO_MEMORY;
handleDefault = XML_FALSE;
break;
case XML_ROLE_NONE:
switch (tok) {
case XML_TOK_BOM:
handleDefault = XML_FALSE;
break;
}
break;
case XML_ROLE_DOCTYPE_NONE:
if (startDoctypeDeclHandler)
handleDefault = XML_FALSE;
break;
case XML_ROLE_ENTITY_NONE:
if (dtd->keepProcessing && entityDeclHandler)
handleDefault = XML_FALSE;
break;
case XML_ROLE_NOTATION_NONE:
if (notationDeclHandler)
handleDefault = XML_FALSE;
break;
case XML_ROLE_ATTLIST_NONE:
if (dtd->keepProcessing && attlistDeclHandler)
handleDefault = XML_FALSE;
break;
case XML_ROLE_ELEMENT_NONE:
if (elementDeclHandler)
handleDefault = XML_FALSE;
break;
}
if (handleDefault && defaultHandler)
reportDefault(parser, enc, s, next);
switch (ps_parsing) {
case XML_SUSPENDED:
*nextPtr = next;
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
default:
s = next;
tok = XmlPrologTok(enc, s, end, &next);
}
}
}
static enum XML_Error PTRCALL
epilogProcessor(XML_Parser parser,
const char *s,
const char *end,
const char **nextPtr)
{
processor = epilogProcessor;
eventPtr = s;
for (;;) {
const char *next = NULL;
int tok = XmlPrologTok(encoding, s, end, &next);
eventEndPtr = next;
switch (tok) {
case -XML_TOK_PROLOG_S:
if (defaultHandler) {
reportDefault(parser, encoding, s, next);
if (ps_parsing == XML_FINISHED)
return XML_ERROR_ABORTED;
}
*nextPtr = next;
return XML_ERROR_NONE;
case XML_TOK_NONE:
*nextPtr = s;
return XML_ERROR_NONE;
case XML_TOK_PROLOG_S:
if (defaultHandler)
reportDefault(parser, encoding, s, next);
break;
case XML_TOK_PI:
if (!reportProcessingInstruction(parser, encoding, s, next))
return XML_ERROR_NO_MEMORY;
break;
case XML_TOK_COMMENT:
if (!reportComment(parser, encoding, s, next))
return XML_ERROR_NO_MEMORY;
break;
case XML_TOK_INVALID:
eventPtr = next;
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_PARTIAL:
if (!ps_finalBuffer) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
if (!ps_finalBuffer) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_PARTIAL_CHAR;
default:
return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
}
eventPtr = s = next;
switch (ps_parsing) {
case XML_SUSPENDED:
*nextPtr = next;
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
default: ;
}
}
}
static enum XML_Error
processInternalEntity(XML_Parser parser, ENTITY *entity,
XML_Bool betweenDecl)
{
const char *textStart, *textEnd;
const char *next;
enum XML_Error result;
OPEN_INTERNAL_ENTITY *openEntity;
if (freeInternalEntities) {
openEntity = freeInternalEntities;
freeInternalEntities = openEntity->next;
}
else {
openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
if (!openEntity)
return XML_ERROR_NO_MEMORY;
}
entity->open = XML_TRUE;
entity->processed = 0;
openEntity->next = openInternalEntities;
openInternalEntities = openEntity;
openEntity->entity = entity;
openEntity->startTagLevel = tagLevel;
openEntity->betweenDecl = betweenDecl;
openEntity->internalEventPtr = NULL;
openEntity->internalEventEndPtr = NULL;
textStart = (char *)entity->textPtr;
textEnd = (char *)(entity->textPtr + entity->textLen);
#ifdef XML_DTD
if (entity->is_param) {
int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
next, &next, XML_FALSE);
}
else
#endif
result = doContent(parser, tagLevel, internalEncoding, textStart,
textEnd, &next, XML_FALSE);
if (result == XML_ERROR_NONE) {
if (textEnd != next && ps_parsing == XML_SUSPENDED) {
entity->processed = (int)(next - textStart);
processor = internalEntityProcessor;
}
else {
entity->open = XML_FALSE;
openInternalEntities = openEntity->next;
openEntity->next = freeInternalEntities;
freeInternalEntities = openEntity;
}
}
return result;
}
static enum XML_Error PTRCALL
internalEntityProcessor(XML_Parser parser,
const char *s,
const char *end,
const char **nextPtr)
{
ENTITY *entity;
const char *textStart, *textEnd;
const char *next;
enum XML_Error result;
OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
if (!openEntity)
return XML_ERROR_UNEXPECTED_STATE;
entity = openEntity->entity;
textStart = ((char *)entity->textPtr) + entity->processed;
textEnd = (char *)(entity->textPtr + entity->textLen);
#ifdef XML_DTD
if (entity->is_param) {
int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
next, &next, XML_FALSE);
}
else
#endif
result = doContent(parser, openEntity->startTagLevel, internalEncoding,
textStart, textEnd, &next, XML_FALSE);
if (result != XML_ERROR_NONE)
return result;
else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
entity->processed = (int)(next - (char *)entity->textPtr);
return result;
}
else {
entity->open = XML_FALSE;
openInternalEntities = openEntity->next;
openEntity->next = freeInternalEntities;
freeInternalEntities = openEntity;
}
#ifdef XML_DTD
if (entity->is_param) {
int tok;
processor = prologProcessor;
tok = XmlPrologTok(encoding, s, end, &next);
return doProlog(parser, encoding, s, end, tok, next, nextPtr,
(XML_Bool)!ps_finalBuffer);
}
else
#endif
{
processor = contentProcessor;
return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
nextPtr, (XML_Bool)!ps_finalBuffer);
}
}
static enum XML_Error PTRCALL
errorProcessor(XML_Parser parser,
const char *s,
const char *end,
const char **nextPtr)
{
return errorCode;
}
static enum XML_Error
storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
const char *ptr, const char *end,
STRING_POOL *pool)
{
enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
end, pool);
if (result)
return result;
if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
poolChop(pool);
if (!poolAppendChar(pool, XML_T('\0')))
return XML_ERROR_NO_MEMORY;
return XML_ERROR_NONE;
}
static enum XML_Error
appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
const char *ptr, const char *end,
STRING_POOL *pool)
{
DTD * const dtd = _dtd;
for (;;) {
const char *next;
int tok = XmlAttributeValueTok(enc, ptr, end, &next);
switch (tok) {
case XML_TOK_NONE:
return XML_ERROR_NONE;
case XML_TOK_INVALID:
if (enc == encoding)
eventPtr = next;
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_PARTIAL:
if (enc == encoding)
eventPtr = ptr;
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_CHAR_REF:
{
XML_Char buf[XML_ENCODE_MAX];
int i;
int n = XmlCharRefNumber(enc, ptr);
if (n < 0) {
if (enc == encoding)
eventPtr = ptr;
return XML_ERROR_BAD_CHAR_REF;
}
if (!isCdata
&& n == 0x20
&& (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
break;
n = XmlEncode(n, (ICHAR *)buf);
if (!n) {
if (enc == encoding)
eventPtr = ptr;
return XML_ERROR_BAD_CHAR_REF;
}
for (i = 0; i < n; i++) {
if (!poolAppendChar(pool, buf[i]))
return XML_ERROR_NO_MEMORY;
}
}
break;
case XML_TOK_DATA_CHARS:
if (!poolAppend(pool, enc, ptr, next))
return XML_ERROR_NO_MEMORY;
break;
case XML_TOK_TRAILING_CR:
next = ptr + enc->minBytesPerChar;
case XML_TOK_ATTRIBUTE_VALUE_S:
case XML_TOK_DATA_NEWLINE:
if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
break;
if (!poolAppendChar(pool, 0x20))
return XML_ERROR_NO_MEMORY;
break;
case XML_TOK_ENTITY_REF:
{
const XML_Char *name;
ENTITY *entity;
char checkEntityDecl;
XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
ptr + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (ch) {
if (!poolAppendChar(pool, ch))
return XML_ERROR_NO_MEMORY;
break;
}
name = poolStoreString(&temp2Pool, enc,
ptr + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (!name)
return XML_ERROR_NO_MEMORY;
entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
poolDiscard(&temp2Pool);
if (pool == &dtd->pool)
checkEntityDecl =
#ifdef XML_DTD
prologState.documentEntity &&
#endif
(dtd->standalone
? !openInternalEntities
: !dtd->hasParamEntityRefs);
else
checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
if (checkEntityDecl) {
if (!entity)
return XML_ERROR_UNDEFINED_ENTITY;
else if (!entity->is_internal)
return XML_ERROR_ENTITY_DECLARED_IN_PE;
}
else if (!entity) {
break;
}
if (entity->open) {
if (enc == encoding)
eventPtr = ptr;
return XML_ERROR_RECURSIVE_ENTITY_REF;
}
if (entity->notation) {
if (enc == encoding)
eventPtr = ptr;
return XML_ERROR_BINARY_ENTITY_REF;
}
if (!entity->textPtr) {
if (enc == encoding)
eventPtr = ptr;
return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
}
else {
enum XML_Error result;
const XML_Char *textEnd = entity->textPtr + entity->textLen;
entity->open = XML_TRUE;
result = appendAttributeValue(parser, internalEncoding, isCdata,
(char *)entity->textPtr,
(char *)textEnd, pool);
entity->open = XML_FALSE;
if (result)
return result;
}
}
break;
default:
if (enc == encoding)
eventPtr = ptr;
return XML_ERROR_UNEXPECTED_STATE;
}
ptr = next;
}
}
static enum XML_Error
storeEntityValue(XML_Parser parser,
const ENCODING *enc,
const char *entityTextPtr,
const char *entityTextEnd)
{
DTD * const dtd = _dtd;
STRING_POOL *pool = &(dtd->entityValuePool);
enum XML_Error result = XML_ERROR_NONE;
#ifdef XML_DTD
int oldInEntityValue = prologState.inEntityValue;
prologState.inEntityValue = 1;
#endif
if (!pool->blocks) {
if (!poolGrow(pool))
return XML_ERROR_NO_MEMORY;
}
for (;;) {
const char *next;
int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
switch (tok) {
case XML_TOK_PARAM_ENTITY_REF:
#ifdef XML_DTD
if (isParamEntity || enc != encoding) {
const XML_Char *name;
ENTITY *entity;
name = poolStoreString(&tempPool, enc,
entityTextPtr + enc->minBytesPerChar,
next - enc->minBytesPerChar);
if (!name) {
result = XML_ERROR_NO_MEMORY;
goto endEntityValue;
}
entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
poolDiscard(&tempPool);
if (!entity) {
dtd->keepProcessing = dtd->standalone;
goto endEntityValue;
}
if (entity->open) {
if (enc == encoding)
eventPtr = entityTextPtr;
result = XML_ERROR_RECURSIVE_ENTITY_REF;
goto endEntityValue;
}
if (entity->systemId) {
if (externalEntityRefHandler) {
dtd->paramEntityRead = XML_FALSE;
entity->open = XML_TRUE;
if (!externalEntityRefHandler(externalEntityRefHandlerArg,
0,
entity->base,
entity->systemId,
entity->publicId)) {
entity->open = XML_FALSE;
result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
goto endEntityValue;
}
entity->open = XML_FALSE;
if (!dtd->paramEntityRead)
dtd->keepProcessing = dtd->standalone;
}
else
dtd->keepProcessing = dtd->standalone;
}
else {
entity->open = XML_TRUE;
result = storeEntityValue(parser,
internalEncoding,
(char *)entity->textPtr,
(char *)(entity->textPtr
+ entity->textLen));
entity->open = XML_FALSE;
if (result)
goto endEntityValue;
}
break;
}
#endif
eventPtr = entityTextPtr;
result = XML_ERROR_PARAM_ENTITY_REF;
goto endEntityValue;
case XML_TOK_NONE:
result = XML_ERROR_NONE;
goto endEntityValue;
case XML_TOK_ENTITY_REF:
case XML_TOK_DATA_CHARS:
if (!poolAppend(pool, enc, entityTextPtr, next)) {
result = XML_ERROR_NO_MEMORY;
goto endEntityValue;
}
break;
case XML_TOK_TRAILING_CR:
next = entityTextPtr + enc->minBytesPerChar;
case XML_TOK_DATA_NEWLINE:
if (pool->end == pool->ptr && !poolGrow(pool)) {
result = XML_ERROR_NO_MEMORY;
goto endEntityValue;
}
*(pool->ptr)++ = 0xA;
break;
case XML_TOK_CHAR_REF:
{
XML_Char buf[XML_ENCODE_MAX];
int i;
int n = XmlCharRefNumber(enc, entityTextPtr);
if (n < 0) {
if (enc == encoding)
eventPtr = entityTextPtr;
result = XML_ERROR_BAD_CHAR_REF;
goto endEntityValue;
}
n = XmlEncode(n, (ICHAR *)buf);
if (!n) {
if (enc == encoding)
eventPtr = entityTextPtr;
result = XML_ERROR_BAD_CHAR_REF;
goto endEntityValue;
}
for (i = 0; i < n; i++) {
if (pool->end == pool->ptr && !poolGrow(pool)) {
result = XML_ERROR_NO_MEMORY;
goto endEntityValue;
}
*(pool->ptr)++ = buf[i];
}
}
break;
case XML_TOK_PARTIAL:
if (enc == encoding)
eventPtr = entityTextPtr;
result = XML_ERROR_INVALID_TOKEN;
goto endEntityValue;
case XML_TOK_INVALID:
if (enc == encoding)
eventPtr = next;
result = XML_ERROR_INVALID_TOKEN;
goto endEntityValue;
default:
if (enc == encoding)
eventPtr = entityTextPtr;
result = XML_ERROR_UNEXPECTED_STATE;
goto endEntityValue;
}
entityTextPtr = next;
}
endEntityValue:
#ifdef XML_DTD
prologState.inEntityValue = oldInEntityValue;
#endif
return result;
}
static void FASTCALL
normalizeLines(XML_Char *s)
{
XML_Char *p;
for (;; s++) {
if (*s == XML_T('\0'))
return;
if (*s == 0xD)
break;
}
p = s;
do {
if (*s == 0xD) {
*p++ = 0xA;
if (*++s == 0xA)
s++;
}
else
*p++ = *s++;
} while (*s);
*p = XML_T('\0');
}
static int
reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end)
{
const XML_Char *target;
XML_Char *data;
const char *tem;
if (!processingInstructionHandler) {
if (defaultHandler)
reportDefault(parser, enc, start, end);
return 1;
}
start += enc->minBytesPerChar * 2;
tem = start + XmlNameLength(enc, start);
target = poolStoreString(&tempPool, enc, start, tem);
if (!target)
return 0;
poolFinish(&tempPool);
data = poolStoreString(&tempPool, enc,
XmlSkipS(enc, tem),
end - enc->minBytesPerChar*2);
if (!data)
return 0;
normalizeLines(data);
processingInstructionHandler(handlerArg, target, data);
poolClear(&tempPool);
return 1;
}
static int
reportComment(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end)
{
XML_Char *data;
if (!commentHandler) {
if (defaultHandler)
reportDefault(parser, enc, start, end);
return 1;
}
data = poolStoreString(&tempPool,
enc,
start + enc->minBytesPerChar * 4,
end - enc->minBytesPerChar * 3);
if (!data)
return 0;
normalizeLines(data);
commentHandler(handlerArg, data);
poolClear(&tempPool);
return 1;
}
static void
reportDefault(XML_Parser parser, const ENCODING *enc,
const char *s, const char *end)
{
if (MUST_CONVERT(enc, s)) {
const char **eventPP;
const char **eventEndPP;
if (enc == encoding) {
eventPP = &eventPtr;
eventEndPP = &eventEndPtr;
}
else {
eventPP = &(openInternalEntities->internalEventPtr);
eventEndPP = &(openInternalEntities->internalEventEndPtr);
}
do {
ICHAR *dataPtr = (ICHAR *)dataBuf;
XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
*eventEndPP = s;
defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
*eventPP = s;
} while (s != end);
}
else
defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
}
static int
defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
XML_Bool isId, const XML_Char *value, XML_Parser parser)
{
DEFAULT_ATTRIBUTE *att;
if (value || isId) {
int i;
for (i = 0; i < type->nDefaultAtts; i++)
if (attId == type->defaultAtts[i].id)
return 1;
if (isId && !type->idAtt && !attId->xmlns)
type->idAtt = attId;
}
if (type->nDefaultAtts == type->allocDefaultAtts) {
if (type->allocDefaultAtts == 0) {
type->allocDefaultAtts = 8;
type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
* sizeof(DEFAULT_ATTRIBUTE));
if (!type->defaultAtts)
return 0;
}
else {
DEFAULT_ATTRIBUTE *temp;
int count = type->allocDefaultAtts * 2;
temp = (DEFAULT_ATTRIBUTE *)
REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
if (temp == NULL)
return 0;
type->allocDefaultAtts = count;
type->defaultAtts = temp;
}
}
att = type->defaultAtts + type->nDefaultAtts;
att->id = attId;
att->value = value;
att->isCdata = isCdata;
if (!isCdata)
attId->maybeTokenized = XML_TRUE;
type->nDefaultAtts += 1;
return 1;
}
static int
setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
{
DTD * const dtd = _dtd;
const XML_Char *name;
for (name = elementType->name; *name; name++) {
if (*name == XML_T(ASCII_COLON)) {
PREFIX *prefix;
const XML_Char *s;
for (s = elementType->name; s != name; s++) {
if (!poolAppendChar(&dtd->pool, *s))
return 0;
}
if (!poolAppendChar(&dtd->pool, XML_T('\0')))
return 0;
prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
sizeof(PREFIX));
if (!prefix)
return 0;
if (prefix->name == poolStart(&dtd->pool))
poolFinish(&dtd->pool);
else
poolDiscard(&dtd->pool);
elementType->prefix = prefix;
}
}
return 1;
}
static ATTRIBUTE_ID *
getAttributeId(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end)
{
DTD * const dtd = _dtd;
ATTRIBUTE_ID *id;
const XML_Char *name;
if (!poolAppendChar(&dtd->pool, XML_T('\0')))
return NULL;
name = poolStoreString(&dtd->pool, enc, start, end);
if (!name)
return NULL;
++name;
id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
if (!id)
return NULL;
if (id->name != name)
poolDiscard(&dtd->pool);
else {
poolFinish(&dtd->pool);
if (!ns)
;
else if (name[0] == XML_T(ASCII_x)
&& name[1] == XML_T(ASCII_m)
&& name[2] == XML_T(ASCII_l)
&& name[3] == XML_T(ASCII_n)
&& name[4] == XML_T(ASCII_s)
&& (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
if (name[5] == XML_T('\0'))
id->prefix = &dtd->defaultPrefix;
else
id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
id->xmlns = XML_TRUE;
}
else {
int i;
for (i = 0; name[i]; i++) {
if (name[i] == XML_T(ASCII_COLON)) {
int j;
for (j = 0; j < i; j++) {
if (!poolAppendChar(&dtd->pool, name[j]))
return NULL;
}
if (!poolAppendChar(&dtd->pool, XML_T('\0')))
return NULL;
id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
sizeof(PREFIX));
if (id->prefix->name == poolStart(&dtd->pool))
poolFinish(&dtd->pool);
else
poolDiscard(&dtd->pool);
break;
}
}
}
}
return id;
}
#define CONTEXT_SEP XML_T(ASCII_FF)
static const XML_Char *
getContext(XML_Parser parser)
{
DTD * const dtd = _dtd;
HASH_TABLE_ITER iter;
XML_Bool needSep = XML_FALSE;
if (dtd->defaultPrefix.binding) {
int i;
int len;
if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
return NULL;
len = dtd->defaultPrefix.binding->uriLen;
if (namespaceSeparator)
len--;
for (i = 0; i < len; i++)
if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
return NULL;
needSep = XML_TRUE;
}
hashTableIterInit(&iter, &(dtd->prefixes));
for (;;) {
int i;
int len;
const XML_Char *s;
PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
if (!prefix)
break;
if (!prefix->binding)
continue;
if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
return NULL;
for (s = prefix->name; *s; s++)
if (!poolAppendChar(&tempPool, *s))
return NULL;
if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
return NULL;
len = prefix->binding->uriLen;
if (namespaceSeparator)
len--;
for (i = 0; i < len; i++)
if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
return NULL;
needSep = XML_TRUE;
}
hashTableIterInit(&iter, &(dtd->generalEntities));
for (;;) {
const XML_Char *s;
ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
if (!e)
break;
if (!e->open)
continue;
if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
return NULL;
for (s = e->name; *s; s++)
if (!poolAppendChar(&tempPool, *s))
return 0;
needSep = XML_TRUE;
}
if (!poolAppendChar(&tempPool, XML_T('\0')))
return NULL;
return tempPool.start;
}
static XML_Bool
setContext(XML_Parser parser, const XML_Char *context)
{
DTD * const dtd = _dtd;
const XML_Char *s = context;
while (*context != XML_T('\0')) {
if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
ENTITY *e;
if (!poolAppendChar(&tempPool, XML_T('\0')))
return XML_FALSE;
e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0);
if (e)
e->open = XML_TRUE;
if (*s != XML_T('\0'))
s++;
context = s;
poolDiscard(&tempPool);
}
else if (*s == XML_T(ASCII_EQUALS)) {
PREFIX *prefix;
if (poolLength(&tempPool) == 0)
prefix = &dtd->defaultPrefix;
else {
if (!poolAppendChar(&tempPool, XML_T('\0')))
return XML_FALSE;
prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool),
sizeof(PREFIX));
if (!prefix)
return XML_FALSE;
if (prefix->name == poolStart(&tempPool)) {
prefix->name = poolCopyString(&dtd->pool, prefix->name);
if (!prefix->name)
return XML_FALSE;
}
poolDiscard(&tempPool);
}
for (context = s + 1;
*context != CONTEXT_SEP && *context != XML_T('\0');
context++)
if (!poolAppendChar(&tempPool, *context))
return XML_FALSE;
if (!poolAppendChar(&tempPool, XML_T('\0')))
return XML_FALSE;
if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
&inheritedBindings) != XML_ERROR_NONE)
return XML_FALSE;
poolDiscard(&tempPool);
if (*context != XML_T('\0'))
++context;
s = context;
}
else {
if (!poolAppendChar(&tempPool, *s))
return XML_FALSE;
s++;
}
}
return XML_TRUE;
}
static void FASTCALL
normalizePublicId(XML_Char *publicId)
{
XML_Char *p = publicId;
XML_Char *s;
for (s = publicId; *s; s++) {
switch (*s) {
case 0x20:
case 0xD:
case 0xA:
if (p != publicId && p[-1] != 0x20)
*p++ = 0x20;
break;
default:
*p++ = *s;
}
}
if (p != publicId && p[-1] == 0x20)
--p;
*p = XML_T('\0');
}
static DTD *
dtdCreate(const XML_Memory_Handling_Suite *ms)
{
DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
if (p == NULL)
return p;
poolInit(&(p->pool), ms);
poolInit(&(p->entityValuePool), ms);
hashTableInit(&(p->generalEntities), ms);
hashTableInit(&(p->elementTypes), ms);
hashTableInit(&(p->attributeIds), ms);
hashTableInit(&(p->prefixes), ms);
#ifdef XML_DTD
p->paramEntityRead = XML_FALSE;
hashTableInit(&(p->paramEntities), ms);
#endif
p->defaultPrefix.name = NULL;
p->defaultPrefix.binding = NULL;
p->in_eldecl = XML_FALSE;
p->scaffIndex = NULL;
p->scaffold = NULL;
p->scaffLevel = 0;
p->scaffSize = 0;
p->scaffCount = 0;
p->contentStringLen = 0;
p->keepProcessing = XML_TRUE;
p->hasParamEntityRefs = XML_FALSE;
p->standalone = XML_FALSE;
return p;
}
static void
dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
{
HASH_TABLE_ITER iter;
hashTableIterInit(&iter, &(p->elementTypes));
for (;;) {
ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
if (!e)
break;
if (e->allocDefaultAtts != 0)
ms->free_fcn(e->defaultAtts);
}
hashTableClear(&(p->generalEntities));
#ifdef XML_DTD
p->paramEntityRead = XML_FALSE;
hashTableClear(&(p->paramEntities));
#endif
hashTableClear(&(p->elementTypes));
hashTableClear(&(p->attributeIds));
hashTableClear(&(p->prefixes));
poolClear(&(p->pool));
poolClear(&(p->entityValuePool));
p->defaultPrefix.name = NULL;
p->defaultPrefix.binding = NULL;
p->in_eldecl = XML_FALSE;
ms->free_fcn(p->scaffIndex);
p->scaffIndex = NULL;
ms->free_fcn(p->scaffold);
p->scaffold = NULL;
p->scaffLevel = 0;
p->scaffSize = 0;
p->scaffCount = 0;
p->contentStringLen = 0;
p->keepProcessing = XML_TRUE;
p->hasParamEntityRefs = XML_FALSE;
p->standalone = XML_FALSE;
}
static void
dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
{
HASH_TABLE_ITER iter;
hashTableIterInit(&iter, &(p->elementTypes));
for (;;) {
ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
if (!e)
break;
if (e->allocDefaultAtts != 0)
ms->free_fcn(e->defaultAtts);
}
hashTableDestroy(&(p->generalEntities));
#ifdef XML_DTD
hashTableDestroy(&(p->paramEntities));
#endif
hashTableDestroy(&(p->elementTypes));
hashTableDestroy(&(p->attributeIds));
hashTableDestroy(&(p->prefixes));
poolDestroy(&(p->pool));
poolDestroy(&(p->entityValuePool));
if (isDocEntity) {
ms->free_fcn(p->scaffIndex);
ms->free_fcn(p->scaffold);
}
ms->free_fcn(p);
}
static int
dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
{
HASH_TABLE_ITER iter;
hashTableIterInit(&iter, &(oldDtd->prefixes));
for (;;) {
const XML_Char *name;
const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
if (!oldP)
break;
name = poolCopyString(&(newDtd->pool), oldP->name);
if (!name)
return 0;
if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
return 0;
}
hashTableIterInit(&iter, &(oldDtd->attributeIds));
for (;;) {
ATTRIBUTE_ID *newA;
const XML_Char *name;
const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
if (!oldA)
break;
if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
return 0;
name = poolCopyString(&(newDtd->pool), oldA->name);
if (!name)
return 0;
++name;
newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
sizeof(ATTRIBUTE_ID));
if (!newA)
return 0;
newA->maybeTokenized = oldA->maybeTokenized;
if (oldA->prefix) {
newA->xmlns = oldA->xmlns;
if (oldA->prefix == &oldDtd->defaultPrefix)
newA->prefix = &newDtd->defaultPrefix;
else
newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
oldA->prefix->name, 0);
}
}
hashTableIterInit(&iter, &(oldDtd->elementTypes));
for (;;) {
int i;
ELEMENT_TYPE *newE;
const XML_Char *name;
const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
if (!oldE)
break;
name = poolCopyString(&(newDtd->pool), oldE->name);
if (!name)
return 0;
newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
sizeof(ELEMENT_TYPE));
if (!newE)
return 0;
if (oldE->nDefaultAtts) {
newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
if (!newE->defaultAtts) {
ms->free_fcn(newE);
return 0;
}
}
if (oldE->idAtt)
newE->idAtt = (ATTRIBUTE_ID *)
lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
if (oldE->prefix)
newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
oldE->prefix->name, 0);
for (i = 0; i < newE->nDefaultAtts; i++) {
newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
if (oldE->defaultAtts[i].value) {
newE->defaultAtts[i].value
= poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
if (!newE->defaultAtts[i].value)
return 0;
}
else
newE->defaultAtts[i].value = NULL;
}
}
if (!copyEntityTable(oldParser,
&(newDtd->generalEntities),
&(newDtd->pool),
&(oldDtd->generalEntities)))
return 0;
#ifdef XML_DTD
if (!copyEntityTable(oldParser,
&(newDtd->paramEntities),
&(newDtd->pool),
&(oldDtd->paramEntities)))
return 0;
newDtd->paramEntityRead = oldDtd->paramEntityRead;
#endif
newDtd->keepProcessing = oldDtd->keepProcessing;
newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
newDtd->standalone = oldDtd->standalone;
newDtd->in_eldecl = oldDtd->in_eldecl;
newDtd->scaffold = oldDtd->scaffold;
newDtd->contentStringLen = oldDtd->contentStringLen;
newDtd->scaffSize = oldDtd->scaffSize;
newDtd->scaffLevel = oldDtd->scaffLevel;
newDtd->scaffIndex = oldDtd->scaffIndex;
return 1;
}
static int
copyEntityTable(XML_Parser oldParser,
HASH_TABLE *newTable,
STRING_POOL *newPool,
const HASH_TABLE *oldTable)
{
HASH_TABLE_ITER iter;
const XML_Char *cachedOldBase = NULL;
const XML_Char *cachedNewBase = NULL;
hashTableIterInit(&iter, oldTable);
for (;;) {
ENTITY *newE;
const XML_Char *name;
const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
if (!oldE)
break;
name = poolCopyString(newPool, oldE->name);
if (!name)
return 0;
newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
if (!newE)
return 0;
if (oldE->systemId) {
const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
if (!tem)
return 0;
newE->systemId = tem;
if (oldE->base) {
if (oldE->base == cachedOldBase)
newE->base = cachedNewBase;
else {
cachedOldBase = oldE->base;
tem = poolCopyString(newPool, cachedOldBase);
if (!tem)
return 0;
cachedNewBase = newE->base = tem;
}
}
if (oldE->publicId) {
tem = poolCopyString(newPool, oldE->publicId);
if (!tem)
return 0;
newE->publicId = tem;
}
}
else {
const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
oldE->textLen);
if (!tem)
return 0;
newE->textPtr = tem;
newE->textLen = oldE->textLen;
}
if (oldE->notation) {
const XML_Char *tem = poolCopyString(newPool, oldE->notation);
if (!tem)
return 0;
newE->notation = tem;
}
newE->is_param = oldE->is_param;
newE->is_internal = oldE->is_internal;
}
return 1;
}
#define INIT_POWER 6
static XML_Bool FASTCALL
keyeq(KEY s1, KEY s2)
{
for (; *s1 == *s2; s1++, s2++)
if (*s1 == 0)
return XML_TRUE;
return XML_FALSE;
}
static unsigned long FASTCALL
hash(XML_Parser parser, KEY s)
{
unsigned long h = hash_secret_salt;
while (*s)
h = CHAR_HASH(h, *s++);
return h;
}
static NAMED *
lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
{
size_t i;
if (table->size == 0) {
size_t tsize;
if (!createSize)
return NULL;
table->power = INIT_POWER;
table->size = (size_t)1 << INIT_POWER;
tsize = table->size * sizeof(NAMED *);
table->v = (NAMED **)table->mem->malloc_fcn(tsize);
if (!table->v) {
table->size = 0;
return NULL;
}
memset(table->v, 0, tsize);
i = hash(parser, name) & ((unsigned long)table->size - 1);
}
else {
unsigned long h = hash(parser, name);
unsigned long mask = (unsigned long)table->size - 1;
unsigned char step = 0;
i = h & mask;
while (table->v[i]) {
if (keyeq(name, table->v[i]->name))
return table->v[i];
if (!step)
step = PROBE_STEP(h, mask, table->power);
i < step ? (i += table->size - step) : (i -= step);
}
if (!createSize)
return NULL;
if (table->used >> (table->power - 1)) {
unsigned char newPower = table->power + 1;
size_t newSize = (size_t)1 << newPower;
unsigned long newMask = (unsigned long)newSize - 1;
size_t tsize = newSize * sizeof(NAMED *);
NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
if (!newV)
return NULL;
memset(newV, 0, tsize);
for (i = 0; i < table->size; i++)
if (table->v[i]) {
unsigned long newHash = hash(parser, table->v[i]->name);
size_t j = newHash & newMask;
step = 0;
while (newV[j]) {
if (!step)
step = PROBE_STEP(newHash, newMask, newPower);
j < step ? (j += newSize - step) : (j -= step);
}
newV[j] = table->v[i];
}
table->mem->free_fcn(table->v);
table->v = newV;
table->power = newPower;
table->size = newSize;
i = h & newMask;
step = 0;
while (table->v[i]) {
if (!step)
step = PROBE_STEP(h, newMask, newPower);
i < step ? (i += newSize - step) : (i -= step);
}
}
}
table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
if (!table->v[i])
return NULL;
memset(table->v[i], 0, createSize);
table->v[i]->name = name;
(table->used)++;
return table->v[i];
}
static void FASTCALL
hashTableClear(HASH_TABLE *table)
{
size_t i;
for (i = 0; i < table->size; i++) {
table->mem->free_fcn(table->v[i]);
table->v[i] = NULL;
}
table->used = 0;
}
static void FASTCALL
hashTableDestroy(HASH_TABLE *table)
{
size_t i;
for (i = 0; i < table->size; i++)
table->mem->free_fcn(table->v[i]);
table->mem->free_fcn(table->v);
}
static void FASTCALL
hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
{
p->power = 0;
p->size = 0;
p->used = 0;
p->v = NULL;
p->mem = ms;
}
static void FASTCALL
hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
{
iter->p = table->v;
iter->end = iter->p + table->size;
}
static NAMED * FASTCALL
hashTableIterNext(HASH_TABLE_ITER *iter)
{
while (iter->p != iter->end) {
NAMED *tem = *(iter->p)++;
if (tem)
return tem;
}
return NULL;
}
static void FASTCALL
poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
{
pool->blocks = NULL;
pool->freeBlocks = NULL;
pool->start = NULL;
pool->ptr = NULL;
pool->end = NULL;
pool->mem = ms;
}
static void FASTCALL
poolClear(STRING_POOL *pool)
{
if (!pool->freeBlocks)
pool->freeBlocks = pool->blocks;
else {
BLOCK *p = pool->blocks;
while (p) {
BLOCK *tem = p->next;
p->next = pool->freeBlocks;
pool->freeBlocks = p;
p = tem;
}
}
pool->blocks = NULL;
pool->start = NULL;
pool->ptr = NULL;
pool->end = NULL;
}
static void FASTCALL
poolDestroy(STRING_POOL *pool)
{
BLOCK *p = pool->blocks;
while (p) {
BLOCK *tem = p->next;
pool->mem->free_fcn(p);
p = tem;
}
p = pool->freeBlocks;
while (p) {
BLOCK *tem = p->next;
pool->mem->free_fcn(p);
p = tem;
}
}
static XML_Char *
poolAppend(STRING_POOL *pool, const ENCODING *enc,
const char *ptr, const char *end)
{
if (!pool->ptr && !poolGrow(pool))
return NULL;
for (;;) {
XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
if (ptr == end)
break;
if (!poolGrow(pool))
return NULL;
}
return pool->start;
}
static const XML_Char * FASTCALL
poolCopyString(STRING_POOL *pool, const XML_Char *s)
{
do {
if (!poolAppendChar(pool, *s))
return NULL;
} while (*s++);
s = pool->start;
poolFinish(pool);
return s;
}
static const XML_Char *
poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
{
if (!pool->ptr && !poolGrow(pool))
return NULL;
for (; n > 0; --n, s++) {
if (!poolAppendChar(pool, *s))
return NULL;
}
s = pool->start;
poolFinish(pool);
return s;
}
static const XML_Char * FASTCALL
poolAppendString(STRING_POOL *pool, const XML_Char *s)
{
while (*s) {
if (!poolAppendChar(pool, *s))
return NULL;
s++;
}
return pool->start;
}
static XML_Char *
poolStoreString(STRING_POOL *pool, const ENCODING *enc,
const char *ptr, const char *end)
{
if (!poolAppend(pool, enc, ptr, end))
return NULL;
if (pool->ptr == pool->end && !poolGrow(pool))
return NULL;
*(pool->ptr)++ = 0;
return pool->start;
}
static XML_Bool FASTCALL
poolGrow(STRING_POOL *pool)
{
if (pool->freeBlocks) {
if (pool->start == 0) {
pool->blocks = pool->freeBlocks;
pool->freeBlocks = pool->freeBlocks->next;
pool->blocks->next = NULL;
pool->start = pool->blocks->s;
pool->end = pool->start + pool->blocks->size;
pool->ptr = pool->start;
return XML_TRUE;
}
if (pool->end - pool->start < pool->freeBlocks->size) {
BLOCK *tem = pool->freeBlocks->next;
pool->freeBlocks->next = pool->blocks;
pool->blocks = pool->freeBlocks;
pool->freeBlocks = tem;
memcpy(pool->blocks->s, pool->start,
(pool->end - pool->start) * sizeof(XML_Char));
pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
pool->start = pool->blocks->s;
pool->end = pool->start + pool->blocks->size;
return XML_TRUE;
}
}
if (pool->blocks && pool->start == pool->blocks->s) {
int blockSize = (int)(pool->end - pool->start)*2;
BLOCK *temp = (BLOCK *)
pool->mem->realloc_fcn(pool->blocks,
(offsetof(BLOCK, s)
+ blockSize * sizeof(XML_Char)));
if (temp == NULL)
return XML_FALSE;
pool->blocks = temp;
pool->blocks->size = blockSize;
pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
pool->start = pool->blocks->s;
pool->end = pool->start + blockSize;
}
else {
BLOCK *tem;
int blockSize = (int)(pool->end - pool->start);
if (blockSize < INIT_BLOCK_SIZE)
blockSize = INIT_BLOCK_SIZE;
else
blockSize *= 2;
tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
+ blockSize * sizeof(XML_Char));
if (!tem)
return XML_FALSE;
tem->size = blockSize;
tem->next = pool->blocks;
pool->blocks = tem;
if (pool->ptr != pool->start)
memcpy(tem->s, pool->start,
(pool->ptr - pool->start) * sizeof(XML_Char));
pool->ptr = tem->s + (pool->ptr - pool->start);
pool->start = tem->s;
pool->end = tem->s + blockSize;
}
return XML_TRUE;
}
static int FASTCALL
nextScaffoldPart(XML_Parser parser)
{
DTD * const dtd = _dtd;
CONTENT_SCAFFOLD * me;
int next;
if (!dtd->scaffIndex) {
dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
if (!dtd->scaffIndex)
return -1;
dtd->scaffIndex[0] = 0;
}
if (dtd->scaffCount >= dtd->scaffSize) {
CONTENT_SCAFFOLD *temp;
if (dtd->scaffold) {
temp = (CONTENT_SCAFFOLD *)
REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
if (temp == NULL)
return -1;
dtd->scaffSize *= 2;
}
else {
temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
* sizeof(CONTENT_SCAFFOLD));
if (temp == NULL)
return -1;
dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
}
dtd->scaffold = temp;
}
next = dtd->scaffCount++;
me = &dtd->scaffold[next];
if (dtd->scaffLevel) {
CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
if (parent->lastchild) {
dtd->scaffold[parent->lastchild].nextsib = next;
}
if (!parent->childcnt)
parent->firstchild = next;
parent->lastchild = next;
parent->childcnt++;
}
me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
return next;
}
static void
build_node(XML_Parser parser,
int src_node,
XML_Content *dest,
XML_Content **contpos,
XML_Char **strpos)
{
DTD * const dtd = _dtd;
dest->type = dtd->scaffold[src_node].type;
dest->quant = dtd->scaffold[src_node].quant;
if (dest->type == XML_CTYPE_NAME) {
const XML_Char *src;
dest->name = *strpos;
src = dtd->scaffold[src_node].name;
for (;;) {
*(*strpos)++ = *src;
if (!*src)
break;
src++;
}
dest->numchildren = 0;
dest->children = NULL;
}
else {
unsigned int i;
int cn;
dest->numchildren = dtd->scaffold[src_node].childcnt;
dest->children = *contpos;
*contpos += dest->numchildren;
for (i = 0, cn = dtd->scaffold[src_node].firstchild;
i < dest->numchildren;
i++, cn = dtd->scaffold[cn].nextsib) {
build_node(parser, cn, &(dest->children[i]), contpos, strpos);
}
dest->name = NULL;
}
}
static XML_Content *
build_model (XML_Parser parser)
{
DTD * const dtd = _dtd;
XML_Content *ret;
XML_Content *cpos;
XML_Char * str;
int allocsize = (dtd->scaffCount * sizeof(XML_Content)
+ (dtd->contentStringLen * sizeof(XML_Char)));
ret = (XML_Content *)MALLOC(allocsize);
if (!ret)
return NULL;
str = (XML_Char *) (&ret[dtd->scaffCount]);
cpos = &ret[1];
build_node(parser, 0, ret, &cpos, &str);
return ret;
}
static ELEMENT_TYPE *
getElementType(XML_Parser parser,
const ENCODING *enc,
const char *ptr,
const char *end)
{
DTD * const dtd = _dtd;
const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
ELEMENT_TYPE *ret;
if (!name)
return NULL;
ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
if (!ret)
return NULL;
if (ret->name != name)
poolDiscard(&dtd->pool);
else {
poolFinish(&dtd->pool);
if (!setElementTypePrefix(parser, ret))
return NULL;
}
return ret;
}