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