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