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