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