parser/expat/lib/xmlparse.c

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

michael@0 1 /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
michael@0 2 See the file COPYING for copying permission.
michael@0 3 */
michael@0 4
michael@0 5 #include <stddef.h>
michael@0 6 #include <string.h> /* memset(), memcpy() */
michael@0 7 #include <assert.h>
michael@0 8
michael@0 9 #define XML_BUILDING_EXPAT 1
michael@0 10
michael@0 11 #ifdef COMPILED_FROM_DSP
michael@0 12 #include "winconfig.h"
michael@0 13 #elif defined(MACOS_CLASSIC)
michael@0 14 #include "macconfig.h"
michael@0 15 #elif defined(__amigaos4__)
michael@0 16 #include "amigaconfig.h"
michael@0 17 #elif defined(HAVE_EXPAT_CONFIG_H)
michael@0 18 #include <expat_config.h>
michael@0 19 #endif /* ndef COMPILED_FROM_DSP */
michael@0 20
michael@0 21 #include "expat.h"
michael@0 22
michael@0 23 #ifdef XML_UNICODE
michael@0 24 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
michael@0 25 #define XmlConvert XmlUtf16Convert
michael@0 26 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
michael@0 27 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
michael@0 28 #define XmlEncode XmlUtf16Encode
michael@0 29 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
michael@0 30 typedef unsigned short ICHAR;
michael@0 31 #else
michael@0 32 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
michael@0 33 #define XmlConvert XmlUtf8Convert
michael@0 34 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
michael@0 35 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
michael@0 36 #define XmlEncode XmlUtf8Encode
michael@0 37 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
michael@0 38 typedef char ICHAR;
michael@0 39 #endif
michael@0 40
michael@0 41
michael@0 42 #ifndef XML_NS
michael@0 43
michael@0 44 #define XmlInitEncodingNS XmlInitEncoding
michael@0 45 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
michael@0 46 #undef XmlGetInternalEncodingNS
michael@0 47 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
michael@0 48 #define XmlParseXmlDeclNS XmlParseXmlDecl
michael@0 49
michael@0 50 #endif
michael@0 51
michael@0 52 /* BEGIN MOZILLA CHANGE (typedef XML_Char to char16_t) */
michael@0 53 #if 0
michael@0 54
michael@0 55 #ifdef XML_UNICODE
michael@0 56
michael@0 57 #ifdef XML_UNICODE_WCHAR_T
michael@0 58 #define XML_T(x) (const wchar_t)x
michael@0 59 #define XML_L(x) L ## x
michael@0 60 #else
michael@0 61 #define XML_T(x) (const unsigned short)x
michael@0 62 #define XML_L(x) x
michael@0 63 #endif
michael@0 64
michael@0 65 #else
michael@0 66
michael@0 67 #define XML_T(x) x
michael@0 68 #define XML_L(x) x
michael@0 69
michael@0 70 #endif
michael@0 71
michael@0 72 #endif
michael@0 73 /* END MOZILLA CHANGE */
michael@0 74
michael@0 75 /* Round up n to be a multiple of sz, where sz is a power of 2. */
michael@0 76 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
michael@0 77
michael@0 78 /* Handle the case where memmove() doesn't exist. */
michael@0 79 #ifndef HAVE_MEMMOVE
michael@0 80 #ifdef HAVE_BCOPY
michael@0 81 #define memmove(d,s,l) bcopy((s),(d),(l))
michael@0 82 #else
michael@0 83 #error memmove does not exist on this platform, nor is a substitute available
michael@0 84 #endif /* HAVE_BCOPY */
michael@0 85 #endif /* HAVE_MEMMOVE */
michael@0 86
michael@0 87 #include "internal.h"
michael@0 88 #include "xmltok.h"
michael@0 89 #include "xmlrole.h"
michael@0 90
michael@0 91 typedef const XML_Char *KEY;
michael@0 92
michael@0 93 typedef struct {
michael@0 94 KEY name;
michael@0 95 } NAMED;
michael@0 96
michael@0 97 typedef struct {
michael@0 98 NAMED **v;
michael@0 99 unsigned char power;
michael@0 100 size_t size;
michael@0 101 size_t used;
michael@0 102 const XML_Memory_Handling_Suite *mem;
michael@0 103 } HASH_TABLE;
michael@0 104
michael@0 105 /* Basic character hash algorithm, taken from Python's string hash:
michael@0 106 h = h * 1000003 ^ character, the constant being a prime number.
michael@0 107
michael@0 108 */
michael@0 109 #ifdef XML_UNICODE
michael@0 110 #define CHAR_HASH(h, c) \
michael@0 111 (((h) * 0xF4243) ^ (unsigned short)(c))
michael@0 112 #else
michael@0 113 #define CHAR_HASH(h, c) \
michael@0 114 (((h) * 0xF4243) ^ (unsigned char)(c))
michael@0 115 #endif
michael@0 116
michael@0 117 /* For probing (after a collision) we need a step size relative prime
michael@0 118 to the hash table size, which is a power of 2. We use double-hashing,
michael@0 119 since we can calculate a second hash value cheaply by taking those bits
michael@0 120 of the first hash value that were discarded (masked out) when the table
michael@0 121 index was calculated: index = hash & mask, where mask = table->size - 1.
michael@0 122 We limit the maximum step size to table->size / 4 (mask >> 2) and make
michael@0 123 it odd, since odd numbers are always relative prime to a power of 2.
michael@0 124 */
michael@0 125 #define SECOND_HASH(hash, mask, power) \
michael@0 126 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
michael@0 127 #define PROBE_STEP(hash, mask, power) \
michael@0 128 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
michael@0 129
michael@0 130 typedef struct {
michael@0 131 NAMED **p;
michael@0 132 NAMED **end;
michael@0 133 } HASH_TABLE_ITER;
michael@0 134
michael@0 135 #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
michael@0 136 #define INIT_DATA_BUF_SIZE 1024
michael@0 137 #define INIT_ATTS_SIZE 16
michael@0 138 #define INIT_ATTS_VERSION 0xFFFFFFFF
michael@0 139 #define INIT_BLOCK_SIZE 1024
michael@0 140 #define INIT_BUFFER_SIZE 1024
michael@0 141
michael@0 142 #define EXPAND_SPARE 24
michael@0 143
michael@0 144 typedef struct binding {
michael@0 145 struct prefix *prefix;
michael@0 146 struct binding *nextTagBinding;
michael@0 147 struct binding *prevPrefixBinding;
michael@0 148 const struct attribute_id *attId;
michael@0 149 XML_Char *uri;
michael@0 150 int uriLen;
michael@0 151 int uriAlloc;
michael@0 152 } BINDING;
michael@0 153
michael@0 154 typedef struct prefix {
michael@0 155 const XML_Char *name;
michael@0 156 BINDING *binding;
michael@0 157 } PREFIX;
michael@0 158
michael@0 159 typedef struct {
michael@0 160 const XML_Char *str;
michael@0 161 const XML_Char *localPart;
michael@0 162 const XML_Char *prefix;
michael@0 163 int strLen;
michael@0 164 int uriLen;
michael@0 165 int prefixLen;
michael@0 166 } TAG_NAME;
michael@0 167
michael@0 168 /* TAG represents an open element.
michael@0 169 The name of the element is stored in both the document and API
michael@0 170 encodings. The memory buffer 'buf' is a separately-allocated
michael@0 171 memory area which stores the name. During the XML_Parse()/
michael@0 172 XMLParseBuffer() when the element is open, the memory for the 'raw'
michael@0 173 version of the name (in the document encoding) is shared with the
michael@0 174 document buffer. If the element is open across calls to
michael@0 175 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
michael@0 176 contain the 'raw' name as well.
michael@0 177
michael@0 178 A parser re-uses these structures, maintaining a list of allocated
michael@0 179 TAG objects in a free list.
michael@0 180 */
michael@0 181 typedef struct tag {
michael@0 182 struct tag *parent; /* parent of this element */
michael@0 183 const char *rawName; /* tagName in the original encoding */
michael@0 184 int rawNameLength;
michael@0 185 TAG_NAME name; /* tagName in the API encoding */
michael@0 186 char *buf; /* buffer for name components */
michael@0 187 char *bufEnd; /* end of the buffer */
michael@0 188 BINDING *bindings;
michael@0 189 } TAG;
michael@0 190
michael@0 191 typedef struct {
michael@0 192 const XML_Char *name;
michael@0 193 const XML_Char *textPtr;
michael@0 194 int textLen; /* length in XML_Chars */
michael@0 195 int processed; /* # of processed bytes - when suspended */
michael@0 196 const XML_Char *systemId;
michael@0 197 const XML_Char *base;
michael@0 198 const XML_Char *publicId;
michael@0 199 const XML_Char *notation;
michael@0 200 XML_Bool open;
michael@0 201 XML_Bool is_param;
michael@0 202 XML_Bool is_internal; /* true if declared in internal subset outside PE */
michael@0 203 } ENTITY;
michael@0 204
michael@0 205 typedef struct {
michael@0 206 enum XML_Content_Type type;
michael@0 207 enum XML_Content_Quant quant;
michael@0 208 const XML_Char * name;
michael@0 209 int firstchild;
michael@0 210 int lastchild;
michael@0 211 int childcnt;
michael@0 212 int nextsib;
michael@0 213 } CONTENT_SCAFFOLD;
michael@0 214
michael@0 215 #define INIT_SCAFFOLD_ELEMENTS 32
michael@0 216
michael@0 217 typedef struct block {
michael@0 218 struct block *next;
michael@0 219 int size;
michael@0 220 XML_Char s[1];
michael@0 221 } BLOCK;
michael@0 222
michael@0 223 typedef struct {
michael@0 224 BLOCK *blocks;
michael@0 225 BLOCK *freeBlocks;
michael@0 226 const XML_Char *end;
michael@0 227 XML_Char *ptr;
michael@0 228 XML_Char *start;
michael@0 229 const XML_Memory_Handling_Suite *mem;
michael@0 230 } STRING_POOL;
michael@0 231
michael@0 232 /* The XML_Char before the name is used to determine whether
michael@0 233 an attribute has been specified. */
michael@0 234 typedef struct attribute_id {
michael@0 235 XML_Char *name;
michael@0 236 PREFIX *prefix;
michael@0 237 XML_Bool maybeTokenized;
michael@0 238 XML_Bool xmlns;
michael@0 239 } ATTRIBUTE_ID;
michael@0 240
michael@0 241 typedef struct {
michael@0 242 const ATTRIBUTE_ID *id;
michael@0 243 XML_Bool isCdata;
michael@0 244 const XML_Char *value;
michael@0 245 } DEFAULT_ATTRIBUTE;
michael@0 246
michael@0 247 typedef struct {
michael@0 248 unsigned long version;
michael@0 249 unsigned long hash;
michael@0 250 const XML_Char *uriName;
michael@0 251 } NS_ATT;
michael@0 252
michael@0 253 typedef struct {
michael@0 254 const XML_Char *name;
michael@0 255 PREFIX *prefix;
michael@0 256 const ATTRIBUTE_ID *idAtt;
michael@0 257 int nDefaultAtts;
michael@0 258 int allocDefaultAtts;
michael@0 259 DEFAULT_ATTRIBUTE *defaultAtts;
michael@0 260 } ELEMENT_TYPE;
michael@0 261
michael@0 262 typedef struct {
michael@0 263 HASH_TABLE generalEntities;
michael@0 264 HASH_TABLE elementTypes;
michael@0 265 HASH_TABLE attributeIds;
michael@0 266 HASH_TABLE prefixes;
michael@0 267 STRING_POOL pool;
michael@0 268 STRING_POOL entityValuePool;
michael@0 269 /* false once a parameter entity reference has been skipped */
michael@0 270 XML_Bool keepProcessing;
michael@0 271 /* true once an internal or external PE reference has been encountered;
michael@0 272 this includes the reference to an external subset */
michael@0 273 XML_Bool hasParamEntityRefs;
michael@0 274 XML_Bool standalone;
michael@0 275 #ifdef XML_DTD
michael@0 276 /* indicates if external PE has been read */
michael@0 277 XML_Bool paramEntityRead;
michael@0 278 HASH_TABLE paramEntities;
michael@0 279 #endif /* XML_DTD */
michael@0 280 PREFIX defaultPrefix;
michael@0 281 /* === scaffolding for building content model === */
michael@0 282 XML_Bool in_eldecl;
michael@0 283 CONTENT_SCAFFOLD *scaffold;
michael@0 284 unsigned contentStringLen;
michael@0 285 unsigned scaffSize;
michael@0 286 unsigned scaffCount;
michael@0 287 int scaffLevel;
michael@0 288 int *scaffIndex;
michael@0 289 } DTD;
michael@0 290
michael@0 291 typedef struct open_internal_entity {
michael@0 292 const char *internalEventPtr;
michael@0 293 const char *internalEventEndPtr;
michael@0 294 struct open_internal_entity *next;
michael@0 295 ENTITY *entity;
michael@0 296 int startTagLevel;
michael@0 297 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
michael@0 298 } OPEN_INTERNAL_ENTITY;
michael@0 299
michael@0 300 typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
michael@0 301 const char *start,
michael@0 302 const char *end,
michael@0 303 const char **endPtr);
michael@0 304
michael@0 305 static Processor prologProcessor;
michael@0 306 static Processor prologInitProcessor;
michael@0 307 static Processor contentProcessor;
michael@0 308 static Processor cdataSectionProcessor;
michael@0 309 #ifdef XML_DTD
michael@0 310 static Processor ignoreSectionProcessor;
michael@0 311 static Processor externalParEntProcessor;
michael@0 312 static Processor externalParEntInitProcessor;
michael@0 313 static Processor entityValueProcessor;
michael@0 314 static Processor entityValueInitProcessor;
michael@0 315 #endif /* XML_DTD */
michael@0 316 static Processor epilogProcessor;
michael@0 317 static Processor errorProcessor;
michael@0 318 static Processor externalEntityInitProcessor;
michael@0 319 static Processor externalEntityInitProcessor2;
michael@0 320 static Processor externalEntityInitProcessor3;
michael@0 321 static Processor externalEntityContentProcessor;
michael@0 322 static Processor internalEntityProcessor;
michael@0 323
michael@0 324 static enum XML_Error
michael@0 325 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
michael@0 326 static enum XML_Error
michael@0 327 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
michael@0 328 const char *s, const char *next);
michael@0 329 static enum XML_Error
michael@0 330 initializeEncoding(XML_Parser parser);
michael@0 331 static enum XML_Error
michael@0 332 doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
michael@0 333 const char *end, int tok, const char *next, const char **nextPtr,
michael@0 334 XML_Bool haveMore);
michael@0 335 static enum XML_Error
michael@0 336 processInternalEntity(XML_Parser parser, ENTITY *entity,
michael@0 337 XML_Bool betweenDecl);
michael@0 338 static enum XML_Error
michael@0 339 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
michael@0 340 const char *start, const char *end, const char **endPtr,
michael@0 341 XML_Bool haveMore);
michael@0 342 static enum XML_Error
michael@0 343 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
michael@0 344 const char *end, const char **nextPtr, XML_Bool haveMore);
michael@0 345 #ifdef XML_DTD
michael@0 346 static enum XML_Error
michael@0 347 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
michael@0 348 const char *end, const char **nextPtr, XML_Bool haveMore);
michael@0 349 #endif /* XML_DTD */
michael@0 350
michael@0 351 static enum XML_Error
michael@0 352 storeAtts(XML_Parser parser, const ENCODING *, const char *s,
michael@0 353 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
michael@0 354 static enum XML_Error
michael@0 355 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
michael@0 356 const XML_Char *uri, BINDING **bindingsPtr);
michael@0 357 static int
michael@0 358 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
michael@0 359 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
michael@0 360 static enum XML_Error
michael@0 361 storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
michael@0 362 const char *, const char *, STRING_POOL *);
michael@0 363 static enum XML_Error
michael@0 364 appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
michael@0 365 const char *, const char *, STRING_POOL *);
michael@0 366 static ATTRIBUTE_ID *
michael@0 367 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
michael@0 368 const char *end);
michael@0 369 static int
michael@0 370 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
michael@0 371 static enum XML_Error
michael@0 372 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
michael@0 373 const char *end);
michael@0 374 static int
michael@0 375 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
michael@0 376 const char *start, const char *end);
michael@0 377 static int
michael@0 378 reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
michael@0 379 const char *end);
michael@0 380 static void
michael@0 381 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
michael@0 382 const char *end);
michael@0 383
michael@0 384 static const XML_Char * getContext(XML_Parser parser);
michael@0 385 static XML_Bool
michael@0 386 setContext(XML_Parser parser, const XML_Char *context);
michael@0 387
michael@0 388 static void FASTCALL normalizePublicId(XML_Char *s);
michael@0 389
michael@0 390 static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
michael@0 391 /* do not call if parentParser != NULL */
michael@0 392 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
michael@0 393 static void
michael@0 394 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
michael@0 395 static int
michael@0 396 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
michael@0 397 static int
michael@0 398 copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
michael@0 399
michael@0 400 static NAMED *
michael@0 401 lookup(HASH_TABLE *table, KEY name, size_t createSize);
michael@0 402 static void FASTCALL
michael@0 403 hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
michael@0 404 static void FASTCALL hashTableClear(HASH_TABLE *);
michael@0 405 static void FASTCALL hashTableDestroy(HASH_TABLE *);
michael@0 406 static void FASTCALL
michael@0 407 hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
michael@0 408 static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
michael@0 409
michael@0 410 static void FASTCALL
michael@0 411 poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
michael@0 412 static void FASTCALL poolClear(STRING_POOL *);
michael@0 413 static void FASTCALL poolDestroy(STRING_POOL *);
michael@0 414 static XML_Char *
michael@0 415 poolAppend(STRING_POOL *pool, const ENCODING *enc,
michael@0 416 const char *ptr, const char *end);
michael@0 417 static XML_Char *
michael@0 418 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
michael@0 419 const char *ptr, const char *end);
michael@0 420 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
michael@0 421 static const XML_Char * FASTCALL
michael@0 422 poolCopyString(STRING_POOL *pool, const XML_Char *s);
michael@0 423 static const XML_Char *
michael@0 424 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
michael@0 425 static const XML_Char * FASTCALL
michael@0 426 poolAppendString(STRING_POOL *pool, const XML_Char *s);
michael@0 427
michael@0 428 static int FASTCALL nextScaffoldPart(XML_Parser parser);
michael@0 429 static XML_Content * build_model(XML_Parser parser);
michael@0 430 static ELEMENT_TYPE *
michael@0 431 getElementType(XML_Parser parser, const ENCODING *enc,
michael@0 432 const char *ptr, const char *end);
michael@0 433
michael@0 434 static XML_Parser
michael@0 435 parserCreate(const XML_Char *encodingName,
michael@0 436 const XML_Memory_Handling_Suite *memsuite,
michael@0 437 const XML_Char *nameSep,
michael@0 438 DTD *dtd);
michael@0 439 static void
michael@0 440 parserInit(XML_Parser parser, const XML_Char *encodingName);
michael@0 441
michael@0 442 #define poolStart(pool) ((pool)->start)
michael@0 443 #define poolEnd(pool) ((pool)->ptr)
michael@0 444 #define poolLength(pool) ((pool)->ptr - (pool)->start)
michael@0 445 #define poolChop(pool) ((void)--(pool->ptr))
michael@0 446 #define poolLastChar(pool) (((pool)->ptr)[-1])
michael@0 447 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
michael@0 448 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
michael@0 449 #define poolAppendChar(pool, c) \
michael@0 450 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
michael@0 451 ? 0 \
michael@0 452 : ((*((pool)->ptr)++ = c), 1))
michael@0 453
michael@0 454 struct XML_ParserStruct {
michael@0 455 /* The first member must be userData so that the XML_GetUserData
michael@0 456 macro works. */
michael@0 457 void *m_userData;
michael@0 458 void *m_handlerArg;
michael@0 459 char *m_buffer;
michael@0 460 const XML_Memory_Handling_Suite m_mem;
michael@0 461 /* first character to be parsed */
michael@0 462 const char *m_bufferPtr;
michael@0 463 /* past last character to be parsed */
michael@0 464 char *m_bufferEnd;
michael@0 465 /* allocated end of buffer */
michael@0 466 const char *m_bufferLim;
michael@0 467 XML_Index m_parseEndByteIndex;
michael@0 468 const char *m_parseEndPtr;
michael@0 469 XML_Char *m_dataBuf;
michael@0 470 XML_Char *m_dataBufEnd;
michael@0 471 XML_StartElementHandler m_startElementHandler;
michael@0 472 XML_EndElementHandler m_endElementHandler;
michael@0 473 XML_CharacterDataHandler m_characterDataHandler;
michael@0 474 XML_ProcessingInstructionHandler m_processingInstructionHandler;
michael@0 475 XML_CommentHandler m_commentHandler;
michael@0 476 XML_StartCdataSectionHandler m_startCdataSectionHandler;
michael@0 477 XML_EndCdataSectionHandler m_endCdataSectionHandler;
michael@0 478 XML_DefaultHandler m_defaultHandler;
michael@0 479 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
michael@0 480 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
michael@0 481 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
michael@0 482 XML_NotationDeclHandler m_notationDeclHandler;
michael@0 483 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
michael@0 484 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
michael@0 485 XML_NotStandaloneHandler m_notStandaloneHandler;
michael@0 486 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
michael@0 487 XML_Parser m_externalEntityRefHandlerArg;
michael@0 488 XML_SkippedEntityHandler m_skippedEntityHandler;
michael@0 489 XML_UnknownEncodingHandler m_unknownEncodingHandler;
michael@0 490 XML_ElementDeclHandler m_elementDeclHandler;
michael@0 491 XML_AttlistDeclHandler m_attlistDeclHandler;
michael@0 492 XML_EntityDeclHandler m_entityDeclHandler;
michael@0 493 XML_XmlDeclHandler m_xmlDeclHandler;
michael@0 494 const ENCODING *m_encoding;
michael@0 495 INIT_ENCODING m_initEncoding;
michael@0 496 const ENCODING *m_internalEncoding;
michael@0 497 const XML_Char *m_protocolEncodingName;
michael@0 498 XML_Bool m_ns;
michael@0 499 XML_Bool m_ns_triplets;
michael@0 500 void *m_unknownEncodingMem;
michael@0 501 void *m_unknownEncodingData;
michael@0 502 void *m_unknownEncodingHandlerData;
michael@0 503 void (XMLCALL *m_unknownEncodingRelease)(void *);
michael@0 504 PROLOG_STATE m_prologState;
michael@0 505 Processor *m_processor;
michael@0 506 enum XML_Error m_errorCode;
michael@0 507 const char *m_eventPtr;
michael@0 508 const char *m_eventEndPtr;
michael@0 509 const char *m_positionPtr;
michael@0 510 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
michael@0 511 OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
michael@0 512 XML_Bool m_defaultExpandInternalEntities;
michael@0 513 int m_tagLevel;
michael@0 514 ENTITY *m_declEntity;
michael@0 515 const XML_Char *m_doctypeName;
michael@0 516 const XML_Char *m_doctypeSysid;
michael@0 517 const XML_Char *m_doctypePubid;
michael@0 518 const XML_Char *m_declAttributeType;
michael@0 519 const XML_Char *m_declNotationName;
michael@0 520 const XML_Char *m_declNotationPublicId;
michael@0 521 ELEMENT_TYPE *m_declElementType;
michael@0 522 ATTRIBUTE_ID *m_declAttributeId;
michael@0 523 XML_Bool m_declAttributeIsCdata;
michael@0 524 XML_Bool m_declAttributeIsId;
michael@0 525 DTD *m_dtd;
michael@0 526 const XML_Char *m_curBase;
michael@0 527 TAG *m_tagStack;
michael@0 528 TAG *m_freeTagList;
michael@0 529 BINDING *m_inheritedBindings;
michael@0 530 BINDING *m_freeBindingList;
michael@0 531 int m_attsSize;
michael@0 532 int m_nSpecifiedAtts;
michael@0 533 int m_idAttIndex;
michael@0 534 ATTRIBUTE *m_atts;
michael@0 535 NS_ATT *m_nsAtts;
michael@0 536 unsigned long m_nsAttsVersion;
michael@0 537 unsigned char m_nsAttsPower;
michael@0 538 POSITION m_position;
michael@0 539 STRING_POOL m_tempPool;
michael@0 540 STRING_POOL m_temp2Pool;
michael@0 541 char *m_groupConnector;
michael@0 542 unsigned int m_groupSize;
michael@0 543 XML_Char m_namespaceSeparator;
michael@0 544 XML_Parser m_parentParser;
michael@0 545 XML_ParsingStatus m_parsingStatus;
michael@0 546 #ifdef XML_DTD
michael@0 547 XML_Bool m_isParamEntity;
michael@0 548 XML_Bool m_useForeignDTD;
michael@0 549 enum XML_ParamEntityParsing m_paramEntityParsing;
michael@0 550 #endif
michael@0 551 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
michael@0 552 const XML_Char* m_mismatch;
michael@0 553 /* END MOZILLA CHANGE */
michael@0 554 };
michael@0 555
michael@0 556 #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
michael@0 557 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
michael@0 558 #define FREE(p) (parser->m_mem.free_fcn((p)))
michael@0 559
michael@0 560 #define userData (parser->m_userData)
michael@0 561 #define handlerArg (parser->m_handlerArg)
michael@0 562 #define startElementHandler (parser->m_startElementHandler)
michael@0 563 #define endElementHandler (parser->m_endElementHandler)
michael@0 564 #define characterDataHandler (parser->m_characterDataHandler)
michael@0 565 #define processingInstructionHandler \
michael@0 566 (parser->m_processingInstructionHandler)
michael@0 567 #define commentHandler (parser->m_commentHandler)
michael@0 568 #define startCdataSectionHandler \
michael@0 569 (parser->m_startCdataSectionHandler)
michael@0 570 #define endCdataSectionHandler (parser->m_endCdataSectionHandler)
michael@0 571 #define defaultHandler (parser->m_defaultHandler)
michael@0 572 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
michael@0 573 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
michael@0 574 #define unparsedEntityDeclHandler \
michael@0 575 (parser->m_unparsedEntityDeclHandler)
michael@0 576 #define notationDeclHandler (parser->m_notationDeclHandler)
michael@0 577 #define startNamespaceDeclHandler \
michael@0 578 (parser->m_startNamespaceDeclHandler)
michael@0 579 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
michael@0 580 #define notStandaloneHandler (parser->m_notStandaloneHandler)
michael@0 581 #define externalEntityRefHandler \
michael@0 582 (parser->m_externalEntityRefHandler)
michael@0 583 #define externalEntityRefHandlerArg \
michael@0 584 (parser->m_externalEntityRefHandlerArg)
michael@0 585 #define internalEntityRefHandler \
michael@0 586 (parser->m_internalEntityRefHandler)
michael@0 587 #define skippedEntityHandler (parser->m_skippedEntityHandler)
michael@0 588 #define unknownEncodingHandler (parser->m_unknownEncodingHandler)
michael@0 589 #define elementDeclHandler (parser->m_elementDeclHandler)
michael@0 590 #define attlistDeclHandler (parser->m_attlistDeclHandler)
michael@0 591 #define entityDeclHandler (parser->m_entityDeclHandler)
michael@0 592 #define xmlDeclHandler (parser->m_xmlDeclHandler)
michael@0 593 #define encoding (parser->m_encoding)
michael@0 594 #define initEncoding (parser->m_initEncoding)
michael@0 595 #define internalEncoding (parser->m_internalEncoding)
michael@0 596 #define unknownEncodingMem (parser->m_unknownEncodingMem)
michael@0 597 #define unknownEncodingData (parser->m_unknownEncodingData)
michael@0 598 #define unknownEncodingHandlerData \
michael@0 599 (parser->m_unknownEncodingHandlerData)
michael@0 600 #define unknownEncodingRelease (parser->m_unknownEncodingRelease)
michael@0 601 #define protocolEncodingName (parser->m_protocolEncodingName)
michael@0 602 #define ns (parser->m_ns)
michael@0 603 #define ns_triplets (parser->m_ns_triplets)
michael@0 604 #define prologState (parser->m_prologState)
michael@0 605 #define processor (parser->m_processor)
michael@0 606 #define errorCode (parser->m_errorCode)
michael@0 607 #define eventPtr (parser->m_eventPtr)
michael@0 608 #define eventEndPtr (parser->m_eventEndPtr)
michael@0 609 #define positionPtr (parser->m_positionPtr)
michael@0 610 #define position (parser->m_position)
michael@0 611 #define openInternalEntities (parser->m_openInternalEntities)
michael@0 612 #define freeInternalEntities (parser->m_freeInternalEntities)
michael@0 613 #define defaultExpandInternalEntities \
michael@0 614 (parser->m_defaultExpandInternalEntities)
michael@0 615 #define tagLevel (parser->m_tagLevel)
michael@0 616 #define buffer (parser->m_buffer)
michael@0 617 #define bufferPtr (parser->m_bufferPtr)
michael@0 618 #define bufferEnd (parser->m_bufferEnd)
michael@0 619 #define parseEndByteIndex (parser->m_parseEndByteIndex)
michael@0 620 #define parseEndPtr (parser->m_parseEndPtr)
michael@0 621 #define bufferLim (parser->m_bufferLim)
michael@0 622 #define dataBuf (parser->m_dataBuf)
michael@0 623 #define dataBufEnd (parser->m_dataBufEnd)
michael@0 624 #define _dtd (parser->m_dtd)
michael@0 625 #define curBase (parser->m_curBase)
michael@0 626 #define declEntity (parser->m_declEntity)
michael@0 627 #define doctypeName (parser->m_doctypeName)
michael@0 628 #define doctypeSysid (parser->m_doctypeSysid)
michael@0 629 #define doctypePubid (parser->m_doctypePubid)
michael@0 630 #define declAttributeType (parser->m_declAttributeType)
michael@0 631 #define declNotationName (parser->m_declNotationName)
michael@0 632 #define declNotationPublicId (parser->m_declNotationPublicId)
michael@0 633 #define declElementType (parser->m_declElementType)
michael@0 634 #define declAttributeId (parser->m_declAttributeId)
michael@0 635 #define declAttributeIsCdata (parser->m_declAttributeIsCdata)
michael@0 636 #define declAttributeIsId (parser->m_declAttributeIsId)
michael@0 637 #define freeTagList (parser->m_freeTagList)
michael@0 638 #define freeBindingList (parser->m_freeBindingList)
michael@0 639 #define inheritedBindings (parser->m_inheritedBindings)
michael@0 640 #define tagStack (parser->m_tagStack)
michael@0 641 #define atts (parser->m_atts)
michael@0 642 #define attsSize (parser->m_attsSize)
michael@0 643 #define nSpecifiedAtts (parser->m_nSpecifiedAtts)
michael@0 644 #define idAttIndex (parser->m_idAttIndex)
michael@0 645 #define nsAtts (parser->m_nsAtts)
michael@0 646 #define nsAttsVersion (parser->m_nsAttsVersion)
michael@0 647 #define nsAttsPower (parser->m_nsAttsPower)
michael@0 648 #define tempPool (parser->m_tempPool)
michael@0 649 #define temp2Pool (parser->m_temp2Pool)
michael@0 650 #define groupConnector (parser->m_groupConnector)
michael@0 651 #define groupSize (parser->m_groupSize)
michael@0 652 #define namespaceSeparator (parser->m_namespaceSeparator)
michael@0 653 #define parentParser (parser->m_parentParser)
michael@0 654 #define ps_parsing (parser->m_parsingStatus.parsing)
michael@0 655 #define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
michael@0 656 #ifdef XML_DTD
michael@0 657 #define isParamEntity (parser->m_isParamEntity)
michael@0 658 #define useForeignDTD (parser->m_useForeignDTD)
michael@0 659 #define paramEntityParsing (parser->m_paramEntityParsing)
michael@0 660 #endif /* XML_DTD */
michael@0 661 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
michael@0 662 #define mismatch (parser->m_mismatch)
michael@0 663 /* END MOZILLA CHANGE */
michael@0 664
michael@0 665 /* BEGIN MOZILLA CHANGE (unused API) */
michael@0 666 #if 0
michael@0 667 XML_Parser XMLCALL
michael@0 668 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
michael@0 669 {
michael@0 670 XML_Char tmp[2];
michael@0 671 *tmp = nsSep;
michael@0 672 return XML_ParserCreate_MM(encodingName, NULL, tmp);
michael@0 673 }
michael@0 674 #endif
michael@0 675 /* END MOZILLA CHANGE */
michael@0 676
michael@0 677 static const XML_Char implicitContext[] = {
michael@0 678 'x', 'm', 'l', '=', 'h', 't', 't', 'p', ':', '/', '/',
michael@0 679 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
michael@0 680 'X', 'M', 'L', '/', '1', '9', '9', '8', '/',
michael@0 681 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0'
michael@0 682 };
michael@0 683
michael@0 684 XML_Parser XMLCALL
michael@0 685 XML_ParserCreate_MM(const XML_Char *encodingName,
michael@0 686 const XML_Memory_Handling_Suite *memsuite,
michael@0 687 const XML_Char *nameSep)
michael@0 688 {
michael@0 689 XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL);
michael@0 690 if (parser != NULL && ns) {
michael@0 691 /* implicit context only set for root parser, since child
michael@0 692 parsers (i.e. external entity parsers) will inherit it
michael@0 693 */
michael@0 694 if (!setContext(parser, implicitContext)) {
michael@0 695 XML_ParserFree(parser);
michael@0 696 return NULL;
michael@0 697 }
michael@0 698 }
michael@0 699 return parser;
michael@0 700 }
michael@0 701
michael@0 702 static XML_Parser
michael@0 703 parserCreate(const XML_Char *encodingName,
michael@0 704 const XML_Memory_Handling_Suite *memsuite,
michael@0 705 const XML_Char *nameSep,
michael@0 706 DTD *dtd)
michael@0 707 {
michael@0 708 XML_Parser parser;
michael@0 709
michael@0 710 if (memsuite) {
michael@0 711 XML_Memory_Handling_Suite *mtemp;
michael@0 712 parser = (XML_Parser)
michael@0 713 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
michael@0 714 if (parser != NULL) {
michael@0 715 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
michael@0 716 mtemp->malloc_fcn = memsuite->malloc_fcn;
michael@0 717 mtemp->realloc_fcn = memsuite->realloc_fcn;
michael@0 718 mtemp->free_fcn = memsuite->free_fcn;
michael@0 719 }
michael@0 720 }
michael@0 721 else {
michael@0 722 XML_Memory_Handling_Suite *mtemp;
michael@0 723 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
michael@0 724 if (parser != NULL) {
michael@0 725 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
michael@0 726 mtemp->malloc_fcn = malloc;
michael@0 727 mtemp->realloc_fcn = realloc;
michael@0 728 mtemp->free_fcn = free;
michael@0 729 }
michael@0 730 }
michael@0 731
michael@0 732 if (!parser)
michael@0 733 return parser;
michael@0 734
michael@0 735 buffer = NULL;
michael@0 736 bufferLim = NULL;
michael@0 737
michael@0 738 attsSize = INIT_ATTS_SIZE;
michael@0 739 atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
michael@0 740 if (atts == NULL) {
michael@0 741 FREE(parser);
michael@0 742 return NULL;
michael@0 743 }
michael@0 744 dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
michael@0 745 if (dataBuf == NULL) {
michael@0 746 FREE(atts);
michael@0 747 FREE(parser);
michael@0 748 return NULL;
michael@0 749 }
michael@0 750 dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
michael@0 751
michael@0 752 if (dtd)
michael@0 753 _dtd = dtd;
michael@0 754 else {
michael@0 755 _dtd = dtdCreate(&parser->m_mem);
michael@0 756 if (_dtd == NULL) {
michael@0 757 FREE(dataBuf);
michael@0 758 FREE(atts);
michael@0 759 FREE(parser);
michael@0 760 return NULL;
michael@0 761 }
michael@0 762 }
michael@0 763
michael@0 764 freeBindingList = NULL;
michael@0 765 freeTagList = NULL;
michael@0 766 freeInternalEntities = NULL;
michael@0 767
michael@0 768 groupSize = 0;
michael@0 769 groupConnector = NULL;
michael@0 770
michael@0 771 unknownEncodingHandler = NULL;
michael@0 772 unknownEncodingHandlerData = NULL;
michael@0 773
michael@0 774 namespaceSeparator = '!';
michael@0 775 ns = XML_FALSE;
michael@0 776 ns_triplets = XML_FALSE;
michael@0 777
michael@0 778 nsAtts = NULL;
michael@0 779 nsAttsVersion = 0;
michael@0 780 nsAttsPower = 0;
michael@0 781
michael@0 782 poolInit(&tempPool, &(parser->m_mem));
michael@0 783 poolInit(&temp2Pool, &(parser->m_mem));
michael@0 784 parserInit(parser, encodingName);
michael@0 785
michael@0 786 if (encodingName && !protocolEncodingName) {
michael@0 787 XML_ParserFree(parser);
michael@0 788 return NULL;
michael@0 789 }
michael@0 790
michael@0 791 if (nameSep) {
michael@0 792 ns = XML_TRUE;
michael@0 793 internalEncoding = XmlGetInternalEncodingNS();
michael@0 794 namespaceSeparator = *nameSep;
michael@0 795 }
michael@0 796 else {
michael@0 797 internalEncoding = XmlGetInternalEncoding();
michael@0 798 }
michael@0 799
michael@0 800 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
michael@0 801 mismatch = NULL;
michael@0 802 /* END MOZILLA CHANGE */
michael@0 803
michael@0 804 return parser;
michael@0 805 }
michael@0 806
michael@0 807 static void
michael@0 808 parserInit(XML_Parser parser, const XML_Char *encodingName)
michael@0 809 {
michael@0 810 processor = prologInitProcessor;
michael@0 811 XmlPrologStateInit(&prologState);
michael@0 812 protocolEncodingName = (encodingName != NULL
michael@0 813 ? poolCopyString(&tempPool, encodingName)
michael@0 814 : NULL);
michael@0 815 curBase = NULL;
michael@0 816 XmlInitEncoding(&initEncoding, &encoding, 0);
michael@0 817 userData = NULL;
michael@0 818 handlerArg = NULL;
michael@0 819 startElementHandler = NULL;
michael@0 820 endElementHandler = NULL;
michael@0 821 characterDataHandler = NULL;
michael@0 822 processingInstructionHandler = NULL;
michael@0 823 commentHandler = NULL;
michael@0 824 startCdataSectionHandler = NULL;
michael@0 825 endCdataSectionHandler = NULL;
michael@0 826 defaultHandler = NULL;
michael@0 827 startDoctypeDeclHandler = NULL;
michael@0 828 endDoctypeDeclHandler = NULL;
michael@0 829 unparsedEntityDeclHandler = NULL;
michael@0 830 notationDeclHandler = NULL;
michael@0 831 startNamespaceDeclHandler = NULL;
michael@0 832 endNamespaceDeclHandler = NULL;
michael@0 833 notStandaloneHandler = NULL;
michael@0 834 externalEntityRefHandler = NULL;
michael@0 835 externalEntityRefHandlerArg = parser;
michael@0 836 skippedEntityHandler = NULL;
michael@0 837 elementDeclHandler = NULL;
michael@0 838 attlistDeclHandler = NULL;
michael@0 839 entityDeclHandler = NULL;
michael@0 840 xmlDeclHandler = NULL;
michael@0 841 bufferPtr = buffer;
michael@0 842 bufferEnd = buffer;
michael@0 843 parseEndByteIndex = 0;
michael@0 844 parseEndPtr = NULL;
michael@0 845 declElementType = NULL;
michael@0 846 declAttributeId = NULL;
michael@0 847 declEntity = NULL;
michael@0 848 doctypeName = NULL;
michael@0 849 doctypeSysid = NULL;
michael@0 850 doctypePubid = NULL;
michael@0 851 declAttributeType = NULL;
michael@0 852 declNotationName = NULL;
michael@0 853 declNotationPublicId = NULL;
michael@0 854 declAttributeIsCdata = XML_FALSE;
michael@0 855 declAttributeIsId = XML_FALSE;
michael@0 856 memset(&position, 0, sizeof(POSITION));
michael@0 857 errorCode = XML_ERROR_NONE;
michael@0 858 eventPtr = NULL;
michael@0 859 eventEndPtr = NULL;
michael@0 860 positionPtr = NULL;
michael@0 861 openInternalEntities = NULL;
michael@0 862 defaultExpandInternalEntities = XML_TRUE;
michael@0 863 tagLevel = 0;
michael@0 864 tagStack = NULL;
michael@0 865 inheritedBindings = NULL;
michael@0 866 nSpecifiedAtts = 0;
michael@0 867 unknownEncodingMem = NULL;
michael@0 868 unknownEncodingRelease = NULL;
michael@0 869 unknownEncodingData = NULL;
michael@0 870 parentParser = NULL;
michael@0 871 ps_parsing = XML_INITIALIZED;
michael@0 872 #ifdef XML_DTD
michael@0 873 isParamEntity = XML_FALSE;
michael@0 874 useForeignDTD = XML_FALSE;
michael@0 875 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
michael@0 876 #endif
michael@0 877 }
michael@0 878
michael@0 879 /* moves list of bindings to freeBindingList */
michael@0 880 static void FASTCALL
michael@0 881 moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
michael@0 882 {
michael@0 883 while (bindings) {
michael@0 884 BINDING *b = bindings;
michael@0 885 bindings = bindings->nextTagBinding;
michael@0 886 b->nextTagBinding = freeBindingList;
michael@0 887 freeBindingList = b;
michael@0 888 }
michael@0 889 }
michael@0 890
michael@0 891 /* BEGIN MOZILLA CHANGE (unused API) */
michael@0 892 #if 0
michael@0 893 XML_Bool XMLCALL
michael@0 894 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
michael@0 895 {
michael@0 896 TAG *tStk;
michael@0 897 OPEN_INTERNAL_ENTITY *openEntityList;
michael@0 898 if (parentParser)
michael@0 899 return XML_FALSE;
michael@0 900 /* move tagStack to freeTagList */
michael@0 901 tStk = tagStack;
michael@0 902 while (tStk) {
michael@0 903 TAG *tag = tStk;
michael@0 904 tStk = tStk->parent;
michael@0 905 tag->parent = freeTagList;
michael@0 906 moveToFreeBindingList(parser, tag->bindings);
michael@0 907 tag->bindings = NULL;
michael@0 908 freeTagList = tag;
michael@0 909 }
michael@0 910 /* move openInternalEntities to freeInternalEntities */
michael@0 911 openEntityList = openInternalEntities;
michael@0 912 while (openEntityList) {
michael@0 913 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
michael@0 914 openEntityList = openEntity->next;
michael@0 915 openEntity->next = freeInternalEntities;
michael@0 916 freeInternalEntities = openEntity;
michael@0 917 }
michael@0 918 moveToFreeBindingList(parser, inheritedBindings);
michael@0 919 FREE(unknownEncodingMem);
michael@0 920 if (unknownEncodingRelease)
michael@0 921 unknownEncodingRelease(unknownEncodingData);
michael@0 922 poolClear(&tempPool);
michael@0 923 poolClear(&temp2Pool);
michael@0 924 parserInit(parser, encodingName);
michael@0 925 dtdReset(_dtd, &parser->m_mem);
michael@0 926 return setContext(parser, implicitContext);
michael@0 927 }
michael@0 928
michael@0 929 enum XML_Status XMLCALL
michael@0 930 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
michael@0 931 {
michael@0 932 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
michael@0 933 XXX There's no way for the caller to determine which of the
michael@0 934 XXX possible error cases caused the XML_STATUS_ERROR return.
michael@0 935 */
michael@0 936 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
michael@0 937 return XML_STATUS_ERROR;
michael@0 938 if (encodingName == NULL)
michael@0 939 protocolEncodingName = NULL;
michael@0 940 else {
michael@0 941 protocolEncodingName = poolCopyString(&tempPool, encodingName);
michael@0 942 if (!protocolEncodingName)
michael@0 943 return XML_STATUS_ERROR;
michael@0 944 }
michael@0 945 return XML_STATUS_OK;
michael@0 946 }
michael@0 947 #endif
michael@0 948 /* END MOZILLA CHANGE */
michael@0 949
michael@0 950 XML_Parser XMLCALL
michael@0 951 XML_ExternalEntityParserCreate(XML_Parser oldParser,
michael@0 952 const XML_Char *context,
michael@0 953 const XML_Char *encodingName)
michael@0 954 {
michael@0 955 XML_Parser parser = oldParser;
michael@0 956 DTD *newDtd = NULL;
michael@0 957 DTD *oldDtd = _dtd;
michael@0 958 XML_StartElementHandler oldStartElementHandler = startElementHandler;
michael@0 959 XML_EndElementHandler oldEndElementHandler = endElementHandler;
michael@0 960 XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
michael@0 961 XML_ProcessingInstructionHandler oldProcessingInstructionHandler
michael@0 962 = processingInstructionHandler;
michael@0 963 XML_CommentHandler oldCommentHandler = commentHandler;
michael@0 964 XML_StartCdataSectionHandler oldStartCdataSectionHandler
michael@0 965 = startCdataSectionHandler;
michael@0 966 XML_EndCdataSectionHandler oldEndCdataSectionHandler
michael@0 967 = endCdataSectionHandler;
michael@0 968 XML_DefaultHandler oldDefaultHandler = defaultHandler;
michael@0 969 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
michael@0 970 = unparsedEntityDeclHandler;
michael@0 971 XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
michael@0 972 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
michael@0 973 = startNamespaceDeclHandler;
michael@0 974 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
michael@0 975 = endNamespaceDeclHandler;
michael@0 976 XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
michael@0 977 XML_ExternalEntityRefHandler oldExternalEntityRefHandler
michael@0 978 = externalEntityRefHandler;
michael@0 979 XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
michael@0 980 XML_UnknownEncodingHandler oldUnknownEncodingHandler
michael@0 981 = unknownEncodingHandler;
michael@0 982 XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
michael@0 983 XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
michael@0 984 XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
michael@0 985 XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
michael@0 986 ELEMENT_TYPE * oldDeclElementType = declElementType;
michael@0 987
michael@0 988 void *oldUserData = userData;
michael@0 989 void *oldHandlerArg = handlerArg;
michael@0 990 XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
michael@0 991 XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
michael@0 992 #ifdef XML_DTD
michael@0 993 enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
michael@0 994 int oldInEntityValue = prologState.inEntityValue;
michael@0 995 #endif
michael@0 996 XML_Bool oldns_triplets = ns_triplets;
michael@0 997
michael@0 998 #ifdef XML_DTD
michael@0 999 if (!context)
michael@0 1000 newDtd = oldDtd;
michael@0 1001 #endif /* XML_DTD */
michael@0 1002
michael@0 1003 /* Note that the magical uses of the pre-processor to make field
michael@0 1004 access look more like C++ require that `parser' be overwritten
michael@0 1005 here. This makes this function more painful to follow than it
michael@0 1006 would be otherwise.
michael@0 1007 */
michael@0 1008 if (ns) {
michael@0 1009 XML_Char tmp[2];
michael@0 1010 *tmp = namespaceSeparator;
michael@0 1011 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
michael@0 1012 }
michael@0 1013 else {
michael@0 1014 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
michael@0 1015 }
michael@0 1016
michael@0 1017 if (!parser)
michael@0 1018 return NULL;
michael@0 1019
michael@0 1020 startElementHandler = oldStartElementHandler;
michael@0 1021 endElementHandler = oldEndElementHandler;
michael@0 1022 characterDataHandler = oldCharacterDataHandler;
michael@0 1023 processingInstructionHandler = oldProcessingInstructionHandler;
michael@0 1024 commentHandler = oldCommentHandler;
michael@0 1025 startCdataSectionHandler = oldStartCdataSectionHandler;
michael@0 1026 endCdataSectionHandler = oldEndCdataSectionHandler;
michael@0 1027 defaultHandler = oldDefaultHandler;
michael@0 1028 unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
michael@0 1029 notationDeclHandler = oldNotationDeclHandler;
michael@0 1030 startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
michael@0 1031 endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
michael@0 1032 notStandaloneHandler = oldNotStandaloneHandler;
michael@0 1033 externalEntityRefHandler = oldExternalEntityRefHandler;
michael@0 1034 skippedEntityHandler = oldSkippedEntityHandler;
michael@0 1035 unknownEncodingHandler = oldUnknownEncodingHandler;
michael@0 1036 elementDeclHandler = oldElementDeclHandler;
michael@0 1037 attlistDeclHandler = oldAttlistDeclHandler;
michael@0 1038 entityDeclHandler = oldEntityDeclHandler;
michael@0 1039 xmlDeclHandler = oldXmlDeclHandler;
michael@0 1040 declElementType = oldDeclElementType;
michael@0 1041 userData = oldUserData;
michael@0 1042 if (oldUserData == oldHandlerArg)
michael@0 1043 handlerArg = userData;
michael@0 1044 else
michael@0 1045 handlerArg = parser;
michael@0 1046 if (oldExternalEntityRefHandlerArg != oldParser)
michael@0 1047 externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
michael@0 1048 defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
michael@0 1049 ns_triplets = oldns_triplets;
michael@0 1050 parentParser = oldParser;
michael@0 1051 #ifdef XML_DTD
michael@0 1052 paramEntityParsing = oldParamEntityParsing;
michael@0 1053 prologState.inEntityValue = oldInEntityValue;
michael@0 1054 if (context) {
michael@0 1055 #endif /* XML_DTD */
michael@0 1056 if (!dtdCopy(_dtd, oldDtd, &parser->m_mem)
michael@0 1057 || !setContext(parser, context)) {
michael@0 1058 XML_ParserFree(parser);
michael@0 1059 return NULL;
michael@0 1060 }
michael@0 1061 processor = externalEntityInitProcessor;
michael@0 1062 #ifdef XML_DTD
michael@0 1063 }
michael@0 1064 else {
michael@0 1065 /* The DTD instance referenced by _dtd is shared between the document's
michael@0 1066 root parser and external PE parsers, therefore one does not need to
michael@0 1067 call setContext. In addition, one also *must* not call setContext,
michael@0 1068 because this would overwrite existing prefix->binding pointers in
michael@0 1069 _dtd with ones that get destroyed with the external PE parser.
michael@0 1070 This would leave those prefixes with dangling pointers.
michael@0 1071 */
michael@0 1072 isParamEntity = XML_TRUE;
michael@0 1073 XmlPrologStateInitExternalEntity(&prologState);
michael@0 1074 processor = externalParEntInitProcessor;
michael@0 1075 }
michael@0 1076 #endif /* XML_DTD */
michael@0 1077 return parser;
michael@0 1078 }
michael@0 1079
michael@0 1080 static void FASTCALL
michael@0 1081 destroyBindings(BINDING *bindings, XML_Parser parser)
michael@0 1082 {
michael@0 1083 for (;;) {
michael@0 1084 BINDING *b = bindings;
michael@0 1085 if (!b)
michael@0 1086 break;
michael@0 1087 bindings = b->nextTagBinding;
michael@0 1088 FREE(b->uri);
michael@0 1089 FREE(b);
michael@0 1090 }
michael@0 1091 }
michael@0 1092
michael@0 1093 void XMLCALL
michael@0 1094 XML_ParserFree(XML_Parser parser)
michael@0 1095 {
michael@0 1096 TAG *tagList;
michael@0 1097 OPEN_INTERNAL_ENTITY *entityList;
michael@0 1098 if (parser == NULL)
michael@0 1099 return;
michael@0 1100 /* free tagStack and freeTagList */
michael@0 1101 tagList = tagStack;
michael@0 1102 for (;;) {
michael@0 1103 TAG *p;
michael@0 1104 if (tagList == NULL) {
michael@0 1105 if (freeTagList == NULL)
michael@0 1106 break;
michael@0 1107 tagList = freeTagList;
michael@0 1108 freeTagList = NULL;
michael@0 1109 }
michael@0 1110 p = tagList;
michael@0 1111 tagList = tagList->parent;
michael@0 1112 FREE(p->buf);
michael@0 1113 destroyBindings(p->bindings, parser);
michael@0 1114 FREE(p);
michael@0 1115 }
michael@0 1116 /* free openInternalEntities and freeInternalEntities */
michael@0 1117 entityList = openInternalEntities;
michael@0 1118 for (;;) {
michael@0 1119 OPEN_INTERNAL_ENTITY *openEntity;
michael@0 1120 if (entityList == NULL) {
michael@0 1121 if (freeInternalEntities == NULL)
michael@0 1122 break;
michael@0 1123 entityList = freeInternalEntities;
michael@0 1124 freeInternalEntities = NULL;
michael@0 1125 }
michael@0 1126 openEntity = entityList;
michael@0 1127 entityList = entityList->next;
michael@0 1128 FREE(openEntity);
michael@0 1129 }
michael@0 1130
michael@0 1131 destroyBindings(freeBindingList, parser);
michael@0 1132 destroyBindings(inheritedBindings, parser);
michael@0 1133 poolDestroy(&tempPool);
michael@0 1134 poolDestroy(&temp2Pool);
michael@0 1135 #ifdef XML_DTD
michael@0 1136 /* external parameter entity parsers share the DTD structure
michael@0 1137 parser->m_dtd with the root parser, so we must not destroy it
michael@0 1138 */
michael@0 1139 if (!isParamEntity && _dtd)
michael@0 1140 #else
michael@0 1141 if (_dtd)
michael@0 1142 #endif /* XML_DTD */
michael@0 1143 dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
michael@0 1144 FREE((void *)atts);
michael@0 1145 FREE(groupConnector);
michael@0 1146 FREE(buffer);
michael@0 1147 FREE(dataBuf);
michael@0 1148 FREE(nsAtts);
michael@0 1149 FREE(unknownEncodingMem);
michael@0 1150 if (unknownEncodingRelease)
michael@0 1151 unknownEncodingRelease(unknownEncodingData);
michael@0 1152 FREE(parser);
michael@0 1153 }
michael@0 1154
michael@0 1155 void XMLCALL
michael@0 1156 XML_UseParserAsHandlerArg(XML_Parser parser)
michael@0 1157 {
michael@0 1158 handlerArg = parser;
michael@0 1159 }
michael@0 1160
michael@0 1161 /* BEGIN MOZILLA CHANGE (unused API) */
michael@0 1162 #if 0
michael@0 1163 enum XML_Error XMLCALL
michael@0 1164 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
michael@0 1165 {
michael@0 1166 #ifdef XML_DTD
michael@0 1167 /* block after XML_Parse()/XML_ParseBuffer() has been called */
michael@0 1168 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
michael@0 1169 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
michael@0 1170 useForeignDTD = useDTD;
michael@0 1171 return XML_ERROR_NONE;
michael@0 1172 #else
michael@0 1173 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
michael@0 1174 #endif
michael@0 1175 }
michael@0 1176 #endif
michael@0 1177 /* END MOZILLA CHANGE */
michael@0 1178
michael@0 1179 void XMLCALL
michael@0 1180 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
michael@0 1181 {
michael@0 1182 /* block after XML_Parse()/XML_ParseBuffer() has been called */
michael@0 1183 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
michael@0 1184 return;
michael@0 1185 ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
michael@0 1186 }
michael@0 1187
michael@0 1188 void XMLCALL
michael@0 1189 XML_SetUserData(XML_Parser parser, void *p)
michael@0 1190 {
michael@0 1191 if (handlerArg == userData)
michael@0 1192 handlerArg = userData = p;
michael@0 1193 else
michael@0 1194 userData = p;
michael@0 1195 }
michael@0 1196
michael@0 1197 enum XML_Status XMLCALL
michael@0 1198 XML_SetBase(XML_Parser parser, const XML_Char *p)
michael@0 1199 {
michael@0 1200 if (p) {
michael@0 1201 p = poolCopyString(&_dtd->pool, p);
michael@0 1202 if (!p)
michael@0 1203 return XML_STATUS_ERROR;
michael@0 1204 curBase = p;
michael@0 1205 }
michael@0 1206 else
michael@0 1207 curBase = NULL;
michael@0 1208 return XML_STATUS_OK;
michael@0 1209 }
michael@0 1210
michael@0 1211 const XML_Char * XMLCALL
michael@0 1212 XML_GetBase(XML_Parser parser)
michael@0 1213 {
michael@0 1214 return curBase;
michael@0 1215 }
michael@0 1216
michael@0 1217 int XMLCALL
michael@0 1218 XML_GetSpecifiedAttributeCount(XML_Parser parser)
michael@0 1219 {
michael@0 1220 return nSpecifiedAtts;
michael@0 1221 }
michael@0 1222
michael@0 1223 int XMLCALL
michael@0 1224 XML_GetIdAttributeIndex(XML_Parser parser)
michael@0 1225 {
michael@0 1226 return idAttIndex;
michael@0 1227 }
michael@0 1228
michael@0 1229 void XMLCALL
michael@0 1230 XML_SetElementHandler(XML_Parser parser,
michael@0 1231 XML_StartElementHandler start,
michael@0 1232 XML_EndElementHandler end)
michael@0 1233 {
michael@0 1234 startElementHandler = start;
michael@0 1235 endElementHandler = end;
michael@0 1236 }
michael@0 1237
michael@0 1238 /* BEGIN MOZILLA CHANGE (unused API) */
michael@0 1239 #if 0
michael@0 1240 void XMLCALL
michael@0 1241 XML_SetStartElementHandler(XML_Parser parser,
michael@0 1242 XML_StartElementHandler start) {
michael@0 1243 startElementHandler = start;
michael@0 1244 }
michael@0 1245
michael@0 1246 void XMLCALL
michael@0 1247 XML_SetEndElementHandler(XML_Parser parser,
michael@0 1248 XML_EndElementHandler end) {
michael@0 1249 endElementHandler = end;
michael@0 1250 }
michael@0 1251 #endif
michael@0 1252 /* END MOZILLA CHANGE */
michael@0 1253
michael@0 1254 void XMLCALL
michael@0 1255 XML_SetCharacterDataHandler(XML_Parser parser,
michael@0 1256 XML_CharacterDataHandler handler)
michael@0 1257 {
michael@0 1258 characterDataHandler = handler;
michael@0 1259 }
michael@0 1260
michael@0 1261 void XMLCALL
michael@0 1262 XML_SetProcessingInstructionHandler(XML_Parser parser,
michael@0 1263 XML_ProcessingInstructionHandler handler)
michael@0 1264 {
michael@0 1265 processingInstructionHandler = handler;
michael@0 1266 }
michael@0 1267
michael@0 1268 void XMLCALL
michael@0 1269 XML_SetCommentHandler(XML_Parser parser,
michael@0 1270 XML_CommentHandler handler)
michael@0 1271 {
michael@0 1272 commentHandler = handler;
michael@0 1273 }
michael@0 1274
michael@0 1275 void XMLCALL
michael@0 1276 XML_SetCdataSectionHandler(XML_Parser parser,
michael@0 1277 XML_StartCdataSectionHandler start,
michael@0 1278 XML_EndCdataSectionHandler end)
michael@0 1279 {
michael@0 1280 startCdataSectionHandler = start;
michael@0 1281 endCdataSectionHandler = end;
michael@0 1282 }
michael@0 1283
michael@0 1284 /* BEGIN MOZILLA CHANGE (unused API) */
michael@0 1285 #if 0
michael@0 1286 void XMLCALL
michael@0 1287 XML_SetStartCdataSectionHandler(XML_Parser parser,
michael@0 1288 XML_StartCdataSectionHandler start) {
michael@0 1289 startCdataSectionHandler = start;
michael@0 1290 }
michael@0 1291
michael@0 1292 void XMLCALL
michael@0 1293 XML_SetEndCdataSectionHandler(XML_Parser parser,
michael@0 1294 XML_EndCdataSectionHandler end) {
michael@0 1295 endCdataSectionHandler = end;
michael@0 1296 }
michael@0 1297
michael@0 1298 void XMLCALL
michael@0 1299 XML_SetDefaultHandler(XML_Parser parser,
michael@0 1300 XML_DefaultHandler handler)
michael@0 1301 {
michael@0 1302 defaultHandler = handler;
michael@0 1303 defaultExpandInternalEntities = XML_FALSE;
michael@0 1304 }
michael@0 1305 #endif
michael@0 1306 /* END MOZILLA CHANGE */
michael@0 1307
michael@0 1308 void XMLCALL
michael@0 1309 XML_SetDefaultHandlerExpand(XML_Parser parser,
michael@0 1310 XML_DefaultHandler handler)
michael@0 1311 {
michael@0 1312 defaultHandler = handler;
michael@0 1313 defaultExpandInternalEntities = XML_TRUE;
michael@0 1314 }
michael@0 1315
michael@0 1316 void XMLCALL
michael@0 1317 XML_SetDoctypeDeclHandler(XML_Parser parser,
michael@0 1318 XML_StartDoctypeDeclHandler start,
michael@0 1319 XML_EndDoctypeDeclHandler end)
michael@0 1320 {
michael@0 1321 startDoctypeDeclHandler = start;
michael@0 1322 endDoctypeDeclHandler = end;
michael@0 1323 }
michael@0 1324
michael@0 1325 /* BEGIN MOZILLA CHANGE (unused API) */
michael@0 1326 #if 0
michael@0 1327 void XMLCALL
michael@0 1328 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
michael@0 1329 XML_StartDoctypeDeclHandler start) {
michael@0 1330 startDoctypeDeclHandler = start;
michael@0 1331 }
michael@0 1332
michael@0 1333 void XMLCALL
michael@0 1334 XML_SetEndDoctypeDeclHandler(XML_Parser parser,
michael@0 1335 XML_EndDoctypeDeclHandler end) {
michael@0 1336 endDoctypeDeclHandler = end;
michael@0 1337 }
michael@0 1338 #endif
michael@0 1339 /* END MOZILLA CHANGE */
michael@0 1340
michael@0 1341 void XMLCALL
michael@0 1342 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
michael@0 1343 XML_UnparsedEntityDeclHandler handler)
michael@0 1344 {
michael@0 1345 unparsedEntityDeclHandler = handler;
michael@0 1346 }
michael@0 1347
michael@0 1348 void XMLCALL
michael@0 1349 XML_SetNotationDeclHandler(XML_Parser parser,
michael@0 1350 XML_NotationDeclHandler handler)
michael@0 1351 {
michael@0 1352 notationDeclHandler = handler;
michael@0 1353 }
michael@0 1354
michael@0 1355 void XMLCALL
michael@0 1356 XML_SetNamespaceDeclHandler(XML_Parser parser,
michael@0 1357 XML_StartNamespaceDeclHandler start,
michael@0 1358 XML_EndNamespaceDeclHandler end)
michael@0 1359 {
michael@0 1360 startNamespaceDeclHandler = start;
michael@0 1361 endNamespaceDeclHandler = end;
michael@0 1362 }
michael@0 1363
michael@0 1364
michael@0 1365 /* BEGIN MOZILLA CHANGE (unused API) */
michael@0 1366 #if 0
michael@0 1367 void XMLCALL
michael@0 1368 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
michael@0 1369 XML_StartNamespaceDeclHandler start) {
michael@0 1370 startNamespaceDeclHandler = start;
michael@0 1371 }
michael@0 1372
michael@0 1373 void XMLCALL
michael@0 1374 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
michael@0 1375 XML_EndNamespaceDeclHandler end) {
michael@0 1376 endNamespaceDeclHandler = end;
michael@0 1377 }
michael@0 1378
michael@0 1379 void XMLCALL
michael@0 1380 XML_SetNotStandaloneHandler(XML_Parser parser,
michael@0 1381 XML_NotStandaloneHandler handler)
michael@0 1382 {
michael@0 1383 notStandaloneHandler = handler;
michael@0 1384 }
michael@0 1385 #endif
michael@0 1386 /* END MOZILLA CHANGE */
michael@0 1387
michael@0 1388 void XMLCALL
michael@0 1389 XML_SetExternalEntityRefHandler(XML_Parser parser,
michael@0 1390 XML_ExternalEntityRefHandler handler)
michael@0 1391 {
michael@0 1392 externalEntityRefHandler = handler;
michael@0 1393 }
michael@0 1394
michael@0 1395 void XMLCALL
michael@0 1396 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
michael@0 1397 {
michael@0 1398 if (arg)
michael@0 1399 externalEntityRefHandlerArg = (XML_Parser)arg;
michael@0 1400 else
michael@0 1401 externalEntityRefHandlerArg = parser;
michael@0 1402 }
michael@0 1403
michael@0 1404 /* BEGIN MOZILLA CHANGE (unused API) */
michael@0 1405 #if 0
michael@0 1406 void XMLCALL
michael@0 1407 XML_SetSkippedEntityHandler(XML_Parser parser,
michael@0 1408 XML_SkippedEntityHandler handler)
michael@0 1409 {
michael@0 1410 skippedEntityHandler = handler;
michael@0 1411 }
michael@0 1412
michael@0 1413 void XMLCALL
michael@0 1414 XML_SetUnknownEncodingHandler(XML_Parser parser,
michael@0 1415 XML_UnknownEncodingHandler handler,
michael@0 1416 void *data)
michael@0 1417 {
michael@0 1418 unknownEncodingHandler = handler;
michael@0 1419 unknownEncodingHandlerData = data;
michael@0 1420 }
michael@0 1421
michael@0 1422 void XMLCALL
michael@0 1423 XML_SetElementDeclHandler(XML_Parser parser,
michael@0 1424 XML_ElementDeclHandler eldecl)
michael@0 1425 {
michael@0 1426 elementDeclHandler = eldecl;
michael@0 1427 }
michael@0 1428
michael@0 1429 void XMLCALL
michael@0 1430 XML_SetAttlistDeclHandler(XML_Parser parser,
michael@0 1431 XML_AttlistDeclHandler attdecl)
michael@0 1432 {
michael@0 1433 attlistDeclHandler = attdecl;
michael@0 1434 }
michael@0 1435
michael@0 1436 void XMLCALL
michael@0 1437 XML_SetEntityDeclHandler(XML_Parser parser,
michael@0 1438 XML_EntityDeclHandler handler)
michael@0 1439 {
michael@0 1440 entityDeclHandler = handler;
michael@0 1441 }
michael@0 1442 #endif
michael@0 1443 /* END MOZILLA CHANGE */
michael@0 1444
michael@0 1445 void XMLCALL
michael@0 1446 XML_SetXmlDeclHandler(XML_Parser parser,
michael@0 1447 XML_XmlDeclHandler handler) {
michael@0 1448 xmlDeclHandler = handler;
michael@0 1449 }
michael@0 1450
michael@0 1451 int XMLCALL
michael@0 1452 XML_SetParamEntityParsing(XML_Parser parser,
michael@0 1453 enum XML_ParamEntityParsing peParsing)
michael@0 1454 {
michael@0 1455 /* block after XML_Parse()/XML_ParseBuffer() has been called */
michael@0 1456 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
michael@0 1457 return 0;
michael@0 1458 #ifdef XML_DTD
michael@0 1459 paramEntityParsing = peParsing;
michael@0 1460 return 1;
michael@0 1461 #else
michael@0 1462 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
michael@0 1463 #endif
michael@0 1464 }
michael@0 1465
michael@0 1466 enum XML_Status XMLCALL
michael@0 1467 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
michael@0 1468 {
michael@0 1469 switch (ps_parsing) {
michael@0 1470 case XML_SUSPENDED:
michael@0 1471 errorCode = XML_ERROR_SUSPENDED;
michael@0 1472 return XML_STATUS_ERROR;
michael@0 1473 case XML_FINISHED:
michael@0 1474 errorCode = XML_ERROR_FINISHED;
michael@0 1475 return XML_STATUS_ERROR;
michael@0 1476 default:
michael@0 1477 ps_parsing = XML_PARSING;
michael@0 1478 }
michael@0 1479
michael@0 1480 if (len == 0) {
michael@0 1481 ps_finalBuffer = (XML_Bool)isFinal;
michael@0 1482 if (!isFinal)
michael@0 1483 return XML_STATUS_OK;
michael@0 1484 positionPtr = bufferPtr;
michael@0 1485 parseEndPtr = bufferEnd;
michael@0 1486
michael@0 1487 /* If data are left over from last buffer, and we now know that these
michael@0 1488 data are the final chunk of input, then we have to check them again
michael@0 1489 to detect errors based on that fact.
michael@0 1490 */
michael@0 1491 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
michael@0 1492
michael@0 1493 if (errorCode == XML_ERROR_NONE) {
michael@0 1494 switch (ps_parsing) {
michael@0 1495 case XML_SUSPENDED:
michael@0 1496 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
michael@0 1497 positionPtr = bufferPtr;
michael@0 1498 return XML_STATUS_SUSPENDED;
michael@0 1499 case XML_INITIALIZED:
michael@0 1500 case XML_PARSING:
michael@0 1501 ps_parsing = XML_FINISHED;
michael@0 1502 /* fall through */
michael@0 1503 default:
michael@0 1504 return XML_STATUS_OK;
michael@0 1505 }
michael@0 1506 }
michael@0 1507 eventEndPtr = eventPtr;
michael@0 1508 processor = errorProcessor;
michael@0 1509 return XML_STATUS_ERROR;
michael@0 1510 }
michael@0 1511 #ifndef XML_CONTEXT_BYTES
michael@0 1512 else if (bufferPtr == bufferEnd) {
michael@0 1513 const char *end;
michael@0 1514 int nLeftOver;
michael@0 1515 /* BEGIN MOZILLA CHANGE (|result| has type XML_Status, not XML_Error) */
michael@0 1516 enum XML_Status result;
michael@0 1517 /* END MOZILLA CHANGE */
michael@0 1518 parseEndByteIndex += len;
michael@0 1519 positionPtr = s;
michael@0 1520 ps_finalBuffer = (XML_Bool)isFinal;
michael@0 1521
michael@0 1522 errorCode = processor(parser, s, parseEndPtr = s + len, &end);
michael@0 1523
michael@0 1524 if (errorCode != XML_ERROR_NONE) {
michael@0 1525 eventEndPtr = eventPtr;
michael@0 1526 processor = errorProcessor;
michael@0 1527 return XML_STATUS_ERROR;
michael@0 1528 }
michael@0 1529 else {
michael@0 1530 switch (ps_parsing) {
michael@0 1531 case XML_SUSPENDED:
michael@0 1532 result = XML_STATUS_SUSPENDED;
michael@0 1533 break;
michael@0 1534 case XML_INITIALIZED:
michael@0 1535 case XML_PARSING:
michael@0 1536 /* BEGIN MOZILLA CHANGE (always initialize result) */
michael@0 1537 #if 0
michael@0 1538 result = XML_STATUS_OK;
michael@0 1539 if (isFinal) {
michael@0 1540 ps_parsing = XML_FINISHED;
michael@0 1541 return result;
michael@0 1542 }
michael@0 1543 #else
michael@0 1544 if (isFinal) {
michael@0 1545 ps_parsing = XML_FINISHED;
michael@0 1546 return XML_STATUS_OK;
michael@0 1547 }
michael@0 1548 /* fall through */
michael@0 1549 default:
michael@0 1550 result = XML_STATUS_OK;
michael@0 1551 #endif
michael@0 1552 /* END MOZILLA CHANGE */
michael@0 1553 }
michael@0 1554 }
michael@0 1555
michael@0 1556 XmlUpdatePosition(encoding, positionPtr, end, &position);
michael@0 1557 nLeftOver = s + len - end;
michael@0 1558 if (nLeftOver) {
michael@0 1559 if (buffer == NULL || nLeftOver > bufferLim - buffer) {
michael@0 1560 /* FIXME avoid integer overflow */
michael@0 1561 char *temp;
michael@0 1562 temp = (buffer == NULL
michael@0 1563 ? (char *)MALLOC(len * 2)
michael@0 1564 : (char *)REALLOC(buffer, len * 2));
michael@0 1565 if (temp == NULL) {
michael@0 1566 errorCode = XML_ERROR_NO_MEMORY;
michael@0 1567 return XML_STATUS_ERROR;
michael@0 1568 }
michael@0 1569 buffer = temp;
michael@0 1570 if (!buffer) {
michael@0 1571 errorCode = XML_ERROR_NO_MEMORY;
michael@0 1572 eventPtr = eventEndPtr = NULL;
michael@0 1573 processor = errorProcessor;
michael@0 1574 return XML_STATUS_ERROR;
michael@0 1575 }
michael@0 1576 bufferLim = buffer + len * 2;
michael@0 1577 }
michael@0 1578 memcpy(buffer, end, nLeftOver);
michael@0 1579 }
michael@0 1580 bufferPtr = buffer;
michael@0 1581 bufferEnd = buffer + nLeftOver;
michael@0 1582 positionPtr = bufferPtr;
michael@0 1583 parseEndPtr = bufferEnd;
michael@0 1584 eventPtr = bufferPtr;
michael@0 1585 eventEndPtr = bufferPtr;
michael@0 1586 return result;
michael@0 1587 }
michael@0 1588 #endif /* not defined XML_CONTEXT_BYTES */
michael@0 1589 else {
michael@0 1590 void *buff = XML_GetBuffer(parser, len);
michael@0 1591 if (buff == NULL)
michael@0 1592 return XML_STATUS_ERROR;
michael@0 1593 else {
michael@0 1594 memcpy(buff, s, len);
michael@0 1595 return XML_ParseBuffer(parser, len, isFinal);
michael@0 1596 }
michael@0 1597 }
michael@0 1598 }
michael@0 1599
michael@0 1600 enum XML_Status XMLCALL
michael@0 1601 XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
michael@0 1602 {
michael@0 1603 const char *start;
michael@0 1604 enum XML_Status result = XML_STATUS_OK;
michael@0 1605
michael@0 1606 switch (ps_parsing) {
michael@0 1607 case XML_SUSPENDED:
michael@0 1608 errorCode = XML_ERROR_SUSPENDED;
michael@0 1609 return XML_STATUS_ERROR;
michael@0 1610 case XML_FINISHED:
michael@0 1611 errorCode = XML_ERROR_FINISHED;
michael@0 1612 return XML_STATUS_ERROR;
michael@0 1613 default:
michael@0 1614 ps_parsing = XML_PARSING;
michael@0 1615 }
michael@0 1616
michael@0 1617 start = bufferPtr;
michael@0 1618 positionPtr = start;
michael@0 1619 bufferEnd += len;
michael@0 1620 parseEndPtr = bufferEnd;
michael@0 1621 parseEndByteIndex += len;
michael@0 1622 ps_finalBuffer = (XML_Bool)isFinal;
michael@0 1623
michael@0 1624 errorCode = processor(parser, start, parseEndPtr, &bufferPtr);
michael@0 1625
michael@0 1626 if (errorCode != XML_ERROR_NONE) {
michael@0 1627 eventEndPtr = eventPtr;
michael@0 1628 processor = errorProcessor;
michael@0 1629 return XML_STATUS_ERROR;
michael@0 1630 }
michael@0 1631 else {
michael@0 1632 switch (ps_parsing) {
michael@0 1633 case XML_SUSPENDED:
michael@0 1634 result = XML_STATUS_SUSPENDED;
michael@0 1635 break;
michael@0 1636 case XML_INITIALIZED:
michael@0 1637 case XML_PARSING:
michael@0 1638 if (isFinal) {
michael@0 1639 ps_parsing = XML_FINISHED;
michael@0 1640 return result;
michael@0 1641 }
michael@0 1642 default: ; /* should not happen */
michael@0 1643 }
michael@0 1644 }
michael@0 1645
michael@0 1646 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
michael@0 1647 positionPtr = bufferPtr;
michael@0 1648 return result;
michael@0 1649 }
michael@0 1650
michael@0 1651 void * XMLCALL
michael@0 1652 XML_GetBuffer(XML_Parser parser, int len)
michael@0 1653 {
michael@0 1654 switch (ps_parsing) {
michael@0 1655 case XML_SUSPENDED:
michael@0 1656 errorCode = XML_ERROR_SUSPENDED;
michael@0 1657 return NULL;
michael@0 1658 case XML_FINISHED:
michael@0 1659 errorCode = XML_ERROR_FINISHED;
michael@0 1660 return NULL;
michael@0 1661 default: ;
michael@0 1662 }
michael@0 1663
michael@0 1664 if (len > bufferLim - bufferEnd) {
michael@0 1665 /* FIXME avoid integer overflow */
michael@0 1666 int neededSize = len + (int)(bufferEnd - bufferPtr);
michael@0 1667 #ifdef XML_CONTEXT_BYTES
michael@0 1668 int keep = (int)(bufferPtr - buffer);
michael@0 1669
michael@0 1670 if (keep > XML_CONTEXT_BYTES)
michael@0 1671 keep = XML_CONTEXT_BYTES;
michael@0 1672 neededSize += keep;
michael@0 1673 #endif /* defined XML_CONTEXT_BYTES */
michael@0 1674 if (neededSize <= bufferLim - buffer) {
michael@0 1675 #ifdef XML_CONTEXT_BYTES
michael@0 1676 if (keep < bufferPtr - buffer) {
michael@0 1677 int offset = (int)(bufferPtr - buffer) - keep;
michael@0 1678 memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
michael@0 1679 bufferEnd -= offset;
michael@0 1680 bufferPtr -= offset;
michael@0 1681 }
michael@0 1682 #else
michael@0 1683 memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
michael@0 1684 bufferEnd = buffer + (bufferEnd - bufferPtr);
michael@0 1685 bufferPtr = buffer;
michael@0 1686 #endif /* not defined XML_CONTEXT_BYTES */
michael@0 1687 }
michael@0 1688 else {
michael@0 1689 char *newBuf;
michael@0 1690 int bufferSize = (int)(bufferLim - bufferPtr);
michael@0 1691 if (bufferSize == 0)
michael@0 1692 bufferSize = INIT_BUFFER_SIZE;
michael@0 1693 do {
michael@0 1694 bufferSize *= 2;
michael@0 1695 } while (bufferSize < neededSize);
michael@0 1696 newBuf = (char *)MALLOC(bufferSize);
michael@0 1697 if (newBuf == 0) {
michael@0 1698 errorCode = XML_ERROR_NO_MEMORY;
michael@0 1699 return NULL;
michael@0 1700 }
michael@0 1701 bufferLim = newBuf + bufferSize;
michael@0 1702 #ifdef XML_CONTEXT_BYTES
michael@0 1703 if (bufferPtr) {
michael@0 1704 int keep = (int)(bufferPtr - buffer);
michael@0 1705 if (keep > XML_CONTEXT_BYTES)
michael@0 1706 keep = XML_CONTEXT_BYTES;
michael@0 1707 memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
michael@0 1708 FREE(buffer);
michael@0 1709 buffer = newBuf;
michael@0 1710 bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
michael@0 1711 bufferPtr = buffer + keep;
michael@0 1712 }
michael@0 1713 else {
michael@0 1714 bufferEnd = newBuf + (bufferEnd - bufferPtr);
michael@0 1715 bufferPtr = buffer = newBuf;
michael@0 1716 }
michael@0 1717 #else
michael@0 1718 if (bufferPtr) {
michael@0 1719 memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
michael@0 1720 FREE(buffer);
michael@0 1721 }
michael@0 1722 bufferEnd = newBuf + (bufferEnd - bufferPtr);
michael@0 1723 bufferPtr = buffer = newBuf;
michael@0 1724 #endif /* not defined XML_CONTEXT_BYTES */
michael@0 1725 }
michael@0 1726 }
michael@0 1727 return bufferEnd;
michael@0 1728 }
michael@0 1729
michael@0 1730 enum XML_Status XMLCALL
michael@0 1731 XML_StopParser(XML_Parser parser, XML_Bool resumable)
michael@0 1732 {
michael@0 1733 switch (ps_parsing) {
michael@0 1734 case XML_SUSPENDED:
michael@0 1735 if (resumable) {
michael@0 1736 errorCode = XML_ERROR_SUSPENDED;
michael@0 1737 return XML_STATUS_ERROR;
michael@0 1738 }
michael@0 1739 ps_parsing = XML_FINISHED;
michael@0 1740 break;
michael@0 1741 case XML_FINISHED:
michael@0 1742 errorCode = XML_ERROR_FINISHED;
michael@0 1743 return XML_STATUS_ERROR;
michael@0 1744 default:
michael@0 1745 if (resumable) {
michael@0 1746 #ifdef XML_DTD
michael@0 1747 if (isParamEntity) {
michael@0 1748 errorCode = XML_ERROR_SUSPEND_PE;
michael@0 1749 return XML_STATUS_ERROR;
michael@0 1750 }
michael@0 1751 #endif
michael@0 1752 ps_parsing = XML_SUSPENDED;
michael@0 1753 }
michael@0 1754 else
michael@0 1755 ps_parsing = XML_FINISHED;
michael@0 1756 }
michael@0 1757 return XML_STATUS_OK;
michael@0 1758 }
michael@0 1759
michael@0 1760 enum XML_Status XMLCALL
michael@0 1761 XML_ResumeParser(XML_Parser parser)
michael@0 1762 {
michael@0 1763 enum XML_Status result = XML_STATUS_OK;
michael@0 1764
michael@0 1765 if (ps_parsing != XML_SUSPENDED) {
michael@0 1766 errorCode = XML_ERROR_NOT_SUSPENDED;
michael@0 1767 return XML_STATUS_ERROR;
michael@0 1768 }
michael@0 1769 ps_parsing = XML_PARSING;
michael@0 1770
michael@0 1771 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
michael@0 1772
michael@0 1773 if (errorCode != XML_ERROR_NONE) {
michael@0 1774 eventEndPtr = eventPtr;
michael@0 1775 processor = errorProcessor;
michael@0 1776 return XML_STATUS_ERROR;
michael@0 1777 }
michael@0 1778 else {
michael@0 1779 switch (ps_parsing) {
michael@0 1780 case XML_SUSPENDED:
michael@0 1781 result = XML_STATUS_SUSPENDED;
michael@0 1782 break;
michael@0 1783 case XML_INITIALIZED:
michael@0 1784 case XML_PARSING:
michael@0 1785 if (ps_finalBuffer) {
michael@0 1786 ps_parsing = XML_FINISHED;
michael@0 1787 return result;
michael@0 1788 }
michael@0 1789 default: ;
michael@0 1790 }
michael@0 1791 }
michael@0 1792
michael@0 1793 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
michael@0 1794 positionPtr = bufferPtr;
michael@0 1795 /* BEGIN MOZILLA CHANGE (always set eventPtr/eventEndPtr) */
michael@0 1796 eventPtr = bufferPtr;
michael@0 1797 eventEndPtr = bufferPtr;
michael@0 1798 /* END MOZILLA CHANGE */
michael@0 1799 return result;
michael@0 1800 }
michael@0 1801
michael@0 1802 void XMLCALL
michael@0 1803 XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
michael@0 1804 {
michael@0 1805 assert(status != NULL);
michael@0 1806 *status = parser->m_parsingStatus;
michael@0 1807 }
michael@0 1808
michael@0 1809 enum XML_Error XMLCALL
michael@0 1810 XML_GetErrorCode(XML_Parser parser)
michael@0 1811 {
michael@0 1812 return errorCode;
michael@0 1813 }
michael@0 1814
michael@0 1815 XML_Index XMLCALL
michael@0 1816 XML_GetCurrentByteIndex(XML_Parser parser)
michael@0 1817 {
michael@0 1818 if (eventPtr)
michael@0 1819 return parseEndByteIndex - (parseEndPtr - eventPtr);
michael@0 1820 /* BEGIN MOZILLA CHANGE (fix XML_GetCurrentByteIndex) */
michael@0 1821 #if 0
michael@0 1822 return -1;
michael@0 1823 #else
michael@0 1824 return parseEndByteIndex;
michael@0 1825 #endif
michael@0 1826 /* END MOZILLA CHANGE */
michael@0 1827 }
michael@0 1828
michael@0 1829 /* BEGIN MOZILLA CHANGE (unused API) */
michael@0 1830 #if 0
michael@0 1831 int XMLCALL
michael@0 1832 XML_GetCurrentByteCount(XML_Parser parser)
michael@0 1833 {
michael@0 1834 if (eventEndPtr && eventPtr)
michael@0 1835 return (int)(eventEndPtr - eventPtr);
michael@0 1836 return 0;
michael@0 1837 }
michael@0 1838
michael@0 1839 const char * XMLCALL
michael@0 1840 XML_GetInputContext(XML_Parser parser, int *offset, int *size)
michael@0 1841 {
michael@0 1842 #ifdef XML_CONTEXT_BYTES
michael@0 1843 if (eventPtr && buffer) {
michael@0 1844 *offset = (int)(eventPtr - buffer);
michael@0 1845 *size = (int)(bufferEnd - buffer);
michael@0 1846 return buffer;
michael@0 1847 }
michael@0 1848 #endif /* defined XML_CONTEXT_BYTES */
michael@0 1849 return (char *) 0;
michael@0 1850 }
michael@0 1851 #endif
michael@0 1852 /* END MOZILLA CHANGE */
michael@0 1853
michael@0 1854 XML_Size XMLCALL
michael@0 1855 XML_GetCurrentLineNumber(XML_Parser parser)
michael@0 1856 {
michael@0 1857 if (eventPtr && eventPtr >= positionPtr) {
michael@0 1858 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
michael@0 1859 positionPtr = eventPtr;
michael@0 1860 }
michael@0 1861 return position.lineNumber + 1;
michael@0 1862 }
michael@0 1863
michael@0 1864 XML_Size XMLCALL
michael@0 1865 XML_GetCurrentColumnNumber(XML_Parser parser)
michael@0 1866 {
michael@0 1867 if (eventPtr && eventPtr >= positionPtr) {
michael@0 1868 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
michael@0 1869 positionPtr = eventPtr;
michael@0 1870 }
michael@0 1871 return position.columnNumber;
michael@0 1872 }
michael@0 1873
michael@0 1874 /* BEGIN MOZILLA CHANGE (unused API) */
michael@0 1875 #if 0
michael@0 1876 void XMLCALL
michael@0 1877 XML_FreeContentModel(XML_Parser parser, XML_Content *model)
michael@0 1878 {
michael@0 1879 FREE(model);
michael@0 1880 }
michael@0 1881
michael@0 1882 void * XMLCALL
michael@0 1883 XML_MemMalloc(XML_Parser parser, size_t size)
michael@0 1884 {
michael@0 1885 return MALLOC(size);
michael@0 1886 }
michael@0 1887
michael@0 1888 void * XMLCALL
michael@0 1889 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
michael@0 1890 {
michael@0 1891 return REALLOC(ptr, size);
michael@0 1892 }
michael@0 1893
michael@0 1894 void XMLCALL
michael@0 1895 XML_MemFree(XML_Parser parser, void *ptr)
michael@0 1896 {
michael@0 1897 FREE(ptr);
michael@0 1898 }
michael@0 1899
michael@0 1900 void XMLCALL
michael@0 1901 XML_DefaultCurrent(XML_Parser parser)
michael@0 1902 {
michael@0 1903 if (defaultHandler) {
michael@0 1904 if (openInternalEntities)
michael@0 1905 reportDefault(parser,
michael@0 1906 internalEncoding,
michael@0 1907 openInternalEntities->internalEventPtr,
michael@0 1908 openInternalEntities->internalEventEndPtr);
michael@0 1909 else
michael@0 1910 reportDefault(parser, encoding, eventPtr, eventEndPtr);
michael@0 1911 }
michael@0 1912 }
michael@0 1913
michael@0 1914 const XML_LChar * XMLCALL
michael@0 1915 XML_ExpatVersion(void) {
michael@0 1916
michael@0 1917 /* V1 is used to string-ize the version number. However, it would
michael@0 1918 string-ize the actual version macro *names* unless we get them
michael@0 1919 substituted before being passed to V1. CPP is defined to expand
michael@0 1920 a macro, then rescan for more expansions. Thus, we use V2 to expand
michael@0 1921 the version macros, then CPP will expand the resulting V1() macro
michael@0 1922 with the correct numerals. */
michael@0 1923 /* ### I'm assuming cpp is portable in this respect... */
michael@0 1924
michael@0 1925 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
michael@0 1926 #define V2(a,b,c) XML_L("expat_")V1(a,b,c)
michael@0 1927
michael@0 1928 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
michael@0 1929
michael@0 1930 #undef V1
michael@0 1931 #undef V2
michael@0 1932 }
michael@0 1933
michael@0 1934 XML_Expat_Version XMLCALL
michael@0 1935 XML_ExpatVersionInfo(void)
michael@0 1936 {
michael@0 1937 XML_Expat_Version version;
michael@0 1938
michael@0 1939 version.major = XML_MAJOR_VERSION;
michael@0 1940 version.minor = XML_MINOR_VERSION;
michael@0 1941 version.micro = XML_MICRO_VERSION;
michael@0 1942
michael@0 1943 return version;
michael@0 1944 }
michael@0 1945
michael@0 1946 const XML_Feature * XMLCALL
michael@0 1947 XML_GetFeatureList(void)
michael@0 1948 {
michael@0 1949 static const XML_Feature features[] = {
michael@0 1950 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
michael@0 1951 sizeof(XML_Char)},
michael@0 1952 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
michael@0 1953 sizeof(XML_LChar)},
michael@0 1954 #ifdef XML_UNICODE
michael@0 1955 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
michael@0 1956 #endif
michael@0 1957 #ifdef XML_UNICODE_WCHAR_T
michael@0 1958 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
michael@0 1959 #endif
michael@0 1960 #ifdef XML_DTD
michael@0 1961 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
michael@0 1962 #endif
michael@0 1963 #ifdef XML_CONTEXT_BYTES
michael@0 1964 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
michael@0 1965 XML_CONTEXT_BYTES},
michael@0 1966 #endif
michael@0 1967 #ifdef XML_MIN_SIZE
michael@0 1968 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
michael@0 1969 #endif
michael@0 1970 #ifdef XML_NS
michael@0 1971 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
michael@0 1972 #endif
michael@0 1973 {XML_FEATURE_END, NULL, 0}
michael@0 1974 };
michael@0 1975
michael@0 1976 return features;
michael@0 1977 }
michael@0 1978 #endif
michael@0 1979 /* END MOZILLA CHANGE */
michael@0 1980
michael@0 1981 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
michael@0 1982 const XML_Char * XMLCALL
michael@0 1983 MOZ_XML_GetMismatchedTag(XML_Parser parser)
michael@0 1984 {
michael@0 1985 return mismatch;
michael@0 1986 }
michael@0 1987 /* END MOZILLA CHANGE */
michael@0 1988
michael@0 1989 /* Initially tag->rawName always points into the parse buffer;
michael@0 1990 for those TAG instances opened while the current parse buffer was
michael@0 1991 processed, and not yet closed, we need to store tag->rawName in a more
michael@0 1992 permanent location, since the parse buffer is about to be discarded.
michael@0 1993 */
michael@0 1994 static XML_Bool
michael@0 1995 storeRawNames(XML_Parser parser)
michael@0 1996 {
michael@0 1997 TAG *tag = tagStack;
michael@0 1998 while (tag) {
michael@0 1999 int bufSize;
michael@0 2000 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
michael@0 2001 char *rawNameBuf = tag->buf + nameLen;
michael@0 2002 /* Stop if already stored. Since tagStack is a stack, we can stop
michael@0 2003 at the first entry that has already been copied; everything
michael@0 2004 below it in the stack is already been accounted for in a
michael@0 2005 previous call to this function.
michael@0 2006 */
michael@0 2007 if (tag->rawName == rawNameBuf)
michael@0 2008 break;
michael@0 2009 /* For re-use purposes we need to ensure that the
michael@0 2010 size of tag->buf is a multiple of sizeof(XML_Char).
michael@0 2011 */
michael@0 2012 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
michael@0 2013 if (bufSize > tag->bufEnd - tag->buf) {
michael@0 2014 char *temp = (char *)REALLOC(tag->buf, bufSize);
michael@0 2015 if (temp == NULL)
michael@0 2016 return XML_FALSE;
michael@0 2017 /* if tag->name.str points to tag->buf (only when namespace
michael@0 2018 processing is off) then we have to update it
michael@0 2019 */
michael@0 2020 if (tag->name.str == (XML_Char *)tag->buf)
michael@0 2021 tag->name.str = (XML_Char *)temp;
michael@0 2022 /* if tag->name.localPart is set (when namespace processing is on)
michael@0 2023 then update it as well, since it will always point into tag->buf
michael@0 2024 */
michael@0 2025 if (tag->name.localPart)
michael@0 2026 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
michael@0 2027 (XML_Char *)tag->buf);
michael@0 2028 tag->buf = temp;
michael@0 2029 tag->bufEnd = temp + bufSize;
michael@0 2030 rawNameBuf = temp + nameLen;
michael@0 2031 }
michael@0 2032 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
michael@0 2033 tag->rawName = rawNameBuf;
michael@0 2034 tag = tag->parent;
michael@0 2035 }
michael@0 2036 return XML_TRUE;
michael@0 2037 }
michael@0 2038
michael@0 2039 static enum XML_Error PTRCALL
michael@0 2040 contentProcessor(XML_Parser parser,
michael@0 2041 const char *start,
michael@0 2042 const char *end,
michael@0 2043 const char **endPtr)
michael@0 2044 {
michael@0 2045 enum XML_Error result = doContent(parser, 0, encoding, start, end,
michael@0 2046 endPtr, (XML_Bool)!ps_finalBuffer);
michael@0 2047 if (result == XML_ERROR_NONE) {
michael@0 2048 if (!storeRawNames(parser))
michael@0 2049 return XML_ERROR_NO_MEMORY;
michael@0 2050 }
michael@0 2051 return result;
michael@0 2052 }
michael@0 2053
michael@0 2054 static enum XML_Error PTRCALL
michael@0 2055 externalEntityInitProcessor(XML_Parser parser,
michael@0 2056 const char *start,
michael@0 2057 const char *end,
michael@0 2058 const char **endPtr)
michael@0 2059 {
michael@0 2060 enum XML_Error result = initializeEncoding(parser);
michael@0 2061 if (result != XML_ERROR_NONE)
michael@0 2062 return result;
michael@0 2063 processor = externalEntityInitProcessor2;
michael@0 2064 return externalEntityInitProcessor2(parser, start, end, endPtr);
michael@0 2065 }
michael@0 2066
michael@0 2067 static enum XML_Error PTRCALL
michael@0 2068 externalEntityInitProcessor2(XML_Parser parser,
michael@0 2069 const char *start,
michael@0 2070 const char *end,
michael@0 2071 const char **endPtr)
michael@0 2072 {
michael@0 2073 const char *next = start; /* XmlContentTok doesn't always set the last arg */
michael@0 2074 int tok = XmlContentTok(encoding, start, end, &next);
michael@0 2075 switch (tok) {
michael@0 2076 case XML_TOK_BOM:
michael@0 2077 /* If we are at the end of the buffer, this would cause the next stage,
michael@0 2078 i.e. externalEntityInitProcessor3, to pass control directly to
michael@0 2079 doContent (by detecting XML_TOK_NONE) without processing any xml text
michael@0 2080 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
michael@0 2081 */
michael@0 2082 if (next == end && !ps_finalBuffer) {
michael@0 2083 *endPtr = next;
michael@0 2084 return XML_ERROR_NONE;
michael@0 2085 }
michael@0 2086 start = next;
michael@0 2087 break;
michael@0 2088 case XML_TOK_PARTIAL:
michael@0 2089 if (!ps_finalBuffer) {
michael@0 2090 *endPtr = start;
michael@0 2091 return XML_ERROR_NONE;
michael@0 2092 }
michael@0 2093 eventPtr = start;
michael@0 2094 return XML_ERROR_UNCLOSED_TOKEN;
michael@0 2095 case XML_TOK_PARTIAL_CHAR:
michael@0 2096 if (!ps_finalBuffer) {
michael@0 2097 *endPtr = start;
michael@0 2098 return XML_ERROR_NONE;
michael@0 2099 }
michael@0 2100 eventPtr = start;
michael@0 2101 return XML_ERROR_PARTIAL_CHAR;
michael@0 2102 }
michael@0 2103 processor = externalEntityInitProcessor3;
michael@0 2104 return externalEntityInitProcessor3(parser, start, end, endPtr);
michael@0 2105 }
michael@0 2106
michael@0 2107 static enum XML_Error PTRCALL
michael@0 2108 externalEntityInitProcessor3(XML_Parser parser,
michael@0 2109 const char *start,
michael@0 2110 const char *end,
michael@0 2111 const char **endPtr)
michael@0 2112 {
michael@0 2113 int tok;
michael@0 2114 const char *next = start; /* XmlContentTok doesn't always set the last arg */
michael@0 2115 eventPtr = start;
michael@0 2116 tok = XmlContentTok(encoding, start, end, &next);
michael@0 2117 eventEndPtr = next;
michael@0 2118
michael@0 2119 switch (tok) {
michael@0 2120 case XML_TOK_XML_DECL:
michael@0 2121 {
michael@0 2122 enum XML_Error result;
michael@0 2123 result = processXmlDecl(parser, 1, start, next);
michael@0 2124 if (result != XML_ERROR_NONE)
michael@0 2125 return result;
michael@0 2126 switch (ps_parsing) {
michael@0 2127 case XML_SUSPENDED:
michael@0 2128 *endPtr = next;
michael@0 2129 return XML_ERROR_NONE;
michael@0 2130 case XML_FINISHED:
michael@0 2131 return XML_ERROR_ABORTED;
michael@0 2132 default:
michael@0 2133 start = next;
michael@0 2134 }
michael@0 2135 }
michael@0 2136 break;
michael@0 2137 case XML_TOK_PARTIAL:
michael@0 2138 if (!ps_finalBuffer) {
michael@0 2139 *endPtr = start;
michael@0 2140 return XML_ERROR_NONE;
michael@0 2141 }
michael@0 2142 return XML_ERROR_UNCLOSED_TOKEN;
michael@0 2143 case XML_TOK_PARTIAL_CHAR:
michael@0 2144 if (!ps_finalBuffer) {
michael@0 2145 *endPtr = start;
michael@0 2146 return XML_ERROR_NONE;
michael@0 2147 }
michael@0 2148 return XML_ERROR_PARTIAL_CHAR;
michael@0 2149 }
michael@0 2150 processor = externalEntityContentProcessor;
michael@0 2151 tagLevel = 1;
michael@0 2152 return externalEntityContentProcessor(parser, start, end, endPtr);
michael@0 2153 }
michael@0 2154
michael@0 2155 static enum XML_Error PTRCALL
michael@0 2156 externalEntityContentProcessor(XML_Parser parser,
michael@0 2157 const char *start,
michael@0 2158 const char *end,
michael@0 2159 const char **endPtr)
michael@0 2160 {
michael@0 2161 enum XML_Error result = doContent(parser, 1, encoding, start, end,
michael@0 2162 endPtr, (XML_Bool)!ps_finalBuffer);
michael@0 2163 if (result == XML_ERROR_NONE) {
michael@0 2164 if (!storeRawNames(parser))
michael@0 2165 return XML_ERROR_NO_MEMORY;
michael@0 2166 }
michael@0 2167 return result;
michael@0 2168 }
michael@0 2169
michael@0 2170 static enum XML_Error
michael@0 2171 doContent(XML_Parser parser,
michael@0 2172 int startTagLevel,
michael@0 2173 const ENCODING *enc,
michael@0 2174 const char *s,
michael@0 2175 const char *end,
michael@0 2176 const char **nextPtr,
michael@0 2177 XML_Bool haveMore)
michael@0 2178 {
michael@0 2179 /* save one level of indirection */
michael@0 2180 DTD * const dtd = _dtd;
michael@0 2181
michael@0 2182 const char **eventPP;
michael@0 2183 const char **eventEndPP;
michael@0 2184 if (enc == encoding) {
michael@0 2185 eventPP = &eventPtr;
michael@0 2186 eventEndPP = &eventEndPtr;
michael@0 2187 }
michael@0 2188 else {
michael@0 2189 eventPP = &(openInternalEntities->internalEventPtr);
michael@0 2190 eventEndPP = &(openInternalEntities->internalEventEndPtr);
michael@0 2191 }
michael@0 2192 *eventPP = s;
michael@0 2193
michael@0 2194 for (;;) {
michael@0 2195 const char *next = s; /* XmlContentTok doesn't always set the last arg */
michael@0 2196 int tok = XmlContentTok(enc, s, end, &next);
michael@0 2197 *eventEndPP = next;
michael@0 2198 switch (tok) {
michael@0 2199 case XML_TOK_TRAILING_CR:
michael@0 2200 if (haveMore) {
michael@0 2201 *nextPtr = s;
michael@0 2202 return XML_ERROR_NONE;
michael@0 2203 }
michael@0 2204 *eventEndPP = end;
michael@0 2205 if (characterDataHandler) {
michael@0 2206 XML_Char c = 0xA;
michael@0 2207 characterDataHandler(handlerArg, &c, 1);
michael@0 2208 }
michael@0 2209 else if (defaultHandler)
michael@0 2210 reportDefault(parser, enc, s, end);
michael@0 2211 /* We are at the end of the final buffer, should we check for
michael@0 2212 XML_SUSPENDED, XML_FINISHED?
michael@0 2213 */
michael@0 2214 if (startTagLevel == 0)
michael@0 2215 return XML_ERROR_NO_ELEMENTS;
michael@0 2216 if (tagLevel != startTagLevel)
michael@0 2217 return XML_ERROR_ASYNC_ENTITY;
michael@0 2218 *nextPtr = end;
michael@0 2219 return XML_ERROR_NONE;
michael@0 2220 case XML_TOK_NONE:
michael@0 2221 if (haveMore) {
michael@0 2222 *nextPtr = s;
michael@0 2223 return XML_ERROR_NONE;
michael@0 2224 }
michael@0 2225 if (startTagLevel > 0) {
michael@0 2226 if (tagLevel != startTagLevel)
michael@0 2227 return XML_ERROR_ASYNC_ENTITY;
michael@0 2228 *nextPtr = s;
michael@0 2229 return XML_ERROR_NONE;
michael@0 2230 }
michael@0 2231 return XML_ERROR_NO_ELEMENTS;
michael@0 2232 case XML_TOK_INVALID:
michael@0 2233 *eventPP = next;
michael@0 2234 return XML_ERROR_INVALID_TOKEN;
michael@0 2235 case XML_TOK_PARTIAL:
michael@0 2236 if (haveMore) {
michael@0 2237 *nextPtr = s;
michael@0 2238 return XML_ERROR_NONE;
michael@0 2239 }
michael@0 2240 return XML_ERROR_UNCLOSED_TOKEN;
michael@0 2241 case XML_TOK_PARTIAL_CHAR:
michael@0 2242 if (haveMore) {
michael@0 2243 *nextPtr = s;
michael@0 2244 return XML_ERROR_NONE;
michael@0 2245 }
michael@0 2246 return XML_ERROR_PARTIAL_CHAR;
michael@0 2247 case XML_TOK_ENTITY_REF:
michael@0 2248 {
michael@0 2249 const XML_Char *name;
michael@0 2250 ENTITY *entity;
michael@0 2251 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
michael@0 2252 s + enc->minBytesPerChar,
michael@0 2253 next - enc->minBytesPerChar);
michael@0 2254 if (ch) {
michael@0 2255 if (characterDataHandler)
michael@0 2256 characterDataHandler(handlerArg, &ch, 1);
michael@0 2257 else if (defaultHandler)
michael@0 2258 reportDefault(parser, enc, s, next);
michael@0 2259 break;
michael@0 2260 }
michael@0 2261 name = poolStoreString(&dtd->pool, enc,
michael@0 2262 s + enc->minBytesPerChar,
michael@0 2263 next - enc->minBytesPerChar);
michael@0 2264 if (!name)
michael@0 2265 return XML_ERROR_NO_MEMORY;
michael@0 2266 entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
michael@0 2267 poolDiscard(&dtd->pool);
michael@0 2268 /* First, determine if a check for an existing declaration is needed;
michael@0 2269 if yes, check that the entity exists, and that it is internal,
michael@0 2270 otherwise call the skipped entity or default handler.
michael@0 2271 */
michael@0 2272 if (!dtd->hasParamEntityRefs || dtd->standalone) {
michael@0 2273 if (!entity)
michael@0 2274 return XML_ERROR_UNDEFINED_ENTITY;
michael@0 2275 else if (!entity->is_internal)
michael@0 2276 return XML_ERROR_ENTITY_DECLARED_IN_PE;
michael@0 2277 }
michael@0 2278 else if (!entity) {
michael@0 2279 if (skippedEntityHandler)
michael@0 2280 skippedEntityHandler(handlerArg, name, 0);
michael@0 2281 /* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=35984) */
michael@0 2282 #if 0
michael@0 2283 else if (defaultHandler)
michael@0 2284 reportDefault(parser, enc, s, next);
michael@0 2285 break;
michael@0 2286 #else
michael@0 2287 return XML_ERROR_UNDEFINED_ENTITY;
michael@0 2288 #endif
michael@0 2289 /* END MOZILLA CHANGE */
michael@0 2290 }
michael@0 2291 if (entity->open)
michael@0 2292 return XML_ERROR_RECURSIVE_ENTITY_REF;
michael@0 2293 if (entity->notation)
michael@0 2294 return XML_ERROR_BINARY_ENTITY_REF;
michael@0 2295 if (entity->textPtr) {
michael@0 2296 enum XML_Error result;
michael@0 2297 if (!defaultExpandInternalEntities) {
michael@0 2298 if (skippedEntityHandler)
michael@0 2299 skippedEntityHandler(handlerArg, entity->name, 0);
michael@0 2300 else if (defaultHandler)
michael@0 2301 reportDefault(parser, enc, s, next);
michael@0 2302 break;
michael@0 2303 }
michael@0 2304 result = processInternalEntity(parser, entity, XML_FALSE);
michael@0 2305 if (result != XML_ERROR_NONE)
michael@0 2306 return result;
michael@0 2307 }
michael@0 2308 else if (externalEntityRefHandler) {
michael@0 2309 const XML_Char *context;
michael@0 2310 entity->open = XML_TRUE;
michael@0 2311 context = getContext(parser);
michael@0 2312 entity->open = XML_FALSE;
michael@0 2313 if (!context)
michael@0 2314 return XML_ERROR_NO_MEMORY;
michael@0 2315 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
michael@0 2316 context,
michael@0 2317 entity->base,
michael@0 2318 entity->systemId,
michael@0 2319 entity->publicId))
michael@0 2320 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
michael@0 2321 poolDiscard(&tempPool);
michael@0 2322 }
michael@0 2323 else if (defaultHandler)
michael@0 2324 reportDefault(parser, enc, s, next);
michael@0 2325 break;
michael@0 2326 }
michael@0 2327 case XML_TOK_START_TAG_NO_ATTS:
michael@0 2328 /* fall through */
michael@0 2329 case XML_TOK_START_TAG_WITH_ATTS:
michael@0 2330 {
michael@0 2331 TAG *tag;
michael@0 2332 enum XML_Error result;
michael@0 2333 XML_Char *toPtr;
michael@0 2334 if (freeTagList) {
michael@0 2335 tag = freeTagList;
michael@0 2336 freeTagList = freeTagList->parent;
michael@0 2337 }
michael@0 2338 else {
michael@0 2339 tag = (TAG *)MALLOC(sizeof(TAG));
michael@0 2340 if (!tag)
michael@0 2341 return XML_ERROR_NO_MEMORY;
michael@0 2342 tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
michael@0 2343 if (!tag->buf) {
michael@0 2344 FREE(tag);
michael@0 2345 return XML_ERROR_NO_MEMORY;
michael@0 2346 }
michael@0 2347 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
michael@0 2348 }
michael@0 2349 tag->bindings = NULL;
michael@0 2350 tag->parent = tagStack;
michael@0 2351 tagStack = tag;
michael@0 2352 tag->name.localPart = NULL;
michael@0 2353 tag->name.prefix = NULL;
michael@0 2354 tag->rawName = s + enc->minBytesPerChar;
michael@0 2355 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
michael@0 2356 ++tagLevel;
michael@0 2357 {
michael@0 2358 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
michael@0 2359 const char *fromPtr = tag->rawName;
michael@0 2360 toPtr = (XML_Char *)tag->buf;
michael@0 2361 for (;;) {
michael@0 2362 int bufSize;
michael@0 2363 int convLen;
michael@0 2364 XmlConvert(enc,
michael@0 2365 &fromPtr, rawNameEnd,
michael@0 2366 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
michael@0 2367 convLen = (int)(toPtr - (XML_Char *)tag->buf);
michael@0 2368 if (fromPtr == rawNameEnd) {
michael@0 2369 tag->name.strLen = convLen;
michael@0 2370 break;
michael@0 2371 }
michael@0 2372 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
michael@0 2373 {
michael@0 2374 char *temp = (char *)REALLOC(tag->buf, bufSize);
michael@0 2375 if (temp == NULL)
michael@0 2376 return XML_ERROR_NO_MEMORY;
michael@0 2377 tag->buf = temp;
michael@0 2378 tag->bufEnd = temp + bufSize;
michael@0 2379 toPtr = (XML_Char *)temp + convLen;
michael@0 2380 }
michael@0 2381 }
michael@0 2382 }
michael@0 2383 tag->name.str = (XML_Char *)tag->buf;
michael@0 2384 *toPtr = XML_T('\0');
michael@0 2385 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
michael@0 2386 if (result)
michael@0 2387 return result;
michael@0 2388 if (startElementHandler)
michael@0 2389 startElementHandler(handlerArg, tag->name.str,
michael@0 2390 (const XML_Char **)atts);
michael@0 2391 else if (defaultHandler)
michael@0 2392 reportDefault(parser, enc, s, next);
michael@0 2393 poolClear(&tempPool);
michael@0 2394 break;
michael@0 2395 }
michael@0 2396 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
michael@0 2397 /* fall through */
michael@0 2398 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
michael@0 2399 {
michael@0 2400 const char *rawName = s + enc->minBytesPerChar;
michael@0 2401 enum XML_Error result;
michael@0 2402 BINDING *bindings = NULL;
michael@0 2403 XML_Bool noElmHandlers = XML_TRUE;
michael@0 2404 TAG_NAME name;
michael@0 2405 name.str = poolStoreString(&tempPool, enc, rawName,
michael@0 2406 rawName + XmlNameLength(enc, rawName));
michael@0 2407 if (!name.str)
michael@0 2408 return XML_ERROR_NO_MEMORY;
michael@0 2409 poolFinish(&tempPool);
michael@0 2410 result = storeAtts(parser, enc, s, &name, &bindings);
michael@0 2411 if (result)
michael@0 2412 return result;
michael@0 2413 poolFinish(&tempPool);
michael@0 2414 if (startElementHandler) {
michael@0 2415 startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
michael@0 2416 noElmHandlers = XML_FALSE;
michael@0 2417 }
michael@0 2418 if (endElementHandler) {
michael@0 2419 if (startElementHandler)
michael@0 2420 *eventPP = *eventEndPP;
michael@0 2421 endElementHandler(handlerArg, name.str);
michael@0 2422 noElmHandlers = XML_FALSE;
michael@0 2423 }
michael@0 2424 if (noElmHandlers && defaultHandler)
michael@0 2425 reportDefault(parser, enc, s, next);
michael@0 2426 poolClear(&tempPool);
michael@0 2427 while (bindings) {
michael@0 2428 BINDING *b = bindings;
michael@0 2429 if (endNamespaceDeclHandler)
michael@0 2430 endNamespaceDeclHandler(handlerArg, b->prefix->name);
michael@0 2431 bindings = bindings->nextTagBinding;
michael@0 2432 b->nextTagBinding = freeBindingList;
michael@0 2433 freeBindingList = b;
michael@0 2434 b->prefix->binding = b->prevPrefixBinding;
michael@0 2435 }
michael@0 2436 }
michael@0 2437 if (tagLevel == 0)
michael@0 2438 return epilogProcessor(parser, next, end, nextPtr);
michael@0 2439 break;
michael@0 2440 case XML_TOK_END_TAG:
michael@0 2441 if (tagLevel == startTagLevel)
michael@0 2442 return XML_ERROR_ASYNC_ENTITY;
michael@0 2443 else {
michael@0 2444 int len;
michael@0 2445 const char *rawName;
michael@0 2446 TAG *tag = tagStack;
michael@0 2447 tagStack = tag->parent;
michael@0 2448 tag->parent = freeTagList;
michael@0 2449 freeTagList = tag;
michael@0 2450 rawName = s + enc->minBytesPerChar*2;
michael@0 2451 len = XmlNameLength(enc, rawName);
michael@0 2452 if (len != tag->rawNameLength
michael@0 2453 || memcmp(tag->rawName, rawName, len) != 0) {
michael@0 2454 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
michael@0 2455 /* This code is copied from the |if (endElementHandler)| block below */
michael@0 2456 const XML_Char *localPart;
michael@0 2457 const XML_Char *prefix;
michael@0 2458 XML_Char *uri;
michael@0 2459 localPart = tag->name.localPart;
michael@0 2460 if (ns && localPart) {
michael@0 2461 /* localPart and prefix may have been overwritten in
michael@0 2462 tag->name.str, since this points to the binding->uri
michael@0 2463 buffer which gets re-used; so we have to add them again
michael@0 2464 */
michael@0 2465 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
michael@0 2466 /* don't need to check for space - already done in storeAtts() */
michael@0 2467 while (*localPart) *uri++ = *localPart++;
michael@0 2468 prefix = (XML_Char *)tag->name.prefix;
michael@0 2469 if (ns_triplets && prefix) {
michael@0 2470 *uri++ = namespaceSeparator;
michael@0 2471 while (*prefix) *uri++ = *prefix++;
michael@0 2472 }
michael@0 2473 *uri = XML_T('\0');
michael@0 2474 }
michael@0 2475 mismatch = tag->name.str;
michael@0 2476 /* END MOZILLA CHANGE */
michael@0 2477 *eventPP = rawName;
michael@0 2478 return XML_ERROR_TAG_MISMATCH;
michael@0 2479 }
michael@0 2480 --tagLevel;
michael@0 2481 if (endElementHandler) {
michael@0 2482 const XML_Char *localPart;
michael@0 2483 const XML_Char *prefix;
michael@0 2484 XML_Char *uri;
michael@0 2485 localPart = tag->name.localPart;
michael@0 2486 if (ns && localPart) {
michael@0 2487 /* localPart and prefix may have been overwritten in
michael@0 2488 tag->name.str, since this points to the binding->uri
michael@0 2489 buffer which gets re-used; so we have to add them again
michael@0 2490 */
michael@0 2491 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
michael@0 2492 /* don't need to check for space - already done in storeAtts() */
michael@0 2493 while (*localPart) *uri++ = *localPart++;
michael@0 2494 prefix = (XML_Char *)tag->name.prefix;
michael@0 2495 if (ns_triplets && prefix) {
michael@0 2496 *uri++ = namespaceSeparator;
michael@0 2497 while (*prefix) *uri++ = *prefix++;
michael@0 2498 }
michael@0 2499 *uri = XML_T('\0');
michael@0 2500 }
michael@0 2501 endElementHandler(handlerArg, tag->name.str);
michael@0 2502 }
michael@0 2503 else if (defaultHandler)
michael@0 2504 reportDefault(parser, enc, s, next);
michael@0 2505 while (tag->bindings) {
michael@0 2506 BINDING *b = tag->bindings;
michael@0 2507 if (endNamespaceDeclHandler)
michael@0 2508 endNamespaceDeclHandler(handlerArg, b->prefix->name);
michael@0 2509 tag->bindings = tag->bindings->nextTagBinding;
michael@0 2510 b->nextTagBinding = freeBindingList;
michael@0 2511 freeBindingList = b;
michael@0 2512 b->prefix->binding = b->prevPrefixBinding;
michael@0 2513 }
michael@0 2514 if (tagLevel == 0)
michael@0 2515 return epilogProcessor(parser, next, end, nextPtr);
michael@0 2516 }
michael@0 2517 break;
michael@0 2518 case XML_TOK_CHAR_REF:
michael@0 2519 {
michael@0 2520 int n = XmlCharRefNumber(enc, s);
michael@0 2521 if (n < 0)
michael@0 2522 return XML_ERROR_BAD_CHAR_REF;
michael@0 2523 if (characterDataHandler) {
michael@0 2524 XML_Char buf[XML_ENCODE_MAX];
michael@0 2525 characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
michael@0 2526 }
michael@0 2527 else if (defaultHandler)
michael@0 2528 reportDefault(parser, enc, s, next);
michael@0 2529 }
michael@0 2530 break;
michael@0 2531 case XML_TOK_XML_DECL:
michael@0 2532 return XML_ERROR_MISPLACED_XML_PI;
michael@0 2533 case XML_TOK_DATA_NEWLINE:
michael@0 2534 if (characterDataHandler) {
michael@0 2535 XML_Char c = 0xA;
michael@0 2536 characterDataHandler(handlerArg, &c, 1);
michael@0 2537 }
michael@0 2538 else if (defaultHandler)
michael@0 2539 reportDefault(parser, enc, s, next);
michael@0 2540 break;
michael@0 2541 case XML_TOK_CDATA_SECT_OPEN:
michael@0 2542 {
michael@0 2543 enum XML_Error result;
michael@0 2544 if (startCdataSectionHandler)
michael@0 2545 startCdataSectionHandler(handlerArg);
michael@0 2546 #if 0
michael@0 2547 /* Suppose you doing a transformation on a document that involves
michael@0 2548 changing only the character data. You set up a defaultHandler
michael@0 2549 and a characterDataHandler. The defaultHandler simply copies
michael@0 2550 characters through. The characterDataHandler does the
michael@0 2551 transformation and writes the characters out escaping them as
michael@0 2552 necessary. This case will fail to work if we leave out the
michael@0 2553 following two lines (because & and < inside CDATA sections will
michael@0 2554 be incorrectly escaped).
michael@0 2555
michael@0 2556 However, now we have a start/endCdataSectionHandler, so it seems
michael@0 2557 easier to let the user deal with this.
michael@0 2558 */
michael@0 2559 else if (characterDataHandler)
michael@0 2560 characterDataHandler(handlerArg, dataBuf, 0);
michael@0 2561 #endif
michael@0 2562 else if (defaultHandler)
michael@0 2563 reportDefault(parser, enc, s, next);
michael@0 2564 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
michael@0 2565 if (result != XML_ERROR_NONE)
michael@0 2566 return result;
michael@0 2567 else if (!next) {
michael@0 2568 processor = cdataSectionProcessor;
michael@0 2569 return result;
michael@0 2570 }
michael@0 2571 }
michael@0 2572 break;
michael@0 2573 case XML_TOK_TRAILING_RSQB:
michael@0 2574 if (haveMore) {
michael@0 2575 *nextPtr = s;
michael@0 2576 return XML_ERROR_NONE;
michael@0 2577 }
michael@0 2578 if (characterDataHandler) {
michael@0 2579 if (MUST_CONVERT(enc, s)) {
michael@0 2580 ICHAR *dataPtr = (ICHAR *)dataBuf;
michael@0 2581 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
michael@0 2582 characterDataHandler(handlerArg, dataBuf,
michael@0 2583 (int)(dataPtr - (ICHAR *)dataBuf));
michael@0 2584 }
michael@0 2585 else
michael@0 2586 characterDataHandler(handlerArg,
michael@0 2587 (XML_Char *)s,
michael@0 2588 (int)((XML_Char *)end - (XML_Char *)s));
michael@0 2589 }
michael@0 2590 else if (defaultHandler)
michael@0 2591 reportDefault(parser, enc, s, end);
michael@0 2592 /* We are at the end of the final buffer, should we check for
michael@0 2593 XML_SUSPENDED, XML_FINISHED?
michael@0 2594 */
michael@0 2595 if (startTagLevel == 0) {
michael@0 2596 *eventPP = end;
michael@0 2597 return XML_ERROR_NO_ELEMENTS;
michael@0 2598 }
michael@0 2599 if (tagLevel != startTagLevel) {
michael@0 2600 *eventPP = end;
michael@0 2601 return XML_ERROR_ASYNC_ENTITY;
michael@0 2602 }
michael@0 2603 *nextPtr = end;
michael@0 2604 return XML_ERROR_NONE;
michael@0 2605 case XML_TOK_DATA_CHARS:
michael@0 2606 if (characterDataHandler) {
michael@0 2607 if (MUST_CONVERT(enc, s)) {
michael@0 2608 for (;;) {
michael@0 2609 ICHAR *dataPtr = (ICHAR *)dataBuf;
michael@0 2610 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
michael@0 2611 *eventEndPP = s;
michael@0 2612 characterDataHandler(handlerArg, dataBuf,
michael@0 2613 (int)(dataPtr - (ICHAR *)dataBuf));
michael@0 2614 if (s == next)
michael@0 2615 break;
michael@0 2616 *eventPP = s;
michael@0 2617 }
michael@0 2618 }
michael@0 2619 else
michael@0 2620 characterDataHandler(handlerArg,
michael@0 2621 (XML_Char *)s,
michael@0 2622 (int)((XML_Char *)next - (XML_Char *)s));
michael@0 2623 }
michael@0 2624 else if (defaultHandler)
michael@0 2625 reportDefault(parser, enc, s, next);
michael@0 2626 break;
michael@0 2627 case XML_TOK_PI:
michael@0 2628 if (!reportProcessingInstruction(parser, enc, s, next))
michael@0 2629 return XML_ERROR_NO_MEMORY;
michael@0 2630 break;
michael@0 2631 case XML_TOK_COMMENT:
michael@0 2632 if (!reportComment(parser, enc, s, next))
michael@0 2633 return XML_ERROR_NO_MEMORY;
michael@0 2634 break;
michael@0 2635 default:
michael@0 2636 if (defaultHandler)
michael@0 2637 reportDefault(parser, enc, s, next);
michael@0 2638 break;
michael@0 2639 }
michael@0 2640 *eventPP = s = next;
michael@0 2641 switch (ps_parsing) {
michael@0 2642 case XML_SUSPENDED:
michael@0 2643 *nextPtr = next;
michael@0 2644 return XML_ERROR_NONE;
michael@0 2645 case XML_FINISHED:
michael@0 2646 return XML_ERROR_ABORTED;
michael@0 2647 default: ;
michael@0 2648 }
michael@0 2649 }
michael@0 2650 /* not reached */
michael@0 2651 }
michael@0 2652
michael@0 2653 /* Precondition: all arguments must be non-NULL;
michael@0 2654 Purpose:
michael@0 2655 - normalize attributes
michael@0 2656 - check attributes for well-formedness
michael@0 2657 - generate namespace aware attribute names (URI, prefix)
michael@0 2658 - build list of attributes for startElementHandler
michael@0 2659 - default attributes
michael@0 2660 - process namespace declarations (check and report them)
michael@0 2661 - generate namespace aware element name (URI, prefix)
michael@0 2662 */
michael@0 2663 static enum XML_Error
michael@0 2664 storeAtts(XML_Parser parser, const ENCODING *enc,
michael@0 2665 const char *attStr, TAG_NAME *tagNamePtr,
michael@0 2666 BINDING **bindingsPtr)
michael@0 2667 {
michael@0 2668 DTD * const dtd = _dtd; /* save one level of indirection */
michael@0 2669 ELEMENT_TYPE *elementType;
michael@0 2670 int nDefaultAtts;
michael@0 2671 const XML_Char **appAtts; /* the attribute list for the application */
michael@0 2672 int attIndex = 0;
michael@0 2673 int prefixLen;
michael@0 2674 int i;
michael@0 2675 int n;
michael@0 2676 XML_Char *uri;
michael@0 2677 int nPrefixes = 0;
michael@0 2678 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
michael@0 2679 int nXMLNSDeclarations = 0;
michael@0 2680 /* END MOZILLA CHANGE */
michael@0 2681 BINDING *binding;
michael@0 2682 const XML_Char *localPart;
michael@0 2683
michael@0 2684 /* lookup the element type name */
michael@0 2685 elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0);
michael@0 2686 if (!elementType) {
michael@0 2687 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
michael@0 2688 if (!name)
michael@0 2689 return XML_ERROR_NO_MEMORY;
michael@0 2690 elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name,
michael@0 2691 sizeof(ELEMENT_TYPE));
michael@0 2692 if (!elementType)
michael@0 2693 return XML_ERROR_NO_MEMORY;
michael@0 2694 if (ns && !setElementTypePrefix(parser, elementType))
michael@0 2695 return XML_ERROR_NO_MEMORY;
michael@0 2696 }
michael@0 2697 nDefaultAtts = elementType->nDefaultAtts;
michael@0 2698
michael@0 2699 /* get the attributes from the tokenizer */
michael@0 2700 n = XmlGetAttributes(enc, attStr, attsSize, atts);
michael@0 2701 if (n + nDefaultAtts > attsSize) {
michael@0 2702 int oldAttsSize = attsSize;
michael@0 2703 ATTRIBUTE *temp;
michael@0 2704 attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
michael@0 2705 temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
michael@0 2706 if (temp == NULL)
michael@0 2707 return XML_ERROR_NO_MEMORY;
michael@0 2708 atts = temp;
michael@0 2709 if (n > oldAttsSize)
michael@0 2710 XmlGetAttributes(enc, attStr, n, atts);
michael@0 2711 }
michael@0 2712
michael@0 2713 appAtts = (const XML_Char **)atts;
michael@0 2714 for (i = 0; i < n; i++) {
michael@0 2715 /* add the name and value to the attribute list */
michael@0 2716 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
michael@0 2717 atts[i].name
michael@0 2718 + XmlNameLength(enc, atts[i].name));
michael@0 2719 if (!attId)
michael@0 2720 return XML_ERROR_NO_MEMORY;
michael@0 2721 /* Detect duplicate attributes by their QNames. This does not work when
michael@0 2722 namespace processing is turned on and different prefixes for the same
michael@0 2723 namespace are used. For this case we have a check further down.
michael@0 2724 */
michael@0 2725 if ((attId->name)[-1]) {
michael@0 2726 if (enc == encoding)
michael@0 2727 eventPtr = atts[i].name;
michael@0 2728 return XML_ERROR_DUPLICATE_ATTRIBUTE;
michael@0 2729 }
michael@0 2730 (attId->name)[-1] = 1;
michael@0 2731 appAtts[attIndex++] = attId->name;
michael@0 2732 if (!atts[i].normalized) {
michael@0 2733 enum XML_Error result;
michael@0 2734 XML_Bool isCdata = XML_TRUE;
michael@0 2735
michael@0 2736 /* figure out whether declared as other than CDATA */
michael@0 2737 if (attId->maybeTokenized) {
michael@0 2738 int j;
michael@0 2739 for (j = 0; j < nDefaultAtts; j++) {
michael@0 2740 if (attId == elementType->defaultAtts[j].id) {
michael@0 2741 isCdata = elementType->defaultAtts[j].isCdata;
michael@0 2742 break;
michael@0 2743 }
michael@0 2744 }
michael@0 2745 }
michael@0 2746
michael@0 2747 /* normalize the attribute value */
michael@0 2748 result = storeAttributeValue(parser, enc, isCdata,
michael@0 2749 atts[i].valuePtr, atts[i].valueEnd,
michael@0 2750 &tempPool);
michael@0 2751 if (result)
michael@0 2752 return result;
michael@0 2753 appAtts[attIndex] = poolStart(&tempPool);
michael@0 2754 poolFinish(&tempPool);
michael@0 2755 }
michael@0 2756 else {
michael@0 2757 /* the value did not need normalizing */
michael@0 2758 appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
michael@0 2759 atts[i].valueEnd);
michael@0 2760 if (appAtts[attIndex] == 0)
michael@0 2761 return XML_ERROR_NO_MEMORY;
michael@0 2762 poolFinish(&tempPool);
michael@0 2763 }
michael@0 2764 /* handle prefixed attribute names */
michael@0 2765 if (attId->prefix) {
michael@0 2766 if (attId->xmlns) {
michael@0 2767 /* deal with namespace declarations here */
michael@0 2768 enum XML_Error result = addBinding(parser, attId->prefix, attId,
michael@0 2769 appAtts[attIndex], bindingsPtr);
michael@0 2770 if (result)
michael@0 2771 return result;
michael@0 2772 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
michael@0 2773 #if 0
michael@0 2774 --attIndex;
michael@0 2775 #else
michael@0 2776 attIndex++;
michael@0 2777 nXMLNSDeclarations++;
michael@0 2778 (attId->name)[-1] = 3;
michael@0 2779 #endif
michael@0 2780 /* END MOZILLA CHANGE */
michael@0 2781 }
michael@0 2782 else {
michael@0 2783 /* deal with other prefixed names later */
michael@0 2784 attIndex++;
michael@0 2785 nPrefixes++;
michael@0 2786 (attId->name)[-1] = 2;
michael@0 2787 }
michael@0 2788 }
michael@0 2789 else
michael@0 2790 attIndex++;
michael@0 2791 }
michael@0 2792
michael@0 2793 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
michael@0 2794 nSpecifiedAtts = attIndex;
michael@0 2795 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
michael@0 2796 for (i = 0; i < attIndex; i += 2)
michael@0 2797 if (appAtts[i] == elementType->idAtt->name) {
michael@0 2798 idAttIndex = i;
michael@0 2799 break;
michael@0 2800 }
michael@0 2801 }
michael@0 2802 else
michael@0 2803 idAttIndex = -1;
michael@0 2804
michael@0 2805 /* do attribute defaulting */
michael@0 2806 for (i = 0; i < nDefaultAtts; i++) {
michael@0 2807 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
michael@0 2808 if (!(da->id->name)[-1] && da->value) {
michael@0 2809 if (da->id->prefix) {
michael@0 2810 if (da->id->xmlns) {
michael@0 2811 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
michael@0 2812 da->value, bindingsPtr);
michael@0 2813 if (result)
michael@0 2814 return result;
michael@0 2815 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
michael@0 2816 (da->id->name)[-1] = 3;
michael@0 2817 nXMLNSDeclarations++;
michael@0 2818 appAtts[attIndex++] = da->id->name;
michael@0 2819 appAtts[attIndex++] = da->value;
michael@0 2820 /* END MOZILLA CHANGE */
michael@0 2821 }
michael@0 2822 else {
michael@0 2823 (da->id->name)[-1] = 2;
michael@0 2824 nPrefixes++;
michael@0 2825 appAtts[attIndex++] = da->id->name;
michael@0 2826 appAtts[attIndex++] = da->value;
michael@0 2827 }
michael@0 2828 }
michael@0 2829 else {
michael@0 2830 (da->id->name)[-1] = 1;
michael@0 2831 appAtts[attIndex++] = da->id->name;
michael@0 2832 appAtts[attIndex++] = da->value;
michael@0 2833 }
michael@0 2834 }
michael@0 2835 }
michael@0 2836 appAtts[attIndex] = 0;
michael@0 2837
michael@0 2838 /* expand prefixed attribute names, check for duplicates,
michael@0 2839 and clear flags that say whether attributes were specified */
michael@0 2840 i = 0;
michael@0 2841 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
michael@0 2842 #if 0
michael@0 2843 if (nPrefixes) {
michael@0 2844 #else
michael@0 2845 if (nPrefixes || nXMLNSDeclarations) {
michael@0 2846 #endif
michael@0 2847 /* END MOZILLA CHANGE */
michael@0 2848 int j; /* hash table index */
michael@0 2849 unsigned long version = nsAttsVersion;
michael@0 2850 int nsAttsSize = (int)1 << nsAttsPower;
michael@0 2851 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
michael@0 2852 if (nPrefixes) {
michael@0 2853 /* END MOZILLA CHANGE */
michael@0 2854 /* size of hash table must be at least 2 * (# of prefixed attributes) */
michael@0 2855 if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */
michael@0 2856 NS_ATT *temp;
michael@0 2857 /* hash table size must also be a power of 2 and >= 8 */
michael@0 2858 while (nPrefixes >> nsAttsPower++);
michael@0 2859 if (nsAttsPower < 3)
michael@0 2860 nsAttsPower = 3;
michael@0 2861 nsAttsSize = (int)1 << nsAttsPower;
michael@0 2862 temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
michael@0 2863 if (!temp)
michael@0 2864 return XML_ERROR_NO_MEMORY;
michael@0 2865 nsAtts = temp;
michael@0 2866 version = 0; /* force re-initialization of nsAtts hash table */
michael@0 2867 }
michael@0 2868 /* using a version flag saves us from initializing nsAtts every time */
michael@0 2869 if (!version) { /* initialize version flags when version wraps around */
michael@0 2870 version = INIT_ATTS_VERSION;
michael@0 2871 for (j = nsAttsSize; j != 0; )
michael@0 2872 nsAtts[--j].version = version;
michael@0 2873 }
michael@0 2874 nsAttsVersion = --version;
michael@0 2875 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
michael@0 2876 }
michael@0 2877 /* END MOZILLA CHANGE */
michael@0 2878
michael@0 2879 /* expand prefixed names and check for duplicates */
michael@0 2880 for (; i < attIndex; i += 2) {
michael@0 2881 const XML_Char *s = appAtts[i];
michael@0 2882 if (s[-1] == 2) { /* prefixed */
michael@0 2883 ATTRIBUTE_ID *id;
michael@0 2884 const BINDING *b;
michael@0 2885 unsigned long uriHash = 0;
michael@0 2886 ((XML_Char *)s)[-1] = 0; /* clear flag */
michael@0 2887 id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);
michael@0 2888 b = id->prefix->binding;
michael@0 2889 if (!b)
michael@0 2890 return XML_ERROR_UNBOUND_PREFIX;
michael@0 2891
michael@0 2892 /* as we expand the name we also calculate its hash value */
michael@0 2893 for (j = 0; j < b->uriLen; j++) {
michael@0 2894 const XML_Char c = b->uri[j];
michael@0 2895 if (!poolAppendChar(&tempPool, c))
michael@0 2896 return XML_ERROR_NO_MEMORY;
michael@0 2897 uriHash = CHAR_HASH(uriHash, c);
michael@0 2898 }
michael@0 2899 while (*s++ != XML_T(':'))
michael@0 2900 ;
michael@0 2901 do { /* copies null terminator */
michael@0 2902 const XML_Char c = *s;
michael@0 2903 if (!poolAppendChar(&tempPool, *s))
michael@0 2904 return XML_ERROR_NO_MEMORY;
michael@0 2905 uriHash = CHAR_HASH(uriHash, c);
michael@0 2906 } while (*s++);
michael@0 2907
michael@0 2908 { /* Check hash table for duplicate of expanded name (uriName).
michael@0 2909 Derived from code in lookup(HASH_TABLE *table, ...).
michael@0 2910 */
michael@0 2911 unsigned char step = 0;
michael@0 2912 unsigned long mask = nsAttsSize - 1;
michael@0 2913 j = uriHash & mask; /* index into hash table */
michael@0 2914 while (nsAtts[j].version == version) {
michael@0 2915 /* for speed we compare stored hash values first */
michael@0 2916 if (uriHash == nsAtts[j].hash) {
michael@0 2917 const XML_Char *s1 = poolStart(&tempPool);
michael@0 2918 const XML_Char *s2 = nsAtts[j].uriName;
michael@0 2919 /* s1 is null terminated, but not s2 */
michael@0 2920 for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
michael@0 2921 if (*s1 == 0)
michael@0 2922 return XML_ERROR_DUPLICATE_ATTRIBUTE;
michael@0 2923 }
michael@0 2924 if (!step)
michael@0 2925 step = PROBE_STEP(uriHash, mask, nsAttsPower);
michael@0 2926 j < step ? (j += nsAttsSize - step) : (j -= step);
michael@0 2927 }
michael@0 2928 }
michael@0 2929
michael@0 2930 if (ns_triplets) { /* append namespace separator and prefix */
michael@0 2931 tempPool.ptr[-1] = namespaceSeparator;
michael@0 2932 s = b->prefix->name;
michael@0 2933 do {
michael@0 2934 if (!poolAppendChar(&tempPool, *s))
michael@0 2935 return XML_ERROR_NO_MEMORY;
michael@0 2936 } while (*s++);
michael@0 2937 }
michael@0 2938
michael@0 2939 /* store expanded name in attribute list */
michael@0 2940 s = poolStart(&tempPool);
michael@0 2941 poolFinish(&tempPool);
michael@0 2942 appAtts[i] = s;
michael@0 2943
michael@0 2944 /* fill empty slot with new version, uriName and hash value */
michael@0 2945 nsAtts[j].version = version;
michael@0 2946 nsAtts[j].hash = uriHash;
michael@0 2947 nsAtts[j].uriName = s;
michael@0 2948
michael@0 2949 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
michael@0 2950 #if 0
michael@0 2951 if (!--nPrefixes)
michael@0 2952 #else
michael@0 2953 if (!--nPrefixes && !nXMLNSDeclarations) {
michael@0 2954 #endif
michael@0 2955 /* END MOZILLA CHANGE */
michael@0 2956 i += 2;
michael@0 2957 break;
michael@0 2958 }
michael@0 2959 }
michael@0 2960 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
michael@0 2961 else if (s[-1] == 3) { /* xmlns attribute */
michael@0 2962 static const XML_Char xmlnsNamespace[] = {
michael@0 2963 'h', 't', 't', 'p', ':', '/', '/',
michael@0 2964 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
michael@0 2965 '2', '0', '0', '0', '/', 'x', 'm', 'l', 'n', 's', '/', '\0'
michael@0 2966 };
michael@0 2967 static const XML_Char xmlnsPrefix[] = {
michael@0 2968 'x', 'm', 'l', 'n', 's', '\0'
michael@0 2969 };
michael@0 2970 XML_Bool appendXMLNS = XML_TRUE;
michael@0 2971
michael@0 2972 ((XML_Char *)s)[-1] = 0; /* clear flag */
michael@0 2973 if (!poolAppendString(&tempPool, xmlnsNamespace)
michael@0 2974 || !poolAppendChar(&tempPool, namespaceSeparator))
michael@0 2975 return XML_ERROR_NO_MEMORY;
michael@0 2976 s += sizeof(xmlnsPrefix) / sizeof(xmlnsPrefix[0]) - 1;
michael@0 2977 if (*s == XML_T(':')) {
michael@0 2978 ++s;
michael@0 2979 do { /* copies null terminator */
michael@0 2980 if (!poolAppendChar(&tempPool, *s))
michael@0 2981 return XML_ERROR_NO_MEMORY;
michael@0 2982 } while (*s++);
michael@0 2983 if (ns_triplets) { /* append namespace separator and prefix */
michael@0 2984 tempPool.ptr[-1] = namespaceSeparator;
michael@0 2985 if (!poolAppendString(&tempPool, xmlnsPrefix)
michael@0 2986 || !poolAppendChar(&tempPool, '\0'))
michael@0 2987 return XML_ERROR_NO_MEMORY;
michael@0 2988 }
michael@0 2989 }
michael@0 2990 else {
michael@0 2991 /* xlmns attribute without a prefix. */
michael@0 2992 if (!poolAppendString(&tempPool, xmlnsPrefix)
michael@0 2993 || !poolAppendChar(&tempPool, '\0'))
michael@0 2994 return XML_ERROR_NO_MEMORY;
michael@0 2995 }
michael@0 2996
michael@0 2997 /* store expanded name in attribute list */
michael@0 2998 s = poolStart(&tempPool);
michael@0 2999 poolFinish(&tempPool);
michael@0 3000 appAtts[i] = s;
michael@0 3001
michael@0 3002 if (!--nXMLNSDeclarations && !nPrefixes) {
michael@0 3003 i += 2;
michael@0 3004 break;
michael@0 3005 }
michael@0 3006 }
michael@0 3007 /* END MOZILLA CHANGE */
michael@0 3008 else /* not prefixed */
michael@0 3009 ((XML_Char *)s)[-1] = 0; /* clear flag */
michael@0 3010 }
michael@0 3011 }
michael@0 3012 /* clear flags for the remaining attributes */
michael@0 3013 for (; i < attIndex; i += 2)
michael@0 3014 ((XML_Char *)(appAtts[i]))[-1] = 0;
michael@0 3015 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
michael@0 3016 binding->attId->name[-1] = 0;
michael@0 3017
michael@0 3018 if (!ns)
michael@0 3019 return XML_ERROR_NONE;
michael@0 3020
michael@0 3021 /* expand the element type name */
michael@0 3022 if (elementType->prefix) {
michael@0 3023 binding = elementType->prefix->binding;
michael@0 3024 if (!binding)
michael@0 3025 return XML_ERROR_UNBOUND_PREFIX;
michael@0 3026 localPart = tagNamePtr->str;
michael@0 3027 while (*localPart++ != XML_T(':'))
michael@0 3028 ;
michael@0 3029 }
michael@0 3030 else if (dtd->defaultPrefix.binding) {
michael@0 3031 binding = dtd->defaultPrefix.binding;
michael@0 3032 localPart = tagNamePtr->str;
michael@0 3033 }
michael@0 3034 else
michael@0 3035 return XML_ERROR_NONE;
michael@0 3036 prefixLen = 0;
michael@0 3037 if (ns_triplets && binding->prefix->name) {
michael@0 3038 for (; binding->prefix->name[prefixLen++];)
michael@0 3039 ; /* prefixLen includes null terminator */
michael@0 3040 }
michael@0 3041 tagNamePtr->localPart = localPart;
michael@0 3042 tagNamePtr->uriLen = binding->uriLen;
michael@0 3043 tagNamePtr->prefix = binding->prefix->name;
michael@0 3044 tagNamePtr->prefixLen = prefixLen;
michael@0 3045 for (i = 0; localPart[i++];)
michael@0 3046 ; /* i includes null terminator */
michael@0 3047 n = i + binding->uriLen + prefixLen;
michael@0 3048 if (n > binding->uriAlloc) {
michael@0 3049 TAG *p;
michael@0 3050 uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
michael@0 3051 if (!uri)
michael@0 3052 return XML_ERROR_NO_MEMORY;
michael@0 3053 binding->uriAlloc = n + EXPAND_SPARE;
michael@0 3054 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
michael@0 3055 for (p = tagStack; p; p = p->parent)
michael@0 3056 if (p->name.str == binding->uri)
michael@0 3057 p->name.str = uri;
michael@0 3058 FREE(binding->uri);
michael@0 3059 binding->uri = uri;
michael@0 3060 }
michael@0 3061 /* if namespaceSeparator != '\0' then uri includes it already */
michael@0 3062 uri = binding->uri + binding->uriLen;
michael@0 3063 memcpy(uri, localPart, i * sizeof(XML_Char));
michael@0 3064 /* we always have a namespace separator between localPart and prefix */
michael@0 3065 if (prefixLen) {
michael@0 3066 uri += i - 1;
michael@0 3067 *uri = namespaceSeparator; /* replace null terminator */
michael@0 3068 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
michael@0 3069 }
michael@0 3070 tagNamePtr->str = binding->uri;
michael@0 3071 return XML_ERROR_NONE;
michael@0 3072 }
michael@0 3073
michael@0 3074 /* addBinding() overwrites the value of prefix->binding without checking.
michael@0 3075 Therefore one must keep track of the old value outside of addBinding().
michael@0 3076 */
michael@0 3077 static enum XML_Error
michael@0 3078 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
michael@0 3079 const XML_Char *uri, BINDING **bindingsPtr)
michael@0 3080 {
michael@0 3081 static const XML_Char xmlNamespace[] = {
michael@0 3082 'h', 't', 't', 'p', ':', '/', '/',
michael@0 3083 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
michael@0 3084 'X', 'M', 'L', '/', '1', '9', '9', '8', '/',
michael@0 3085 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0'
michael@0 3086 };
michael@0 3087 static const int xmlLen =
michael@0 3088 (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
michael@0 3089 static const XML_Char xmlnsNamespace[] = {
michael@0 3090 'h', 't', 't', 'p', ':', '/', '/',
michael@0 3091 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
michael@0 3092 '2', '0', '0', '0', '/', 'x', 'm', 'l', 'n', 's', '/', '\0'
michael@0 3093 };
michael@0 3094 static const int xmlnsLen =
michael@0 3095 (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
michael@0 3096
michael@0 3097 XML_Bool mustBeXML = XML_FALSE;
michael@0 3098 XML_Bool isXML = XML_TRUE;
michael@0 3099 XML_Bool isXMLNS = XML_TRUE;
michael@0 3100
michael@0 3101 BINDING *b;
michael@0 3102 int len;
michael@0 3103
michael@0 3104 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
michael@0 3105 if (*uri == XML_T('\0') && prefix->name)
michael@0 3106 return XML_ERROR_UNDECLARING_PREFIX;
michael@0 3107
michael@0 3108 if (prefix->name
michael@0 3109 && prefix->name[0] == XML_T('x')
michael@0 3110 && prefix->name[1] == XML_T('m')
michael@0 3111 && prefix->name[2] == XML_T('l')) {
michael@0 3112
michael@0 3113 /* Not allowed to bind xmlns */
michael@0 3114 if (prefix->name[3] == XML_T('n')
michael@0 3115 && prefix->name[4] == XML_T('s')
michael@0 3116 && prefix->name[5] == XML_T('\0'))
michael@0 3117 return XML_ERROR_RESERVED_PREFIX_XMLNS;
michael@0 3118
michael@0 3119 if (prefix->name[3] == XML_T('\0'))
michael@0 3120 mustBeXML = XML_TRUE;
michael@0 3121 }
michael@0 3122
michael@0 3123 for (len = 0; uri[len]; len++) {
michael@0 3124 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
michael@0 3125 isXML = XML_FALSE;
michael@0 3126
michael@0 3127 if (!mustBeXML && isXMLNS
michael@0 3128 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
michael@0 3129 isXMLNS = XML_FALSE;
michael@0 3130 }
michael@0 3131 isXML = isXML && len == xmlLen;
michael@0 3132 isXMLNS = isXMLNS && len == xmlnsLen;
michael@0 3133
michael@0 3134 if (mustBeXML != isXML)
michael@0 3135 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
michael@0 3136 : XML_ERROR_RESERVED_NAMESPACE_URI;
michael@0 3137
michael@0 3138 if (isXMLNS)
michael@0 3139 return XML_ERROR_RESERVED_NAMESPACE_URI;
michael@0 3140
michael@0 3141 if (namespaceSeparator)
michael@0 3142 len++;
michael@0 3143 if (freeBindingList) {
michael@0 3144 b = freeBindingList;
michael@0 3145 if (len > b->uriAlloc) {
michael@0 3146 XML_Char *temp = (XML_Char *)REALLOC(b->uri,
michael@0 3147 sizeof(XML_Char) * (len + EXPAND_SPARE));
michael@0 3148 if (temp == NULL)
michael@0 3149 return XML_ERROR_NO_MEMORY;
michael@0 3150 b->uri = temp;
michael@0 3151 b->uriAlloc = len + EXPAND_SPARE;
michael@0 3152 }
michael@0 3153 freeBindingList = b->nextTagBinding;
michael@0 3154 }
michael@0 3155 else {
michael@0 3156 b = (BINDING *)MALLOC(sizeof(BINDING));
michael@0 3157 if (!b)
michael@0 3158 return XML_ERROR_NO_MEMORY;
michael@0 3159 b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
michael@0 3160 if (!b->uri) {
michael@0 3161 FREE(b);
michael@0 3162 return XML_ERROR_NO_MEMORY;
michael@0 3163 }
michael@0 3164 b->uriAlloc = len + EXPAND_SPARE;
michael@0 3165 }
michael@0 3166 b->uriLen = len;
michael@0 3167 memcpy(b->uri, uri, len * sizeof(XML_Char));
michael@0 3168 if (namespaceSeparator)
michael@0 3169 b->uri[len - 1] = namespaceSeparator;
michael@0 3170 b->prefix = prefix;
michael@0 3171 b->attId = attId;
michael@0 3172 b->prevPrefixBinding = prefix->binding;
michael@0 3173 /* NULL binding when default namespace undeclared */
michael@0 3174 if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
michael@0 3175 prefix->binding = NULL;
michael@0 3176 else
michael@0 3177 prefix->binding = b;
michael@0 3178 b->nextTagBinding = *bindingsPtr;
michael@0 3179 *bindingsPtr = b;
michael@0 3180 /* if attId == NULL then we are not starting a namespace scope */
michael@0 3181 if (attId && startNamespaceDeclHandler)
michael@0 3182 startNamespaceDeclHandler(handlerArg, prefix->name,
michael@0 3183 prefix->binding ? uri : 0);
michael@0 3184 return XML_ERROR_NONE;
michael@0 3185 }
michael@0 3186
michael@0 3187 /* The idea here is to avoid using stack for each CDATA section when
michael@0 3188 the whole file is parsed with one call.
michael@0 3189 */
michael@0 3190 static enum XML_Error PTRCALL
michael@0 3191 cdataSectionProcessor(XML_Parser parser,
michael@0 3192 const char *start,
michael@0 3193 const char *end,
michael@0 3194 const char **endPtr)
michael@0 3195 {
michael@0 3196 enum XML_Error result = doCdataSection(parser, encoding, &start, end,
michael@0 3197 endPtr, (XML_Bool)!ps_finalBuffer);
michael@0 3198 if (result != XML_ERROR_NONE)
michael@0 3199 return result;
michael@0 3200 if (start) {
michael@0 3201 if (parentParser) { /* we are parsing an external entity */
michael@0 3202 processor = externalEntityContentProcessor;
michael@0 3203 return externalEntityContentProcessor(parser, start, end, endPtr);
michael@0 3204 }
michael@0 3205 else {
michael@0 3206 processor = contentProcessor;
michael@0 3207 return contentProcessor(parser, start, end, endPtr);
michael@0 3208 }
michael@0 3209 }
michael@0 3210 return result;
michael@0 3211 }
michael@0 3212
michael@0 3213 /* startPtr gets set to non-null if the section is closed, and to null if
michael@0 3214 the section is not yet closed.
michael@0 3215 */
michael@0 3216 static enum XML_Error
michael@0 3217 doCdataSection(XML_Parser parser,
michael@0 3218 const ENCODING *enc,
michael@0 3219 const char **startPtr,
michael@0 3220 const char *end,
michael@0 3221 const char **nextPtr,
michael@0 3222 XML_Bool haveMore)
michael@0 3223 {
michael@0 3224 const char *s = *startPtr;
michael@0 3225 const char **eventPP;
michael@0 3226 const char **eventEndPP;
michael@0 3227 if (enc == encoding) {
michael@0 3228 eventPP = &eventPtr;
michael@0 3229 *eventPP = s;
michael@0 3230 eventEndPP = &eventEndPtr;
michael@0 3231 }
michael@0 3232 else {
michael@0 3233 eventPP = &(openInternalEntities->internalEventPtr);
michael@0 3234 eventEndPP = &(openInternalEntities->internalEventEndPtr);
michael@0 3235 }
michael@0 3236 *eventPP = s;
michael@0 3237 *startPtr = NULL;
michael@0 3238
michael@0 3239 for (;;) {
michael@0 3240 const char *next;
michael@0 3241 int tok = XmlCdataSectionTok(enc, s, end, &next);
michael@0 3242 *eventEndPP = next;
michael@0 3243 switch (tok) {
michael@0 3244 case XML_TOK_CDATA_SECT_CLOSE:
michael@0 3245 if (endCdataSectionHandler)
michael@0 3246 endCdataSectionHandler(handlerArg);
michael@0 3247 #if 0
michael@0 3248 /* see comment under XML_TOK_CDATA_SECT_OPEN */
michael@0 3249 else if (characterDataHandler)
michael@0 3250 characterDataHandler(handlerArg, dataBuf, 0);
michael@0 3251 #endif
michael@0 3252 else if (defaultHandler)
michael@0 3253 reportDefault(parser, enc, s, next);
michael@0 3254 *startPtr = next;
michael@0 3255 *nextPtr = next;
michael@0 3256 if (ps_parsing == XML_FINISHED)
michael@0 3257 return XML_ERROR_ABORTED;
michael@0 3258 else
michael@0 3259 return XML_ERROR_NONE;
michael@0 3260 case XML_TOK_DATA_NEWLINE:
michael@0 3261 if (characterDataHandler) {
michael@0 3262 XML_Char c = 0xA;
michael@0 3263 characterDataHandler(handlerArg, &c, 1);
michael@0 3264 }
michael@0 3265 else if (defaultHandler)
michael@0 3266 reportDefault(parser, enc, s, next);
michael@0 3267 break;
michael@0 3268 case XML_TOK_DATA_CHARS:
michael@0 3269 if (characterDataHandler) {
michael@0 3270 if (MUST_CONVERT(enc, s)) {
michael@0 3271 for (;;) {
michael@0 3272 ICHAR *dataPtr = (ICHAR *)dataBuf;
michael@0 3273 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
michael@0 3274 *eventEndPP = next;
michael@0 3275 characterDataHandler(handlerArg, dataBuf,
michael@0 3276 (int)(dataPtr - (ICHAR *)dataBuf));
michael@0 3277 if (s == next)
michael@0 3278 break;
michael@0 3279 *eventPP = s;
michael@0 3280 }
michael@0 3281 }
michael@0 3282 else
michael@0 3283 characterDataHandler(handlerArg,
michael@0 3284 (XML_Char *)s,
michael@0 3285 (int)((XML_Char *)next - (XML_Char *)s));
michael@0 3286 }
michael@0 3287 else if (defaultHandler)
michael@0 3288 reportDefault(parser, enc, s, next);
michael@0 3289 break;
michael@0 3290 case XML_TOK_INVALID:
michael@0 3291 *eventPP = next;
michael@0 3292 return XML_ERROR_INVALID_TOKEN;
michael@0 3293 case XML_TOK_PARTIAL_CHAR:
michael@0 3294 if (haveMore) {
michael@0 3295 *nextPtr = s;
michael@0 3296 return XML_ERROR_NONE;
michael@0 3297 }
michael@0 3298 return XML_ERROR_PARTIAL_CHAR;
michael@0 3299 case XML_TOK_PARTIAL:
michael@0 3300 case XML_TOK_NONE:
michael@0 3301 if (haveMore) {
michael@0 3302 *nextPtr = s;
michael@0 3303 return XML_ERROR_NONE;
michael@0 3304 }
michael@0 3305 return XML_ERROR_UNCLOSED_CDATA_SECTION;
michael@0 3306 default:
michael@0 3307 *eventPP = next;
michael@0 3308 return XML_ERROR_UNEXPECTED_STATE;
michael@0 3309 }
michael@0 3310
michael@0 3311 *eventPP = s = next;
michael@0 3312 switch (ps_parsing) {
michael@0 3313 case XML_SUSPENDED:
michael@0 3314 *nextPtr = next;
michael@0 3315 return XML_ERROR_NONE;
michael@0 3316 case XML_FINISHED:
michael@0 3317 return XML_ERROR_ABORTED;
michael@0 3318 default: ;
michael@0 3319 }
michael@0 3320 }
michael@0 3321 /* not reached */
michael@0 3322 }
michael@0 3323
michael@0 3324 #ifdef XML_DTD
michael@0 3325
michael@0 3326 /* The idea here is to avoid using stack for each IGNORE section when
michael@0 3327 the whole file is parsed with one call.
michael@0 3328 */
michael@0 3329 static enum XML_Error PTRCALL
michael@0 3330 ignoreSectionProcessor(XML_Parser parser,
michael@0 3331 const char *start,
michael@0 3332 const char *end,
michael@0 3333 const char **endPtr)
michael@0 3334 {
michael@0 3335 enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
michael@0 3336 endPtr, (XML_Bool)!ps_finalBuffer);
michael@0 3337 if (result != XML_ERROR_NONE)
michael@0 3338 return result;
michael@0 3339 if (start) {
michael@0 3340 processor = prologProcessor;
michael@0 3341 return prologProcessor(parser, start, end, endPtr);
michael@0 3342 }
michael@0 3343 return result;
michael@0 3344 }
michael@0 3345
michael@0 3346 /* startPtr gets set to non-null is the section is closed, and to null
michael@0 3347 if the section is not yet closed.
michael@0 3348 */
michael@0 3349 static enum XML_Error
michael@0 3350 doIgnoreSection(XML_Parser parser,
michael@0 3351 const ENCODING *enc,
michael@0 3352 const char **startPtr,
michael@0 3353 const char *end,
michael@0 3354 const char **nextPtr,
michael@0 3355 XML_Bool haveMore)
michael@0 3356 {
michael@0 3357 const char *next;
michael@0 3358 int tok;
michael@0 3359 const char *s = *startPtr;
michael@0 3360 const char **eventPP;
michael@0 3361 const char **eventEndPP;
michael@0 3362 if (enc == encoding) {
michael@0 3363 eventPP = &eventPtr;
michael@0 3364 *eventPP = s;
michael@0 3365 eventEndPP = &eventEndPtr;
michael@0 3366 }
michael@0 3367 else {
michael@0 3368 eventPP = &(openInternalEntities->internalEventPtr);
michael@0 3369 eventEndPP = &(openInternalEntities->internalEventEndPtr);
michael@0 3370 }
michael@0 3371 *eventPP = s;
michael@0 3372 *startPtr = NULL;
michael@0 3373 tok = XmlIgnoreSectionTok(enc, s, end, &next);
michael@0 3374 *eventEndPP = next;
michael@0 3375 switch (tok) {
michael@0 3376 case XML_TOK_IGNORE_SECT:
michael@0 3377 if (defaultHandler)
michael@0 3378 reportDefault(parser, enc, s, next);
michael@0 3379 *startPtr = next;
michael@0 3380 *nextPtr = next;
michael@0 3381 if (ps_parsing == XML_FINISHED)
michael@0 3382 return XML_ERROR_ABORTED;
michael@0 3383 else
michael@0 3384 return XML_ERROR_NONE;
michael@0 3385 case XML_TOK_INVALID:
michael@0 3386 *eventPP = next;
michael@0 3387 return XML_ERROR_INVALID_TOKEN;
michael@0 3388 case XML_TOK_PARTIAL_CHAR:
michael@0 3389 if (haveMore) {
michael@0 3390 *nextPtr = s;
michael@0 3391 return XML_ERROR_NONE;
michael@0 3392 }
michael@0 3393 return XML_ERROR_PARTIAL_CHAR;
michael@0 3394 case XML_TOK_PARTIAL:
michael@0 3395 case XML_TOK_NONE:
michael@0 3396 if (haveMore) {
michael@0 3397 *nextPtr = s;
michael@0 3398 return XML_ERROR_NONE;
michael@0 3399 }
michael@0 3400 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
michael@0 3401 default:
michael@0 3402 *eventPP = next;
michael@0 3403 return XML_ERROR_UNEXPECTED_STATE;
michael@0 3404 }
michael@0 3405 /* not reached */
michael@0 3406 }
michael@0 3407
michael@0 3408 #endif /* XML_DTD */
michael@0 3409
michael@0 3410 static enum XML_Error
michael@0 3411 initializeEncoding(XML_Parser parser)
michael@0 3412 {
michael@0 3413 const char *s;
michael@0 3414 #ifdef XML_UNICODE
michael@0 3415 char encodingBuf[128];
michael@0 3416 if (!protocolEncodingName)
michael@0 3417 s = NULL;
michael@0 3418 else {
michael@0 3419 int i;
michael@0 3420 for (i = 0; protocolEncodingName[i]; i++) {
michael@0 3421 if (i == sizeof(encodingBuf) - 1
michael@0 3422 || (protocolEncodingName[i] & ~0x7f) != 0) {
michael@0 3423 encodingBuf[0] = '\0';
michael@0 3424 break;
michael@0 3425 }
michael@0 3426 encodingBuf[i] = (char)protocolEncodingName[i];
michael@0 3427 }
michael@0 3428 encodingBuf[i] = '\0';
michael@0 3429 s = encodingBuf;
michael@0 3430 }
michael@0 3431 #else
michael@0 3432 s = protocolEncodingName;
michael@0 3433 #endif
michael@0 3434 if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
michael@0 3435 return XML_ERROR_NONE;
michael@0 3436 return handleUnknownEncoding(parser, protocolEncodingName);
michael@0 3437 }
michael@0 3438
michael@0 3439 static enum XML_Error
michael@0 3440 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
michael@0 3441 const char *s, const char *next)
michael@0 3442 {
michael@0 3443 const char *encodingName = NULL;
michael@0 3444 const XML_Char *storedEncName = NULL;
michael@0 3445 const ENCODING *newEncoding = NULL;
michael@0 3446 const char *version = NULL;
michael@0 3447 const char *versionend;
michael@0 3448 const XML_Char *storedversion = NULL;
michael@0 3449 int standalone = -1;
michael@0 3450 if (!(ns
michael@0 3451 ? XmlParseXmlDeclNS
michael@0 3452 : XmlParseXmlDecl)(isGeneralTextEntity,
michael@0 3453 encoding,
michael@0 3454 s,
michael@0 3455 next,
michael@0 3456 &eventPtr,
michael@0 3457 &version,
michael@0 3458 &versionend,
michael@0 3459 &encodingName,
michael@0 3460 &newEncoding,
michael@0 3461 &standalone)) {
michael@0 3462 if (isGeneralTextEntity)
michael@0 3463 return XML_ERROR_TEXT_DECL;
michael@0 3464 else
michael@0 3465 return XML_ERROR_XML_DECL;
michael@0 3466 }
michael@0 3467 if (!isGeneralTextEntity && standalone == 1) {
michael@0 3468 _dtd->standalone = XML_TRUE;
michael@0 3469 #ifdef XML_DTD
michael@0 3470 if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
michael@0 3471 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
michael@0 3472 #endif /* XML_DTD */
michael@0 3473 }
michael@0 3474 if (xmlDeclHandler) {
michael@0 3475 if (encodingName != NULL) {
michael@0 3476 storedEncName = poolStoreString(&temp2Pool,
michael@0 3477 encoding,
michael@0 3478 encodingName,
michael@0 3479 encodingName
michael@0 3480 + XmlNameLength(encoding, encodingName));
michael@0 3481 if (!storedEncName)
michael@0 3482 return XML_ERROR_NO_MEMORY;
michael@0 3483 poolFinish(&temp2Pool);
michael@0 3484 }
michael@0 3485 if (version) {
michael@0 3486 storedversion = poolStoreString(&temp2Pool,
michael@0 3487 encoding,
michael@0 3488 version,
michael@0 3489 versionend - encoding->minBytesPerChar);
michael@0 3490 if (!storedversion)
michael@0 3491 return XML_ERROR_NO_MEMORY;
michael@0 3492 }
michael@0 3493 xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
michael@0 3494 }
michael@0 3495 else if (defaultHandler)
michael@0 3496 reportDefault(parser, encoding, s, next);
michael@0 3497 if (protocolEncodingName == NULL) {
michael@0 3498 if (newEncoding) {
michael@0 3499 if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
michael@0 3500 eventPtr = encodingName;
michael@0 3501 return XML_ERROR_INCORRECT_ENCODING;
michael@0 3502 }
michael@0 3503 encoding = newEncoding;
michael@0 3504 }
michael@0 3505 else if (encodingName) {
michael@0 3506 enum XML_Error result;
michael@0 3507 if (!storedEncName) {
michael@0 3508 storedEncName = poolStoreString(
michael@0 3509 &temp2Pool, encoding, encodingName,
michael@0 3510 encodingName + XmlNameLength(encoding, encodingName));
michael@0 3511 if (!storedEncName)
michael@0 3512 return XML_ERROR_NO_MEMORY;
michael@0 3513 }
michael@0 3514 result = handleUnknownEncoding(parser, storedEncName);
michael@0 3515 poolClear(&temp2Pool);
michael@0 3516 if (result == XML_ERROR_UNKNOWN_ENCODING)
michael@0 3517 eventPtr = encodingName;
michael@0 3518 return result;
michael@0 3519 }
michael@0 3520 }
michael@0 3521
michael@0 3522 if (storedEncName || storedversion)
michael@0 3523 poolClear(&temp2Pool);
michael@0 3524
michael@0 3525 return XML_ERROR_NONE;
michael@0 3526 }
michael@0 3527
michael@0 3528 static enum XML_Error
michael@0 3529 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
michael@0 3530 {
michael@0 3531 if (unknownEncodingHandler) {
michael@0 3532 XML_Encoding info;
michael@0 3533 int i;
michael@0 3534 for (i = 0; i < 256; i++)
michael@0 3535 info.map[i] = -1;
michael@0 3536 info.convert = NULL;
michael@0 3537 info.data = NULL;
michael@0 3538 info.release = NULL;
michael@0 3539 if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
michael@0 3540 &info)) {
michael@0 3541 ENCODING *enc;
michael@0 3542 unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
michael@0 3543 if (!unknownEncodingMem) {
michael@0 3544 if (info.release)
michael@0 3545 info.release(info.data);
michael@0 3546 return XML_ERROR_NO_MEMORY;
michael@0 3547 }
michael@0 3548 enc = (ns
michael@0 3549 ? XmlInitUnknownEncodingNS
michael@0 3550 : XmlInitUnknownEncoding)(unknownEncodingMem,
michael@0 3551 info.map,
michael@0 3552 info.convert,
michael@0 3553 info.data);
michael@0 3554 if (enc) {
michael@0 3555 unknownEncodingData = info.data;
michael@0 3556 unknownEncodingRelease = info.release;
michael@0 3557 encoding = enc;
michael@0 3558 return XML_ERROR_NONE;
michael@0 3559 }
michael@0 3560 }
michael@0 3561 if (info.release != NULL)
michael@0 3562 info.release(info.data);
michael@0 3563 }
michael@0 3564 return XML_ERROR_UNKNOWN_ENCODING;
michael@0 3565 }
michael@0 3566
michael@0 3567 static enum XML_Error PTRCALL
michael@0 3568 prologInitProcessor(XML_Parser parser,
michael@0 3569 const char *s,
michael@0 3570 const char *end,
michael@0 3571 const char **nextPtr)
michael@0 3572 {
michael@0 3573 enum XML_Error result = initializeEncoding(parser);
michael@0 3574 if (result != XML_ERROR_NONE)
michael@0 3575 return result;
michael@0 3576 processor = prologProcessor;
michael@0 3577 return prologProcessor(parser, s, end, nextPtr);
michael@0 3578 }
michael@0 3579
michael@0 3580 #ifdef XML_DTD
michael@0 3581
michael@0 3582 static enum XML_Error PTRCALL
michael@0 3583 externalParEntInitProcessor(XML_Parser parser,
michael@0 3584 const char *s,
michael@0 3585 const char *end,
michael@0 3586 const char **nextPtr)
michael@0 3587 {
michael@0 3588 enum XML_Error result = initializeEncoding(parser);
michael@0 3589 if (result != XML_ERROR_NONE)
michael@0 3590 return result;
michael@0 3591
michael@0 3592 /* we know now that XML_Parse(Buffer) has been called,
michael@0 3593 so we consider the external parameter entity read */
michael@0 3594 _dtd->paramEntityRead = XML_TRUE;
michael@0 3595
michael@0 3596 if (prologState.inEntityValue) {
michael@0 3597 processor = entityValueInitProcessor;
michael@0 3598 return entityValueInitProcessor(parser, s, end, nextPtr);
michael@0 3599 }
michael@0 3600 else {
michael@0 3601 processor = externalParEntProcessor;
michael@0 3602 return externalParEntProcessor(parser, s, end, nextPtr);
michael@0 3603 }
michael@0 3604 }
michael@0 3605
michael@0 3606 static enum XML_Error PTRCALL
michael@0 3607 entityValueInitProcessor(XML_Parser parser,
michael@0 3608 const char *s,
michael@0 3609 const char *end,
michael@0 3610 const char **nextPtr)
michael@0 3611 {
michael@0 3612 int tok;
michael@0 3613 const char *start = s;
michael@0 3614 const char *next = start;
michael@0 3615 eventPtr = start;
michael@0 3616
michael@0 3617 for (;;) {
michael@0 3618 tok = XmlPrologTok(encoding, start, end, &next);
michael@0 3619 eventEndPtr = next;
michael@0 3620 if (tok <= 0) {
michael@0 3621 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
michael@0 3622 *nextPtr = s;
michael@0 3623 return XML_ERROR_NONE;
michael@0 3624 }
michael@0 3625 switch (tok) {
michael@0 3626 case XML_TOK_INVALID:
michael@0 3627 return XML_ERROR_INVALID_TOKEN;
michael@0 3628 case XML_TOK_PARTIAL:
michael@0 3629 return XML_ERROR_UNCLOSED_TOKEN;
michael@0 3630 case XML_TOK_PARTIAL_CHAR:
michael@0 3631 return XML_ERROR_PARTIAL_CHAR;
michael@0 3632 case XML_TOK_NONE: /* start == end */
michael@0 3633 default:
michael@0 3634 break;
michael@0 3635 }
michael@0 3636 /* found end of entity value - can store it now */
michael@0 3637 return storeEntityValue(parser, encoding, s, end);
michael@0 3638 }
michael@0 3639 else if (tok == XML_TOK_XML_DECL) {
michael@0 3640 enum XML_Error result;
michael@0 3641 result = processXmlDecl(parser, 0, start, next);
michael@0 3642 if (result != XML_ERROR_NONE)
michael@0 3643 return result;
michael@0 3644 switch (ps_parsing) {
michael@0 3645 case XML_SUSPENDED:
michael@0 3646 *nextPtr = next;
michael@0 3647 return XML_ERROR_NONE;
michael@0 3648 case XML_FINISHED:
michael@0 3649 return XML_ERROR_ABORTED;
michael@0 3650 default:
michael@0 3651 *nextPtr = next;
michael@0 3652 }
michael@0 3653 /* stop scanning for text declaration - we found one */
michael@0 3654 processor = entityValueProcessor;
michael@0 3655 return entityValueProcessor(parser, next, end, nextPtr);
michael@0 3656 }
michael@0 3657 /* If we are at the end of the buffer, this would cause XmlPrologTok to
michael@0 3658 return XML_TOK_NONE on the next call, which would then cause the
michael@0 3659 function to exit with *nextPtr set to s - that is what we want for other
michael@0 3660 tokens, but not for the BOM - we would rather like to skip it;
michael@0 3661 then, when this routine is entered the next time, XmlPrologTok will
michael@0 3662 return XML_TOK_INVALID, since the BOM is still in the buffer
michael@0 3663 */
michael@0 3664 else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
michael@0 3665 *nextPtr = next;
michael@0 3666 return XML_ERROR_NONE;
michael@0 3667 }
michael@0 3668 start = next;
michael@0 3669 eventPtr = start;
michael@0 3670 }
michael@0 3671 }
michael@0 3672
michael@0 3673 static enum XML_Error PTRCALL
michael@0 3674 externalParEntProcessor(XML_Parser parser,
michael@0 3675 const char *s,
michael@0 3676 const char *end,
michael@0 3677 const char **nextPtr)
michael@0 3678 {
michael@0 3679 const char *next = s;
michael@0 3680 int tok;
michael@0 3681
michael@0 3682 tok = XmlPrologTok(encoding, s, end, &next);
michael@0 3683 if (tok <= 0) {
michael@0 3684 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
michael@0 3685 *nextPtr = s;
michael@0 3686 return XML_ERROR_NONE;
michael@0 3687 }
michael@0 3688 switch (tok) {
michael@0 3689 case XML_TOK_INVALID:
michael@0 3690 return XML_ERROR_INVALID_TOKEN;
michael@0 3691 case XML_TOK_PARTIAL:
michael@0 3692 return XML_ERROR_UNCLOSED_TOKEN;
michael@0 3693 case XML_TOK_PARTIAL_CHAR:
michael@0 3694 return XML_ERROR_PARTIAL_CHAR;
michael@0 3695 case XML_TOK_NONE: /* start == end */
michael@0 3696 default:
michael@0 3697 break;
michael@0 3698 }
michael@0 3699 }
michael@0 3700 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
michael@0 3701 However, when parsing an external subset, doProlog will not accept a BOM
michael@0 3702 as valid, and report a syntax error, so we have to skip the BOM
michael@0 3703 */
michael@0 3704 else if (tok == XML_TOK_BOM) {
michael@0 3705 s = next;
michael@0 3706 tok = XmlPrologTok(encoding, s, end, &next);
michael@0 3707 }
michael@0 3708
michael@0 3709 processor = prologProcessor;
michael@0 3710 return doProlog(parser, encoding, s, end, tok, next,
michael@0 3711 nextPtr, (XML_Bool)!ps_finalBuffer);
michael@0 3712 }
michael@0 3713
michael@0 3714 static enum XML_Error PTRCALL
michael@0 3715 entityValueProcessor(XML_Parser parser,
michael@0 3716 const char *s,
michael@0 3717 const char *end,
michael@0 3718 const char **nextPtr)
michael@0 3719 {
michael@0 3720 const char *start = s;
michael@0 3721 const char *next = s;
michael@0 3722 const ENCODING *enc = encoding;
michael@0 3723 int tok;
michael@0 3724
michael@0 3725 for (;;) {
michael@0 3726 tok = XmlPrologTok(enc, start, end, &next);
michael@0 3727 if (tok <= 0) {
michael@0 3728 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
michael@0 3729 *nextPtr = s;
michael@0 3730 return XML_ERROR_NONE;
michael@0 3731 }
michael@0 3732 switch (tok) {
michael@0 3733 case XML_TOK_INVALID:
michael@0 3734 return XML_ERROR_INVALID_TOKEN;
michael@0 3735 case XML_TOK_PARTIAL:
michael@0 3736 return XML_ERROR_UNCLOSED_TOKEN;
michael@0 3737 case XML_TOK_PARTIAL_CHAR:
michael@0 3738 return XML_ERROR_PARTIAL_CHAR;
michael@0 3739 case XML_TOK_NONE: /* start == end */
michael@0 3740 default:
michael@0 3741 break;
michael@0 3742 }
michael@0 3743 /* found end of entity value - can store it now */
michael@0 3744 return storeEntityValue(parser, enc, s, end);
michael@0 3745 }
michael@0 3746 start = next;
michael@0 3747 }
michael@0 3748 }
michael@0 3749
michael@0 3750 #endif /* XML_DTD */
michael@0 3751
michael@0 3752 static enum XML_Error PTRCALL
michael@0 3753 prologProcessor(XML_Parser parser,
michael@0 3754 const char *s,
michael@0 3755 const char *end,
michael@0 3756 const char **nextPtr)
michael@0 3757 {
michael@0 3758 const char *next = s;
michael@0 3759 int tok = XmlPrologTok(encoding, s, end, &next);
michael@0 3760 return doProlog(parser, encoding, s, end, tok, next,
michael@0 3761 nextPtr, (XML_Bool)!ps_finalBuffer);
michael@0 3762 }
michael@0 3763
michael@0 3764 static enum XML_Error
michael@0 3765 doProlog(XML_Parser parser,
michael@0 3766 const ENCODING *enc,
michael@0 3767 const char *s,
michael@0 3768 const char *end,
michael@0 3769 int tok,
michael@0 3770 const char *next,
michael@0 3771 const char **nextPtr,
michael@0 3772 XML_Bool haveMore)
michael@0 3773 {
michael@0 3774 #ifdef XML_DTD
michael@0 3775 static const XML_Char externalSubsetName[] = { '#' , '\0' };
michael@0 3776 #endif /* XML_DTD */
michael@0 3777 static const XML_Char atypeCDATA[] = { 'C', 'D', 'A', 'T', 'A', '\0' };
michael@0 3778 static const XML_Char atypeID[] = { 'I', 'D', '\0' };
michael@0 3779 static const XML_Char atypeIDREF[] = { 'I', 'D', 'R', 'E', 'F', '\0' };
michael@0 3780 static const XML_Char atypeIDREFS[] = { 'I', 'D', 'R', 'E', 'F', 'S', '\0' };
michael@0 3781 static const XML_Char atypeENTITY[] = { 'E', 'N', 'T', 'I', 'T', 'Y', '\0' };
michael@0 3782 static const XML_Char atypeENTITIES[] =
michael@0 3783 { 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S', '\0' };
michael@0 3784 static const XML_Char atypeNMTOKEN[] = {
michael@0 3785 'N', 'M', 'T', 'O', 'K', 'E', 'N', '\0' };
michael@0 3786 static const XML_Char atypeNMTOKENS[] = {
michael@0 3787 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S', '\0' };
michael@0 3788 static const XML_Char notationPrefix[] = {
michael@0 3789 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', '(', '\0' };
michael@0 3790 static const XML_Char enumValueSep[] = { '|', '\0' };
michael@0 3791 static const XML_Char enumValueStart[] = { '(', '\0' };
michael@0 3792
michael@0 3793 /* save one level of indirection */
michael@0 3794 DTD * const dtd = _dtd;
michael@0 3795
michael@0 3796 const char **eventPP;
michael@0 3797 const char **eventEndPP;
michael@0 3798 enum XML_Content_Quant quant;
michael@0 3799
michael@0 3800 if (enc == encoding) {
michael@0 3801 eventPP = &eventPtr;
michael@0 3802 eventEndPP = &eventEndPtr;
michael@0 3803 }
michael@0 3804 else {
michael@0 3805 eventPP = &(openInternalEntities->internalEventPtr);
michael@0 3806 eventEndPP = &(openInternalEntities->internalEventEndPtr);
michael@0 3807 }
michael@0 3808
michael@0 3809 for (;;) {
michael@0 3810 int role;
michael@0 3811 XML_Bool handleDefault = XML_TRUE;
michael@0 3812 *eventPP = s;
michael@0 3813 *eventEndPP = next;
michael@0 3814 if (tok <= 0) {
michael@0 3815 if (haveMore && tok != XML_TOK_INVALID) {
michael@0 3816 *nextPtr = s;
michael@0 3817 return XML_ERROR_NONE;
michael@0 3818 }
michael@0 3819 switch (tok) {
michael@0 3820 case XML_TOK_INVALID:
michael@0 3821 *eventPP = next;
michael@0 3822 return XML_ERROR_INVALID_TOKEN;
michael@0 3823 case XML_TOK_PARTIAL:
michael@0 3824 return XML_ERROR_UNCLOSED_TOKEN;
michael@0 3825 case XML_TOK_PARTIAL_CHAR:
michael@0 3826 return XML_ERROR_PARTIAL_CHAR;
michael@0 3827 case XML_TOK_NONE:
michael@0 3828 #ifdef XML_DTD
michael@0 3829 /* for internal PE NOT referenced between declarations */
michael@0 3830 if (enc != encoding && !openInternalEntities->betweenDecl) {
michael@0 3831 *nextPtr = s;
michael@0 3832 return XML_ERROR_NONE;
michael@0 3833 }
michael@0 3834 /* WFC: PE Between Declarations - must check that PE contains
michael@0 3835 complete markup, not only for external PEs, but also for
michael@0 3836 internal PEs if the reference occurs between declarations.
michael@0 3837 */
michael@0 3838 if (isParamEntity || enc != encoding) {
michael@0 3839 if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
michael@0 3840 == XML_ROLE_ERROR)
michael@0 3841 return XML_ERROR_INCOMPLETE_PE;
michael@0 3842 *nextPtr = s;
michael@0 3843 return XML_ERROR_NONE;
michael@0 3844 }
michael@0 3845 #endif /* XML_DTD */
michael@0 3846 return XML_ERROR_NO_ELEMENTS;
michael@0 3847 default:
michael@0 3848 tok = -tok;
michael@0 3849 next = end;
michael@0 3850 break;
michael@0 3851 }
michael@0 3852 }
michael@0 3853 role = XmlTokenRole(&prologState, tok, s, next, enc);
michael@0 3854 switch (role) {
michael@0 3855 case XML_ROLE_XML_DECL:
michael@0 3856 {
michael@0 3857 enum XML_Error result = processXmlDecl(parser, 0, s, next);
michael@0 3858 if (result != XML_ERROR_NONE)
michael@0 3859 return result;
michael@0 3860 enc = encoding;
michael@0 3861 handleDefault = XML_FALSE;
michael@0 3862 }
michael@0 3863 break;
michael@0 3864 case XML_ROLE_DOCTYPE_NAME:
michael@0 3865 if (startDoctypeDeclHandler) {
michael@0 3866 doctypeName = poolStoreString(&tempPool, enc, s, next);
michael@0 3867 if (!doctypeName)
michael@0 3868 return XML_ERROR_NO_MEMORY;
michael@0 3869 poolFinish(&tempPool);
michael@0 3870 doctypePubid = NULL;
michael@0 3871 handleDefault = XML_FALSE;
michael@0 3872 }
michael@0 3873 doctypeSysid = NULL; /* always initialize to NULL */
michael@0 3874 break;
michael@0 3875 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
michael@0 3876 if (startDoctypeDeclHandler) {
michael@0 3877 startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
michael@0 3878 doctypePubid, 1);
michael@0 3879 doctypeName = NULL;
michael@0 3880 poolClear(&tempPool);
michael@0 3881 handleDefault = XML_FALSE;
michael@0 3882 }
michael@0 3883 break;
michael@0 3884 #ifdef XML_DTD
michael@0 3885 case XML_ROLE_TEXT_DECL:
michael@0 3886 {
michael@0 3887 enum XML_Error result = processXmlDecl(parser, 1, s, next);
michael@0 3888 if (result != XML_ERROR_NONE)
michael@0 3889 return result;
michael@0 3890 enc = encoding;
michael@0 3891 handleDefault = XML_FALSE;
michael@0 3892 }
michael@0 3893 break;
michael@0 3894 #endif /* XML_DTD */
michael@0 3895 case XML_ROLE_DOCTYPE_PUBLIC_ID:
michael@0 3896 #ifdef XML_DTD
michael@0 3897 useForeignDTD = XML_FALSE;
michael@0 3898 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
michael@0 3899 externalSubsetName,
michael@0 3900 sizeof(ENTITY));
michael@0 3901 if (!declEntity)
michael@0 3902 return XML_ERROR_NO_MEMORY;
michael@0 3903 #endif /* XML_DTD */
michael@0 3904 dtd->hasParamEntityRefs = XML_TRUE;
michael@0 3905 if (startDoctypeDeclHandler) {
michael@0 3906 if (!XmlIsPublicId(enc, s, next, eventPP))
michael@0 3907 return XML_ERROR_PUBLICID;
michael@0 3908 doctypePubid = poolStoreString(&tempPool, enc,
michael@0 3909 s + enc->minBytesPerChar,
michael@0 3910 next - enc->minBytesPerChar);
michael@0 3911 if (!doctypePubid)
michael@0 3912 return XML_ERROR_NO_MEMORY;
michael@0 3913 normalizePublicId((XML_Char *)doctypePubid);
michael@0 3914 poolFinish(&tempPool);
michael@0 3915 handleDefault = XML_FALSE;
michael@0 3916 goto alreadyChecked;
michael@0 3917 }
michael@0 3918 /* fall through */
michael@0 3919 case XML_ROLE_ENTITY_PUBLIC_ID:
michael@0 3920 if (!XmlIsPublicId(enc, s, next, eventPP))
michael@0 3921 return XML_ERROR_PUBLICID;
michael@0 3922 alreadyChecked:
michael@0 3923 if (dtd->keepProcessing && declEntity) {
michael@0 3924 XML_Char *tem = poolStoreString(&dtd->pool,
michael@0 3925 enc,
michael@0 3926 s + enc->minBytesPerChar,
michael@0 3927 next - enc->minBytesPerChar);
michael@0 3928 if (!tem)
michael@0 3929 return XML_ERROR_NO_MEMORY;
michael@0 3930 normalizePublicId(tem);
michael@0 3931 declEntity->publicId = tem;
michael@0 3932 poolFinish(&dtd->pool);
michael@0 3933 if (entityDeclHandler)
michael@0 3934 handleDefault = XML_FALSE;
michael@0 3935 }
michael@0 3936 break;
michael@0 3937 case XML_ROLE_DOCTYPE_CLOSE:
michael@0 3938 if (doctypeName) {
michael@0 3939 startDoctypeDeclHandler(handlerArg, doctypeName,
michael@0 3940 doctypeSysid, doctypePubid, 0);
michael@0 3941 poolClear(&tempPool);
michael@0 3942 handleDefault = XML_FALSE;
michael@0 3943 }
michael@0 3944 /* doctypeSysid will be non-NULL in the case of a previous
michael@0 3945 XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
michael@0 3946 was not set, indicating an external subset
michael@0 3947 */
michael@0 3948 #ifdef XML_DTD
michael@0 3949 if (doctypeSysid || useForeignDTD) {
michael@0 3950 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
michael@0 3951 dtd->hasParamEntityRefs = XML_TRUE;
michael@0 3952 if (paramEntityParsing && externalEntityRefHandler) {
michael@0 3953 ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
michael@0 3954 externalSubsetName,
michael@0 3955 sizeof(ENTITY));
michael@0 3956 if (!entity)
michael@0 3957 return XML_ERROR_NO_MEMORY;
michael@0 3958 if (useForeignDTD)
michael@0 3959 entity->base = curBase;
michael@0 3960 dtd->paramEntityRead = XML_FALSE;
michael@0 3961 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
michael@0 3962 0,
michael@0 3963 entity->base,
michael@0 3964 entity->systemId,
michael@0 3965 entity->publicId))
michael@0 3966 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
michael@0 3967 if (dtd->paramEntityRead) {
michael@0 3968 if (!dtd->standalone &&
michael@0 3969 notStandaloneHandler &&
michael@0 3970 !notStandaloneHandler(handlerArg))
michael@0 3971 return XML_ERROR_NOT_STANDALONE;
michael@0 3972 }
michael@0 3973 /* if we didn't read the foreign DTD then this means that there
michael@0 3974 is no external subset and we must reset dtd->hasParamEntityRefs
michael@0 3975 */
michael@0 3976 else if (!doctypeSysid)
michael@0 3977 dtd->hasParamEntityRefs = hadParamEntityRefs;
michael@0 3978 /* end of DTD - no need to update dtd->keepProcessing */
michael@0 3979 }
michael@0 3980 useForeignDTD = XML_FALSE;
michael@0 3981 }
michael@0 3982 #endif /* XML_DTD */
michael@0 3983 if (endDoctypeDeclHandler) {
michael@0 3984 endDoctypeDeclHandler(handlerArg);
michael@0 3985 handleDefault = XML_FALSE;
michael@0 3986 }
michael@0 3987 break;
michael@0 3988 case XML_ROLE_INSTANCE_START:
michael@0 3989 #ifdef XML_DTD
michael@0 3990 /* if there is no DOCTYPE declaration then now is the
michael@0 3991 last chance to read the foreign DTD
michael@0 3992 */
michael@0 3993 if (useForeignDTD) {
michael@0 3994 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
michael@0 3995 dtd->hasParamEntityRefs = XML_TRUE;
michael@0 3996 if (paramEntityParsing && externalEntityRefHandler) {
michael@0 3997 ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
michael@0 3998 externalSubsetName,
michael@0 3999 sizeof(ENTITY));
michael@0 4000 if (!entity)
michael@0 4001 return XML_ERROR_NO_MEMORY;
michael@0 4002 entity->base = curBase;
michael@0 4003 dtd->paramEntityRead = XML_FALSE;
michael@0 4004 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
michael@0 4005 0,
michael@0 4006 entity->base,
michael@0 4007 entity->systemId,
michael@0 4008 entity->publicId))
michael@0 4009 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
michael@0 4010 if (dtd->paramEntityRead) {
michael@0 4011 if (!dtd->standalone &&
michael@0 4012 notStandaloneHandler &&
michael@0 4013 !notStandaloneHandler(handlerArg))
michael@0 4014 return XML_ERROR_NOT_STANDALONE;
michael@0 4015 }
michael@0 4016 /* if we didn't read the foreign DTD then this means that there
michael@0 4017 is no external subset and we must reset dtd->hasParamEntityRefs
michael@0 4018 */
michael@0 4019 else
michael@0 4020 dtd->hasParamEntityRefs = hadParamEntityRefs;
michael@0 4021 /* end of DTD - no need to update dtd->keepProcessing */
michael@0 4022 }
michael@0 4023 }
michael@0 4024 #endif /* XML_DTD */
michael@0 4025 processor = contentProcessor;
michael@0 4026 return contentProcessor(parser, s, end, nextPtr);
michael@0 4027 case XML_ROLE_ATTLIST_ELEMENT_NAME:
michael@0 4028 declElementType = getElementType(parser, enc, s, next);
michael@0 4029 if (!declElementType)
michael@0 4030 return XML_ERROR_NO_MEMORY;
michael@0 4031 goto checkAttListDeclHandler;
michael@0 4032 case XML_ROLE_ATTRIBUTE_NAME:
michael@0 4033 declAttributeId = getAttributeId(parser, enc, s, next);
michael@0 4034 if (!declAttributeId)
michael@0 4035 return XML_ERROR_NO_MEMORY;
michael@0 4036 declAttributeIsCdata = XML_FALSE;
michael@0 4037 declAttributeType = NULL;
michael@0 4038 declAttributeIsId = XML_FALSE;
michael@0 4039 goto checkAttListDeclHandler;
michael@0 4040 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
michael@0 4041 declAttributeIsCdata = XML_TRUE;
michael@0 4042 declAttributeType = atypeCDATA;
michael@0 4043 goto checkAttListDeclHandler;
michael@0 4044 case XML_ROLE_ATTRIBUTE_TYPE_ID:
michael@0 4045 declAttributeIsId = XML_TRUE;
michael@0 4046 declAttributeType = atypeID;
michael@0 4047 goto checkAttListDeclHandler;
michael@0 4048 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
michael@0 4049 declAttributeType = atypeIDREF;
michael@0 4050 goto checkAttListDeclHandler;
michael@0 4051 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
michael@0 4052 declAttributeType = atypeIDREFS;
michael@0 4053 goto checkAttListDeclHandler;
michael@0 4054 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
michael@0 4055 declAttributeType = atypeENTITY;
michael@0 4056 goto checkAttListDeclHandler;
michael@0 4057 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
michael@0 4058 declAttributeType = atypeENTITIES;
michael@0 4059 goto checkAttListDeclHandler;
michael@0 4060 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
michael@0 4061 declAttributeType = atypeNMTOKEN;
michael@0 4062 goto checkAttListDeclHandler;
michael@0 4063 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
michael@0 4064 declAttributeType = atypeNMTOKENS;
michael@0 4065 checkAttListDeclHandler:
michael@0 4066 if (dtd->keepProcessing && attlistDeclHandler)
michael@0 4067 handleDefault = XML_FALSE;
michael@0 4068 break;
michael@0 4069 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
michael@0 4070 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
michael@0 4071 if (dtd->keepProcessing && attlistDeclHandler) {
michael@0 4072 const XML_Char *prefix;
michael@0 4073 if (declAttributeType) {
michael@0 4074 prefix = enumValueSep;
michael@0 4075 }
michael@0 4076 else {
michael@0 4077 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
michael@0 4078 ? notationPrefix
michael@0 4079 : enumValueStart);
michael@0 4080 }
michael@0 4081 if (!poolAppendString(&tempPool, prefix))
michael@0 4082 return XML_ERROR_NO_MEMORY;
michael@0 4083 if (!poolAppend(&tempPool, enc, s, next))
michael@0 4084 return XML_ERROR_NO_MEMORY;
michael@0 4085 declAttributeType = tempPool.start;
michael@0 4086 handleDefault = XML_FALSE;
michael@0 4087 }
michael@0 4088 break;
michael@0 4089 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
michael@0 4090 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
michael@0 4091 if (dtd->keepProcessing) {
michael@0 4092 if (!defineAttribute(declElementType, declAttributeId,
michael@0 4093 declAttributeIsCdata, declAttributeIsId,
michael@0 4094 0, parser))
michael@0 4095 return XML_ERROR_NO_MEMORY;
michael@0 4096 if (attlistDeclHandler && declAttributeType) {
michael@0 4097 if (*declAttributeType == XML_T('(')
michael@0 4098 || (*declAttributeType == XML_T('N')
michael@0 4099 && declAttributeType[1] == XML_T('O'))) {
michael@0 4100 /* Enumerated or Notation type */
michael@0 4101 if (!poolAppendChar(&tempPool, XML_T(')'))
michael@0 4102 || !poolAppendChar(&tempPool, XML_T('\0')))
michael@0 4103 return XML_ERROR_NO_MEMORY;
michael@0 4104 declAttributeType = tempPool.start;
michael@0 4105 poolFinish(&tempPool);
michael@0 4106 }
michael@0 4107 *eventEndPP = s;
michael@0 4108 attlistDeclHandler(handlerArg, declElementType->name,
michael@0 4109 declAttributeId->name, declAttributeType,
michael@0 4110 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
michael@0 4111 poolClear(&tempPool);
michael@0 4112 handleDefault = XML_FALSE;
michael@0 4113 }
michael@0 4114 }
michael@0 4115 break;
michael@0 4116 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
michael@0 4117 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
michael@0 4118 if (dtd->keepProcessing) {
michael@0 4119 const XML_Char *attVal;
michael@0 4120 enum XML_Error result =
michael@0 4121 storeAttributeValue(parser, enc, declAttributeIsCdata,
michael@0 4122 s + enc->minBytesPerChar,
michael@0 4123 next - enc->minBytesPerChar,
michael@0 4124 &dtd->pool);
michael@0 4125 if (result)
michael@0 4126 return result;
michael@0 4127 attVal = poolStart(&dtd->pool);
michael@0 4128 poolFinish(&dtd->pool);
michael@0 4129 /* ID attributes aren't allowed to have a default */
michael@0 4130 if (!defineAttribute(declElementType, declAttributeId,
michael@0 4131 declAttributeIsCdata, XML_FALSE, attVal, parser))
michael@0 4132 return XML_ERROR_NO_MEMORY;
michael@0 4133 if (attlistDeclHandler && declAttributeType) {
michael@0 4134 if (*declAttributeType == XML_T('(')
michael@0 4135 || (*declAttributeType == XML_T('N')
michael@0 4136 && declAttributeType[1] == XML_T('O'))) {
michael@0 4137 /* Enumerated or Notation type */
michael@0 4138 if (!poolAppendChar(&tempPool, XML_T(')'))
michael@0 4139 || !poolAppendChar(&tempPool, XML_T('\0')))
michael@0 4140 return XML_ERROR_NO_MEMORY;
michael@0 4141 declAttributeType = tempPool.start;
michael@0 4142 poolFinish(&tempPool);
michael@0 4143 }
michael@0 4144 *eventEndPP = s;
michael@0 4145 attlistDeclHandler(handlerArg, declElementType->name,
michael@0 4146 declAttributeId->name, declAttributeType,
michael@0 4147 attVal,
michael@0 4148 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
michael@0 4149 poolClear(&tempPool);
michael@0 4150 handleDefault = XML_FALSE;
michael@0 4151 }
michael@0 4152 }
michael@0 4153 break;
michael@0 4154 case XML_ROLE_ENTITY_VALUE:
michael@0 4155 if (dtd->keepProcessing) {
michael@0 4156 enum XML_Error result = storeEntityValue(parser, enc,
michael@0 4157 s + enc->minBytesPerChar,
michael@0 4158 next - enc->minBytesPerChar);
michael@0 4159 if (declEntity) {
michael@0 4160 declEntity->textPtr = poolStart(&dtd->entityValuePool);
michael@0 4161 declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
michael@0 4162 poolFinish(&dtd->entityValuePool);
michael@0 4163 if (entityDeclHandler) {
michael@0 4164 *eventEndPP = s;
michael@0 4165 entityDeclHandler(handlerArg,
michael@0 4166 declEntity->name,
michael@0 4167 declEntity->is_param,
michael@0 4168 declEntity->textPtr,
michael@0 4169 declEntity->textLen,
michael@0 4170 curBase, 0, 0, 0);
michael@0 4171 handleDefault = XML_FALSE;
michael@0 4172 }
michael@0 4173 }
michael@0 4174 else
michael@0 4175 poolDiscard(&dtd->entityValuePool);
michael@0 4176 if (result != XML_ERROR_NONE)
michael@0 4177 return result;
michael@0 4178 }
michael@0 4179 break;
michael@0 4180 case XML_ROLE_DOCTYPE_SYSTEM_ID:
michael@0 4181 #ifdef XML_DTD
michael@0 4182 useForeignDTD = XML_FALSE;
michael@0 4183 #endif /* XML_DTD */
michael@0 4184 dtd->hasParamEntityRefs = XML_TRUE;
michael@0 4185 if (startDoctypeDeclHandler) {
michael@0 4186 doctypeSysid = poolStoreString(&tempPool, enc,
michael@0 4187 s + enc->minBytesPerChar,
michael@0 4188 next - enc->minBytesPerChar);
michael@0 4189 if (doctypeSysid == NULL)
michael@0 4190 return XML_ERROR_NO_MEMORY;
michael@0 4191 poolFinish(&tempPool);
michael@0 4192 handleDefault = XML_FALSE;
michael@0 4193 }
michael@0 4194 #ifdef XML_DTD
michael@0 4195 else
michael@0 4196 /* use externalSubsetName to make doctypeSysid non-NULL
michael@0 4197 for the case where no startDoctypeDeclHandler is set */
michael@0 4198 doctypeSysid = externalSubsetName;
michael@0 4199 #endif /* XML_DTD */
michael@0 4200 if (!dtd->standalone
michael@0 4201 #ifdef XML_DTD
michael@0 4202 && !paramEntityParsing
michael@0 4203 #endif /* XML_DTD */
michael@0 4204 && notStandaloneHandler
michael@0 4205 && !notStandaloneHandler(handlerArg))
michael@0 4206 return XML_ERROR_NOT_STANDALONE;
michael@0 4207 #ifndef XML_DTD
michael@0 4208 break;
michael@0 4209 #else /* XML_DTD */
michael@0 4210 if (!declEntity) {
michael@0 4211 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
michael@0 4212 externalSubsetName,
michael@0 4213 sizeof(ENTITY));
michael@0 4214 if (!declEntity)
michael@0 4215 return XML_ERROR_NO_MEMORY;
michael@0 4216 declEntity->publicId = NULL;
michael@0 4217 }
michael@0 4218 /* fall through */
michael@0 4219 #endif /* XML_DTD */
michael@0 4220 case XML_ROLE_ENTITY_SYSTEM_ID:
michael@0 4221 if (dtd->keepProcessing && declEntity) {
michael@0 4222 declEntity->systemId = poolStoreString(&dtd->pool, enc,
michael@0 4223 s + enc->minBytesPerChar,
michael@0 4224 next - enc->minBytesPerChar);
michael@0 4225 if (!declEntity->systemId)
michael@0 4226 return XML_ERROR_NO_MEMORY;
michael@0 4227 declEntity->base = curBase;
michael@0 4228 poolFinish(&dtd->pool);
michael@0 4229 if (entityDeclHandler)
michael@0 4230 handleDefault = XML_FALSE;
michael@0 4231 }
michael@0 4232 break;
michael@0 4233 case XML_ROLE_ENTITY_COMPLETE:
michael@0 4234 if (dtd->keepProcessing && declEntity && entityDeclHandler) {
michael@0 4235 *eventEndPP = s;
michael@0 4236 entityDeclHandler(handlerArg,
michael@0 4237 declEntity->name,
michael@0 4238 declEntity->is_param,
michael@0 4239 0,0,
michael@0 4240 declEntity->base,
michael@0 4241 declEntity->systemId,
michael@0 4242 declEntity->publicId,
michael@0 4243 0);
michael@0 4244 handleDefault = XML_FALSE;
michael@0 4245 }
michael@0 4246 break;
michael@0 4247 case XML_ROLE_ENTITY_NOTATION_NAME:
michael@0 4248 if (dtd->keepProcessing && declEntity) {
michael@0 4249 declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
michael@0 4250 if (!declEntity->notation)
michael@0 4251 return XML_ERROR_NO_MEMORY;
michael@0 4252 poolFinish(&dtd->pool);
michael@0 4253 if (unparsedEntityDeclHandler) {
michael@0 4254 *eventEndPP = s;
michael@0 4255 unparsedEntityDeclHandler(handlerArg,
michael@0 4256 declEntity->name,
michael@0 4257 declEntity->base,
michael@0 4258 declEntity->systemId,
michael@0 4259 declEntity->publicId,
michael@0 4260 declEntity->notation);
michael@0 4261 handleDefault = XML_FALSE;
michael@0 4262 }
michael@0 4263 else if (entityDeclHandler) {
michael@0 4264 *eventEndPP = s;
michael@0 4265 entityDeclHandler(handlerArg,
michael@0 4266 declEntity->name,
michael@0 4267 0,0,0,
michael@0 4268 declEntity->base,
michael@0 4269 declEntity->systemId,
michael@0 4270 declEntity->publicId,
michael@0 4271 declEntity->notation);
michael@0 4272 handleDefault = XML_FALSE;
michael@0 4273 }
michael@0 4274 }
michael@0 4275 break;
michael@0 4276 case XML_ROLE_GENERAL_ENTITY_NAME:
michael@0 4277 {
michael@0 4278 if (XmlPredefinedEntityName(enc, s, next)) {
michael@0 4279 declEntity = NULL;
michael@0 4280 break;
michael@0 4281 }
michael@0 4282 if (dtd->keepProcessing) {
michael@0 4283 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
michael@0 4284 if (!name)
michael@0 4285 return XML_ERROR_NO_MEMORY;
michael@0 4286 declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
michael@0 4287 sizeof(ENTITY));
michael@0 4288 if (!declEntity)
michael@0 4289 return XML_ERROR_NO_MEMORY;
michael@0 4290 if (declEntity->name != name) {
michael@0 4291 poolDiscard(&dtd->pool);
michael@0 4292 declEntity = NULL;
michael@0 4293 }
michael@0 4294 else {
michael@0 4295 poolFinish(&dtd->pool);
michael@0 4296 declEntity->publicId = NULL;
michael@0 4297 declEntity->is_param = XML_FALSE;
michael@0 4298 /* if we have a parent parser or are reading an internal parameter
michael@0 4299 entity, then the entity declaration is not considered "internal"
michael@0 4300 */
michael@0 4301 declEntity->is_internal = !(parentParser || openInternalEntities);
michael@0 4302 if (entityDeclHandler)
michael@0 4303 handleDefault = XML_FALSE;
michael@0 4304 }
michael@0 4305 }
michael@0 4306 else {
michael@0 4307 poolDiscard(&dtd->pool);
michael@0 4308 declEntity = NULL;
michael@0 4309 }
michael@0 4310 }
michael@0 4311 break;
michael@0 4312 case XML_ROLE_PARAM_ENTITY_NAME:
michael@0 4313 #ifdef XML_DTD
michael@0 4314 if (dtd->keepProcessing) {
michael@0 4315 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
michael@0 4316 if (!name)
michael@0 4317 return XML_ERROR_NO_MEMORY;
michael@0 4318 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
michael@0 4319 name, sizeof(ENTITY));
michael@0 4320 if (!declEntity)
michael@0 4321 return XML_ERROR_NO_MEMORY;
michael@0 4322 if (declEntity->name != name) {
michael@0 4323 poolDiscard(&dtd->pool);
michael@0 4324 declEntity = NULL;
michael@0 4325 }
michael@0 4326 else {
michael@0 4327 poolFinish(&dtd->pool);
michael@0 4328 declEntity->publicId = NULL;
michael@0 4329 declEntity->is_param = XML_TRUE;
michael@0 4330 /* if we have a parent parser or are reading an internal parameter
michael@0 4331 entity, then the entity declaration is not considered "internal"
michael@0 4332 */
michael@0 4333 declEntity->is_internal = !(parentParser || openInternalEntities);
michael@0 4334 if (entityDeclHandler)
michael@0 4335 handleDefault = XML_FALSE;
michael@0 4336 }
michael@0 4337 }
michael@0 4338 else {
michael@0 4339 poolDiscard(&dtd->pool);
michael@0 4340 declEntity = NULL;
michael@0 4341 }
michael@0 4342 #else /* not XML_DTD */
michael@0 4343 declEntity = NULL;
michael@0 4344 #endif /* XML_DTD */
michael@0 4345 break;
michael@0 4346 case XML_ROLE_NOTATION_NAME:
michael@0 4347 declNotationPublicId = NULL;
michael@0 4348 declNotationName = NULL;
michael@0 4349 if (notationDeclHandler) {
michael@0 4350 declNotationName = poolStoreString(&tempPool, enc, s, next);
michael@0 4351 if (!declNotationName)
michael@0 4352 return XML_ERROR_NO_MEMORY;
michael@0 4353 poolFinish(&tempPool);
michael@0 4354 handleDefault = XML_FALSE;
michael@0 4355 }
michael@0 4356 break;
michael@0 4357 case XML_ROLE_NOTATION_PUBLIC_ID:
michael@0 4358 if (!XmlIsPublicId(enc, s, next, eventPP))
michael@0 4359 return XML_ERROR_PUBLICID;
michael@0 4360 if (declNotationName) { /* means notationDeclHandler != NULL */
michael@0 4361 XML_Char *tem = poolStoreString(&tempPool,
michael@0 4362 enc,
michael@0 4363 s + enc->minBytesPerChar,
michael@0 4364 next - enc->minBytesPerChar);
michael@0 4365 if (!tem)
michael@0 4366 return XML_ERROR_NO_MEMORY;
michael@0 4367 normalizePublicId(tem);
michael@0 4368 declNotationPublicId = tem;
michael@0 4369 poolFinish(&tempPool);
michael@0 4370 handleDefault = XML_FALSE;
michael@0 4371 }
michael@0 4372 break;
michael@0 4373 case XML_ROLE_NOTATION_SYSTEM_ID:
michael@0 4374 if (declNotationName && notationDeclHandler) {
michael@0 4375 const XML_Char *systemId
michael@0 4376 = poolStoreString(&tempPool, enc,
michael@0 4377 s + enc->minBytesPerChar,
michael@0 4378 next - enc->minBytesPerChar);
michael@0 4379 if (!systemId)
michael@0 4380 return XML_ERROR_NO_MEMORY;
michael@0 4381 *eventEndPP = s;
michael@0 4382 notationDeclHandler(handlerArg,
michael@0 4383 declNotationName,
michael@0 4384 curBase,
michael@0 4385 systemId,
michael@0 4386 declNotationPublicId);
michael@0 4387 handleDefault = XML_FALSE;
michael@0 4388 }
michael@0 4389 poolClear(&tempPool);
michael@0 4390 break;
michael@0 4391 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
michael@0 4392 if (declNotationPublicId && notationDeclHandler) {
michael@0 4393 *eventEndPP = s;
michael@0 4394 notationDeclHandler(handlerArg,
michael@0 4395 declNotationName,
michael@0 4396 curBase,
michael@0 4397 0,
michael@0 4398 declNotationPublicId);
michael@0 4399 handleDefault = XML_FALSE;
michael@0 4400 }
michael@0 4401 poolClear(&tempPool);
michael@0 4402 break;
michael@0 4403 case XML_ROLE_ERROR:
michael@0 4404 switch (tok) {
michael@0 4405 case XML_TOK_PARAM_ENTITY_REF:
michael@0 4406 /* PE references in internal subset are
michael@0 4407 not allowed within declarations. */
michael@0 4408 return XML_ERROR_PARAM_ENTITY_REF;
michael@0 4409 case XML_TOK_XML_DECL:
michael@0 4410 return XML_ERROR_MISPLACED_XML_PI;
michael@0 4411 default:
michael@0 4412 return XML_ERROR_SYNTAX;
michael@0 4413 }
michael@0 4414 #ifdef XML_DTD
michael@0 4415 case XML_ROLE_IGNORE_SECT:
michael@0 4416 {
michael@0 4417 enum XML_Error result;
michael@0 4418 if (defaultHandler)
michael@0 4419 reportDefault(parser, enc, s, next);
michael@0 4420 handleDefault = XML_FALSE;
michael@0 4421 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
michael@0 4422 if (result != XML_ERROR_NONE)
michael@0 4423 return result;
michael@0 4424 else if (!next) {
michael@0 4425 processor = ignoreSectionProcessor;
michael@0 4426 return result;
michael@0 4427 }
michael@0 4428 }
michael@0 4429 break;
michael@0 4430 #endif /* XML_DTD */
michael@0 4431 case XML_ROLE_GROUP_OPEN:
michael@0 4432 if (prologState.level >= groupSize) {
michael@0 4433 if (groupSize) {
michael@0 4434 char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
michael@0 4435 if (temp == NULL)
michael@0 4436 return XML_ERROR_NO_MEMORY;
michael@0 4437 groupConnector = temp;
michael@0 4438 if (dtd->scaffIndex) {
michael@0 4439 int *temp = (int *)REALLOC(dtd->scaffIndex,
michael@0 4440 groupSize * sizeof(int));
michael@0 4441 if (temp == NULL)
michael@0 4442 return XML_ERROR_NO_MEMORY;
michael@0 4443 dtd->scaffIndex = temp;
michael@0 4444 }
michael@0 4445 }
michael@0 4446 else {
michael@0 4447 groupConnector = (char *)MALLOC(groupSize = 32);
michael@0 4448 if (!groupConnector)
michael@0 4449 return XML_ERROR_NO_MEMORY;
michael@0 4450 }
michael@0 4451 }
michael@0 4452 groupConnector[prologState.level] = 0;
michael@0 4453 if (dtd->in_eldecl) {
michael@0 4454 int myindex = nextScaffoldPart(parser);
michael@0 4455 if (myindex < 0)
michael@0 4456 return XML_ERROR_NO_MEMORY;
michael@0 4457 dtd->scaffIndex[dtd->scaffLevel] = myindex;
michael@0 4458 dtd->scaffLevel++;
michael@0 4459 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
michael@0 4460 if (elementDeclHandler)
michael@0 4461 handleDefault = XML_FALSE;
michael@0 4462 }
michael@0 4463 break;
michael@0 4464 case XML_ROLE_GROUP_SEQUENCE:
michael@0 4465 if (groupConnector[prologState.level] == '|')
michael@0 4466 return XML_ERROR_SYNTAX;
michael@0 4467 groupConnector[prologState.level] = ',';
michael@0 4468 if (dtd->in_eldecl && elementDeclHandler)
michael@0 4469 handleDefault = XML_FALSE;
michael@0 4470 break;
michael@0 4471 case XML_ROLE_GROUP_CHOICE:
michael@0 4472 if (groupConnector[prologState.level] == ',')
michael@0 4473 return XML_ERROR_SYNTAX;
michael@0 4474 if (dtd->in_eldecl
michael@0 4475 && !groupConnector[prologState.level]
michael@0 4476 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
michael@0 4477 != XML_CTYPE_MIXED)
michael@0 4478 ) {
michael@0 4479 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
michael@0 4480 = XML_CTYPE_CHOICE;
michael@0 4481 if (elementDeclHandler)
michael@0 4482 handleDefault = XML_FALSE;
michael@0 4483 }
michael@0 4484 groupConnector[prologState.level] = '|';
michael@0 4485 break;
michael@0 4486 case XML_ROLE_PARAM_ENTITY_REF:
michael@0 4487 #ifdef XML_DTD
michael@0 4488 case XML_ROLE_INNER_PARAM_ENTITY_REF:
michael@0 4489 dtd->hasParamEntityRefs = XML_TRUE;
michael@0 4490 if (!paramEntityParsing)
michael@0 4491 dtd->keepProcessing = dtd->standalone;
michael@0 4492 else {
michael@0 4493 const XML_Char *name;
michael@0 4494 ENTITY *entity;
michael@0 4495 name = poolStoreString(&dtd->pool, enc,
michael@0 4496 s + enc->minBytesPerChar,
michael@0 4497 next - enc->minBytesPerChar);
michael@0 4498 if (!name)
michael@0 4499 return XML_ERROR_NO_MEMORY;
michael@0 4500 entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
michael@0 4501 poolDiscard(&dtd->pool);
michael@0 4502 /* first, determine if a check for an existing declaration is needed;
michael@0 4503 if yes, check that the entity exists, and that it is internal,
michael@0 4504 otherwise call the skipped entity handler
michael@0 4505 */
michael@0 4506 if (prologState.documentEntity &&
michael@0 4507 (dtd->standalone
michael@0 4508 ? !openInternalEntities
michael@0 4509 : !dtd->hasParamEntityRefs)) {
michael@0 4510 if (!entity)
michael@0 4511 return XML_ERROR_UNDEFINED_ENTITY;
michael@0 4512 else if (!entity->is_internal)
michael@0 4513 return XML_ERROR_ENTITY_DECLARED_IN_PE;
michael@0 4514 }
michael@0 4515 else if (!entity) {
michael@0 4516 dtd->keepProcessing = dtd->standalone;
michael@0 4517 /* cannot report skipped entities in declarations */
michael@0 4518 if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
michael@0 4519 skippedEntityHandler(handlerArg, name, 1);
michael@0 4520 handleDefault = XML_FALSE;
michael@0 4521 }
michael@0 4522 break;
michael@0 4523 }
michael@0 4524 if (entity->open)
michael@0 4525 return XML_ERROR_RECURSIVE_ENTITY_REF;
michael@0 4526 if (entity->textPtr) {
michael@0 4527 enum XML_Error result;
michael@0 4528 XML_Bool betweenDecl =
michael@0 4529 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
michael@0 4530 result = processInternalEntity(parser, entity, betweenDecl);
michael@0 4531 if (result != XML_ERROR_NONE)
michael@0 4532 return result;
michael@0 4533 handleDefault = XML_FALSE;
michael@0 4534 break;
michael@0 4535 }
michael@0 4536 if (externalEntityRefHandler) {
michael@0 4537 dtd->paramEntityRead = XML_FALSE;
michael@0 4538 entity->open = XML_TRUE;
michael@0 4539 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
michael@0 4540 /* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=191482) */
michael@0 4541 #if 0
michael@0 4542 0,
michael@0 4543 #else
michael@0 4544 entity->name,
michael@0 4545 #endif
michael@0 4546 /* END MOZILLA CHANGE */
michael@0 4547 entity->base,
michael@0 4548 entity->systemId,
michael@0 4549 entity->publicId)) {
michael@0 4550 entity->open = XML_FALSE;
michael@0 4551 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
michael@0 4552 }
michael@0 4553 entity->open = XML_FALSE;
michael@0 4554 handleDefault = XML_FALSE;
michael@0 4555 if (!dtd->paramEntityRead) {
michael@0 4556 dtd->keepProcessing = dtd->standalone;
michael@0 4557 break;
michael@0 4558 }
michael@0 4559 }
michael@0 4560 else {
michael@0 4561 dtd->keepProcessing = dtd->standalone;
michael@0 4562 break;
michael@0 4563 }
michael@0 4564 }
michael@0 4565 #endif /* XML_DTD */
michael@0 4566 if (!dtd->standalone &&
michael@0 4567 notStandaloneHandler &&
michael@0 4568 !notStandaloneHandler(handlerArg))
michael@0 4569 return XML_ERROR_NOT_STANDALONE;
michael@0 4570 break;
michael@0 4571
michael@0 4572 /* Element declaration stuff */
michael@0 4573
michael@0 4574 case XML_ROLE_ELEMENT_NAME:
michael@0 4575 if (elementDeclHandler) {
michael@0 4576 declElementType = getElementType(parser, enc, s, next);
michael@0 4577 if (!declElementType)
michael@0 4578 return XML_ERROR_NO_MEMORY;
michael@0 4579 dtd->scaffLevel = 0;
michael@0 4580 dtd->scaffCount = 0;
michael@0 4581 dtd->in_eldecl = XML_TRUE;
michael@0 4582 handleDefault = XML_FALSE;
michael@0 4583 }
michael@0 4584 break;
michael@0 4585
michael@0 4586 case XML_ROLE_CONTENT_ANY:
michael@0 4587 case XML_ROLE_CONTENT_EMPTY:
michael@0 4588 if (dtd->in_eldecl) {
michael@0 4589 if (elementDeclHandler) {
michael@0 4590 XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
michael@0 4591 if (!content)
michael@0 4592 return XML_ERROR_NO_MEMORY;
michael@0 4593 content->quant = XML_CQUANT_NONE;
michael@0 4594 content->name = NULL;
michael@0 4595 content->numchildren = 0;
michael@0 4596 content->children = NULL;
michael@0 4597 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
michael@0 4598 XML_CTYPE_ANY :
michael@0 4599 XML_CTYPE_EMPTY);
michael@0 4600 *eventEndPP = s;
michael@0 4601 elementDeclHandler(handlerArg, declElementType->name, content);
michael@0 4602 handleDefault = XML_FALSE;
michael@0 4603 }
michael@0 4604 dtd->in_eldecl = XML_FALSE;
michael@0 4605 }
michael@0 4606 break;
michael@0 4607
michael@0 4608 case XML_ROLE_CONTENT_PCDATA:
michael@0 4609 if (dtd->in_eldecl) {
michael@0 4610 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
michael@0 4611 = XML_CTYPE_MIXED;
michael@0 4612 if (elementDeclHandler)
michael@0 4613 handleDefault = XML_FALSE;
michael@0 4614 }
michael@0 4615 break;
michael@0 4616
michael@0 4617 case XML_ROLE_CONTENT_ELEMENT:
michael@0 4618 quant = XML_CQUANT_NONE;
michael@0 4619 goto elementContent;
michael@0 4620 case XML_ROLE_CONTENT_ELEMENT_OPT:
michael@0 4621 quant = XML_CQUANT_OPT;
michael@0 4622 goto elementContent;
michael@0 4623 case XML_ROLE_CONTENT_ELEMENT_REP:
michael@0 4624 quant = XML_CQUANT_REP;
michael@0 4625 goto elementContent;
michael@0 4626 case XML_ROLE_CONTENT_ELEMENT_PLUS:
michael@0 4627 quant = XML_CQUANT_PLUS;
michael@0 4628 elementContent:
michael@0 4629 if (dtd->in_eldecl) {
michael@0 4630 ELEMENT_TYPE *el;
michael@0 4631 const XML_Char *name;
michael@0 4632 int nameLen;
michael@0 4633 const char *nxt = (quant == XML_CQUANT_NONE
michael@0 4634 ? next
michael@0 4635 : next - enc->minBytesPerChar);
michael@0 4636 int myindex = nextScaffoldPart(parser);
michael@0 4637 if (myindex < 0)
michael@0 4638 return XML_ERROR_NO_MEMORY;
michael@0 4639 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
michael@0 4640 dtd->scaffold[myindex].quant = quant;
michael@0 4641 el = getElementType(parser, enc, s, nxt);
michael@0 4642 if (!el)
michael@0 4643 return XML_ERROR_NO_MEMORY;
michael@0 4644 name = el->name;
michael@0 4645 dtd->scaffold[myindex].name = name;
michael@0 4646 nameLen = 0;
michael@0 4647 for (; name[nameLen++]; );
michael@0 4648 dtd->contentStringLen += nameLen;
michael@0 4649 if (elementDeclHandler)
michael@0 4650 handleDefault = XML_FALSE;
michael@0 4651 }
michael@0 4652 break;
michael@0 4653
michael@0 4654 case XML_ROLE_GROUP_CLOSE:
michael@0 4655 quant = XML_CQUANT_NONE;
michael@0 4656 goto closeGroup;
michael@0 4657 case XML_ROLE_GROUP_CLOSE_OPT:
michael@0 4658 quant = XML_CQUANT_OPT;
michael@0 4659 goto closeGroup;
michael@0 4660 case XML_ROLE_GROUP_CLOSE_REP:
michael@0 4661 quant = XML_CQUANT_REP;
michael@0 4662 goto closeGroup;
michael@0 4663 case XML_ROLE_GROUP_CLOSE_PLUS:
michael@0 4664 quant = XML_CQUANT_PLUS;
michael@0 4665 closeGroup:
michael@0 4666 if (dtd->in_eldecl) {
michael@0 4667 if (elementDeclHandler)
michael@0 4668 handleDefault = XML_FALSE;
michael@0 4669 dtd->scaffLevel--;
michael@0 4670 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
michael@0 4671 if (dtd->scaffLevel == 0) {
michael@0 4672 if (!handleDefault) {
michael@0 4673 XML_Content *model = build_model(parser);
michael@0 4674 if (!model)
michael@0 4675 return XML_ERROR_NO_MEMORY;
michael@0 4676 *eventEndPP = s;
michael@0 4677 elementDeclHandler(handlerArg, declElementType->name, model);
michael@0 4678 }
michael@0 4679 dtd->in_eldecl = XML_FALSE;
michael@0 4680 dtd->contentStringLen = 0;
michael@0 4681 }
michael@0 4682 }
michael@0 4683 break;
michael@0 4684 /* End element declaration stuff */
michael@0 4685
michael@0 4686 case XML_ROLE_PI:
michael@0 4687 if (!reportProcessingInstruction(parser, enc, s, next))
michael@0 4688 return XML_ERROR_NO_MEMORY;
michael@0 4689 handleDefault = XML_FALSE;
michael@0 4690 break;
michael@0 4691 case XML_ROLE_COMMENT:
michael@0 4692 if (!reportComment(parser, enc, s, next))
michael@0 4693 return XML_ERROR_NO_MEMORY;
michael@0 4694 handleDefault = XML_FALSE;
michael@0 4695 break;
michael@0 4696 case XML_ROLE_NONE:
michael@0 4697 switch (tok) {
michael@0 4698 case XML_TOK_BOM:
michael@0 4699 handleDefault = XML_FALSE;
michael@0 4700 break;
michael@0 4701 }
michael@0 4702 break;
michael@0 4703 case XML_ROLE_DOCTYPE_NONE:
michael@0 4704 if (startDoctypeDeclHandler)
michael@0 4705 handleDefault = XML_FALSE;
michael@0 4706 break;
michael@0 4707 case XML_ROLE_ENTITY_NONE:
michael@0 4708 if (dtd->keepProcessing && entityDeclHandler)
michael@0 4709 handleDefault = XML_FALSE;
michael@0 4710 break;
michael@0 4711 case XML_ROLE_NOTATION_NONE:
michael@0 4712 if (notationDeclHandler)
michael@0 4713 handleDefault = XML_FALSE;
michael@0 4714 break;
michael@0 4715 case XML_ROLE_ATTLIST_NONE:
michael@0 4716 if (dtd->keepProcessing && attlistDeclHandler)
michael@0 4717 handleDefault = XML_FALSE;
michael@0 4718 break;
michael@0 4719 case XML_ROLE_ELEMENT_NONE:
michael@0 4720 if (elementDeclHandler)
michael@0 4721 handleDefault = XML_FALSE;
michael@0 4722 break;
michael@0 4723 } /* end of big switch */
michael@0 4724
michael@0 4725 if (handleDefault && defaultHandler)
michael@0 4726 reportDefault(parser, enc, s, next);
michael@0 4727
michael@0 4728 switch (ps_parsing) {
michael@0 4729 case XML_SUSPENDED:
michael@0 4730 *nextPtr = next;
michael@0 4731 return XML_ERROR_NONE;
michael@0 4732 case XML_FINISHED:
michael@0 4733 return XML_ERROR_ABORTED;
michael@0 4734 default:
michael@0 4735 s = next;
michael@0 4736 tok = XmlPrologTok(enc, s, end, &next);
michael@0 4737 }
michael@0 4738 }
michael@0 4739 /* not reached */
michael@0 4740 }
michael@0 4741
michael@0 4742 static enum XML_Error PTRCALL
michael@0 4743 epilogProcessor(XML_Parser parser,
michael@0 4744 const char *s,
michael@0 4745 const char *end,
michael@0 4746 const char **nextPtr)
michael@0 4747 {
michael@0 4748 processor = epilogProcessor;
michael@0 4749 eventPtr = s;
michael@0 4750 for (;;) {
michael@0 4751 const char *next = NULL;
michael@0 4752 int tok = XmlPrologTok(encoding, s, end, &next);
michael@0 4753 eventEndPtr = next;
michael@0 4754 switch (tok) {
michael@0 4755 /* report partial linebreak - it might be the last token */
michael@0 4756 case -XML_TOK_PROLOG_S:
michael@0 4757 if (defaultHandler) {
michael@0 4758 reportDefault(parser, encoding, s, next);
michael@0 4759 if (ps_parsing == XML_FINISHED)
michael@0 4760 return XML_ERROR_ABORTED;
michael@0 4761 }
michael@0 4762 *nextPtr = next;
michael@0 4763 return XML_ERROR_NONE;
michael@0 4764 case XML_TOK_NONE:
michael@0 4765 *nextPtr = s;
michael@0 4766 return XML_ERROR_NONE;
michael@0 4767 case XML_TOK_PROLOG_S:
michael@0 4768 if (defaultHandler)
michael@0 4769 reportDefault(parser, encoding, s, next);
michael@0 4770 break;
michael@0 4771 case XML_TOK_PI:
michael@0 4772 if (!reportProcessingInstruction(parser, encoding, s, next))
michael@0 4773 return XML_ERROR_NO_MEMORY;
michael@0 4774 break;
michael@0 4775 case XML_TOK_COMMENT:
michael@0 4776 if (!reportComment(parser, encoding, s, next))
michael@0 4777 return XML_ERROR_NO_MEMORY;
michael@0 4778 break;
michael@0 4779 case XML_TOK_INVALID:
michael@0 4780 eventPtr = next;
michael@0 4781 return XML_ERROR_INVALID_TOKEN;
michael@0 4782 case XML_TOK_PARTIAL:
michael@0 4783 if (!ps_finalBuffer) {
michael@0 4784 *nextPtr = s;
michael@0 4785 return XML_ERROR_NONE;
michael@0 4786 }
michael@0 4787 return XML_ERROR_UNCLOSED_TOKEN;
michael@0 4788 case XML_TOK_PARTIAL_CHAR:
michael@0 4789 if (!ps_finalBuffer) {
michael@0 4790 *nextPtr = s;
michael@0 4791 return XML_ERROR_NONE;
michael@0 4792 }
michael@0 4793 return XML_ERROR_PARTIAL_CHAR;
michael@0 4794 default:
michael@0 4795 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
michael@0 4796 }
michael@0 4797 eventPtr = s = next;
michael@0 4798 switch (ps_parsing) {
michael@0 4799 case XML_SUSPENDED:
michael@0 4800 *nextPtr = next;
michael@0 4801 return XML_ERROR_NONE;
michael@0 4802 case XML_FINISHED:
michael@0 4803 return XML_ERROR_ABORTED;
michael@0 4804 default: ;
michael@0 4805 }
michael@0 4806 }
michael@0 4807 }
michael@0 4808
michael@0 4809 static enum XML_Error
michael@0 4810 processInternalEntity(XML_Parser parser, ENTITY *entity,
michael@0 4811 XML_Bool betweenDecl)
michael@0 4812 {
michael@0 4813 const char *textStart, *textEnd;
michael@0 4814 const char *next;
michael@0 4815 enum XML_Error result;
michael@0 4816 OPEN_INTERNAL_ENTITY *openEntity;
michael@0 4817
michael@0 4818 if (freeInternalEntities) {
michael@0 4819 openEntity = freeInternalEntities;
michael@0 4820 freeInternalEntities = openEntity->next;
michael@0 4821 }
michael@0 4822 else {
michael@0 4823 openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
michael@0 4824 if (!openEntity)
michael@0 4825 return XML_ERROR_NO_MEMORY;
michael@0 4826 }
michael@0 4827 entity->open = XML_TRUE;
michael@0 4828 entity->processed = 0;
michael@0 4829 openEntity->next = openInternalEntities;
michael@0 4830 openInternalEntities = openEntity;
michael@0 4831 openEntity->entity = entity;
michael@0 4832 openEntity->startTagLevel = tagLevel;
michael@0 4833 openEntity->betweenDecl = betweenDecl;
michael@0 4834 openEntity->internalEventPtr = NULL;
michael@0 4835 openEntity->internalEventEndPtr = NULL;
michael@0 4836 textStart = (char *)entity->textPtr;
michael@0 4837 textEnd = (char *)(entity->textPtr + entity->textLen);
michael@0 4838
michael@0 4839 #ifdef XML_DTD
michael@0 4840 if (entity->is_param) {
michael@0 4841 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
michael@0 4842 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
michael@0 4843 next, &next, XML_FALSE);
michael@0 4844 }
michael@0 4845 else
michael@0 4846 #endif /* XML_DTD */
michael@0 4847 result = doContent(parser, tagLevel, internalEncoding, textStart,
michael@0 4848 textEnd, &next, XML_FALSE);
michael@0 4849
michael@0 4850 if (result == XML_ERROR_NONE) {
michael@0 4851 if (textEnd != next && ps_parsing == XML_SUSPENDED) {
michael@0 4852 entity->processed = (int)(next - textStart);
michael@0 4853 processor = internalEntityProcessor;
michael@0 4854 }
michael@0 4855 else {
michael@0 4856 entity->open = XML_FALSE;
michael@0 4857 openInternalEntities = openEntity->next;
michael@0 4858 /* put openEntity back in list of free instances */
michael@0 4859 openEntity->next = freeInternalEntities;
michael@0 4860 freeInternalEntities = openEntity;
michael@0 4861 }
michael@0 4862 }
michael@0 4863 return result;
michael@0 4864 }
michael@0 4865
michael@0 4866 static enum XML_Error PTRCALL
michael@0 4867 internalEntityProcessor(XML_Parser parser,
michael@0 4868 const char *s,
michael@0 4869 const char *end,
michael@0 4870 const char **nextPtr)
michael@0 4871 {
michael@0 4872 ENTITY *entity;
michael@0 4873 const char *textStart, *textEnd;
michael@0 4874 const char *next;
michael@0 4875 enum XML_Error result;
michael@0 4876 OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
michael@0 4877 if (!openEntity)
michael@0 4878 return XML_ERROR_UNEXPECTED_STATE;
michael@0 4879
michael@0 4880 entity = openEntity->entity;
michael@0 4881 textStart = ((char *)entity->textPtr) + entity->processed;
michael@0 4882 textEnd = (char *)(entity->textPtr + entity->textLen);
michael@0 4883
michael@0 4884 #ifdef XML_DTD
michael@0 4885 if (entity->is_param) {
michael@0 4886 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
michael@0 4887 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
michael@0 4888 next, &next, XML_FALSE);
michael@0 4889 }
michael@0 4890 else
michael@0 4891 #endif /* XML_DTD */
michael@0 4892 result = doContent(parser, openEntity->startTagLevel, internalEncoding,
michael@0 4893 textStart, textEnd, &next, XML_FALSE);
michael@0 4894
michael@0 4895 if (result != XML_ERROR_NONE)
michael@0 4896 return result;
michael@0 4897 else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
michael@0 4898 entity->processed = (int)(next - (char *)entity->textPtr);
michael@0 4899 return result;
michael@0 4900 }
michael@0 4901 else {
michael@0 4902 entity->open = XML_FALSE;
michael@0 4903 openInternalEntities = openEntity->next;
michael@0 4904 /* put openEntity back in list of free instances */
michael@0 4905 openEntity->next = freeInternalEntities;
michael@0 4906 freeInternalEntities = openEntity;
michael@0 4907 }
michael@0 4908
michael@0 4909 #ifdef XML_DTD
michael@0 4910 if (entity->is_param) {
michael@0 4911 int tok;
michael@0 4912 processor = prologProcessor;
michael@0 4913 tok = XmlPrologTok(encoding, s, end, &next);
michael@0 4914 return doProlog(parser, encoding, s, end, tok, next, nextPtr,
michael@0 4915 (XML_Bool)!ps_finalBuffer);
michael@0 4916 }
michael@0 4917 else
michael@0 4918 #endif /* XML_DTD */
michael@0 4919 {
michael@0 4920 processor = contentProcessor;
michael@0 4921 /* see externalEntityContentProcessor vs contentProcessor */
michael@0 4922 return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
michael@0 4923 nextPtr, (XML_Bool)!ps_finalBuffer);
michael@0 4924 }
michael@0 4925 }
michael@0 4926
michael@0 4927 static enum XML_Error PTRCALL
michael@0 4928 errorProcessor(XML_Parser parser,
michael@0 4929 const char *s,
michael@0 4930 const char *end,
michael@0 4931 const char **nextPtr)
michael@0 4932 {
michael@0 4933 return errorCode;
michael@0 4934 }
michael@0 4935
michael@0 4936 static enum XML_Error
michael@0 4937 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
michael@0 4938 const char *ptr, const char *end,
michael@0 4939 STRING_POOL *pool)
michael@0 4940 {
michael@0 4941 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
michael@0 4942 end, pool);
michael@0 4943 if (result)
michael@0 4944 return result;
michael@0 4945 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
michael@0 4946 poolChop(pool);
michael@0 4947 if (!poolAppendChar(pool, XML_T('\0')))
michael@0 4948 return XML_ERROR_NO_MEMORY;
michael@0 4949 return XML_ERROR_NONE;
michael@0 4950 }
michael@0 4951
michael@0 4952 static enum XML_Error
michael@0 4953 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
michael@0 4954 const char *ptr, const char *end,
michael@0 4955 STRING_POOL *pool)
michael@0 4956 {
michael@0 4957 DTD * const dtd = _dtd; /* save one level of indirection */
michael@0 4958 for (;;) {
michael@0 4959 const char *next;
michael@0 4960 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
michael@0 4961 switch (tok) {
michael@0 4962 case XML_TOK_NONE:
michael@0 4963 return XML_ERROR_NONE;
michael@0 4964 case XML_TOK_INVALID:
michael@0 4965 if (enc == encoding)
michael@0 4966 eventPtr = next;
michael@0 4967 return XML_ERROR_INVALID_TOKEN;
michael@0 4968 case XML_TOK_PARTIAL:
michael@0 4969 if (enc == encoding)
michael@0 4970 eventPtr = ptr;
michael@0 4971 return XML_ERROR_INVALID_TOKEN;
michael@0 4972 case XML_TOK_CHAR_REF:
michael@0 4973 {
michael@0 4974 XML_Char buf[XML_ENCODE_MAX];
michael@0 4975 int i;
michael@0 4976 int n = XmlCharRefNumber(enc, ptr);
michael@0 4977 if (n < 0) {
michael@0 4978 if (enc == encoding)
michael@0 4979 eventPtr = ptr;
michael@0 4980 return XML_ERROR_BAD_CHAR_REF;
michael@0 4981 }
michael@0 4982 if (!isCdata
michael@0 4983 && n == 0x20 /* space */
michael@0 4984 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
michael@0 4985 break;
michael@0 4986 n = XmlEncode(n, (ICHAR *)buf);
michael@0 4987 if (!n) {
michael@0 4988 if (enc == encoding)
michael@0 4989 eventPtr = ptr;
michael@0 4990 return XML_ERROR_BAD_CHAR_REF;
michael@0 4991 }
michael@0 4992 for (i = 0; i < n; i++) {
michael@0 4993 if (!poolAppendChar(pool, buf[i]))
michael@0 4994 return XML_ERROR_NO_MEMORY;
michael@0 4995 }
michael@0 4996 }
michael@0 4997 break;
michael@0 4998 case XML_TOK_DATA_CHARS:
michael@0 4999 if (!poolAppend(pool, enc, ptr, next))
michael@0 5000 return XML_ERROR_NO_MEMORY;
michael@0 5001 break;
michael@0 5002 case XML_TOK_TRAILING_CR:
michael@0 5003 next = ptr + enc->minBytesPerChar;
michael@0 5004 /* fall through */
michael@0 5005 case XML_TOK_ATTRIBUTE_VALUE_S:
michael@0 5006 case XML_TOK_DATA_NEWLINE:
michael@0 5007 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
michael@0 5008 break;
michael@0 5009 if (!poolAppendChar(pool, 0x20))
michael@0 5010 return XML_ERROR_NO_MEMORY;
michael@0 5011 break;
michael@0 5012 case XML_TOK_ENTITY_REF:
michael@0 5013 {
michael@0 5014 const XML_Char *name;
michael@0 5015 ENTITY *entity;
michael@0 5016 char checkEntityDecl;
michael@0 5017 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
michael@0 5018 ptr + enc->minBytesPerChar,
michael@0 5019 next - enc->minBytesPerChar);
michael@0 5020 if (ch) {
michael@0 5021 if (!poolAppendChar(pool, ch))
michael@0 5022 return XML_ERROR_NO_MEMORY;
michael@0 5023 break;
michael@0 5024 }
michael@0 5025 name = poolStoreString(&temp2Pool, enc,
michael@0 5026 ptr + enc->minBytesPerChar,
michael@0 5027 next - enc->minBytesPerChar);
michael@0 5028 if (!name)
michael@0 5029 return XML_ERROR_NO_MEMORY;
michael@0 5030 entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
michael@0 5031 poolDiscard(&temp2Pool);
michael@0 5032 /* First, determine if a check for an existing declaration is needed;
michael@0 5033 if yes, check that the entity exists, and that it is internal.
michael@0 5034 */
michael@0 5035 if (pool == &dtd->pool) /* are we called from prolog? */
michael@0 5036 checkEntityDecl =
michael@0 5037 #ifdef XML_DTD
michael@0 5038 prologState.documentEntity &&
michael@0 5039 #endif /* XML_DTD */
michael@0 5040 (dtd->standalone
michael@0 5041 ? !openInternalEntities
michael@0 5042 : !dtd->hasParamEntityRefs);
michael@0 5043 else /* if (pool == &tempPool): we are called from content */
michael@0 5044 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
michael@0 5045 if (checkEntityDecl) {
michael@0 5046 if (!entity)
michael@0 5047 return XML_ERROR_UNDEFINED_ENTITY;
michael@0 5048 else if (!entity->is_internal)
michael@0 5049 return XML_ERROR_ENTITY_DECLARED_IN_PE;
michael@0 5050 }
michael@0 5051 else if (!entity) {
michael@0 5052 /* Cannot report skipped entity here - see comments on
michael@0 5053 skippedEntityHandler.
michael@0 5054 if (skippedEntityHandler)
michael@0 5055 skippedEntityHandler(handlerArg, name, 0);
michael@0 5056 */
michael@0 5057 /* Cannot call the default handler because this would be
michael@0 5058 out of sync with the call to the startElementHandler.
michael@0 5059 if ((pool == &tempPool) && defaultHandler)
michael@0 5060 reportDefault(parser, enc, ptr, next);
michael@0 5061 */
michael@0 5062 /* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=35984) */
michael@0 5063 #if 0
michael@0 5064 break;
michael@0 5065 #else
michael@0 5066 return XML_ERROR_UNDEFINED_ENTITY;
michael@0 5067 #endif
michael@0 5068 /* END MOZILLA CHANGE */
michael@0 5069 }
michael@0 5070 if (entity->open) {
michael@0 5071 if (enc == encoding)
michael@0 5072 eventPtr = ptr;
michael@0 5073 return XML_ERROR_RECURSIVE_ENTITY_REF;
michael@0 5074 }
michael@0 5075 if (entity->notation) {
michael@0 5076 if (enc == encoding)
michael@0 5077 eventPtr = ptr;
michael@0 5078 return XML_ERROR_BINARY_ENTITY_REF;
michael@0 5079 }
michael@0 5080 if (!entity->textPtr) {
michael@0 5081 if (enc == encoding)
michael@0 5082 eventPtr = ptr;
michael@0 5083 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
michael@0 5084 }
michael@0 5085 else {
michael@0 5086 enum XML_Error result;
michael@0 5087 const XML_Char *textEnd = entity->textPtr + entity->textLen;
michael@0 5088 entity->open = XML_TRUE;
michael@0 5089 result = appendAttributeValue(parser, internalEncoding, isCdata,
michael@0 5090 (char *)entity->textPtr,
michael@0 5091 (char *)textEnd, pool);
michael@0 5092 entity->open = XML_FALSE;
michael@0 5093 if (result)
michael@0 5094 return result;
michael@0 5095 }
michael@0 5096 }
michael@0 5097 break;
michael@0 5098 default:
michael@0 5099 if (enc == encoding)
michael@0 5100 eventPtr = ptr;
michael@0 5101 return XML_ERROR_UNEXPECTED_STATE;
michael@0 5102 }
michael@0 5103 ptr = next;
michael@0 5104 }
michael@0 5105 /* not reached */
michael@0 5106 }
michael@0 5107
michael@0 5108 static enum XML_Error
michael@0 5109 storeEntityValue(XML_Parser parser,
michael@0 5110 const ENCODING *enc,
michael@0 5111 const char *entityTextPtr,
michael@0 5112 const char *entityTextEnd)
michael@0 5113 {
michael@0 5114 DTD * const dtd = _dtd; /* save one level of indirection */
michael@0 5115 STRING_POOL *pool = &(dtd->entityValuePool);
michael@0 5116 enum XML_Error result = XML_ERROR_NONE;
michael@0 5117 #ifdef XML_DTD
michael@0 5118 int oldInEntityValue = prologState.inEntityValue;
michael@0 5119 prologState.inEntityValue = 1;
michael@0 5120 #endif /* XML_DTD */
michael@0 5121 /* never return Null for the value argument in EntityDeclHandler,
michael@0 5122 since this would indicate an external entity; therefore we
michael@0 5123 have to make sure that entityValuePool.start is not null */
michael@0 5124 if (!pool->blocks) {
michael@0 5125 if (!poolGrow(pool))
michael@0 5126 return XML_ERROR_NO_MEMORY;
michael@0 5127 }
michael@0 5128
michael@0 5129 for (;;) {
michael@0 5130 const char *next;
michael@0 5131 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
michael@0 5132 switch (tok) {
michael@0 5133 case XML_TOK_PARAM_ENTITY_REF:
michael@0 5134 #ifdef XML_DTD
michael@0 5135 if (isParamEntity || enc != encoding) {
michael@0 5136 const XML_Char *name;
michael@0 5137 ENTITY *entity;
michael@0 5138 name = poolStoreString(&tempPool, enc,
michael@0 5139 entityTextPtr + enc->minBytesPerChar,
michael@0 5140 next - enc->minBytesPerChar);
michael@0 5141 if (!name) {
michael@0 5142 result = XML_ERROR_NO_MEMORY;
michael@0 5143 goto endEntityValue;
michael@0 5144 }
michael@0 5145 entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
michael@0 5146 poolDiscard(&tempPool);
michael@0 5147 if (!entity) {
michael@0 5148 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
michael@0 5149 /* cannot report skipped entity here - see comments on
michael@0 5150 skippedEntityHandler
michael@0 5151 if (skippedEntityHandler)
michael@0 5152 skippedEntityHandler(handlerArg, name, 0);
michael@0 5153 */
michael@0 5154 dtd->keepProcessing = dtd->standalone;
michael@0 5155 goto endEntityValue;
michael@0 5156 }
michael@0 5157 if (entity->open) {
michael@0 5158 if (enc == encoding)
michael@0 5159 eventPtr = entityTextPtr;
michael@0 5160 result = XML_ERROR_RECURSIVE_ENTITY_REF;
michael@0 5161 goto endEntityValue;
michael@0 5162 }
michael@0 5163 if (entity->systemId) {
michael@0 5164 if (externalEntityRefHandler) {
michael@0 5165 dtd->paramEntityRead = XML_FALSE;
michael@0 5166 entity->open = XML_TRUE;
michael@0 5167 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
michael@0 5168 0,
michael@0 5169 entity->base,
michael@0 5170 entity->systemId,
michael@0 5171 entity->publicId)) {
michael@0 5172 entity->open = XML_FALSE;
michael@0 5173 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
michael@0 5174 goto endEntityValue;
michael@0 5175 }
michael@0 5176 entity->open = XML_FALSE;
michael@0 5177 if (!dtd->paramEntityRead)
michael@0 5178 dtd->keepProcessing = dtd->standalone;
michael@0 5179 }
michael@0 5180 else
michael@0 5181 dtd->keepProcessing = dtd->standalone;
michael@0 5182 }
michael@0 5183 else {
michael@0 5184 entity->open = XML_TRUE;
michael@0 5185 result = storeEntityValue(parser,
michael@0 5186 internalEncoding,
michael@0 5187 (char *)entity->textPtr,
michael@0 5188 (char *)(entity->textPtr
michael@0 5189 + entity->textLen));
michael@0 5190 entity->open = XML_FALSE;
michael@0 5191 if (result)
michael@0 5192 goto endEntityValue;
michael@0 5193 }
michael@0 5194 break;
michael@0 5195 }
michael@0 5196 #endif /* XML_DTD */
michael@0 5197 /* In the internal subset, PE references are not legal
michael@0 5198 within markup declarations, e.g entity values in this case. */
michael@0 5199 eventPtr = entityTextPtr;
michael@0 5200 result = XML_ERROR_PARAM_ENTITY_REF;
michael@0 5201 goto endEntityValue;
michael@0 5202 case XML_TOK_NONE:
michael@0 5203 result = XML_ERROR_NONE;
michael@0 5204 goto endEntityValue;
michael@0 5205 case XML_TOK_ENTITY_REF:
michael@0 5206 case XML_TOK_DATA_CHARS:
michael@0 5207 if (!poolAppend(pool, enc, entityTextPtr, next)) {
michael@0 5208 result = XML_ERROR_NO_MEMORY;
michael@0 5209 goto endEntityValue;
michael@0 5210 }
michael@0 5211 break;
michael@0 5212 case XML_TOK_TRAILING_CR:
michael@0 5213 next = entityTextPtr + enc->minBytesPerChar;
michael@0 5214 /* fall through */
michael@0 5215 case XML_TOK_DATA_NEWLINE:
michael@0 5216 if (pool->end == pool->ptr && !poolGrow(pool)) {
michael@0 5217 result = XML_ERROR_NO_MEMORY;
michael@0 5218 goto endEntityValue;
michael@0 5219 }
michael@0 5220 *(pool->ptr)++ = 0xA;
michael@0 5221 break;
michael@0 5222 case XML_TOK_CHAR_REF:
michael@0 5223 {
michael@0 5224 XML_Char buf[XML_ENCODE_MAX];
michael@0 5225 int i;
michael@0 5226 int n = XmlCharRefNumber(enc, entityTextPtr);
michael@0 5227 if (n < 0) {
michael@0 5228 if (enc == encoding)
michael@0 5229 eventPtr = entityTextPtr;
michael@0 5230 result = XML_ERROR_BAD_CHAR_REF;
michael@0 5231 goto endEntityValue;
michael@0 5232 }
michael@0 5233 n = XmlEncode(n, (ICHAR *)buf);
michael@0 5234 if (!n) {
michael@0 5235 if (enc == encoding)
michael@0 5236 eventPtr = entityTextPtr;
michael@0 5237 result = XML_ERROR_BAD_CHAR_REF;
michael@0 5238 goto endEntityValue;
michael@0 5239 }
michael@0 5240 for (i = 0; i < n; i++) {
michael@0 5241 if (pool->end == pool->ptr && !poolGrow(pool)) {
michael@0 5242 result = XML_ERROR_NO_MEMORY;
michael@0 5243 goto endEntityValue;
michael@0 5244 }
michael@0 5245 *(pool->ptr)++ = buf[i];
michael@0 5246 }
michael@0 5247 }
michael@0 5248 break;
michael@0 5249 case XML_TOK_PARTIAL:
michael@0 5250 if (enc == encoding)
michael@0 5251 eventPtr = entityTextPtr;
michael@0 5252 result = XML_ERROR_INVALID_TOKEN;
michael@0 5253 goto endEntityValue;
michael@0 5254 case XML_TOK_INVALID:
michael@0 5255 if (enc == encoding)
michael@0 5256 eventPtr = next;
michael@0 5257 result = XML_ERROR_INVALID_TOKEN;
michael@0 5258 goto endEntityValue;
michael@0 5259 default:
michael@0 5260 if (enc == encoding)
michael@0 5261 eventPtr = entityTextPtr;
michael@0 5262 result = XML_ERROR_UNEXPECTED_STATE;
michael@0 5263 goto endEntityValue;
michael@0 5264 }
michael@0 5265 entityTextPtr = next;
michael@0 5266 }
michael@0 5267 endEntityValue:
michael@0 5268 #ifdef XML_DTD
michael@0 5269 prologState.inEntityValue = oldInEntityValue;
michael@0 5270 #endif /* XML_DTD */
michael@0 5271 return result;
michael@0 5272 }
michael@0 5273
michael@0 5274 static void FASTCALL
michael@0 5275 normalizeLines(XML_Char *s)
michael@0 5276 {
michael@0 5277 XML_Char *p;
michael@0 5278 for (;; s++) {
michael@0 5279 if (*s == XML_T('\0'))
michael@0 5280 return;
michael@0 5281 if (*s == 0xD)
michael@0 5282 break;
michael@0 5283 }
michael@0 5284 p = s;
michael@0 5285 do {
michael@0 5286 if (*s == 0xD) {
michael@0 5287 *p++ = 0xA;
michael@0 5288 if (*++s == 0xA)
michael@0 5289 s++;
michael@0 5290 }
michael@0 5291 else
michael@0 5292 *p++ = *s++;
michael@0 5293 } while (*s);
michael@0 5294 *p = XML_T('\0');
michael@0 5295 }
michael@0 5296
michael@0 5297 static int
michael@0 5298 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
michael@0 5299 const char *start, const char *end)
michael@0 5300 {
michael@0 5301 const XML_Char *target;
michael@0 5302 XML_Char *data;
michael@0 5303 const char *tem;
michael@0 5304 if (!processingInstructionHandler) {
michael@0 5305 if (defaultHandler)
michael@0 5306 reportDefault(parser, enc, start, end);
michael@0 5307 return 1;
michael@0 5308 }
michael@0 5309 start += enc->minBytesPerChar * 2;
michael@0 5310 tem = start + XmlNameLength(enc, start);
michael@0 5311 target = poolStoreString(&tempPool, enc, start, tem);
michael@0 5312 if (!target)
michael@0 5313 return 0;
michael@0 5314 poolFinish(&tempPool);
michael@0 5315 data = poolStoreString(&tempPool, enc,
michael@0 5316 XmlSkipS(enc, tem),
michael@0 5317 end - enc->minBytesPerChar*2);
michael@0 5318 if (!data)
michael@0 5319 return 0;
michael@0 5320 normalizeLines(data);
michael@0 5321 processingInstructionHandler(handlerArg, target, data);
michael@0 5322 poolClear(&tempPool);
michael@0 5323 return 1;
michael@0 5324 }
michael@0 5325
michael@0 5326 static int
michael@0 5327 reportComment(XML_Parser parser, const ENCODING *enc,
michael@0 5328 const char *start, const char *end)
michael@0 5329 {
michael@0 5330 XML_Char *data;
michael@0 5331 if (!commentHandler) {
michael@0 5332 if (defaultHandler)
michael@0 5333 reportDefault(parser, enc, start, end);
michael@0 5334 return 1;
michael@0 5335 }
michael@0 5336 data = poolStoreString(&tempPool,
michael@0 5337 enc,
michael@0 5338 start + enc->minBytesPerChar * 4,
michael@0 5339 end - enc->minBytesPerChar * 3);
michael@0 5340 if (!data)
michael@0 5341 return 0;
michael@0 5342 normalizeLines(data);
michael@0 5343 commentHandler(handlerArg, data);
michael@0 5344 poolClear(&tempPool);
michael@0 5345 return 1;
michael@0 5346 }
michael@0 5347
michael@0 5348 static void
michael@0 5349 reportDefault(XML_Parser parser, const ENCODING *enc,
michael@0 5350 const char *s, const char *end)
michael@0 5351 {
michael@0 5352 if (MUST_CONVERT(enc, s)) {
michael@0 5353 const char **eventPP;
michael@0 5354 const char **eventEndPP;
michael@0 5355 if (enc == encoding) {
michael@0 5356 eventPP = &eventPtr;
michael@0 5357 eventEndPP = &eventEndPtr;
michael@0 5358 }
michael@0 5359 else {
michael@0 5360 eventPP = &(openInternalEntities->internalEventPtr);
michael@0 5361 eventEndPP = &(openInternalEntities->internalEventEndPtr);
michael@0 5362 }
michael@0 5363 do {
michael@0 5364 ICHAR *dataPtr = (ICHAR *)dataBuf;
michael@0 5365 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
michael@0 5366 *eventEndPP = s;
michael@0 5367 defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
michael@0 5368 *eventPP = s;
michael@0 5369 } while (s != end);
michael@0 5370 }
michael@0 5371 else
michael@0 5372 defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
michael@0 5373 }
michael@0 5374
michael@0 5375
michael@0 5376 static int
michael@0 5377 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
michael@0 5378 XML_Bool isId, const XML_Char *value, XML_Parser parser)
michael@0 5379 {
michael@0 5380 DEFAULT_ATTRIBUTE *att;
michael@0 5381 if (value || isId) {
michael@0 5382 /* The handling of default attributes gets messed up if we have
michael@0 5383 a default which duplicates a non-default. */
michael@0 5384 int i;
michael@0 5385 for (i = 0; i < type->nDefaultAtts; i++)
michael@0 5386 if (attId == type->defaultAtts[i].id)
michael@0 5387 return 1;
michael@0 5388 if (isId && !type->idAtt && !attId->xmlns)
michael@0 5389 type->idAtt = attId;
michael@0 5390 }
michael@0 5391 if (type->nDefaultAtts == type->allocDefaultAtts) {
michael@0 5392 if (type->allocDefaultAtts == 0) {
michael@0 5393 type->allocDefaultAtts = 8;
michael@0 5394 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
michael@0 5395 * sizeof(DEFAULT_ATTRIBUTE));
michael@0 5396 if (!type->defaultAtts)
michael@0 5397 return 0;
michael@0 5398 }
michael@0 5399 else {
michael@0 5400 DEFAULT_ATTRIBUTE *temp;
michael@0 5401 int count = type->allocDefaultAtts * 2;
michael@0 5402 temp = (DEFAULT_ATTRIBUTE *)
michael@0 5403 REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
michael@0 5404 if (temp == NULL)
michael@0 5405 return 0;
michael@0 5406 type->allocDefaultAtts = count;
michael@0 5407 type->defaultAtts = temp;
michael@0 5408 }
michael@0 5409 }
michael@0 5410 att = type->defaultAtts + type->nDefaultAtts;
michael@0 5411 att->id = attId;
michael@0 5412 att->value = value;
michael@0 5413 att->isCdata = isCdata;
michael@0 5414 if (!isCdata)
michael@0 5415 attId->maybeTokenized = XML_TRUE;
michael@0 5416 type->nDefaultAtts += 1;
michael@0 5417 return 1;
michael@0 5418 }
michael@0 5419
michael@0 5420 static int
michael@0 5421 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
michael@0 5422 {
michael@0 5423 DTD * const dtd = _dtd; /* save one level of indirection */
michael@0 5424 const XML_Char *name;
michael@0 5425 for (name = elementType->name; *name; name++) {
michael@0 5426 if (*name == XML_T(':')) {
michael@0 5427 PREFIX *prefix;
michael@0 5428 const XML_Char *s;
michael@0 5429 for (s = elementType->name; s != name; s++) {
michael@0 5430 if (!poolAppendChar(&dtd->pool, *s))
michael@0 5431 return 0;
michael@0 5432 }
michael@0 5433 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
michael@0 5434 return 0;
michael@0 5435 prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
michael@0 5436 sizeof(PREFIX));
michael@0 5437 if (!prefix)
michael@0 5438 return 0;
michael@0 5439 if (prefix->name == poolStart(&dtd->pool))
michael@0 5440 poolFinish(&dtd->pool);
michael@0 5441 else
michael@0 5442 poolDiscard(&dtd->pool);
michael@0 5443 elementType->prefix = prefix;
michael@0 5444
michael@0 5445 }
michael@0 5446 }
michael@0 5447 return 1;
michael@0 5448 }
michael@0 5449
michael@0 5450 static ATTRIBUTE_ID *
michael@0 5451 getAttributeId(XML_Parser parser, const ENCODING *enc,
michael@0 5452 const char *start, const char *end)
michael@0 5453 {
michael@0 5454 DTD * const dtd = _dtd; /* save one level of indirection */
michael@0 5455 ATTRIBUTE_ID *id;
michael@0 5456 const XML_Char *name;
michael@0 5457 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
michael@0 5458 return NULL;
michael@0 5459 name = poolStoreString(&dtd->pool, enc, start, end);
michael@0 5460 if (!name)
michael@0 5461 return NULL;
michael@0 5462 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
michael@0 5463 ++name;
michael@0 5464 id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
michael@0 5465 if (!id)
michael@0 5466 return NULL;
michael@0 5467 if (id->name != name)
michael@0 5468 poolDiscard(&dtd->pool);
michael@0 5469 else {
michael@0 5470 poolFinish(&dtd->pool);
michael@0 5471 if (!ns)
michael@0 5472 ;
michael@0 5473 else if (name[0] == XML_T('x')
michael@0 5474 && name[1] == XML_T('m')
michael@0 5475 && name[2] == XML_T('l')
michael@0 5476 && name[3] == XML_T('n')
michael@0 5477 && name[4] == XML_T('s')
michael@0 5478 && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
michael@0 5479 if (name[5] == XML_T('\0'))
michael@0 5480 id->prefix = &dtd->defaultPrefix;
michael@0 5481 else
michael@0 5482 id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
michael@0 5483 id->xmlns = XML_TRUE;
michael@0 5484 }
michael@0 5485 else {
michael@0 5486 int i;
michael@0 5487 for (i = 0; name[i]; i++) {
michael@0 5488 /* attributes without prefix are *not* in the default namespace */
michael@0 5489 if (name[i] == XML_T(':')) {
michael@0 5490 int j;
michael@0 5491 for (j = 0; j < i; j++) {
michael@0 5492 if (!poolAppendChar(&dtd->pool, name[j]))
michael@0 5493 return NULL;
michael@0 5494 }
michael@0 5495 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
michael@0 5496 return NULL;
michael@0 5497 id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
michael@0 5498 sizeof(PREFIX));
michael@0 5499 if (id->prefix->name == poolStart(&dtd->pool))
michael@0 5500 poolFinish(&dtd->pool);
michael@0 5501 else
michael@0 5502 poolDiscard(&dtd->pool);
michael@0 5503 break;
michael@0 5504 }
michael@0 5505 }
michael@0 5506 }
michael@0 5507 }
michael@0 5508 return id;
michael@0 5509 }
michael@0 5510
michael@0 5511 #define CONTEXT_SEP XML_T('\f')
michael@0 5512
michael@0 5513 static const XML_Char *
michael@0 5514 getContext(XML_Parser parser)
michael@0 5515 {
michael@0 5516 DTD * const dtd = _dtd; /* save one level of indirection */
michael@0 5517 HASH_TABLE_ITER iter;
michael@0 5518 XML_Bool needSep = XML_FALSE;
michael@0 5519
michael@0 5520 if (dtd->defaultPrefix.binding) {
michael@0 5521 int i;
michael@0 5522 int len;
michael@0 5523 if (!poolAppendChar(&tempPool, XML_T('=')))
michael@0 5524 return NULL;
michael@0 5525 len = dtd->defaultPrefix.binding->uriLen;
michael@0 5526 if (namespaceSeparator)
michael@0 5527 len--;
michael@0 5528 for (i = 0; i < len; i++)
michael@0 5529 if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
michael@0 5530 return NULL;
michael@0 5531 needSep = XML_TRUE;
michael@0 5532 }
michael@0 5533
michael@0 5534 hashTableIterInit(&iter, &(dtd->prefixes));
michael@0 5535 for (;;) {
michael@0 5536 int i;
michael@0 5537 int len;
michael@0 5538 const XML_Char *s;
michael@0 5539 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
michael@0 5540 if (!prefix)
michael@0 5541 break;
michael@0 5542 if (!prefix->binding)
michael@0 5543 continue;
michael@0 5544 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
michael@0 5545 return NULL;
michael@0 5546 for (s = prefix->name; *s; s++)
michael@0 5547 if (!poolAppendChar(&tempPool, *s))
michael@0 5548 return NULL;
michael@0 5549 if (!poolAppendChar(&tempPool, XML_T('=')))
michael@0 5550 return NULL;
michael@0 5551 len = prefix->binding->uriLen;
michael@0 5552 if (namespaceSeparator)
michael@0 5553 len--;
michael@0 5554 for (i = 0; i < len; i++)
michael@0 5555 if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
michael@0 5556 return NULL;
michael@0 5557 needSep = XML_TRUE;
michael@0 5558 }
michael@0 5559
michael@0 5560
michael@0 5561 hashTableIterInit(&iter, &(dtd->generalEntities));
michael@0 5562 for (;;) {
michael@0 5563 const XML_Char *s;
michael@0 5564 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
michael@0 5565 if (!e)
michael@0 5566 break;
michael@0 5567 if (!e->open)
michael@0 5568 continue;
michael@0 5569 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
michael@0 5570 return NULL;
michael@0 5571 for (s = e->name; *s; s++)
michael@0 5572 if (!poolAppendChar(&tempPool, *s))
michael@0 5573 return 0;
michael@0 5574 needSep = XML_TRUE;
michael@0 5575 }
michael@0 5576
michael@0 5577 if (!poolAppendChar(&tempPool, XML_T('\0')))
michael@0 5578 return NULL;
michael@0 5579 return tempPool.start;
michael@0 5580 }
michael@0 5581
michael@0 5582 static XML_Bool
michael@0 5583 setContext(XML_Parser parser, const XML_Char *context)
michael@0 5584 {
michael@0 5585 DTD * const dtd = _dtd; /* save one level of indirection */
michael@0 5586 const XML_Char *s = context;
michael@0 5587
michael@0 5588 while (*context != XML_T('\0')) {
michael@0 5589 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
michael@0 5590 ENTITY *e;
michael@0 5591 if (!poolAppendChar(&tempPool, XML_T('\0')))
michael@0 5592 return XML_FALSE;
michael@0 5593 e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
michael@0 5594 if (e)
michael@0 5595 e->open = XML_TRUE;
michael@0 5596 if (*s != XML_T('\0'))
michael@0 5597 s++;
michael@0 5598 context = s;
michael@0 5599 poolDiscard(&tempPool);
michael@0 5600 }
michael@0 5601 else if (*s == XML_T('=')) {
michael@0 5602 PREFIX *prefix;
michael@0 5603 if (poolLength(&tempPool) == 0)
michael@0 5604 prefix = &dtd->defaultPrefix;
michael@0 5605 else {
michael@0 5606 if (!poolAppendChar(&tempPool, XML_T('\0')))
michael@0 5607 return XML_FALSE;
michael@0 5608 prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
michael@0 5609 sizeof(PREFIX));
michael@0 5610 if (!prefix)
michael@0 5611 return XML_FALSE;
michael@0 5612 if (prefix->name == poolStart(&tempPool)) {
michael@0 5613 prefix->name = poolCopyString(&dtd->pool, prefix->name);
michael@0 5614 if (!prefix->name)
michael@0 5615 return XML_FALSE;
michael@0 5616 }
michael@0 5617 poolDiscard(&tempPool);
michael@0 5618 }
michael@0 5619 for (context = s + 1;
michael@0 5620 *context != CONTEXT_SEP && *context != XML_T('\0');
michael@0 5621 context++)
michael@0 5622 if (!poolAppendChar(&tempPool, *context))
michael@0 5623 return XML_FALSE;
michael@0 5624 if (!poolAppendChar(&tempPool, XML_T('\0')))
michael@0 5625 return XML_FALSE;
michael@0 5626 if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
michael@0 5627 &inheritedBindings) != XML_ERROR_NONE)
michael@0 5628 return XML_FALSE;
michael@0 5629 poolDiscard(&tempPool);
michael@0 5630 if (*context != XML_T('\0'))
michael@0 5631 ++context;
michael@0 5632 s = context;
michael@0 5633 }
michael@0 5634 else {
michael@0 5635 if (!poolAppendChar(&tempPool, *s))
michael@0 5636 return XML_FALSE;
michael@0 5637 s++;
michael@0 5638 }
michael@0 5639 }
michael@0 5640 return XML_TRUE;
michael@0 5641 }
michael@0 5642
michael@0 5643 static void FASTCALL
michael@0 5644 normalizePublicId(XML_Char *publicId)
michael@0 5645 {
michael@0 5646 XML_Char *p = publicId;
michael@0 5647 XML_Char *s;
michael@0 5648 for (s = publicId; *s; s++) {
michael@0 5649 switch (*s) {
michael@0 5650 case 0x20:
michael@0 5651 case 0xD:
michael@0 5652 case 0xA:
michael@0 5653 if (p != publicId && p[-1] != 0x20)
michael@0 5654 *p++ = 0x20;
michael@0 5655 break;
michael@0 5656 default:
michael@0 5657 *p++ = *s;
michael@0 5658 }
michael@0 5659 }
michael@0 5660 if (p != publicId && p[-1] == 0x20)
michael@0 5661 --p;
michael@0 5662 *p = XML_T('\0');
michael@0 5663 }
michael@0 5664
michael@0 5665 static DTD *
michael@0 5666 dtdCreate(const XML_Memory_Handling_Suite *ms)
michael@0 5667 {
michael@0 5668 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
michael@0 5669 if (p == NULL)
michael@0 5670 return p;
michael@0 5671 poolInit(&(p->pool), ms);
michael@0 5672 poolInit(&(p->entityValuePool), ms);
michael@0 5673 hashTableInit(&(p->generalEntities), ms);
michael@0 5674 hashTableInit(&(p->elementTypes), ms);
michael@0 5675 hashTableInit(&(p->attributeIds), ms);
michael@0 5676 hashTableInit(&(p->prefixes), ms);
michael@0 5677 #ifdef XML_DTD
michael@0 5678 p->paramEntityRead = XML_FALSE;
michael@0 5679 hashTableInit(&(p->paramEntities), ms);
michael@0 5680 #endif /* XML_DTD */
michael@0 5681 p->defaultPrefix.name = NULL;
michael@0 5682 p->defaultPrefix.binding = NULL;
michael@0 5683
michael@0 5684 p->in_eldecl = XML_FALSE;
michael@0 5685 p->scaffIndex = NULL;
michael@0 5686 p->scaffold = NULL;
michael@0 5687 p->scaffLevel = 0;
michael@0 5688 p->scaffSize = 0;
michael@0 5689 p->scaffCount = 0;
michael@0 5690 p->contentStringLen = 0;
michael@0 5691
michael@0 5692 p->keepProcessing = XML_TRUE;
michael@0 5693 p->hasParamEntityRefs = XML_FALSE;
michael@0 5694 p->standalone = XML_FALSE;
michael@0 5695 return p;
michael@0 5696 }
michael@0 5697
michael@0 5698 static void
michael@0 5699 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
michael@0 5700 {
michael@0 5701 HASH_TABLE_ITER iter;
michael@0 5702 hashTableIterInit(&iter, &(p->elementTypes));
michael@0 5703 for (;;) {
michael@0 5704 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
michael@0 5705 if (!e)
michael@0 5706 break;
michael@0 5707 if (e->allocDefaultAtts != 0)
michael@0 5708 ms->free_fcn(e->defaultAtts);
michael@0 5709 }
michael@0 5710 hashTableClear(&(p->generalEntities));
michael@0 5711 #ifdef XML_DTD
michael@0 5712 p->paramEntityRead = XML_FALSE;
michael@0 5713 hashTableClear(&(p->paramEntities));
michael@0 5714 #endif /* XML_DTD */
michael@0 5715 hashTableClear(&(p->elementTypes));
michael@0 5716 hashTableClear(&(p->attributeIds));
michael@0 5717 hashTableClear(&(p->prefixes));
michael@0 5718 poolClear(&(p->pool));
michael@0 5719 poolClear(&(p->entityValuePool));
michael@0 5720 p->defaultPrefix.name = NULL;
michael@0 5721 p->defaultPrefix.binding = NULL;
michael@0 5722
michael@0 5723 p->in_eldecl = XML_FALSE;
michael@0 5724
michael@0 5725 ms->free_fcn(p->scaffIndex);
michael@0 5726 p->scaffIndex = NULL;
michael@0 5727 ms->free_fcn(p->scaffold);
michael@0 5728 p->scaffold = NULL;
michael@0 5729
michael@0 5730 p->scaffLevel = 0;
michael@0 5731 p->scaffSize = 0;
michael@0 5732 p->scaffCount = 0;
michael@0 5733 p->contentStringLen = 0;
michael@0 5734
michael@0 5735 p->keepProcessing = XML_TRUE;
michael@0 5736 p->hasParamEntityRefs = XML_FALSE;
michael@0 5737 p->standalone = XML_FALSE;
michael@0 5738 }
michael@0 5739
michael@0 5740 static void
michael@0 5741 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
michael@0 5742 {
michael@0 5743 HASH_TABLE_ITER iter;
michael@0 5744 hashTableIterInit(&iter, &(p->elementTypes));
michael@0 5745 for (;;) {
michael@0 5746 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
michael@0 5747 if (!e)
michael@0 5748 break;
michael@0 5749 if (e->allocDefaultAtts != 0)
michael@0 5750 ms->free_fcn(e->defaultAtts);
michael@0 5751 }
michael@0 5752 hashTableDestroy(&(p->generalEntities));
michael@0 5753 #ifdef XML_DTD
michael@0 5754 hashTableDestroy(&(p->paramEntities));
michael@0 5755 #endif /* XML_DTD */
michael@0 5756 hashTableDestroy(&(p->elementTypes));
michael@0 5757 hashTableDestroy(&(p->attributeIds));
michael@0 5758 hashTableDestroy(&(p->prefixes));
michael@0 5759 poolDestroy(&(p->pool));
michael@0 5760 poolDestroy(&(p->entityValuePool));
michael@0 5761 if (isDocEntity) {
michael@0 5762 ms->free_fcn(p->scaffIndex);
michael@0 5763 ms->free_fcn(p->scaffold);
michael@0 5764 }
michael@0 5765 ms->free_fcn(p);
michael@0 5766 }
michael@0 5767
michael@0 5768 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
michael@0 5769 The new DTD has already been initialized.
michael@0 5770 */
michael@0 5771 static int
michael@0 5772 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
michael@0 5773 {
michael@0 5774 HASH_TABLE_ITER iter;
michael@0 5775
michael@0 5776 /* Copy the prefix table. */
michael@0 5777
michael@0 5778 hashTableIterInit(&iter, &(oldDtd->prefixes));
michael@0 5779 for (;;) {
michael@0 5780 const XML_Char *name;
michael@0 5781 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
michael@0 5782 if (!oldP)
michael@0 5783 break;
michael@0 5784 name = poolCopyString(&(newDtd->pool), oldP->name);
michael@0 5785 if (!name)
michael@0 5786 return 0;
michael@0 5787 if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
michael@0 5788 return 0;
michael@0 5789 }
michael@0 5790
michael@0 5791 hashTableIterInit(&iter, &(oldDtd->attributeIds));
michael@0 5792
michael@0 5793 /* Copy the attribute id table. */
michael@0 5794
michael@0 5795 for (;;) {
michael@0 5796 ATTRIBUTE_ID *newA;
michael@0 5797 const XML_Char *name;
michael@0 5798 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
michael@0 5799
michael@0 5800 if (!oldA)
michael@0 5801 break;
michael@0 5802 /* Remember to allocate the scratch byte before the name. */
michael@0 5803 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
michael@0 5804 return 0;
michael@0 5805 name = poolCopyString(&(newDtd->pool), oldA->name);
michael@0 5806 if (!name)
michael@0 5807 return 0;
michael@0 5808 ++name;
michael@0 5809 newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
michael@0 5810 sizeof(ATTRIBUTE_ID));
michael@0 5811 if (!newA)
michael@0 5812 return 0;
michael@0 5813 newA->maybeTokenized = oldA->maybeTokenized;
michael@0 5814 if (oldA->prefix) {
michael@0 5815 newA->xmlns = oldA->xmlns;
michael@0 5816 if (oldA->prefix == &oldDtd->defaultPrefix)
michael@0 5817 newA->prefix = &newDtd->defaultPrefix;
michael@0 5818 else
michael@0 5819 newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
michael@0 5820 oldA->prefix->name, 0);
michael@0 5821 }
michael@0 5822 }
michael@0 5823
michael@0 5824 /* Copy the element type table. */
michael@0 5825
michael@0 5826 hashTableIterInit(&iter, &(oldDtd->elementTypes));
michael@0 5827
michael@0 5828 for (;;) {
michael@0 5829 int i;
michael@0 5830 ELEMENT_TYPE *newE;
michael@0 5831 const XML_Char *name;
michael@0 5832 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
michael@0 5833 if (!oldE)
michael@0 5834 break;
michael@0 5835 name = poolCopyString(&(newDtd->pool), oldE->name);
michael@0 5836 if (!name)
michael@0 5837 return 0;
michael@0 5838 newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
michael@0 5839 sizeof(ELEMENT_TYPE));
michael@0 5840 if (!newE)
michael@0 5841 return 0;
michael@0 5842 if (oldE->nDefaultAtts) {
michael@0 5843 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
michael@0 5844 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
michael@0 5845 if (!newE->defaultAtts) {
michael@0 5846 ms->free_fcn(newE);
michael@0 5847 return 0;
michael@0 5848 }
michael@0 5849 }
michael@0 5850 if (oldE->idAtt)
michael@0 5851 newE->idAtt = (ATTRIBUTE_ID *)
michael@0 5852 lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
michael@0 5853 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
michael@0 5854 if (oldE->prefix)
michael@0 5855 newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
michael@0 5856 oldE->prefix->name, 0);
michael@0 5857 for (i = 0; i < newE->nDefaultAtts; i++) {
michael@0 5858 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
michael@0 5859 lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
michael@0 5860 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
michael@0 5861 if (oldE->defaultAtts[i].value) {
michael@0 5862 newE->defaultAtts[i].value
michael@0 5863 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
michael@0 5864 if (!newE->defaultAtts[i].value)
michael@0 5865 return 0;
michael@0 5866 }
michael@0 5867 else
michael@0 5868 newE->defaultAtts[i].value = NULL;
michael@0 5869 }
michael@0 5870 }
michael@0 5871
michael@0 5872 /* Copy the entity tables. */
michael@0 5873 if (!copyEntityTable(&(newDtd->generalEntities),
michael@0 5874 &(newDtd->pool),
michael@0 5875 &(oldDtd->generalEntities)))
michael@0 5876 return 0;
michael@0 5877
michael@0 5878 #ifdef XML_DTD
michael@0 5879 if (!copyEntityTable(&(newDtd->paramEntities),
michael@0 5880 &(newDtd->pool),
michael@0 5881 &(oldDtd->paramEntities)))
michael@0 5882 return 0;
michael@0 5883 newDtd->paramEntityRead = oldDtd->paramEntityRead;
michael@0 5884 #endif /* XML_DTD */
michael@0 5885
michael@0 5886 newDtd->keepProcessing = oldDtd->keepProcessing;
michael@0 5887 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
michael@0 5888 newDtd->standalone = oldDtd->standalone;
michael@0 5889
michael@0 5890 /* Don't want deep copying for scaffolding */
michael@0 5891 newDtd->in_eldecl = oldDtd->in_eldecl;
michael@0 5892 newDtd->scaffold = oldDtd->scaffold;
michael@0 5893 newDtd->contentStringLen = oldDtd->contentStringLen;
michael@0 5894 newDtd->scaffSize = oldDtd->scaffSize;
michael@0 5895 newDtd->scaffLevel = oldDtd->scaffLevel;
michael@0 5896 newDtd->scaffIndex = oldDtd->scaffIndex;
michael@0 5897
michael@0 5898 return 1;
michael@0 5899 } /* End dtdCopy */
michael@0 5900
michael@0 5901 static int
michael@0 5902 copyEntityTable(HASH_TABLE *newTable,
michael@0 5903 STRING_POOL *newPool,
michael@0 5904 const HASH_TABLE *oldTable)
michael@0 5905 {
michael@0 5906 HASH_TABLE_ITER iter;
michael@0 5907 const XML_Char *cachedOldBase = NULL;
michael@0 5908 const XML_Char *cachedNewBase = NULL;
michael@0 5909
michael@0 5910 hashTableIterInit(&iter, oldTable);
michael@0 5911
michael@0 5912 for (;;) {
michael@0 5913 ENTITY *newE;
michael@0 5914 const XML_Char *name;
michael@0 5915 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
michael@0 5916 if (!oldE)
michael@0 5917 break;
michael@0 5918 name = poolCopyString(newPool, oldE->name);
michael@0 5919 if (!name)
michael@0 5920 return 0;
michael@0 5921 newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
michael@0 5922 if (!newE)
michael@0 5923 return 0;
michael@0 5924 if (oldE->systemId) {
michael@0 5925 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
michael@0 5926 if (!tem)
michael@0 5927 return 0;
michael@0 5928 newE->systemId = tem;
michael@0 5929 if (oldE->base) {
michael@0 5930 if (oldE->base == cachedOldBase)
michael@0 5931 newE->base = cachedNewBase;
michael@0 5932 else {
michael@0 5933 cachedOldBase = oldE->base;
michael@0 5934 tem = poolCopyString(newPool, cachedOldBase);
michael@0 5935 if (!tem)
michael@0 5936 return 0;
michael@0 5937 cachedNewBase = newE->base = tem;
michael@0 5938 }
michael@0 5939 }
michael@0 5940 if (oldE->publicId) {
michael@0 5941 tem = poolCopyString(newPool, oldE->publicId);
michael@0 5942 if (!tem)
michael@0 5943 return 0;
michael@0 5944 newE->publicId = tem;
michael@0 5945 }
michael@0 5946 }
michael@0 5947 else {
michael@0 5948 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
michael@0 5949 oldE->textLen);
michael@0 5950 if (!tem)
michael@0 5951 return 0;
michael@0 5952 newE->textPtr = tem;
michael@0 5953 newE->textLen = oldE->textLen;
michael@0 5954 }
michael@0 5955 if (oldE->notation) {
michael@0 5956 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
michael@0 5957 if (!tem)
michael@0 5958 return 0;
michael@0 5959 newE->notation = tem;
michael@0 5960 }
michael@0 5961 newE->is_param = oldE->is_param;
michael@0 5962 newE->is_internal = oldE->is_internal;
michael@0 5963 }
michael@0 5964 return 1;
michael@0 5965 }
michael@0 5966
michael@0 5967 #define INIT_POWER 6
michael@0 5968
michael@0 5969 static XML_Bool FASTCALL
michael@0 5970 keyeq(KEY s1, KEY s2)
michael@0 5971 {
michael@0 5972 for (; *s1 == *s2; s1++, s2++)
michael@0 5973 if (*s1 == 0)
michael@0 5974 return XML_TRUE;
michael@0 5975 return XML_FALSE;
michael@0 5976 }
michael@0 5977
michael@0 5978 static unsigned long FASTCALL
michael@0 5979 hash(KEY s)
michael@0 5980 {
michael@0 5981 unsigned long h = 0;
michael@0 5982 while (*s)
michael@0 5983 h = CHAR_HASH(h, *s++);
michael@0 5984 return h;
michael@0 5985 }
michael@0 5986
michael@0 5987 static NAMED *
michael@0 5988 lookup(HASH_TABLE *table, KEY name, size_t createSize)
michael@0 5989 {
michael@0 5990 size_t i;
michael@0 5991 if (table->size == 0) {
michael@0 5992 size_t tsize;
michael@0 5993 if (!createSize)
michael@0 5994 return NULL;
michael@0 5995 table->power = INIT_POWER;
michael@0 5996 /* table->size is a power of 2 */
michael@0 5997 table->size = (size_t)1 << INIT_POWER;
michael@0 5998 tsize = table->size * sizeof(NAMED *);
michael@0 5999 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
michael@0 6000 if (!table->v) {
michael@0 6001 table->size = 0;
michael@0 6002 return NULL;
michael@0 6003 }
michael@0 6004 memset(table->v, 0, tsize);
michael@0 6005 i = hash(name) & ((unsigned long)table->size - 1);
michael@0 6006 }
michael@0 6007 else {
michael@0 6008 unsigned long h = hash(name);
michael@0 6009 unsigned long mask = (unsigned long)table->size - 1;
michael@0 6010 unsigned char step = 0;
michael@0 6011 i = h & mask;
michael@0 6012 while (table->v[i]) {
michael@0 6013 if (keyeq(name, table->v[i]->name))
michael@0 6014 return table->v[i];
michael@0 6015 if (!step)
michael@0 6016 step = PROBE_STEP(h, mask, table->power);
michael@0 6017 i < step ? (i += table->size - step) : (i -= step);
michael@0 6018 }
michael@0 6019 if (!createSize)
michael@0 6020 return NULL;
michael@0 6021
michael@0 6022 /* check for overflow (table is half full) */
michael@0 6023 if (table->used >> (table->power - 1)) {
michael@0 6024 unsigned char newPower = table->power + 1;
michael@0 6025 size_t newSize = (size_t)1 << newPower;
michael@0 6026 unsigned long newMask = (unsigned long)newSize - 1;
michael@0 6027 size_t tsize = newSize * sizeof(NAMED *);
michael@0 6028 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
michael@0 6029 if (!newV)
michael@0 6030 return NULL;
michael@0 6031 memset(newV, 0, tsize);
michael@0 6032 for (i = 0; i < table->size; i++)
michael@0 6033 if (table->v[i]) {
michael@0 6034 unsigned long newHash = hash(table->v[i]->name);
michael@0 6035 size_t j = newHash & newMask;
michael@0 6036 step = 0;
michael@0 6037 while (newV[j]) {
michael@0 6038 if (!step)
michael@0 6039 step = PROBE_STEP(newHash, newMask, newPower);
michael@0 6040 j < step ? (j += newSize - step) : (j -= step);
michael@0 6041 }
michael@0 6042 newV[j] = table->v[i];
michael@0 6043 }
michael@0 6044 table->mem->free_fcn(table->v);
michael@0 6045 table->v = newV;
michael@0 6046 table->power = newPower;
michael@0 6047 table->size = newSize;
michael@0 6048 i = h & newMask;
michael@0 6049 step = 0;
michael@0 6050 while (table->v[i]) {
michael@0 6051 if (!step)
michael@0 6052 step = PROBE_STEP(h, newMask, newPower);
michael@0 6053 i < step ? (i += newSize - step) : (i -= step);
michael@0 6054 }
michael@0 6055 }
michael@0 6056 }
michael@0 6057 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
michael@0 6058 if (!table->v[i])
michael@0 6059 return NULL;
michael@0 6060 memset(table->v[i], 0, createSize);
michael@0 6061 table->v[i]->name = name;
michael@0 6062 (table->used)++;
michael@0 6063 return table->v[i];
michael@0 6064 }
michael@0 6065
michael@0 6066 static void FASTCALL
michael@0 6067 hashTableClear(HASH_TABLE *table)
michael@0 6068 {
michael@0 6069 size_t i;
michael@0 6070 for (i = 0; i < table->size; i++) {
michael@0 6071 table->mem->free_fcn(table->v[i]);
michael@0 6072 table->v[i] = NULL;
michael@0 6073 }
michael@0 6074 table->used = 0;
michael@0 6075 }
michael@0 6076
michael@0 6077 static void FASTCALL
michael@0 6078 hashTableDestroy(HASH_TABLE *table)
michael@0 6079 {
michael@0 6080 size_t i;
michael@0 6081 for (i = 0; i < table->size; i++)
michael@0 6082 table->mem->free_fcn(table->v[i]);
michael@0 6083 table->mem->free_fcn(table->v);
michael@0 6084 }
michael@0 6085
michael@0 6086 static void FASTCALL
michael@0 6087 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
michael@0 6088 {
michael@0 6089 p->power = 0;
michael@0 6090 p->size = 0;
michael@0 6091 p->used = 0;
michael@0 6092 p->v = NULL;
michael@0 6093 p->mem = ms;
michael@0 6094 }
michael@0 6095
michael@0 6096 static void FASTCALL
michael@0 6097 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
michael@0 6098 {
michael@0 6099 iter->p = table->v;
michael@0 6100 iter->end = iter->p + table->size;
michael@0 6101 }
michael@0 6102
michael@0 6103 static NAMED * FASTCALL
michael@0 6104 hashTableIterNext(HASH_TABLE_ITER *iter)
michael@0 6105 {
michael@0 6106 while (iter->p != iter->end) {
michael@0 6107 NAMED *tem = *(iter->p)++;
michael@0 6108 if (tem)
michael@0 6109 return tem;
michael@0 6110 }
michael@0 6111 return NULL;
michael@0 6112 }
michael@0 6113
michael@0 6114 static void FASTCALL
michael@0 6115 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
michael@0 6116 {
michael@0 6117 pool->blocks = NULL;
michael@0 6118 pool->freeBlocks = NULL;
michael@0 6119 pool->start = NULL;
michael@0 6120 pool->ptr = NULL;
michael@0 6121 pool->end = NULL;
michael@0 6122 pool->mem = ms;
michael@0 6123 }
michael@0 6124
michael@0 6125 static void FASTCALL
michael@0 6126 poolClear(STRING_POOL *pool)
michael@0 6127 {
michael@0 6128 if (!pool->freeBlocks)
michael@0 6129 pool->freeBlocks = pool->blocks;
michael@0 6130 else {
michael@0 6131 BLOCK *p = pool->blocks;
michael@0 6132 while (p) {
michael@0 6133 BLOCK *tem = p->next;
michael@0 6134 p->next = pool->freeBlocks;
michael@0 6135 pool->freeBlocks = p;
michael@0 6136 p = tem;
michael@0 6137 }
michael@0 6138 }
michael@0 6139 pool->blocks = NULL;
michael@0 6140 pool->start = NULL;
michael@0 6141 pool->ptr = NULL;
michael@0 6142 pool->end = NULL;
michael@0 6143 }
michael@0 6144
michael@0 6145 static void FASTCALL
michael@0 6146 poolDestroy(STRING_POOL *pool)
michael@0 6147 {
michael@0 6148 BLOCK *p = pool->blocks;
michael@0 6149 while (p) {
michael@0 6150 BLOCK *tem = p->next;
michael@0 6151 pool->mem->free_fcn(p);
michael@0 6152 p = tem;
michael@0 6153 }
michael@0 6154 p = pool->freeBlocks;
michael@0 6155 while (p) {
michael@0 6156 BLOCK *tem = p->next;
michael@0 6157 pool->mem->free_fcn(p);
michael@0 6158 p = tem;
michael@0 6159 }
michael@0 6160 }
michael@0 6161
michael@0 6162 static XML_Char *
michael@0 6163 poolAppend(STRING_POOL *pool, const ENCODING *enc,
michael@0 6164 const char *ptr, const char *end)
michael@0 6165 {
michael@0 6166 if (!pool->ptr && !poolGrow(pool))
michael@0 6167 return NULL;
michael@0 6168 for (;;) {
michael@0 6169 XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
michael@0 6170 if (ptr == end)
michael@0 6171 break;
michael@0 6172 if (!poolGrow(pool))
michael@0 6173 return NULL;
michael@0 6174 }
michael@0 6175 return pool->start;
michael@0 6176 }
michael@0 6177
michael@0 6178 static const XML_Char * FASTCALL
michael@0 6179 poolCopyString(STRING_POOL *pool, const XML_Char *s)
michael@0 6180 {
michael@0 6181 do {
michael@0 6182 if (!poolAppendChar(pool, *s))
michael@0 6183 return NULL;
michael@0 6184 } while (*s++);
michael@0 6185 s = pool->start;
michael@0 6186 poolFinish(pool);
michael@0 6187 return s;
michael@0 6188 }
michael@0 6189
michael@0 6190 static const XML_Char *
michael@0 6191 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
michael@0 6192 {
michael@0 6193 if (!pool->ptr && !poolGrow(pool))
michael@0 6194 return NULL;
michael@0 6195 for (; n > 0; --n, s++) {
michael@0 6196 if (!poolAppendChar(pool, *s))
michael@0 6197 return NULL;
michael@0 6198 }
michael@0 6199 s = pool->start;
michael@0 6200 poolFinish(pool);
michael@0 6201 return s;
michael@0 6202 }
michael@0 6203
michael@0 6204 static const XML_Char * FASTCALL
michael@0 6205 poolAppendString(STRING_POOL *pool, const XML_Char *s)
michael@0 6206 {
michael@0 6207 while (*s) {
michael@0 6208 if (!poolAppendChar(pool, *s))
michael@0 6209 return NULL;
michael@0 6210 s++;
michael@0 6211 }
michael@0 6212 return pool->start;
michael@0 6213 }
michael@0 6214
michael@0 6215 static XML_Char *
michael@0 6216 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
michael@0 6217 const char *ptr, const char *end)
michael@0 6218 {
michael@0 6219 if (!poolAppend(pool, enc, ptr, end))
michael@0 6220 return NULL;
michael@0 6221 if (pool->ptr == pool->end && !poolGrow(pool))
michael@0 6222 return NULL;
michael@0 6223 *(pool->ptr)++ = 0;
michael@0 6224 return pool->start;
michael@0 6225 }
michael@0 6226
michael@0 6227 static XML_Bool FASTCALL
michael@0 6228 poolGrow(STRING_POOL *pool)
michael@0 6229 {
michael@0 6230 if (pool->freeBlocks) {
michael@0 6231 if (pool->start == 0) {
michael@0 6232 pool->blocks = pool->freeBlocks;
michael@0 6233 pool->freeBlocks = pool->freeBlocks->next;
michael@0 6234 pool->blocks->next = NULL;
michael@0 6235 pool->start = pool->blocks->s;
michael@0 6236 pool->end = pool->start + pool->blocks->size;
michael@0 6237 pool->ptr = pool->start;
michael@0 6238 return XML_TRUE;
michael@0 6239 }
michael@0 6240 if (pool->end - pool->start < pool->freeBlocks->size) {
michael@0 6241 BLOCK *tem = pool->freeBlocks->next;
michael@0 6242 pool->freeBlocks->next = pool->blocks;
michael@0 6243 pool->blocks = pool->freeBlocks;
michael@0 6244 pool->freeBlocks = tem;
michael@0 6245 memcpy(pool->blocks->s, pool->start,
michael@0 6246 (pool->end - pool->start) * sizeof(XML_Char));
michael@0 6247 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
michael@0 6248 pool->start = pool->blocks->s;
michael@0 6249 pool->end = pool->start + pool->blocks->size;
michael@0 6250 return XML_TRUE;
michael@0 6251 }
michael@0 6252 }
michael@0 6253 if (pool->blocks && pool->start == pool->blocks->s) {
michael@0 6254 int blockSize = (int)(pool->end - pool->start)*2;
michael@0 6255 pool->blocks = (BLOCK *)
michael@0 6256 pool->mem->realloc_fcn(pool->blocks,
michael@0 6257 (offsetof(BLOCK, s)
michael@0 6258 + blockSize * sizeof(XML_Char)));
michael@0 6259 if (pool->blocks == NULL)
michael@0 6260 return XML_FALSE;
michael@0 6261 pool->blocks->size = blockSize;
michael@0 6262 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
michael@0 6263 pool->start = pool->blocks->s;
michael@0 6264 pool->end = pool->start + blockSize;
michael@0 6265 }
michael@0 6266 else {
michael@0 6267 BLOCK *tem;
michael@0 6268 int blockSize = (int)(pool->end - pool->start);
michael@0 6269 if (blockSize < INIT_BLOCK_SIZE)
michael@0 6270 blockSize = INIT_BLOCK_SIZE;
michael@0 6271 else
michael@0 6272 blockSize *= 2;
michael@0 6273 tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
michael@0 6274 + blockSize * sizeof(XML_Char));
michael@0 6275 if (!tem)
michael@0 6276 return XML_FALSE;
michael@0 6277 tem->size = blockSize;
michael@0 6278 tem->next = pool->blocks;
michael@0 6279 pool->blocks = tem;
michael@0 6280 if (pool->ptr != pool->start)
michael@0 6281 memcpy(tem->s, pool->start,
michael@0 6282 (pool->ptr - pool->start) * sizeof(XML_Char));
michael@0 6283 pool->ptr = tem->s + (pool->ptr - pool->start);
michael@0 6284 pool->start = tem->s;
michael@0 6285 pool->end = tem->s + blockSize;
michael@0 6286 }
michael@0 6287 return XML_TRUE;
michael@0 6288 }
michael@0 6289
michael@0 6290 static int FASTCALL
michael@0 6291 nextScaffoldPart(XML_Parser parser)
michael@0 6292 {
michael@0 6293 DTD * const dtd = _dtd; /* save one level of indirection */
michael@0 6294 CONTENT_SCAFFOLD * me;
michael@0 6295 int next;
michael@0 6296
michael@0 6297 if (!dtd->scaffIndex) {
michael@0 6298 dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
michael@0 6299 if (!dtd->scaffIndex)
michael@0 6300 return -1;
michael@0 6301 dtd->scaffIndex[0] = 0;
michael@0 6302 }
michael@0 6303
michael@0 6304 if (dtd->scaffCount >= dtd->scaffSize) {
michael@0 6305 CONTENT_SCAFFOLD *temp;
michael@0 6306 if (dtd->scaffold) {
michael@0 6307 temp = (CONTENT_SCAFFOLD *)
michael@0 6308 REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
michael@0 6309 if (temp == NULL)
michael@0 6310 return -1;
michael@0 6311 dtd->scaffSize *= 2;
michael@0 6312 }
michael@0 6313 else {
michael@0 6314 temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
michael@0 6315 * sizeof(CONTENT_SCAFFOLD));
michael@0 6316 if (temp == NULL)
michael@0 6317 return -1;
michael@0 6318 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
michael@0 6319 }
michael@0 6320 dtd->scaffold = temp;
michael@0 6321 }
michael@0 6322 next = dtd->scaffCount++;
michael@0 6323 me = &dtd->scaffold[next];
michael@0 6324 if (dtd->scaffLevel) {
michael@0 6325 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
michael@0 6326 if (parent->lastchild) {
michael@0 6327 dtd->scaffold[parent->lastchild].nextsib = next;
michael@0 6328 }
michael@0 6329 if (!parent->childcnt)
michael@0 6330 parent->firstchild = next;
michael@0 6331 parent->lastchild = next;
michael@0 6332 parent->childcnt++;
michael@0 6333 }
michael@0 6334 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
michael@0 6335 return next;
michael@0 6336 }
michael@0 6337
michael@0 6338 static void
michael@0 6339 build_node(XML_Parser parser,
michael@0 6340 int src_node,
michael@0 6341 XML_Content *dest,
michael@0 6342 XML_Content **contpos,
michael@0 6343 XML_Char **strpos)
michael@0 6344 {
michael@0 6345 DTD * const dtd = _dtd; /* save one level of indirection */
michael@0 6346 dest->type = dtd->scaffold[src_node].type;
michael@0 6347 dest->quant = dtd->scaffold[src_node].quant;
michael@0 6348 if (dest->type == XML_CTYPE_NAME) {
michael@0 6349 const XML_Char *src;
michael@0 6350 dest->name = *strpos;
michael@0 6351 src = dtd->scaffold[src_node].name;
michael@0 6352 for (;;) {
michael@0 6353 *(*strpos)++ = *src;
michael@0 6354 if (!*src)
michael@0 6355 break;
michael@0 6356 src++;
michael@0 6357 }
michael@0 6358 dest->numchildren = 0;
michael@0 6359 dest->children = NULL;
michael@0 6360 }
michael@0 6361 else {
michael@0 6362 unsigned int i;
michael@0 6363 int cn;
michael@0 6364 dest->numchildren = dtd->scaffold[src_node].childcnt;
michael@0 6365 dest->children = *contpos;
michael@0 6366 *contpos += dest->numchildren;
michael@0 6367 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
michael@0 6368 i < dest->numchildren;
michael@0 6369 i++, cn = dtd->scaffold[cn].nextsib) {
michael@0 6370 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
michael@0 6371 }
michael@0 6372 dest->name = NULL;
michael@0 6373 }
michael@0 6374 }
michael@0 6375
michael@0 6376 static XML_Content *
michael@0 6377 build_model (XML_Parser parser)
michael@0 6378 {
michael@0 6379 DTD * const dtd = _dtd; /* save one level of indirection */
michael@0 6380 XML_Content *ret;
michael@0 6381 XML_Content *cpos;
michael@0 6382 XML_Char * str;
michael@0 6383 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
michael@0 6384 + (dtd->contentStringLen * sizeof(XML_Char)));
michael@0 6385
michael@0 6386 ret = (XML_Content *)MALLOC(allocsize);
michael@0 6387 if (!ret)
michael@0 6388 return NULL;
michael@0 6389
michael@0 6390 str = (XML_Char *) (&ret[dtd->scaffCount]);
michael@0 6391 cpos = &ret[1];
michael@0 6392
michael@0 6393 build_node(parser, 0, ret, &cpos, &str);
michael@0 6394 return ret;
michael@0 6395 }
michael@0 6396
michael@0 6397 static ELEMENT_TYPE *
michael@0 6398 getElementType(XML_Parser parser,
michael@0 6399 const ENCODING *enc,
michael@0 6400 const char *ptr,
michael@0 6401 const char *end)
michael@0 6402 {
michael@0 6403 DTD * const dtd = _dtd; /* save one level of indirection */
michael@0 6404 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
michael@0 6405 ELEMENT_TYPE *ret;
michael@0 6406
michael@0 6407 if (!name)
michael@0 6408 return NULL;
michael@0 6409 ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
michael@0 6410 if (!ret)
michael@0 6411 return NULL;
michael@0 6412 if (ret->name != name)
michael@0 6413 poolDiscard(&dtd->pool);
michael@0 6414 else {
michael@0 6415 poolFinish(&dtd->pool);
michael@0 6416 if (!setElementTypePrefix(parser, ret))
michael@0 6417 return NULL;
michael@0 6418 }
michael@0 6419 return ret;
michael@0 6420 }

mercurial