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