bzip2: Ignore 'unused but set' errors - we trust upstream.
[AROS.git] / workbench / libs / expat / xmlparse.c
blob5b3801edf8caf5c034ffa91fe151dd2921e85753
1 /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
2 See the file COPYING for copying permission.
3 */
5 #include "amigaconfig.h"
7 #include <stddef.h>
8 #include <string.h> /* memset(), memcpy() */
9 //#include <assert.h>
10 #define assert(...)
12 #define XML_BUILDING_EXPAT 1
14 #ifdef COMPILED_FROM_DSP
15 #include "winconfig.h"
16 #elif defined(MACOS_CLASSIC)
17 #include "macconfig.h"
18 #elif defined(__amigaos4__)
19 #include "amigaconfig.h"
20 #elif defined(__WATCOMC__)
21 #include "watcomconfig.h"
22 #elif defined(HAVE_EXPAT_CONFIG_H)
23 #include <expat_config.h>
24 #endif /* ndef COMPILED_FROM_DSP */
26 #include "ascii.h"
27 #include "expat.h"
29 #ifdef XML_UNICODE
30 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
31 #define XmlConvert XmlUtf16Convert
32 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
33 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
34 #define XmlEncode XmlUtf16Encode
35 /* Using pointer subtraction to convert to integer type. */
36 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
37 typedef unsigned short ICHAR;
38 #else
39 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
40 #define XmlConvert XmlUtf8Convert
41 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
42 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
43 #define XmlEncode XmlUtf8Encode
44 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
45 typedef char ICHAR;
46 #endif
49 #ifndef XML_NS
51 #define XmlInitEncodingNS XmlInitEncoding
52 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
53 #undef XmlGetInternalEncodingNS
54 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
55 #define XmlParseXmlDeclNS XmlParseXmlDecl
57 #endif
59 #ifdef XML_UNICODE
61 #ifdef XML_UNICODE_WCHAR_T
62 #define XML_T(x) (const wchar_t)x
63 #define XML_L(x) L ## x
64 #else
65 #define XML_T(x) (const unsigned short)x
66 #define XML_L(x) x
67 #endif
69 #else
71 #define XML_T(x) x
72 #define XML_L(x) x
74 #endif
76 /* Round up n to be a multiple of sz, where sz is a power of 2. */
77 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
79 /* Handle the case where memmove() doesn't exist. */
80 #ifndef HAVE_MEMMOVE
81 #ifdef HAVE_BCOPY
82 #define memmove(d,s,l) bcopy((s),(d),(l))
83 #else
84 #error memmove does not exist on this platform, nor is a substitute available
85 #endif /* HAVE_BCOPY */
86 #endif /* HAVE_MEMMOVE */
88 #include "internal.h"
89 #include "xmltok.h"
90 #include "xmlrole.h"
92 typedef const XML_Char *KEY;
94 typedef struct {
95 KEY name;
96 } NAMED;
98 typedef struct {
99 NAMED **v;
100 unsigned char power;
101 size_t size;
102 size_t used;
103 const XML_Memory_Handling_Suite *mem;
104 } HASH_TABLE;
106 /* Basic character hash algorithm, taken from Python's string hash:
107 h = h * 1000003 ^ character, the constant being a prime number.
110 #ifdef XML_UNICODE
111 #define CHAR_HASH(h, c) \
112 (((h) * 0xF4243) ^ (unsigned short)(c))
113 #else
114 #define CHAR_HASH(h, c) \
115 (((h) * 0xF4243) ^ (unsigned char)(c))
116 #endif
118 /* For probing (after a collision) we need a step size relative prime
119 to the hash table size, which is a power of 2. We use double-hashing,
120 since we can calculate a second hash value cheaply by taking those bits
121 of the first hash value that were discarded (masked out) when the table
122 index was calculated: index = hash & mask, where mask = table->size - 1.
123 We limit the maximum step size to table->size / 4 (mask >> 2) and make
124 it odd, since odd numbers are always relative prime to a power of 2.
126 #define SECOND_HASH(hash, mask, power) \
127 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
128 #define PROBE_STEP(hash, mask, power) \
129 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
131 typedef struct {
132 NAMED **p;
133 NAMED **end;
134 } HASH_TABLE_ITER;
136 #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
137 #define INIT_DATA_BUF_SIZE 1024
138 #define INIT_ATTS_SIZE 16
139 #define INIT_ATTS_VERSION 0xFFFFFFFF
140 #define INIT_BLOCK_SIZE 1024
141 #define INIT_BUFFER_SIZE 1024
143 #define EXPAND_SPARE 24
145 typedef struct binding {
146 struct prefix *prefix;
147 struct binding *nextTagBinding;
148 struct binding *prevPrefixBinding;
149 const struct attribute_id *attId;
150 XML_Char *uri;
151 int uriLen;
152 int uriAlloc;
153 } BINDING;
155 typedef struct prefix {
156 const XML_Char *name;
157 BINDING *binding;
158 } PREFIX;
160 typedef struct {
161 const XML_Char *str;
162 const XML_Char *localPart;
163 const XML_Char *prefix;
164 int strLen;
165 int uriLen;
166 int prefixLen;
167 } TAG_NAME;
169 /* TAG represents an open element.
170 The name of the element is stored in both the document and API
171 encodings. The memory buffer 'buf' is a separately-allocated
172 memory area which stores the name. During the XML_Parse()/
173 XMLParseBuffer() when the element is open, the memory for the 'raw'
174 version of the name (in the document encoding) is shared with the
175 document buffer. If the element is open across calls to
176 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
177 contain the 'raw' name as well.
179 A parser re-uses these structures, maintaining a list of allocated
180 TAG objects in a free list.
182 typedef struct tag {
183 struct tag *parent; /* parent of this element */
184 const char *rawName; /* tagName in the original encoding */
185 int rawNameLength;
186 TAG_NAME name; /* tagName in the API encoding */
187 char *buf; /* buffer for name components */
188 char *bufEnd; /* end of the buffer */
189 BINDING *bindings;
190 } TAG;
192 typedef struct {
193 const XML_Char *name;
194 const XML_Char *textPtr;
195 int textLen; /* length in XML_Chars */
196 int processed; /* # of processed bytes - when suspended */
197 const XML_Char *systemId;
198 const XML_Char *base;
199 const XML_Char *publicId;
200 const XML_Char *notation;
201 XML_Bool open;
202 XML_Bool is_param;
203 XML_Bool is_internal; /* true if declared in internal subset outside PE */
204 } ENTITY;
206 typedef struct {
207 enum XML_Content_Type type;
208 enum XML_Content_Quant quant;
209 const XML_Char * name;
210 int firstchild;
211 int lastchild;
212 int childcnt;
213 int nextsib;
214 } CONTENT_SCAFFOLD;
216 #define INIT_SCAFFOLD_ELEMENTS 32
218 typedef struct block {
219 struct block *next;
220 int size;
221 XML_Char s[1];
222 } BLOCK;
224 typedef struct {
225 BLOCK *blocks;
226 BLOCK *freeBlocks;
227 const XML_Char *end;
228 XML_Char *ptr;
229 XML_Char *start;
230 const XML_Memory_Handling_Suite *mem;
231 } STRING_POOL;
233 /* The XML_Char before the name is used to determine whether
234 an attribute has been specified. */
235 typedef struct attribute_id {
236 XML_Char *name;
237 PREFIX *prefix;
238 XML_Bool maybeTokenized;
239 XML_Bool xmlns;
240 } ATTRIBUTE_ID;
242 typedef struct {
243 const ATTRIBUTE_ID *id;
244 XML_Bool isCdata;
245 const XML_Char *value;
246 } DEFAULT_ATTRIBUTE;
248 typedef struct {
249 unsigned long version;
250 unsigned long hash;
251 const XML_Char *uriName;
252 } NS_ATT;
254 typedef struct {
255 const XML_Char *name;
256 PREFIX *prefix;
257 const ATTRIBUTE_ID *idAtt;
258 int nDefaultAtts;
259 int allocDefaultAtts;
260 DEFAULT_ATTRIBUTE *defaultAtts;
261 } ELEMENT_TYPE;
263 typedef struct {
264 HASH_TABLE generalEntities;
265 HASH_TABLE elementTypes;
266 HASH_TABLE attributeIds;
267 HASH_TABLE prefixes;
268 STRING_POOL pool;
269 STRING_POOL entityValuePool;
270 /* false once a parameter entity reference has been skipped */
271 XML_Bool keepProcessing;
272 /* true once an internal or external PE reference has been encountered;
273 this includes the reference to an external subset */
274 XML_Bool hasParamEntityRefs;
275 XML_Bool standalone;
276 #ifdef XML_DTD
277 /* indicates if external PE has been read */
278 XML_Bool paramEntityRead;
279 HASH_TABLE paramEntities;
280 #endif /* XML_DTD */
281 PREFIX defaultPrefix;
282 /* === scaffolding for building content model === */
283 XML_Bool in_eldecl;
284 CONTENT_SCAFFOLD *scaffold;
285 unsigned contentStringLen;
286 unsigned scaffSize;
287 unsigned scaffCount;
288 int scaffLevel;
289 int *scaffIndex;
290 } DTD;
292 typedef struct open_internal_entity {
293 const char *internalEventPtr;
294 const char *internalEventEndPtr;
295 struct open_internal_entity *next;
296 ENTITY *entity;
297 int startTagLevel;
298 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
299 } OPEN_INTERNAL_ENTITY;
301 typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
302 const char *start,
303 const char *end,
304 const char **endPtr);
306 static Processor prologProcessor;
307 static Processor prologInitProcessor;
308 static Processor contentProcessor;
309 static Processor cdataSectionProcessor;
310 #ifdef XML_DTD
311 static Processor ignoreSectionProcessor;
312 static Processor externalParEntProcessor;
313 static Processor externalParEntInitProcessor;
314 static Processor entityValueProcessor;
315 static Processor entityValueInitProcessor;
316 #endif /* XML_DTD */
317 static Processor epilogProcessor;
318 static Processor errorProcessor;
319 static Processor externalEntityInitProcessor;
320 static Processor externalEntityInitProcessor2;
321 static Processor externalEntityInitProcessor3;
322 static Processor externalEntityContentProcessor;
323 static Processor internalEntityProcessor;
325 static enum XML_Error
326 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
327 static enum XML_Error
328 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
329 const char *s, const char *next);
330 static enum XML_Error
331 initializeEncoding(XML_Parser parser);
332 static enum XML_Error
333 doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
334 const char *end, int tok, const char *next, const char **nextPtr,
335 XML_Bool haveMore);
336 static enum XML_Error
337 processInternalEntity(XML_Parser parser, ENTITY *entity,
338 XML_Bool betweenDecl);
339 static enum XML_Error
340 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
341 const char *start, const char *end, const char **endPtr,
342 XML_Bool haveMore);
343 static enum XML_Error
344 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
345 const char *end, const char **nextPtr, XML_Bool haveMore);
346 #ifdef XML_DTD
347 static enum XML_Error
348 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
349 const char *end, const char **nextPtr, XML_Bool haveMore);
350 #endif /* XML_DTD */
352 static enum XML_Error
353 storeAtts(XML_Parser parser, const ENCODING *, const char *s,
354 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
355 static enum XML_Error
356 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
357 const XML_Char *uri, BINDING **bindingsPtr);
358 static int
359 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
360 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
361 static enum XML_Error
362 storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
363 const char *, const char *, STRING_POOL *);
364 static enum XML_Error
365 appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
366 const char *, const char *, STRING_POOL *);
367 static ATTRIBUTE_ID *
368 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
369 const char *end);
370 static int
371 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
372 static enum XML_Error
373 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
374 const char *end);
375 static int
376 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
377 const char *start, const char *end);
378 static int
379 reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
380 const char *end);
381 static void
382 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
383 const char *end);
385 static const XML_Char * getContext(XML_Parser parser);
386 static XML_Bool
387 setContext(XML_Parser parser, const XML_Char *context);
389 static void FASTCALL normalizePublicId(XML_Char *s);
391 static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
392 /* do not call if parentParser != NULL */
393 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
394 static void
395 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
396 static int
397 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
398 static int
399 copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
401 static NAMED *
402 lookup(HASH_TABLE *table, KEY name, size_t createSize);
403 static void FASTCALL
404 hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
405 static void FASTCALL hashTableClear(HASH_TABLE *);
406 static void FASTCALL hashTableDestroy(HASH_TABLE *);
407 static void FASTCALL
408 hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
409 static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
411 static void FASTCALL
412 poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
413 static void FASTCALL poolClear(STRING_POOL *);
414 static void FASTCALL poolDestroy(STRING_POOL *);
415 static XML_Char *
416 poolAppend(STRING_POOL *pool, const ENCODING *enc,
417 const char *ptr, const char *end);
418 static XML_Char *
419 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
420 const char *ptr, const char *end);
421 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
422 static const XML_Char * FASTCALL
423 poolCopyString(STRING_POOL *pool, const XML_Char *s);
424 static const XML_Char *
425 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
426 static const XML_Char * FASTCALL
427 poolAppendString(STRING_POOL *pool, const XML_Char *s);
429 static int FASTCALL nextScaffoldPart(XML_Parser parser);
430 static XML_Content * build_model(XML_Parser parser);
431 static ELEMENT_TYPE *
432 getElementType(XML_Parser parser, const ENCODING *enc,
433 const char *ptr, const char *end);
435 static XML_Parser
436 parserCreate(const XML_Char *encodingName,
437 const XML_Memory_Handling_Suite *memsuite,
438 const XML_Char *nameSep,
439 DTD *dtd);
440 static void
441 parserInit(XML_Parser parser, const XML_Char *encodingName);
443 #define poolStart(pool) ((pool)->start)
444 #define poolEnd(pool) ((pool)->ptr)
445 #define poolLength(pool) ((pool)->ptr - (pool)->start)
446 #define poolChop(pool) ((void)--(pool->ptr))
447 #define poolLastChar(pool) (((pool)->ptr)[-1])
448 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
449 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
450 #define poolAppendChar(pool, c) \
451 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
452 ? 0 \
453 : ((*((pool)->ptr)++ = c), 1))
455 struct XML_ParserStruct {
456 /* The first member must be userData so that the XML_GetUserData
457 macro works. */
458 void *m_userData;
459 void *m_handlerArg;
460 char *m_buffer;
461 const XML_Memory_Handling_Suite m_mem;
462 /* first character to be parsed */
463 const char *m_bufferPtr;
464 /* past last character to be parsed */
465 char *m_bufferEnd;
466 /* allocated end of buffer */
467 const char *m_bufferLim;
468 XML_Index m_parseEndByteIndex;
469 const char *m_parseEndPtr;
470 XML_Char *m_dataBuf;
471 XML_Char *m_dataBufEnd;
472 XML_StartElementHandler m_startElementHandler;
473 XML_EndElementHandler m_endElementHandler;
474 XML_CharacterDataHandler m_characterDataHandler;
475 XML_ProcessingInstructionHandler m_processingInstructionHandler;
476 XML_CommentHandler m_commentHandler;
477 XML_StartCdataSectionHandler m_startCdataSectionHandler;
478 XML_EndCdataSectionHandler m_endCdataSectionHandler;
479 XML_DefaultHandler m_defaultHandler;
480 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
481 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
482 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
483 XML_NotationDeclHandler m_notationDeclHandler;
484 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
485 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
486 XML_NotStandaloneHandler m_notStandaloneHandler;
487 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
488 XML_Parser m_externalEntityRefHandlerArg;
489 XML_SkippedEntityHandler m_skippedEntityHandler;
490 XML_UnknownEncodingHandler m_unknownEncodingHandler;
491 XML_ElementDeclHandler m_elementDeclHandler;
492 XML_AttlistDeclHandler m_attlistDeclHandler;
493 XML_EntityDeclHandler m_entityDeclHandler;
494 XML_XmlDeclHandler m_xmlDeclHandler;
495 const ENCODING *m_encoding;
496 INIT_ENCODING m_initEncoding;
497 const ENCODING *m_internalEncoding;
498 const XML_Char *m_protocolEncodingName;
499 XML_Bool m_ns;
500 XML_Bool m_ns_triplets;
501 void *m_unknownEncodingMem;
502 void *m_unknownEncodingData;
503 void *m_unknownEncodingHandlerData;
504 void (XMLCALL *m_unknownEncodingRelease)(void *);
505 PROLOG_STATE m_prologState;
506 Processor *m_processor;
507 enum XML_Error m_errorCode;
508 const char *m_eventPtr;
509 const char *m_eventEndPtr;
510 const char *m_positionPtr;
511 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
512 OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
513 XML_Bool m_defaultExpandInternalEntities;
514 int m_tagLevel;
515 ENTITY *m_declEntity;
516 const XML_Char *m_doctypeName;
517 const XML_Char *m_doctypeSysid;
518 const XML_Char *m_doctypePubid;
519 const XML_Char *m_declAttributeType;
520 const XML_Char *m_declNotationName;
521 const XML_Char *m_declNotationPublicId;
522 ELEMENT_TYPE *m_declElementType;
523 ATTRIBUTE_ID *m_declAttributeId;
524 XML_Bool m_declAttributeIsCdata;
525 XML_Bool m_declAttributeIsId;
526 DTD *m_dtd;
527 const XML_Char *m_curBase;
528 TAG *m_tagStack;
529 TAG *m_freeTagList;
530 BINDING *m_inheritedBindings;
531 BINDING *m_freeBindingList;
532 int m_attsSize;
533 int m_nSpecifiedAtts;
534 int m_idAttIndex;
535 ATTRIBUTE *m_atts;
536 NS_ATT *m_nsAtts;
537 unsigned long m_nsAttsVersion;
538 unsigned char m_nsAttsPower;
539 POSITION m_position;
540 STRING_POOL m_tempPool;
541 STRING_POOL m_temp2Pool;
542 char *m_groupConnector;
543 unsigned int m_groupSize;
544 XML_Char m_namespaceSeparator;
545 XML_Parser m_parentParser;
546 XML_ParsingStatus m_parsingStatus;
547 #ifdef XML_DTD
548 XML_Bool m_isParamEntity;
549 XML_Bool m_useForeignDTD;
550 enum XML_ParamEntityParsing m_paramEntityParsing;
551 #endif
554 #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
555 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
556 #define FREE(p) (parser->m_mem.free_fcn((p)))
558 #define userData (parser->m_userData)
559 #define handlerArg (parser->m_handlerArg)
560 #define startElementHandler (parser->m_startElementHandler)
561 #define endElementHandler (parser->m_endElementHandler)
562 #define characterDataHandler (parser->m_characterDataHandler)
563 #define processingInstructionHandler \
564 (parser->m_processingInstructionHandler)
565 #define commentHandler (parser->m_commentHandler)
566 #define startCdataSectionHandler \
567 (parser->m_startCdataSectionHandler)
568 #define endCdataSectionHandler (parser->m_endCdataSectionHandler)
569 #define defaultHandler (parser->m_defaultHandler)
570 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
571 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
572 #define unparsedEntityDeclHandler \
573 (parser->m_unparsedEntityDeclHandler)
574 #define notationDeclHandler (parser->m_notationDeclHandler)
575 #define startNamespaceDeclHandler \
576 (parser->m_startNamespaceDeclHandler)
577 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
578 #define notStandaloneHandler (parser->m_notStandaloneHandler)
579 #define externalEntityRefHandler \
580 (parser->m_externalEntityRefHandler)
581 #define externalEntityRefHandlerArg \
582 (parser->m_externalEntityRefHandlerArg)
583 #define internalEntityRefHandler \
584 (parser->m_internalEntityRefHandler)
585 #define skippedEntityHandler (parser->m_skippedEntityHandler)
586 #define unknownEncodingHandler (parser->m_unknownEncodingHandler)
587 #define elementDeclHandler (parser->m_elementDeclHandler)
588 #define attlistDeclHandler (parser->m_attlistDeclHandler)
589 #define entityDeclHandler (parser->m_entityDeclHandler)
590 #define xmlDeclHandler (parser->m_xmlDeclHandler)
591 #define encoding (parser->m_encoding)
592 #define initEncoding (parser->m_initEncoding)
593 #define internalEncoding (parser->m_internalEncoding)
594 #define unknownEncodingMem (parser->m_unknownEncodingMem)
595 #define unknownEncodingData (parser->m_unknownEncodingData)
596 #define unknownEncodingHandlerData \
597 (parser->m_unknownEncodingHandlerData)
598 #define unknownEncodingRelease (parser->m_unknownEncodingRelease)
599 #define protocolEncodingName (parser->m_protocolEncodingName)
600 #define ns (parser->m_ns)
601 #define ns_triplets (parser->m_ns_triplets)
602 #define prologState (parser->m_prologState)
603 #define processor (parser->m_processor)
604 #define errorCode (parser->m_errorCode)
605 #define eventPtr (parser->m_eventPtr)
606 #define eventEndPtr (parser->m_eventEndPtr)
607 #define positionPtr (parser->m_positionPtr)
608 #define position (parser->m_position)
609 #define openInternalEntities (parser->m_openInternalEntities)
610 #define freeInternalEntities (parser->m_freeInternalEntities)
611 #define defaultExpandInternalEntities \
612 (parser->m_defaultExpandInternalEntities)
613 #define tagLevel (parser->m_tagLevel)
614 #define buffer (parser->m_buffer)
615 #define bufferPtr (parser->m_bufferPtr)
616 #define bufferEnd (parser->m_bufferEnd)
617 #define parseEndByteIndex (parser->m_parseEndByteIndex)
618 #define parseEndPtr (parser->m_parseEndPtr)
619 #define bufferLim (parser->m_bufferLim)
620 #define dataBuf (parser->m_dataBuf)
621 #define dataBufEnd (parser->m_dataBufEnd)
622 #define _dtd (parser->m_dtd)
623 #define curBase (parser->m_curBase)
624 #define declEntity (parser->m_declEntity)
625 #define doctypeName (parser->m_doctypeName)
626 #define doctypeSysid (parser->m_doctypeSysid)
627 #define doctypePubid (parser->m_doctypePubid)
628 #define declAttributeType (parser->m_declAttributeType)
629 #define declNotationName (parser->m_declNotationName)
630 #define declNotationPublicId (parser->m_declNotationPublicId)
631 #define declElementType (parser->m_declElementType)
632 #define declAttributeId (parser->m_declAttributeId)
633 #define declAttributeIsCdata (parser->m_declAttributeIsCdata)
634 #define declAttributeIsId (parser->m_declAttributeIsId)
635 #define freeTagList (parser->m_freeTagList)
636 #define freeBindingList (parser->m_freeBindingList)
637 #define inheritedBindings (parser->m_inheritedBindings)
638 #define tagStack (parser->m_tagStack)
639 #define atts (parser->m_atts)
640 #define attsSize (parser->m_attsSize)
641 #define nSpecifiedAtts (parser->m_nSpecifiedAtts)
642 #define idAttIndex (parser->m_idAttIndex)
643 #define nsAtts (parser->m_nsAtts)
644 #define nsAttsVersion (parser->m_nsAttsVersion)
645 #define nsAttsPower (parser->m_nsAttsPower)
646 #define tempPool (parser->m_tempPool)
647 #define temp2Pool (parser->m_temp2Pool)
648 #define groupConnector (parser->m_groupConnector)
649 #define groupSize (parser->m_groupSize)
650 #define namespaceSeparator (parser->m_namespaceSeparator)
651 #define parentParser (parser->m_parentParser)
652 #define ps_parsing (parser->m_parsingStatus.parsing)
653 #define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
654 #ifdef XML_DTD
655 #define isParamEntity (parser->m_isParamEntity)
656 #define useForeignDTD (parser->m_useForeignDTD)
657 #define paramEntityParsing (parser->m_paramEntityParsing)
658 #endif /* XML_DTD */
660 XML_Parser XMLCALL
661 XML_ParserCreate(const XML_Char *encodingName)
663 return XML_ParserCreate_MM(encodingName, NULL, NULL);
666 XML_Parser XMLCALL
667 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
669 XML_Char tmp[2];
670 *tmp = nsSep;
671 return XML_ParserCreate_MM(encodingName, NULL, tmp);
674 static const XML_Char implicitContext[] = {
675 ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
676 ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
677 ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
678 ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
679 ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
680 ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
683 XML_Parser XMLCALL
684 XML_ParserCreate_MM(const XML_Char *encodingName,
685 const XML_Memory_Handling_Suite *memsuite,
686 const XML_Char *nameSep)
688 XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL);
689 if (parser != NULL && ns) {
690 /* implicit context only set for root parser, since child
691 parsers (i.e. external entity parsers) will inherit it
693 if (!setContext(parser, implicitContext)) {
694 XML_ParserFree(parser);
695 return NULL;
698 return parser;
701 static XML_Parser
702 parserCreate(const XML_Char *encodingName,
703 const XML_Memory_Handling_Suite *memsuite,
704 const XML_Char *nameSep,
705 DTD *dtd)
707 XML_Parser parser;
709 if (memsuite) {
710 XML_Memory_Handling_Suite *mtemp;
711 parser = (XML_Parser)
712 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
713 if (parser != NULL) {
714 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
715 mtemp->malloc_fcn = memsuite->malloc_fcn;
716 mtemp->realloc_fcn = memsuite->realloc_fcn;
717 mtemp->free_fcn = memsuite->free_fcn;
720 else {
721 XML_Memory_Handling_Suite *mtemp;
722 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
723 if (parser != NULL) {
724 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
725 mtemp->malloc_fcn = malloc;
726 mtemp->realloc_fcn = realloc;
727 mtemp->free_fcn = free;
731 if (!parser)
732 return parser;
734 buffer = NULL;
735 bufferLim = NULL;
737 attsSize = INIT_ATTS_SIZE;
738 atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
739 if (atts == NULL) {
740 FREE(parser);
741 return NULL;
743 dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
744 if (dataBuf == NULL) {
745 FREE(atts);
746 FREE(parser);
747 return NULL;
749 dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
751 if (dtd)
752 _dtd = dtd;
753 else {
754 _dtd = dtdCreate(&parser->m_mem);
755 if (_dtd == NULL) {
756 FREE(dataBuf);
757 FREE(atts);
758 FREE(parser);
759 return NULL;
763 freeBindingList = NULL;
764 freeTagList = NULL;
765 freeInternalEntities = NULL;
767 groupSize = 0;
768 groupConnector = NULL;
770 unknownEncodingHandler = NULL;
771 unknownEncodingHandlerData = NULL;
773 namespaceSeparator = ASCII_EXCL;
774 ns = XML_FALSE;
775 ns_triplets = XML_FALSE;
777 nsAtts = NULL;
778 nsAttsVersion = 0;
779 nsAttsPower = 0;
781 poolInit(&tempPool, &(parser->m_mem));
782 poolInit(&temp2Pool, &(parser->m_mem));
783 parserInit(parser, encodingName);
785 if (encodingName && !protocolEncodingName) {
786 XML_ParserFree(parser);
787 return NULL;
790 if (nameSep) {
791 ns = XML_TRUE;
792 internalEncoding = XmlGetInternalEncodingNS();
793 namespaceSeparator = *nameSep;
795 else {
796 internalEncoding = XmlGetInternalEncoding();
799 return parser;
802 static void
803 parserInit(XML_Parser parser, const XML_Char *encodingName)
805 processor = prologInitProcessor;
806 XmlPrologStateInit(&prologState);
807 protocolEncodingName = (encodingName != NULL
808 ? poolCopyString(&tempPool, encodingName)
809 : NULL);
810 curBase = NULL;
811 XmlInitEncoding(&initEncoding, &encoding, 0);
812 userData = NULL;
813 handlerArg = NULL;
814 startElementHandler = NULL;
815 endElementHandler = NULL;
816 characterDataHandler = NULL;
817 processingInstructionHandler = NULL;
818 commentHandler = NULL;
819 startCdataSectionHandler = NULL;
820 endCdataSectionHandler = NULL;
821 defaultHandler = NULL;
822 startDoctypeDeclHandler = NULL;
823 endDoctypeDeclHandler = NULL;
824 unparsedEntityDeclHandler = NULL;
825 notationDeclHandler = NULL;
826 startNamespaceDeclHandler = NULL;
827 endNamespaceDeclHandler = NULL;
828 notStandaloneHandler = NULL;
829 externalEntityRefHandler = NULL;
830 externalEntityRefHandlerArg = parser;
831 skippedEntityHandler = NULL;
832 elementDeclHandler = NULL;
833 attlistDeclHandler = NULL;
834 entityDeclHandler = NULL;
835 xmlDeclHandler = NULL;
836 bufferPtr = buffer;
837 bufferEnd = buffer;
838 parseEndByteIndex = 0;
839 parseEndPtr = NULL;
840 declElementType = NULL;
841 declAttributeId = NULL;
842 declEntity = NULL;
843 doctypeName = NULL;
844 doctypeSysid = NULL;
845 doctypePubid = NULL;
846 declAttributeType = NULL;
847 declNotationName = NULL;
848 declNotationPublicId = NULL;
849 declAttributeIsCdata = XML_FALSE;
850 declAttributeIsId = XML_FALSE;
851 memset(&position, 0, sizeof(POSITION));
852 errorCode = XML_ERROR_NONE;
853 eventPtr = NULL;
854 eventEndPtr = NULL;
855 positionPtr = NULL;
856 openInternalEntities = NULL;
857 defaultExpandInternalEntities = XML_TRUE;
858 tagLevel = 0;
859 tagStack = NULL;
860 inheritedBindings = NULL;
861 nSpecifiedAtts = 0;
862 unknownEncodingMem = NULL;
863 unknownEncodingRelease = NULL;
864 unknownEncodingData = NULL;
865 parentParser = NULL;
866 ps_parsing = XML_INITIALIZED;
867 #ifdef XML_DTD
868 isParamEntity = XML_FALSE;
869 useForeignDTD = XML_FALSE;
870 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
871 #endif
874 /* moves list of bindings to freeBindingList */
875 static void FASTCALL
876 moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
878 while (bindings) {
879 BINDING *b = bindings;
880 bindings = bindings->nextTagBinding;
881 b->nextTagBinding = freeBindingList;
882 freeBindingList = b;
886 XML_Bool XMLCALL
887 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
889 TAG *tStk;
890 OPEN_INTERNAL_ENTITY *openEntityList;
891 if (parentParser)
892 return XML_FALSE;
893 /* move tagStack to freeTagList */
894 tStk = tagStack;
895 while (tStk) {
896 TAG *tag = tStk;
897 tStk = tStk->parent;
898 tag->parent = freeTagList;
899 moveToFreeBindingList(parser, tag->bindings);
900 tag->bindings = NULL;
901 freeTagList = tag;
903 /* move openInternalEntities to freeInternalEntities */
904 openEntityList = openInternalEntities;
905 while (openEntityList) {
906 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
907 openEntityList = openEntity->next;
908 openEntity->next = freeInternalEntities;
909 freeInternalEntities = openEntity;
911 moveToFreeBindingList(parser, inheritedBindings);
912 FREE(unknownEncodingMem);
913 if (unknownEncodingRelease)
914 unknownEncodingRelease(unknownEncodingData);
915 poolClear(&tempPool);
916 poolClear(&temp2Pool);
917 parserInit(parser, encodingName);
918 dtdReset(_dtd, &parser->m_mem);
919 return setContext(parser, implicitContext);
922 enum XML_Status XMLCALL
923 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
925 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
926 XXX There's no way for the caller to determine which of the
927 XXX possible error cases caused the XML_STATUS_ERROR return.
929 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
930 return XML_STATUS_ERROR;
931 if (encodingName == NULL)
932 protocolEncodingName = NULL;
933 else {
934 protocolEncodingName = poolCopyString(&tempPool, encodingName);
935 if (!protocolEncodingName)
936 return XML_STATUS_ERROR;
938 return XML_STATUS_OK;
941 XML_Parser XMLCALL
942 XML_ExternalEntityParserCreate(XML_Parser oldParser,
943 const XML_Char *context,
944 const XML_Char *encodingName)
946 XML_Parser parser = oldParser;
947 DTD *newDtd = NULL;
948 DTD *oldDtd = _dtd;
949 XML_StartElementHandler oldStartElementHandler = startElementHandler;
950 XML_EndElementHandler oldEndElementHandler = endElementHandler;
951 XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
952 XML_ProcessingInstructionHandler oldProcessingInstructionHandler
953 = processingInstructionHandler;
954 XML_CommentHandler oldCommentHandler = commentHandler;
955 XML_StartCdataSectionHandler oldStartCdataSectionHandler
956 = startCdataSectionHandler;
957 XML_EndCdataSectionHandler oldEndCdataSectionHandler
958 = endCdataSectionHandler;
959 XML_DefaultHandler oldDefaultHandler = defaultHandler;
960 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
961 = unparsedEntityDeclHandler;
962 XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
963 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
964 = startNamespaceDeclHandler;
965 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
966 = endNamespaceDeclHandler;
967 XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
968 XML_ExternalEntityRefHandler oldExternalEntityRefHandler
969 = externalEntityRefHandler;
970 XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
971 XML_UnknownEncodingHandler oldUnknownEncodingHandler
972 = unknownEncodingHandler;
973 XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
974 XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
975 XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
976 XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
977 ELEMENT_TYPE * oldDeclElementType = declElementType;
979 void *oldUserData = userData;
980 void *oldHandlerArg = handlerArg;
981 XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
982 XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
983 #ifdef XML_DTD
984 enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
985 int oldInEntityValue = prologState.inEntityValue;
986 #endif
987 XML_Bool oldns_triplets = ns_triplets;
989 #ifdef XML_DTD
990 if (!context)
991 newDtd = oldDtd;
992 #endif /* XML_DTD */
994 /* Note that the magical uses of the pre-processor to make field
995 access look more like C++ require that `parser' be overwritten
996 here. This makes this function more painful to follow than it
997 would be otherwise.
999 if (ns) {
1000 XML_Char tmp[2];
1001 *tmp = namespaceSeparator;
1002 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
1004 else {
1005 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1008 if (!parser)
1009 return NULL;
1011 startElementHandler = oldStartElementHandler;
1012 endElementHandler = oldEndElementHandler;
1013 characterDataHandler = oldCharacterDataHandler;
1014 processingInstructionHandler = oldProcessingInstructionHandler;
1015 commentHandler = oldCommentHandler;
1016 startCdataSectionHandler = oldStartCdataSectionHandler;
1017 endCdataSectionHandler = oldEndCdataSectionHandler;
1018 defaultHandler = oldDefaultHandler;
1019 unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1020 notationDeclHandler = oldNotationDeclHandler;
1021 startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1022 endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1023 notStandaloneHandler = oldNotStandaloneHandler;
1024 externalEntityRefHandler = oldExternalEntityRefHandler;
1025 skippedEntityHandler = oldSkippedEntityHandler;
1026 unknownEncodingHandler = oldUnknownEncodingHandler;
1027 elementDeclHandler = oldElementDeclHandler;
1028 attlistDeclHandler = oldAttlistDeclHandler;
1029 entityDeclHandler = oldEntityDeclHandler;
1030 xmlDeclHandler = oldXmlDeclHandler;
1031 declElementType = oldDeclElementType;
1032 userData = oldUserData;
1033 if (oldUserData == oldHandlerArg)
1034 handlerArg = userData;
1035 else
1036 handlerArg = parser;
1037 if (oldExternalEntityRefHandlerArg != oldParser)
1038 externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1039 defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1040 ns_triplets = oldns_triplets;
1041 parentParser = oldParser;
1042 #ifdef XML_DTD
1043 paramEntityParsing = oldParamEntityParsing;
1044 prologState.inEntityValue = oldInEntityValue;
1045 if (context) {
1046 #endif /* XML_DTD */
1047 if (!dtdCopy(_dtd, oldDtd, &parser->m_mem)
1048 || !setContext(parser, context)) {
1049 XML_ParserFree(parser);
1050 return NULL;
1052 processor = externalEntityInitProcessor;
1053 #ifdef XML_DTD
1055 else {
1056 /* The DTD instance referenced by _dtd is shared between the document's
1057 root parser and external PE parsers, therefore one does not need to
1058 call setContext. In addition, one also *must* not call setContext,
1059 because this would overwrite existing prefix->binding pointers in
1060 _dtd with ones that get destroyed with the external PE parser.
1061 This would leave those prefixes with dangling pointers.
1063 isParamEntity = XML_TRUE;
1064 XmlPrologStateInitExternalEntity(&prologState);
1065 processor = externalParEntInitProcessor;
1067 #endif /* XML_DTD */
1068 return parser;
1071 static void FASTCALL
1072 destroyBindings(BINDING *bindings, XML_Parser parser)
1074 for (;;) {
1075 BINDING *b = bindings;
1076 if (!b)
1077 break;
1078 bindings = b->nextTagBinding;
1079 FREE(b->uri);
1080 FREE(b);
1084 void XMLCALL
1085 XML_ParserFree(XML_Parser parser)
1087 TAG *tagList;
1088 OPEN_INTERNAL_ENTITY *entityList;
1089 if (parser == NULL)
1090 return;
1091 /* free tagStack and freeTagList */
1092 tagList = tagStack;
1093 for (;;) {
1094 TAG *p;
1095 if (tagList == NULL) {
1096 if (freeTagList == NULL)
1097 break;
1098 tagList = freeTagList;
1099 freeTagList = NULL;
1101 p = tagList;
1102 tagList = tagList->parent;
1103 FREE(p->buf);
1104 destroyBindings(p->bindings, parser);
1105 FREE(p);
1107 /* free openInternalEntities and freeInternalEntities */
1108 entityList = openInternalEntities;
1109 for (;;) {
1110 OPEN_INTERNAL_ENTITY *openEntity;
1111 if (entityList == NULL) {
1112 if (freeInternalEntities == NULL)
1113 break;
1114 entityList = freeInternalEntities;
1115 freeInternalEntities = NULL;
1117 openEntity = entityList;
1118 entityList = entityList->next;
1119 FREE(openEntity);
1122 destroyBindings(freeBindingList, parser);
1123 destroyBindings(inheritedBindings, parser);
1124 poolDestroy(&tempPool);
1125 poolDestroy(&temp2Pool);
1126 #ifdef XML_DTD
1127 /* external parameter entity parsers share the DTD structure
1128 parser->m_dtd with the root parser, so we must not destroy it
1130 if (!isParamEntity && _dtd)
1131 #else
1132 if (_dtd)
1133 #endif /* XML_DTD */
1134 dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
1135 FREE((void *)atts);
1136 FREE(groupConnector);
1137 FREE(buffer);
1138 FREE(dataBuf);
1139 FREE(nsAtts);
1140 FREE(unknownEncodingMem);
1141 if (unknownEncodingRelease)
1142 unknownEncodingRelease(unknownEncodingData);
1143 FREE(parser);
1146 void XMLCALL
1147 XML_UseParserAsHandlerArg(XML_Parser parser)
1149 handlerArg = parser;
1152 enum XML_Error XMLCALL
1153 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
1155 #ifdef XML_DTD
1156 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1157 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1158 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
1159 useForeignDTD = useDTD;
1160 return XML_ERROR_NONE;
1161 #else
1162 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1163 #endif
1166 void XMLCALL
1167 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
1169 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1170 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1171 return;
1172 ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
1175 void XMLCALL
1176 XML_SetUserData(XML_Parser parser, void *p)
1178 if (handlerArg == userData)
1179 handlerArg = userData = p;
1180 else
1181 userData = p;
1184 enum XML_Status XMLCALL
1185 XML_SetBase(XML_Parser parser, const XML_Char *p)
1187 if (p) {
1188 p = poolCopyString(&_dtd->pool, p);
1189 if (!p)
1190 return XML_STATUS_ERROR;
1191 curBase = p;
1193 else
1194 curBase = NULL;
1195 return XML_STATUS_OK;
1198 const XML_Char * XMLCALL
1199 XML_GetBase(XML_Parser parser)
1201 return curBase;
1204 int XMLCALL
1205 XML_GetSpecifiedAttributeCount(XML_Parser parser)
1207 return nSpecifiedAtts;
1210 int XMLCALL
1211 XML_GetIdAttributeIndex(XML_Parser parser)
1213 return idAttIndex;
1216 void XMLCALL
1217 XML_SetElementHandler(XML_Parser parser,
1218 XML_StartElementHandler start,
1219 XML_EndElementHandler end)
1221 startElementHandler = start;
1222 endElementHandler = end;
1225 void XMLCALL
1226 XML_SetStartElementHandler(XML_Parser parser,
1227 XML_StartElementHandler start) {
1228 startElementHandler = start;
1231 void XMLCALL
1232 XML_SetEndElementHandler(XML_Parser parser,
1233 XML_EndElementHandler end) {
1234 endElementHandler = end;
1237 void XMLCALL
1238 XML_SetCharacterDataHandler(XML_Parser parser,
1239 XML_CharacterDataHandler handler)
1241 characterDataHandler = handler;
1244 void XMLCALL
1245 XML_SetProcessingInstructionHandler(XML_Parser parser,
1246 XML_ProcessingInstructionHandler handler)
1248 processingInstructionHandler = handler;
1251 void XMLCALL
1252 XML_SetCommentHandler(XML_Parser parser,
1253 XML_CommentHandler handler)
1255 commentHandler = handler;
1258 void XMLCALL
1259 XML_SetCdataSectionHandler(XML_Parser parser,
1260 XML_StartCdataSectionHandler start,
1261 XML_EndCdataSectionHandler end)
1263 startCdataSectionHandler = start;
1264 endCdataSectionHandler = end;
1267 void XMLCALL
1268 XML_SetStartCdataSectionHandler(XML_Parser parser,
1269 XML_StartCdataSectionHandler start) {
1270 startCdataSectionHandler = start;
1273 void XMLCALL
1274 XML_SetEndCdataSectionHandler(XML_Parser parser,
1275 XML_EndCdataSectionHandler end) {
1276 endCdataSectionHandler = end;
1279 void XMLCALL
1280 XML_SetDefaultHandler(XML_Parser parser,
1281 XML_DefaultHandler handler)
1283 defaultHandler = handler;
1284 defaultExpandInternalEntities = XML_FALSE;
1287 void XMLCALL
1288 XML_SetDefaultHandlerExpand(XML_Parser parser,
1289 XML_DefaultHandler handler)
1291 defaultHandler = handler;
1292 defaultExpandInternalEntities = XML_TRUE;
1295 void XMLCALL
1296 XML_SetDoctypeDeclHandler(XML_Parser parser,
1297 XML_StartDoctypeDeclHandler start,
1298 XML_EndDoctypeDeclHandler end)
1300 startDoctypeDeclHandler = start;
1301 endDoctypeDeclHandler = end;
1304 void XMLCALL
1305 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1306 XML_StartDoctypeDeclHandler start) {
1307 startDoctypeDeclHandler = start;
1310 void XMLCALL
1311 XML_SetEndDoctypeDeclHandler(XML_Parser parser,
1312 XML_EndDoctypeDeclHandler end) {
1313 endDoctypeDeclHandler = end;
1316 void XMLCALL
1317 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1318 XML_UnparsedEntityDeclHandler handler)
1320 unparsedEntityDeclHandler = handler;
1323 void XMLCALL
1324 XML_SetNotationDeclHandler(XML_Parser parser,
1325 XML_NotationDeclHandler handler)
1327 notationDeclHandler = handler;
1330 void XMLCALL
1331 XML_SetNamespaceDeclHandler(XML_Parser parser,
1332 XML_StartNamespaceDeclHandler start,
1333 XML_EndNamespaceDeclHandler end)
1335 startNamespaceDeclHandler = start;
1336 endNamespaceDeclHandler = end;
1339 void XMLCALL
1340 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1341 XML_StartNamespaceDeclHandler start) {
1342 startNamespaceDeclHandler = start;
1345 void XMLCALL
1346 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1347 XML_EndNamespaceDeclHandler end) {
1348 endNamespaceDeclHandler = end;
1351 void XMLCALL
1352 XML_SetNotStandaloneHandler(XML_Parser parser,
1353 XML_NotStandaloneHandler handler)
1355 notStandaloneHandler = handler;
1358 void XMLCALL
1359 XML_SetExternalEntityRefHandler(XML_Parser parser,
1360 XML_ExternalEntityRefHandler handler)
1362 externalEntityRefHandler = handler;
1365 void XMLCALL
1366 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
1368 if (arg)
1369 externalEntityRefHandlerArg = (XML_Parser)arg;
1370 else
1371 externalEntityRefHandlerArg = parser;
1374 void XMLCALL
1375 XML_SetSkippedEntityHandler(XML_Parser parser,
1376 XML_SkippedEntityHandler handler)
1378 skippedEntityHandler = handler;
1381 void XMLCALL
1382 XML_SetUnknownEncodingHandler(XML_Parser parser,
1383 XML_UnknownEncodingHandler handler,
1384 void *data)
1386 unknownEncodingHandler = handler;
1387 unknownEncodingHandlerData = data;
1390 void XMLCALL
1391 XML_SetElementDeclHandler(XML_Parser parser,
1392 XML_ElementDeclHandler eldecl)
1394 elementDeclHandler = eldecl;
1397 void XMLCALL
1398 XML_SetAttlistDeclHandler(XML_Parser parser,
1399 XML_AttlistDeclHandler attdecl)
1401 attlistDeclHandler = attdecl;
1404 void XMLCALL
1405 XML_SetEntityDeclHandler(XML_Parser parser,
1406 XML_EntityDeclHandler handler)
1408 entityDeclHandler = handler;
1411 void XMLCALL
1412 XML_SetXmlDeclHandler(XML_Parser parser,
1413 XML_XmlDeclHandler handler) {
1414 xmlDeclHandler = handler;
1417 int XMLCALL
1418 XML_SetParamEntityParsing(XML_Parser parser,
1419 enum XML_ParamEntityParsing peParsing)
1421 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1422 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1423 return 0;
1424 #ifdef XML_DTD
1425 paramEntityParsing = peParsing;
1426 return 1;
1427 #else
1428 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1429 #endif
1432 enum XML_Status XMLCALL
1433 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
1435 switch (ps_parsing) {
1436 case XML_SUSPENDED:
1437 errorCode = XML_ERROR_SUSPENDED;
1438 return XML_STATUS_ERROR;
1439 case XML_FINISHED:
1440 errorCode = XML_ERROR_FINISHED;
1441 return XML_STATUS_ERROR;
1442 default:
1443 ps_parsing = XML_PARSING;
1446 if (len == 0) {
1447 ps_finalBuffer = (XML_Bool)isFinal;
1448 if (!isFinal)
1449 return XML_STATUS_OK;
1450 positionPtr = bufferPtr;
1451 parseEndPtr = bufferEnd;
1453 /* If data are left over from last buffer, and we now know that these
1454 data are the final chunk of input, then we have to check them again
1455 to detect errors based on that fact.
1457 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
1459 if (errorCode == XML_ERROR_NONE) {
1460 switch (ps_parsing) {
1461 case XML_SUSPENDED:
1462 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1463 positionPtr = bufferPtr;
1464 return XML_STATUS_SUSPENDED;
1465 case XML_INITIALIZED:
1466 case XML_PARSING:
1467 ps_parsing = XML_FINISHED;
1468 /* fall through */
1469 default:
1470 return XML_STATUS_OK;
1473 eventEndPtr = eventPtr;
1474 processor = errorProcessor;
1475 return XML_STATUS_ERROR;
1477 #ifndef XML_CONTEXT_BYTES
1478 else if (bufferPtr == bufferEnd) {
1479 const char *end;
1480 int nLeftOver;
1481 enum XML_Error result;
1482 parseEndByteIndex += len;
1483 positionPtr = s;
1484 ps_finalBuffer = (XML_Bool)isFinal;
1486 errorCode = processor(parser, s, parseEndPtr = s + len, &end);
1488 if (errorCode != XML_ERROR_NONE) {
1489 eventEndPtr = eventPtr;
1490 processor = errorProcessor;
1491 return XML_STATUS_ERROR;
1493 else {
1494 switch (ps_parsing) {
1495 case XML_SUSPENDED:
1496 result = XML_STATUS_SUSPENDED;
1497 break;
1498 case XML_INITIALIZED:
1499 case XML_PARSING:
1500 result = XML_STATUS_OK;
1501 if (isFinal) {
1502 ps_parsing = XML_FINISHED;
1503 return result;
1508 XmlUpdatePosition(encoding, positionPtr, end, &position);
1509 nLeftOver = s + len - end;
1510 if (nLeftOver) {
1511 if (buffer == NULL || nLeftOver > bufferLim - buffer) {
1512 /* FIXME avoid integer overflow */
1513 char *temp;
1514 temp = (buffer == NULL
1515 ? (char *)MALLOC(len * 2)
1516 : (char *)REALLOC(buffer, len * 2));
1517 if (temp == NULL) {
1518 errorCode = XML_ERROR_NO_MEMORY;
1519 return XML_STATUS_ERROR;
1521 buffer = temp;
1522 if (!buffer) {
1523 errorCode = XML_ERROR_NO_MEMORY;
1524 eventPtr = eventEndPtr = NULL;
1525 processor = errorProcessor;
1526 return XML_STATUS_ERROR;
1528 bufferLim = buffer + len * 2;
1530 memcpy(buffer, end, nLeftOver);
1532 bufferPtr = buffer;
1533 bufferEnd = buffer + nLeftOver;
1534 positionPtr = bufferPtr;
1535 parseEndPtr = bufferEnd;
1536 eventPtr = bufferPtr;
1537 eventEndPtr = bufferPtr;
1538 return result;
1540 #endif /* not defined XML_CONTEXT_BYTES */
1541 else {
1542 void *buff = XML_GetBuffer(parser, len);
1543 if (buff == NULL)
1544 return XML_STATUS_ERROR;
1545 else {
1546 memcpy(buff, s, len);
1547 return XML_ParseBuffer(parser, len, isFinal);
1552 enum XML_Status XMLCALL
1553 XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
1555 const char *start;
1556 enum XML_Status result = XML_STATUS_OK;
1558 switch (ps_parsing) {
1559 case XML_SUSPENDED:
1560 errorCode = XML_ERROR_SUSPENDED;
1561 return XML_STATUS_ERROR;
1562 case XML_FINISHED:
1563 errorCode = XML_ERROR_FINISHED;
1564 return XML_STATUS_ERROR;
1565 default:
1566 ps_parsing = XML_PARSING;
1569 start = bufferPtr;
1570 positionPtr = start;
1571 bufferEnd += len;
1572 parseEndPtr = bufferEnd;
1573 parseEndByteIndex += len;
1574 ps_finalBuffer = (XML_Bool)isFinal;
1576 errorCode = processor(parser, start, parseEndPtr, &bufferPtr);
1578 if (errorCode != XML_ERROR_NONE) {
1579 eventEndPtr = eventPtr;
1580 processor = errorProcessor;
1581 return XML_STATUS_ERROR;
1583 else {
1584 switch (ps_parsing) {
1585 case XML_SUSPENDED:
1586 result = XML_STATUS_SUSPENDED;
1587 break;
1588 case XML_INITIALIZED:
1589 case XML_PARSING:
1590 if (isFinal) {
1591 ps_parsing = XML_FINISHED;
1592 return result;
1594 default: ; /* should not happen */
1598 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1599 positionPtr = bufferPtr;
1600 return result;
1603 void * XMLCALL
1604 XML_GetBuffer(XML_Parser parser, int len)
1606 switch (ps_parsing) {
1607 case XML_SUSPENDED:
1608 errorCode = XML_ERROR_SUSPENDED;
1609 return NULL;
1610 case XML_FINISHED:
1611 errorCode = XML_ERROR_FINISHED;
1612 return NULL;
1613 default: ;
1616 if (len > bufferLim - bufferEnd) {
1617 /* FIXME avoid integer overflow */
1618 int neededSize = len + (int)(bufferEnd - bufferPtr);
1619 #ifdef XML_CONTEXT_BYTES
1620 int keep = (int)(bufferPtr - buffer);
1622 if (keep > XML_CONTEXT_BYTES)
1623 keep = XML_CONTEXT_BYTES;
1624 neededSize += keep;
1625 #endif /* defined XML_CONTEXT_BYTES */
1626 if (neededSize <= bufferLim - buffer) {
1627 #ifdef XML_CONTEXT_BYTES
1628 if (keep < bufferPtr - buffer) {
1629 int offset = (int)(bufferPtr - buffer) - keep;
1630 memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
1631 bufferEnd -= offset;
1632 bufferPtr -= offset;
1634 #else
1635 memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
1636 bufferEnd = buffer + (bufferEnd - bufferPtr);
1637 bufferPtr = buffer;
1638 #endif /* not defined XML_CONTEXT_BYTES */
1640 else {
1641 char *newBuf;
1642 int bufferSize = (int)(bufferLim - bufferPtr);
1643 if (bufferSize == 0)
1644 bufferSize = INIT_BUFFER_SIZE;
1645 do {
1646 bufferSize *= 2;
1647 } while (bufferSize < neededSize);
1648 newBuf = (char *)MALLOC(bufferSize);
1649 if (newBuf == 0) {
1650 errorCode = XML_ERROR_NO_MEMORY;
1651 return NULL;
1653 bufferLim = newBuf + bufferSize;
1654 #ifdef XML_CONTEXT_BYTES
1655 if (bufferPtr) {
1656 int keep = (int)(bufferPtr - buffer);
1657 if (keep > XML_CONTEXT_BYTES)
1658 keep = XML_CONTEXT_BYTES;
1659 memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
1660 FREE(buffer);
1661 buffer = newBuf;
1662 bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
1663 bufferPtr = buffer + keep;
1665 else {
1666 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1667 bufferPtr = buffer = newBuf;
1669 #else
1670 if (bufferPtr) {
1671 memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
1672 FREE(buffer);
1674 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1675 bufferPtr = buffer = newBuf;
1676 #endif /* not defined XML_CONTEXT_BYTES */
1679 return bufferEnd;
1682 enum XML_Status XMLCALL
1683 XML_StopParser(XML_Parser parser, XML_Bool resumable)
1685 switch (ps_parsing) {
1686 case XML_SUSPENDED:
1687 if (resumable) {
1688 errorCode = XML_ERROR_SUSPENDED;
1689 return XML_STATUS_ERROR;
1691 ps_parsing = XML_FINISHED;
1692 break;
1693 case XML_FINISHED:
1694 errorCode = XML_ERROR_FINISHED;
1695 return XML_STATUS_ERROR;
1696 default:
1697 if (resumable) {
1698 #ifdef XML_DTD
1699 if (isParamEntity) {
1700 errorCode = XML_ERROR_SUSPEND_PE;
1701 return XML_STATUS_ERROR;
1703 #endif
1704 ps_parsing = XML_SUSPENDED;
1706 else
1707 ps_parsing = XML_FINISHED;
1709 return XML_STATUS_OK;
1712 enum XML_Status XMLCALL
1713 XML_ResumeParser(XML_Parser parser)
1715 enum XML_Status result = XML_STATUS_OK;
1717 if (ps_parsing != XML_SUSPENDED) {
1718 errorCode = XML_ERROR_NOT_SUSPENDED;
1719 return XML_STATUS_ERROR;
1721 ps_parsing = XML_PARSING;
1723 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
1725 if (errorCode != XML_ERROR_NONE) {
1726 eventEndPtr = eventPtr;
1727 processor = errorProcessor;
1728 return XML_STATUS_ERROR;
1730 else {
1731 switch (ps_parsing) {
1732 case XML_SUSPENDED:
1733 result = XML_STATUS_SUSPENDED;
1734 break;
1735 case XML_INITIALIZED:
1736 case XML_PARSING:
1737 if (ps_finalBuffer) {
1738 ps_parsing = XML_FINISHED;
1739 return result;
1741 default: ;
1745 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1746 positionPtr = bufferPtr;
1747 return result;
1750 void XMLCALL
1751 XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
1753 assert(status != NULL);
1754 *status = parser->m_parsingStatus;
1757 enum XML_Error XMLCALL
1758 XML_GetErrorCode(XML_Parser parser)
1760 return errorCode;
1763 XML_Index XMLCALL
1764 XML_GetCurrentByteIndex(XML_Parser parser)
1766 if (eventPtr)
1767 return parseEndByteIndex - (parseEndPtr - eventPtr);
1768 return -1;
1771 int XMLCALL
1772 XML_GetCurrentByteCount(XML_Parser parser)
1774 if (eventEndPtr && eventPtr)
1775 return (int)(eventEndPtr - eventPtr);
1776 return 0;
1779 const char * XMLCALL
1780 XML_GetInputContext(XML_Parser parser, int *offset, int *size)
1782 #ifdef XML_CONTEXT_BYTES
1783 if (eventPtr && buffer) {
1784 *offset = (int)(eventPtr - buffer);
1785 *size = (int)(bufferEnd - buffer);
1786 return buffer;
1788 #endif /* defined XML_CONTEXT_BYTES */
1789 return (char *) 0;
1792 XML_Size XMLCALL
1793 XML_GetCurrentLineNumber(XML_Parser parser)
1795 if (eventPtr && eventPtr >= positionPtr) {
1796 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1797 positionPtr = eventPtr;
1799 return position.lineNumber + 1;
1802 XML_Size XMLCALL
1803 XML_GetCurrentColumnNumber(XML_Parser parser)
1805 if (eventPtr && eventPtr >= positionPtr) {
1806 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1807 positionPtr = eventPtr;
1809 return position.columnNumber;
1812 void XMLCALL
1813 XML_FreeContentModel(XML_Parser parser, XML_Content *model)
1815 FREE(model);
1818 void * XMLCALL
1819 XML_MemMalloc(XML_Parser parser, size_t size)
1821 return MALLOC(size);
1824 void * XMLCALL
1825 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
1827 return REALLOC(ptr, size);
1830 void XMLCALL
1831 XML_MemFree(XML_Parser parser, void *ptr)
1833 FREE(ptr);
1836 void XMLCALL
1837 XML_DefaultCurrent(XML_Parser parser)
1839 if (defaultHandler) {
1840 if (openInternalEntities)
1841 reportDefault(parser,
1842 internalEncoding,
1843 openInternalEntities->internalEventPtr,
1844 openInternalEntities->internalEventEndPtr);
1845 else
1846 reportDefault(parser, encoding, eventPtr, eventEndPtr);
1850 const XML_LChar * XMLCALL
1851 XML_ErrorString(enum XML_Error code)
1853 static const XML_LChar* const message[] = {
1855 XML_L("out of memory"),
1856 XML_L("syntax error"),
1857 XML_L("no element found"),
1858 XML_L("not well-formed (invalid token)"),
1859 XML_L("unclosed token"),
1860 XML_L("partial character"),
1861 XML_L("mismatched tag"),
1862 XML_L("duplicate attribute"),
1863 XML_L("junk after document element"),
1864 XML_L("illegal parameter entity reference"),
1865 XML_L("undefined entity"),
1866 XML_L("recursive entity reference"),
1867 XML_L("asynchronous entity"),
1868 XML_L("reference to invalid character number"),
1869 XML_L("reference to binary entity"),
1870 XML_L("reference to external entity in attribute"),
1871 XML_L("XML or text declaration not at start of entity"),
1872 XML_L("unknown encoding"),
1873 XML_L("encoding specified in XML declaration is incorrect"),
1874 XML_L("unclosed CDATA section"),
1875 XML_L("error in processing external entity reference"),
1876 XML_L("document is not standalone"),
1877 XML_L("unexpected parser state - please send a bug report"),
1878 XML_L("entity declared in parameter entity"),
1879 XML_L("requested feature requires XML_DTD support in Expat"),
1880 XML_L("cannot change setting once parsing has begun"),
1881 XML_L("unbound prefix"),
1882 XML_L("must not undeclare prefix"),
1883 XML_L("incomplete markup in parameter entity"),
1884 XML_L("XML declaration not well-formed"),
1885 XML_L("text declaration not well-formed"),
1886 XML_L("illegal character(s) in public id"),
1887 XML_L("parser suspended"),
1888 XML_L("parser not suspended"),
1889 XML_L("parsing aborted"),
1890 XML_L("parsing finished"),
1891 XML_L("cannot suspend in external parameter entity"),
1892 XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
1893 XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
1894 XML_L("prefix must not be bound to one of the reserved namespace names")
1896 if (code > 0 && code < sizeof(message)/sizeof(message[0]))
1897 return message[code];
1898 return NULL;
1901 const XML_LChar * XMLCALL
1902 XML_ExpatVersion(void) {
1904 /* V1 is used to string-ize the version number. However, it would
1905 string-ize the actual version macro *names* unless we get them
1906 substituted before being passed to V1. CPP is defined to expand
1907 a macro, then rescan for more expansions. Thus, we use V2 to expand
1908 the version macros, then CPP will expand the resulting V1() macro
1909 with the correct numerals. */
1910 /* ### I'm assuming cpp is portable in this respect... */
1912 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
1913 #define V2(a,b,c) XML_L("expat_")V1(a,b,c)
1915 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
1917 #undef V1
1918 #undef V2
1921 XML_Expat_Version XMLCALL
1922 XML_ExpatVersionInfo(void)
1924 XML_Expat_Version version;
1926 version.major = XML_MAJOR_VERSION;
1927 version.minor = XML_MINOR_VERSION;
1928 version.micro = XML_MICRO_VERSION;
1930 return version;
1933 const XML_Feature * XMLCALL
1934 XML_GetFeatureList(void)
1936 static const XML_Feature features[] = {
1937 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
1938 sizeof(XML_Char)},
1939 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
1940 sizeof(XML_LChar)},
1941 #ifdef XML_UNICODE
1942 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
1943 #endif
1944 #ifdef XML_UNICODE_WCHAR_T
1945 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
1946 #endif
1947 #ifdef XML_DTD
1948 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
1949 #endif
1950 #ifdef XML_CONTEXT_BYTES
1951 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
1952 XML_CONTEXT_BYTES},
1953 #endif
1954 #ifdef XML_MIN_SIZE
1955 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
1956 #endif
1957 #ifdef XML_NS
1958 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
1959 #endif
1960 #ifdef XML_LARGE_SIZE
1961 {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
1962 #endif
1963 {XML_FEATURE_END, NULL, 0}
1966 return features;
1969 /* Initially tag->rawName always points into the parse buffer;
1970 for those TAG instances opened while the current parse buffer was
1971 processed, and not yet closed, we need to store tag->rawName in a more
1972 permanent location, since the parse buffer is about to be discarded.
1974 static XML_Bool
1975 storeRawNames(XML_Parser parser)
1977 TAG *tag = tagStack;
1978 while (tag) {
1979 int bufSize;
1980 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
1981 char *rawNameBuf = tag->buf + nameLen;
1982 /* Stop if already stored. Since tagStack is a stack, we can stop
1983 at the first entry that has already been copied; everything
1984 below it in the stack is already been accounted for in a
1985 previous call to this function.
1987 if (tag->rawName == rawNameBuf)
1988 break;
1989 /* For re-use purposes we need to ensure that the
1990 size of tag->buf is a multiple of sizeof(XML_Char).
1992 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
1993 if (bufSize > tag->bufEnd - tag->buf) {
1994 char *temp = (char *)REALLOC(tag->buf, bufSize);
1995 if (temp == NULL)
1996 return XML_FALSE;
1997 /* if tag->name.str points to tag->buf (only when namespace
1998 processing is off) then we have to update it
2000 if (tag->name.str == (XML_Char *)tag->buf)
2001 tag->name.str = (XML_Char *)temp;
2002 /* if tag->name.localPart is set (when namespace processing is on)
2003 then update it as well, since it will always point into tag->buf
2005 if (tag->name.localPart)
2006 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
2007 (XML_Char *)tag->buf);
2008 tag->buf = temp;
2009 tag->bufEnd = temp + bufSize;
2010 rawNameBuf = temp + nameLen;
2012 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2013 tag->rawName = rawNameBuf;
2014 tag = tag->parent;
2016 return XML_TRUE;
2019 static enum XML_Error PTRCALL
2020 contentProcessor(XML_Parser parser,
2021 const char *start,
2022 const char *end,
2023 const char **endPtr)
2025 enum XML_Error result = doContent(parser, 0, encoding, start, end,
2026 endPtr, (XML_Bool)!ps_finalBuffer);
2027 if (result == XML_ERROR_NONE) {
2028 if (!storeRawNames(parser))
2029 return XML_ERROR_NO_MEMORY;
2031 return result;
2034 static enum XML_Error PTRCALL
2035 externalEntityInitProcessor(XML_Parser parser,
2036 const char *start,
2037 const char *end,
2038 const char **endPtr)
2040 enum XML_Error result = initializeEncoding(parser);
2041 if (result != XML_ERROR_NONE)
2042 return result;
2043 processor = externalEntityInitProcessor2;
2044 return externalEntityInitProcessor2(parser, start, end, endPtr);
2047 static enum XML_Error PTRCALL
2048 externalEntityInitProcessor2(XML_Parser parser,
2049 const char *start,
2050 const char *end,
2051 const char **endPtr)
2053 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2054 int tok = XmlContentTok(encoding, start, end, &next);
2055 switch (tok) {
2056 case XML_TOK_BOM:
2057 /* If we are at the end of the buffer, this would cause the next stage,
2058 i.e. externalEntityInitProcessor3, to pass control directly to
2059 doContent (by detecting XML_TOK_NONE) without processing any xml text
2060 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2062 if (next == end && !ps_finalBuffer) {
2063 *endPtr = next;
2064 return XML_ERROR_NONE;
2066 start = next;
2067 break;
2068 case XML_TOK_PARTIAL:
2069 if (!ps_finalBuffer) {
2070 *endPtr = start;
2071 return XML_ERROR_NONE;
2073 eventPtr = start;
2074 return XML_ERROR_UNCLOSED_TOKEN;
2075 case XML_TOK_PARTIAL_CHAR:
2076 if (!ps_finalBuffer) {
2077 *endPtr = start;
2078 return XML_ERROR_NONE;
2080 eventPtr = start;
2081 return XML_ERROR_PARTIAL_CHAR;
2083 processor = externalEntityInitProcessor3;
2084 return externalEntityInitProcessor3(parser, start, end, endPtr);
2087 static enum XML_Error PTRCALL
2088 externalEntityInitProcessor3(XML_Parser parser,
2089 const char *start,
2090 const char *end,
2091 const char **endPtr)
2093 int tok;
2094 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2095 eventPtr = start;
2096 tok = XmlContentTok(encoding, start, end, &next);
2097 eventEndPtr = next;
2099 switch (tok) {
2100 case XML_TOK_XML_DECL:
2102 enum XML_Error result;
2103 result = processXmlDecl(parser, 1, start, next);
2104 if (result != XML_ERROR_NONE)
2105 return result;
2106 switch (ps_parsing) {
2107 case XML_SUSPENDED:
2108 *endPtr = next;
2109 return XML_ERROR_NONE;
2110 case XML_FINISHED:
2111 return XML_ERROR_ABORTED;
2112 default:
2113 start = next;
2116 break;
2117 case XML_TOK_PARTIAL:
2118 if (!ps_finalBuffer) {
2119 *endPtr = start;
2120 return XML_ERROR_NONE;
2122 return XML_ERROR_UNCLOSED_TOKEN;
2123 case XML_TOK_PARTIAL_CHAR:
2124 if (!ps_finalBuffer) {
2125 *endPtr = start;
2126 return XML_ERROR_NONE;
2128 return XML_ERROR_PARTIAL_CHAR;
2130 processor = externalEntityContentProcessor;
2131 tagLevel = 1;
2132 return externalEntityContentProcessor(parser, start, end, endPtr);
2135 static enum XML_Error PTRCALL
2136 externalEntityContentProcessor(XML_Parser parser,
2137 const char *start,
2138 const char *end,
2139 const char **endPtr)
2141 enum XML_Error result = doContent(parser, 1, encoding, start, end,
2142 endPtr, (XML_Bool)!ps_finalBuffer);
2143 if (result == XML_ERROR_NONE) {
2144 if (!storeRawNames(parser))
2145 return XML_ERROR_NO_MEMORY;
2147 return result;
2150 static enum XML_Error
2151 doContent(XML_Parser parser,
2152 int startTagLevel,
2153 const ENCODING *enc,
2154 const char *s,
2155 const char *end,
2156 const char **nextPtr,
2157 XML_Bool haveMore)
2159 /* save one level of indirection */
2160 DTD * const dtd = _dtd;
2162 const char **eventPP;
2163 const char **eventEndPP;
2164 if (enc == encoding) {
2165 eventPP = &eventPtr;
2166 eventEndPP = &eventEndPtr;
2168 else {
2169 eventPP = &(openInternalEntities->internalEventPtr);
2170 eventEndPP = &(openInternalEntities->internalEventEndPtr);
2172 *eventPP = s;
2174 for (;;) {
2175 const char *next = s; /* XmlContentTok doesn't always set the last arg */
2176 int tok = XmlContentTok(enc, s, end, &next);
2177 *eventEndPP = next;
2178 switch (tok) {
2179 case XML_TOK_TRAILING_CR:
2180 if (haveMore) {
2181 *nextPtr = s;
2182 return XML_ERROR_NONE;
2184 *eventEndPP = end;
2185 if (characterDataHandler) {
2186 XML_Char c = 0xA;
2187 characterDataHandler(handlerArg, &c, 1);
2189 else if (defaultHandler)
2190 reportDefault(parser, enc, s, end);
2191 /* We are at the end of the final buffer, should we check for
2192 XML_SUSPENDED, XML_FINISHED?
2194 if (startTagLevel == 0)
2195 return XML_ERROR_NO_ELEMENTS;
2196 if (tagLevel != startTagLevel)
2197 return XML_ERROR_ASYNC_ENTITY;
2198 *nextPtr = end;
2199 return XML_ERROR_NONE;
2200 case XML_TOK_NONE:
2201 if (haveMore) {
2202 *nextPtr = s;
2203 return XML_ERROR_NONE;
2205 if (startTagLevel > 0) {
2206 if (tagLevel != startTagLevel)
2207 return XML_ERROR_ASYNC_ENTITY;
2208 *nextPtr = s;
2209 return XML_ERROR_NONE;
2211 return XML_ERROR_NO_ELEMENTS;
2212 case XML_TOK_INVALID:
2213 *eventPP = next;
2214 return XML_ERROR_INVALID_TOKEN;
2215 case XML_TOK_PARTIAL:
2216 if (haveMore) {
2217 *nextPtr = s;
2218 return XML_ERROR_NONE;
2220 return XML_ERROR_UNCLOSED_TOKEN;
2221 case XML_TOK_PARTIAL_CHAR:
2222 if (haveMore) {
2223 *nextPtr = s;
2224 return XML_ERROR_NONE;
2226 return XML_ERROR_PARTIAL_CHAR;
2227 case XML_TOK_ENTITY_REF:
2229 const XML_Char *name;
2230 ENTITY *entity;
2231 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
2232 s + enc->minBytesPerChar,
2233 next - enc->minBytesPerChar);
2234 if (ch) {
2235 if (characterDataHandler)
2236 characterDataHandler(handlerArg, &ch, 1);
2237 else if (defaultHandler)
2238 reportDefault(parser, enc, s, next);
2239 break;
2241 name = poolStoreString(&dtd->pool, enc,
2242 s + enc->minBytesPerChar,
2243 next - enc->minBytesPerChar);
2244 if (!name)
2245 return XML_ERROR_NO_MEMORY;
2246 entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
2247 poolDiscard(&dtd->pool);
2248 /* First, determine if a check for an existing declaration is needed;
2249 if yes, check that the entity exists, and that it is internal,
2250 otherwise call the skipped entity or default handler.
2252 if (!dtd->hasParamEntityRefs || dtd->standalone) {
2253 if (!entity)
2254 return XML_ERROR_UNDEFINED_ENTITY;
2255 else if (!entity->is_internal)
2256 return XML_ERROR_ENTITY_DECLARED_IN_PE;
2258 else if (!entity) {
2259 if (skippedEntityHandler)
2260 skippedEntityHandler(handlerArg, name, 0);
2261 else if (defaultHandler)
2262 reportDefault(parser, enc, s, next);
2263 break;
2265 if (entity->open)
2266 return XML_ERROR_RECURSIVE_ENTITY_REF;
2267 if (entity->notation)
2268 return XML_ERROR_BINARY_ENTITY_REF;
2269 if (entity->textPtr) {
2270 enum XML_Error result;
2271 if (!defaultExpandInternalEntities) {
2272 if (skippedEntityHandler)
2273 skippedEntityHandler(handlerArg, entity->name, 0);
2274 else if (defaultHandler)
2275 reportDefault(parser, enc, s, next);
2276 break;
2278 result = processInternalEntity(parser, entity, XML_FALSE);
2279 if (result != XML_ERROR_NONE)
2280 return result;
2282 else if (externalEntityRefHandler) {
2283 const XML_Char *context;
2284 entity->open = XML_TRUE;
2285 context = getContext(parser);
2286 entity->open = XML_FALSE;
2287 if (!context)
2288 return XML_ERROR_NO_MEMORY;
2289 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
2290 context,
2291 entity->base,
2292 entity->systemId,
2293 entity->publicId))
2294 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2295 poolDiscard(&tempPool);
2297 else if (defaultHandler)
2298 reportDefault(parser, enc, s, next);
2299 break;
2301 case XML_TOK_START_TAG_NO_ATTS:
2302 /* fall through */
2303 case XML_TOK_START_TAG_WITH_ATTS:
2305 TAG *tag;
2306 enum XML_Error result;
2307 XML_Char *toPtr;
2308 if (freeTagList) {
2309 tag = freeTagList;
2310 freeTagList = freeTagList->parent;
2312 else {
2313 tag = (TAG *)MALLOC(sizeof(TAG));
2314 if (!tag)
2315 return XML_ERROR_NO_MEMORY;
2316 tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
2317 if (!tag->buf) {
2318 FREE(tag);
2319 return XML_ERROR_NO_MEMORY;
2321 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2323 tag->bindings = NULL;
2324 tag->parent = tagStack;
2325 tagStack = tag;
2326 tag->name.localPart = NULL;
2327 tag->name.prefix = NULL;
2328 tag->rawName = s + enc->minBytesPerChar;
2329 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
2330 ++tagLevel;
2332 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2333 const char *fromPtr = tag->rawName;
2334 toPtr = (XML_Char *)tag->buf;
2335 for (;;) {
2336 int bufSize;
2337 int convLen;
2338 XmlConvert(enc,
2339 &fromPtr, rawNameEnd,
2340 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
2341 convLen = (int)(toPtr - (XML_Char *)tag->buf);
2342 if (fromPtr == rawNameEnd) {
2343 tag->name.strLen = convLen;
2344 break;
2346 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2348 char *temp = (char *)REALLOC(tag->buf, bufSize);
2349 if (temp == NULL)
2350 return XML_ERROR_NO_MEMORY;
2351 tag->buf = temp;
2352 tag->bufEnd = temp + bufSize;
2353 toPtr = (XML_Char *)temp + convLen;
2357 tag->name.str = (XML_Char *)tag->buf;
2358 *toPtr = XML_T('\0');
2359 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2360 if (result)
2361 return result;
2362 if (startElementHandler)
2363 startElementHandler(handlerArg, tag->name.str,
2364 (const XML_Char **)atts);
2365 else if (defaultHandler)
2366 reportDefault(parser, enc, s, next);
2367 poolClear(&tempPool);
2368 break;
2370 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2371 /* fall through */
2372 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
2374 const char *rawName = s + enc->minBytesPerChar;
2375 enum XML_Error result;
2376 BINDING *bindings = NULL;
2377 XML_Bool noElmHandlers = XML_TRUE;
2378 TAG_NAME name;
2379 name.str = poolStoreString(&tempPool, enc, rawName,
2380 rawName + XmlNameLength(enc, rawName));
2381 if (!name.str)
2382 return XML_ERROR_NO_MEMORY;
2383 poolFinish(&tempPool);
2384 result = storeAtts(parser, enc, s, &name, &bindings);
2385 if (result)
2386 return result;
2387 poolFinish(&tempPool);
2388 if (startElementHandler) {
2389 startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
2390 noElmHandlers = XML_FALSE;
2392 if (endElementHandler) {
2393 if (startElementHandler)
2394 *eventPP = *eventEndPP;
2395 endElementHandler(handlerArg, name.str);
2396 noElmHandlers = XML_FALSE;
2398 if (noElmHandlers && defaultHandler)
2399 reportDefault(parser, enc, s, next);
2400 poolClear(&tempPool);
2401 while (bindings) {
2402 BINDING *b = bindings;
2403 if (endNamespaceDeclHandler)
2404 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2405 bindings = bindings->nextTagBinding;
2406 b->nextTagBinding = freeBindingList;
2407 freeBindingList = b;
2408 b->prefix->binding = b->prevPrefixBinding;
2411 if (tagLevel == 0)
2412 return epilogProcessor(parser, next, end, nextPtr);
2413 break;
2414 case XML_TOK_END_TAG:
2415 if (tagLevel == startTagLevel)
2416 return XML_ERROR_ASYNC_ENTITY;
2417 else {
2418 int len;
2419 const char *rawName;
2420 TAG *tag = tagStack;
2421 tagStack = tag->parent;
2422 tag->parent = freeTagList;
2423 freeTagList = tag;
2424 rawName = s + enc->minBytesPerChar*2;
2425 len = XmlNameLength(enc, rawName);
2426 if (len != tag->rawNameLength
2427 || memcmp(tag->rawName, rawName, len) != 0) {
2428 *eventPP = rawName;
2429 return XML_ERROR_TAG_MISMATCH;
2431 --tagLevel;
2432 if (endElementHandler) {
2433 const XML_Char *localPart;
2434 const XML_Char *prefix;
2435 XML_Char *uri;
2436 localPart = tag->name.localPart;
2437 if (ns && localPart) {
2438 /* localPart and prefix may have been overwritten in
2439 tag->name.str, since this points to the binding->uri
2440 buffer which gets re-used; so we have to add them again
2442 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2443 /* don't need to check for space - already done in storeAtts() */
2444 while (*localPart) *uri++ = *localPart++;
2445 prefix = (XML_Char *)tag->name.prefix;
2446 if (ns_triplets && prefix) {
2447 *uri++ = namespaceSeparator;
2448 while (*prefix) *uri++ = *prefix++;
2450 *uri = XML_T('\0');
2452 endElementHandler(handlerArg, tag->name.str);
2454 else if (defaultHandler)
2455 reportDefault(parser, enc, s, next);
2456 while (tag->bindings) {
2457 BINDING *b = tag->bindings;
2458 if (endNamespaceDeclHandler)
2459 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2460 tag->bindings = tag->bindings->nextTagBinding;
2461 b->nextTagBinding = freeBindingList;
2462 freeBindingList = b;
2463 b->prefix->binding = b->prevPrefixBinding;
2465 if (tagLevel == 0)
2466 return epilogProcessor(parser, next, end, nextPtr);
2468 break;
2469 case XML_TOK_CHAR_REF:
2471 int n = XmlCharRefNumber(enc, s);
2472 if (n < 0)
2473 return XML_ERROR_BAD_CHAR_REF;
2474 if (characterDataHandler) {
2475 XML_Char buf[XML_ENCODE_MAX];
2476 characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
2478 else if (defaultHandler)
2479 reportDefault(parser, enc, s, next);
2481 break;
2482 case XML_TOK_XML_DECL:
2483 return XML_ERROR_MISPLACED_XML_PI;
2484 case XML_TOK_DATA_NEWLINE:
2485 if (characterDataHandler) {
2486 XML_Char c = 0xA;
2487 characterDataHandler(handlerArg, &c, 1);
2489 else if (defaultHandler)
2490 reportDefault(parser, enc, s, next);
2491 break;
2492 case XML_TOK_CDATA_SECT_OPEN:
2494 enum XML_Error result;
2495 if (startCdataSectionHandler)
2496 startCdataSectionHandler(handlerArg);
2497 #if 0
2498 /* Suppose you doing a transformation on a document that involves
2499 changing only the character data. You set up a defaultHandler
2500 and a characterDataHandler. The defaultHandler simply copies
2501 characters through. The characterDataHandler does the
2502 transformation and writes the characters out escaping them as
2503 necessary. This case will fail to work if we leave out the
2504 following two lines (because & and < inside CDATA sections will
2505 be incorrectly escaped).
2507 However, now we have a start/endCdataSectionHandler, so it seems
2508 easier to let the user deal with this.
2510 else if (characterDataHandler)
2511 characterDataHandler(handlerArg, dataBuf, 0);
2512 #endif
2513 else if (defaultHandler)
2514 reportDefault(parser, enc, s, next);
2515 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
2516 if (result != XML_ERROR_NONE)
2517 return result;
2518 else if (!next) {
2519 processor = cdataSectionProcessor;
2520 return result;
2523 break;
2524 case XML_TOK_TRAILING_RSQB:
2525 if (haveMore) {
2526 *nextPtr = s;
2527 return XML_ERROR_NONE;
2529 if (characterDataHandler) {
2530 if (MUST_CONVERT(enc, s)) {
2531 ICHAR *dataPtr = (ICHAR *)dataBuf;
2532 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
2533 characterDataHandler(handlerArg, dataBuf,
2534 (int)(dataPtr - (ICHAR *)dataBuf));
2536 else
2537 characterDataHandler(handlerArg,
2538 (XML_Char *)s,
2539 (int)((XML_Char *)end - (XML_Char *)s));
2541 else if (defaultHandler)
2542 reportDefault(parser, enc, s, end);
2543 /* We are at the end of the final buffer, should we check for
2544 XML_SUSPENDED, XML_FINISHED?
2546 if (startTagLevel == 0) {
2547 *eventPP = end;
2548 return XML_ERROR_NO_ELEMENTS;
2550 if (tagLevel != startTagLevel) {
2551 *eventPP = end;
2552 return XML_ERROR_ASYNC_ENTITY;
2554 *nextPtr = end;
2555 return XML_ERROR_NONE;
2556 case XML_TOK_DATA_CHARS:
2558 XML_CharacterDataHandler charDataHandler = characterDataHandler;
2559 if (charDataHandler) {
2560 if (MUST_CONVERT(enc, s)) {
2561 for (;;) {
2562 ICHAR *dataPtr = (ICHAR *)dataBuf;
2563 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
2564 *eventEndPP = s;
2565 charDataHandler(handlerArg, dataBuf,
2566 (int)(dataPtr - (ICHAR *)dataBuf));
2567 if (s == next)
2568 break;
2569 *eventPP = s;
2572 else
2573 charDataHandler(handlerArg,
2574 (XML_Char *)s,
2575 (int)((XML_Char *)next - (XML_Char *)s));
2577 else if (defaultHandler)
2578 reportDefault(parser, enc, s, next);
2580 break;
2581 case XML_TOK_PI:
2582 if (!reportProcessingInstruction(parser, enc, s, next))
2583 return XML_ERROR_NO_MEMORY;
2584 break;
2585 case XML_TOK_COMMENT:
2586 if (!reportComment(parser, enc, s, next))
2587 return XML_ERROR_NO_MEMORY;
2588 break;
2589 default:
2590 if (defaultHandler)
2591 reportDefault(parser, enc, s, next);
2592 break;
2594 *eventPP = s = next;
2595 switch (ps_parsing) {
2596 case XML_SUSPENDED:
2597 *nextPtr = next;
2598 return XML_ERROR_NONE;
2599 case XML_FINISHED:
2600 return XML_ERROR_ABORTED;
2601 default: ;
2604 /* not reached */
2607 /* Precondition: all arguments must be non-NULL;
2608 Purpose:
2609 - normalize attributes
2610 - check attributes for well-formedness
2611 - generate namespace aware attribute names (URI, prefix)
2612 - build list of attributes for startElementHandler
2613 - default attributes
2614 - process namespace declarations (check and report them)
2615 - generate namespace aware element name (URI, prefix)
2617 static enum XML_Error
2618 storeAtts(XML_Parser parser, const ENCODING *enc,
2619 const char *attStr, TAG_NAME *tagNamePtr,
2620 BINDING **bindingsPtr)
2622 DTD * const dtd = _dtd; /* save one level of indirection */
2623 ELEMENT_TYPE *elementType;
2624 int nDefaultAtts;
2625 const XML_Char **appAtts; /* the attribute list for the application */
2626 int attIndex = 0;
2627 int prefixLen;
2628 int i;
2629 int n;
2630 XML_Char *uri;
2631 int nPrefixes = 0;
2632 BINDING *binding;
2633 const XML_Char *localPart;
2635 /* lookup the element type name */
2636 elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0);
2637 if (!elementType) {
2638 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
2639 if (!name)
2640 return XML_ERROR_NO_MEMORY;
2641 elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name,
2642 sizeof(ELEMENT_TYPE));
2643 if (!elementType)
2644 return XML_ERROR_NO_MEMORY;
2645 if (ns && !setElementTypePrefix(parser, elementType))
2646 return XML_ERROR_NO_MEMORY;
2648 nDefaultAtts = elementType->nDefaultAtts;
2650 /* get the attributes from the tokenizer */
2651 n = XmlGetAttributes(enc, attStr, attsSize, atts);
2652 if (n + nDefaultAtts > attsSize) {
2653 int oldAttsSize = attsSize;
2654 ATTRIBUTE *temp;
2655 attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
2656 temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
2657 if (temp == NULL)
2658 return XML_ERROR_NO_MEMORY;
2659 atts = temp;
2660 if (n > oldAttsSize)
2661 XmlGetAttributes(enc, attStr, n, atts);
2664 appAtts = (const XML_Char **)atts;
2665 for (i = 0; i < n; i++) {
2666 /* add the name and value to the attribute list */
2667 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
2668 atts[i].name
2669 + XmlNameLength(enc, atts[i].name));
2670 if (!attId)
2671 return XML_ERROR_NO_MEMORY;
2672 /* Detect duplicate attributes by their QNames. This does not work when
2673 namespace processing is turned on and different prefixes for the same
2674 namespace are used. For this case we have a check further down.
2676 if ((attId->name)[-1]) {
2677 if (enc == encoding)
2678 eventPtr = atts[i].name;
2679 return XML_ERROR_DUPLICATE_ATTRIBUTE;
2681 (attId->name)[-1] = 1;
2682 appAtts[attIndex++] = attId->name;
2683 if (!atts[i].normalized) {
2684 enum XML_Error result;
2685 XML_Bool isCdata = XML_TRUE;
2687 /* figure out whether declared as other than CDATA */
2688 if (attId->maybeTokenized) {
2689 int j;
2690 for (j = 0; j < nDefaultAtts; j++) {
2691 if (attId == elementType->defaultAtts[j].id) {
2692 isCdata = elementType->defaultAtts[j].isCdata;
2693 break;
2698 /* normalize the attribute value */
2699 result = storeAttributeValue(parser, enc, isCdata,
2700 atts[i].valuePtr, atts[i].valueEnd,
2701 &tempPool);
2702 if (result)
2703 return result;
2704 appAtts[attIndex] = poolStart(&tempPool);
2705 poolFinish(&tempPool);
2707 else {
2708 /* the value did not need normalizing */
2709 appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
2710 atts[i].valueEnd);
2711 if (appAtts[attIndex] == 0)
2712 return XML_ERROR_NO_MEMORY;
2713 poolFinish(&tempPool);
2715 /* handle prefixed attribute names */
2716 if (attId->prefix) {
2717 if (attId->xmlns) {
2718 /* deal with namespace declarations here */
2719 enum XML_Error result = addBinding(parser, attId->prefix, attId,
2720 appAtts[attIndex], bindingsPtr);
2721 if (result)
2722 return result;
2723 --attIndex;
2725 else {
2726 /* deal with other prefixed names later */
2727 attIndex++;
2728 nPrefixes++;
2729 (attId->name)[-1] = 2;
2732 else
2733 attIndex++;
2736 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
2737 nSpecifiedAtts = attIndex;
2738 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
2739 for (i = 0; i < attIndex; i += 2)
2740 if (appAtts[i] == elementType->idAtt->name) {
2741 idAttIndex = i;
2742 break;
2745 else
2746 idAttIndex = -1;
2748 /* do attribute defaulting */
2749 for (i = 0; i < nDefaultAtts; i++) {
2750 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
2751 if (!(da->id->name)[-1] && da->value) {
2752 if (da->id->prefix) {
2753 if (da->id->xmlns) {
2754 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
2755 da->value, bindingsPtr);
2756 if (result)
2757 return result;
2759 else {
2760 (da->id->name)[-1] = 2;
2761 nPrefixes++;
2762 appAtts[attIndex++] = da->id->name;
2763 appAtts[attIndex++] = da->value;
2766 else {
2767 (da->id->name)[-1] = 1;
2768 appAtts[attIndex++] = da->id->name;
2769 appAtts[attIndex++] = da->value;
2773 appAtts[attIndex] = 0;
2775 /* expand prefixed attribute names, check for duplicates,
2776 and clear flags that say whether attributes were specified */
2777 i = 0;
2778 if (nPrefixes) {
2779 int j; /* hash table index */
2780 unsigned long version = nsAttsVersion;
2781 int nsAttsSize = (int)1 << nsAttsPower;
2782 /* size of hash table must be at least 2 * (# of prefixed attributes) */
2783 if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */
2784 NS_ATT *temp;
2785 /* hash table size must also be a power of 2 and >= 8 */
2786 while (nPrefixes >> nsAttsPower++);
2787 if (nsAttsPower < 3)
2788 nsAttsPower = 3;
2789 nsAttsSize = (int)1 << nsAttsPower;
2790 temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
2791 if (!temp)
2792 return XML_ERROR_NO_MEMORY;
2793 nsAtts = temp;
2794 version = 0; /* force re-initialization of nsAtts hash table */
2796 /* using a version flag saves us from initializing nsAtts every time */
2797 if (!version) { /* initialize version flags when version wraps around */
2798 version = INIT_ATTS_VERSION;
2799 for (j = nsAttsSize; j != 0; )
2800 nsAtts[--j].version = version;
2802 nsAttsVersion = --version;
2804 /* expand prefixed names and check for duplicates */
2805 for (; i < attIndex; i += 2) {
2806 const XML_Char *s = appAtts[i];
2807 if (s[-1] == 2) { /* prefixed */
2808 ATTRIBUTE_ID *id;
2809 const BINDING *b;
2810 unsigned long uriHash = 0;
2811 ((XML_Char *)s)[-1] = 0; /* clear flag */
2812 id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);
2813 b = id->prefix->binding;
2814 if (!b)
2815 return XML_ERROR_UNBOUND_PREFIX;
2817 /* as we expand the name we also calculate its hash value */
2818 for (j = 0; j < b->uriLen; j++) {
2819 const XML_Char c = b->uri[j];
2820 if (!poolAppendChar(&tempPool, c))
2821 return XML_ERROR_NO_MEMORY;
2822 uriHash = CHAR_HASH(uriHash, c);
2824 while (*s++ != XML_T(ASCII_COLON))
2826 do { /* copies null terminator */
2827 const XML_Char c = *s;
2828 if (!poolAppendChar(&tempPool, *s))
2829 return XML_ERROR_NO_MEMORY;
2830 uriHash = CHAR_HASH(uriHash, c);
2831 } while (*s++);
2833 { /* Check hash table for duplicate of expanded name (uriName).
2834 Derived from code in lookup(HASH_TABLE *table, ...).
2836 unsigned char step = 0;
2837 unsigned long mask = nsAttsSize - 1;
2838 j = uriHash & mask; /* index into hash table */
2839 while (nsAtts[j].version == version) {
2840 /* for speed we compare stored hash values first */
2841 if (uriHash == nsAtts[j].hash) {
2842 const XML_Char *s1 = poolStart(&tempPool);
2843 const XML_Char *s2 = nsAtts[j].uriName;
2844 /* s1 is null terminated, but not s2 */
2845 for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
2846 if (*s1 == 0)
2847 return XML_ERROR_DUPLICATE_ATTRIBUTE;
2849 if (!step)
2850 step = PROBE_STEP(uriHash, mask, nsAttsPower);
2851 j < step ? (j += nsAttsSize - step) : (j -= step);
2855 if (ns_triplets) { /* append namespace separator and prefix */
2856 tempPool.ptr[-1] = namespaceSeparator;
2857 s = b->prefix->name;
2858 do {
2859 if (!poolAppendChar(&tempPool, *s))
2860 return XML_ERROR_NO_MEMORY;
2861 } while (*s++);
2864 /* store expanded name in attribute list */
2865 s = poolStart(&tempPool);
2866 poolFinish(&tempPool);
2867 appAtts[i] = s;
2869 /* fill empty slot with new version, uriName and hash value */
2870 nsAtts[j].version = version;
2871 nsAtts[j].hash = uriHash;
2872 nsAtts[j].uriName = s;
2874 if (!--nPrefixes) {
2875 i += 2;
2876 break;
2879 else /* not prefixed */
2880 ((XML_Char *)s)[-1] = 0; /* clear flag */
2883 /* clear flags for the remaining attributes */
2884 for (; i < attIndex; i += 2)
2885 ((XML_Char *)(appAtts[i]))[-1] = 0;
2886 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
2887 binding->attId->name[-1] = 0;
2889 if (!ns)
2890 return XML_ERROR_NONE;
2892 /* expand the element type name */
2893 if (elementType->prefix) {
2894 binding = elementType->prefix->binding;
2895 if (!binding)
2896 return XML_ERROR_UNBOUND_PREFIX;
2897 localPart = tagNamePtr->str;
2898 while (*localPart++ != XML_T(ASCII_COLON))
2901 else if (dtd->defaultPrefix.binding) {
2902 binding = dtd->defaultPrefix.binding;
2903 localPart = tagNamePtr->str;
2905 else
2906 return XML_ERROR_NONE;
2907 prefixLen = 0;
2908 if (ns_triplets && binding->prefix->name) {
2909 for (; binding->prefix->name[prefixLen++];)
2910 ; /* prefixLen includes null terminator */
2912 tagNamePtr->localPart = localPart;
2913 tagNamePtr->uriLen = binding->uriLen;
2914 tagNamePtr->prefix = binding->prefix->name;
2915 tagNamePtr->prefixLen = prefixLen;
2916 for (i = 0; localPart[i++];)
2917 ; /* i includes null terminator */
2918 n = i + binding->uriLen + prefixLen;
2919 if (n > binding->uriAlloc) {
2920 TAG *p;
2921 uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
2922 if (!uri)
2923 return XML_ERROR_NO_MEMORY;
2924 binding->uriAlloc = n + EXPAND_SPARE;
2925 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
2926 for (p = tagStack; p; p = p->parent)
2927 if (p->name.str == binding->uri)
2928 p->name.str = uri;
2929 FREE(binding->uri);
2930 binding->uri = uri;
2932 /* if namespaceSeparator != '\0' then uri includes it already */
2933 uri = binding->uri + binding->uriLen;
2934 memcpy(uri, localPart, i * sizeof(XML_Char));
2935 /* we always have a namespace separator between localPart and prefix */
2936 if (prefixLen) {
2937 uri += i - 1;
2938 *uri = namespaceSeparator; /* replace null terminator */
2939 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
2941 tagNamePtr->str = binding->uri;
2942 return XML_ERROR_NONE;
2945 /* addBinding() overwrites the value of prefix->binding without checking.
2946 Therefore one must keep track of the old value outside of addBinding().
2948 static enum XML_Error
2949 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
2950 const XML_Char *uri, BINDING **bindingsPtr)
2952 static const XML_Char xmlNamespace[] = {
2953 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
2954 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
2955 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
2956 ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
2957 ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
2958 ASCII_e, '\0'
2960 static const int xmlLen =
2961 (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
2962 static const XML_Char xmlnsNamespace[] = {
2963 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
2964 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
2965 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
2966 ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
2967 ASCII_SLASH, '\0'
2969 static const int xmlnsLen =
2970 (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
2972 XML_Bool mustBeXML = XML_FALSE;
2973 XML_Bool isXML = XML_TRUE;
2974 XML_Bool isXMLNS = XML_TRUE;
2976 BINDING *b;
2977 int len;
2979 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
2980 if (*uri == XML_T('\0') && prefix->name)
2981 return XML_ERROR_UNDECLARING_PREFIX;
2983 if (prefix->name
2984 && prefix->name[0] == XML_T(ASCII_x)
2985 && prefix->name[1] == XML_T(ASCII_m)
2986 && prefix->name[2] == XML_T(ASCII_l)) {
2988 /* Not allowed to bind xmlns */
2989 if (prefix->name[3] == XML_T(ASCII_n)
2990 && prefix->name[4] == XML_T(ASCII_s)
2991 && prefix->name[5] == XML_T('\0'))
2992 return XML_ERROR_RESERVED_PREFIX_XMLNS;
2994 if (prefix->name[3] == XML_T('\0'))
2995 mustBeXML = XML_TRUE;
2998 for (len = 0; uri[len]; len++) {
2999 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
3000 isXML = XML_FALSE;
3002 if (!mustBeXML && isXMLNS
3003 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3004 isXMLNS = XML_FALSE;
3006 isXML = isXML && len == xmlLen;
3007 isXMLNS = isXMLNS && len == xmlnsLen;
3009 if (mustBeXML != isXML)
3010 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3011 : XML_ERROR_RESERVED_NAMESPACE_URI;
3013 if (isXMLNS)
3014 return XML_ERROR_RESERVED_NAMESPACE_URI;
3016 if (namespaceSeparator)
3017 len++;
3018 if (freeBindingList) {
3019 b = freeBindingList;
3020 if (len > b->uriAlloc) {
3021 XML_Char *temp = (XML_Char *)REALLOC(b->uri,
3022 sizeof(XML_Char) * (len + EXPAND_SPARE));
3023 if (temp == NULL)
3024 return XML_ERROR_NO_MEMORY;
3025 b->uri = temp;
3026 b->uriAlloc = len + EXPAND_SPARE;
3028 freeBindingList = b->nextTagBinding;
3030 else {
3031 b = (BINDING *)MALLOC(sizeof(BINDING));
3032 if (!b)
3033 return XML_ERROR_NO_MEMORY;
3034 b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
3035 if (!b->uri) {
3036 FREE(b);
3037 return XML_ERROR_NO_MEMORY;
3039 b->uriAlloc = len + EXPAND_SPARE;
3041 b->uriLen = len;
3042 memcpy(b->uri, uri, len * sizeof(XML_Char));
3043 if (namespaceSeparator)
3044 b->uri[len - 1] = namespaceSeparator;
3045 b->prefix = prefix;
3046 b->attId = attId;
3047 b->prevPrefixBinding = prefix->binding;
3048 /* NULL binding when default namespace undeclared */
3049 if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
3050 prefix->binding = NULL;
3051 else
3052 prefix->binding = b;
3053 b->nextTagBinding = *bindingsPtr;
3054 *bindingsPtr = b;
3055 /* if attId == NULL then we are not starting a namespace scope */
3056 if (attId && startNamespaceDeclHandler)
3057 startNamespaceDeclHandler(handlerArg, prefix->name,
3058 prefix->binding ? uri : 0);
3059 return XML_ERROR_NONE;
3062 /* The idea here is to avoid using stack for each CDATA section when
3063 the whole file is parsed with one call.
3065 static enum XML_Error PTRCALL
3066 cdataSectionProcessor(XML_Parser parser,
3067 const char *start,
3068 const char *end,
3069 const char **endPtr)
3071 enum XML_Error result = doCdataSection(parser, encoding, &start, end,
3072 endPtr, (XML_Bool)!ps_finalBuffer);
3073 if (result != XML_ERROR_NONE)
3074 return result;
3075 if (start) {
3076 if (parentParser) { /* we are parsing an external entity */
3077 processor = externalEntityContentProcessor;
3078 return externalEntityContentProcessor(parser, start, end, endPtr);
3080 else {
3081 processor = contentProcessor;
3082 return contentProcessor(parser, start, end, endPtr);
3085 return result;
3088 /* startPtr gets set to non-null if the section is closed, and to null if
3089 the section is not yet closed.
3091 static enum XML_Error
3092 doCdataSection(XML_Parser parser,
3093 const ENCODING *enc,
3094 const char **startPtr,
3095 const char *end,
3096 const char **nextPtr,
3097 XML_Bool haveMore)
3099 const char *s = *startPtr;
3100 const char **eventPP;
3101 const char **eventEndPP;
3102 if (enc == encoding) {
3103 eventPP = &eventPtr;
3104 *eventPP = s;
3105 eventEndPP = &eventEndPtr;
3107 else {
3108 eventPP = &(openInternalEntities->internalEventPtr);
3109 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3111 *eventPP = s;
3112 *startPtr = NULL;
3114 for (;;) {
3115 const char *next;
3116 int tok = XmlCdataSectionTok(enc, s, end, &next);
3117 *eventEndPP = next;
3118 switch (tok) {
3119 case XML_TOK_CDATA_SECT_CLOSE:
3120 if (endCdataSectionHandler)
3121 endCdataSectionHandler(handlerArg);
3122 #if 0
3123 /* see comment under XML_TOK_CDATA_SECT_OPEN */
3124 else if (characterDataHandler)
3125 characterDataHandler(handlerArg, dataBuf, 0);
3126 #endif
3127 else if (defaultHandler)
3128 reportDefault(parser, enc, s, next);
3129 *startPtr = next;
3130 *nextPtr = next;
3131 if (ps_parsing == XML_FINISHED)
3132 return XML_ERROR_ABORTED;
3133 else
3134 return XML_ERROR_NONE;
3135 case XML_TOK_DATA_NEWLINE:
3136 if (characterDataHandler) {
3137 XML_Char c = 0xA;
3138 characterDataHandler(handlerArg, &c, 1);
3140 else if (defaultHandler)
3141 reportDefault(parser, enc, s, next);
3142 break;
3143 case XML_TOK_DATA_CHARS:
3145 XML_CharacterDataHandler charDataHandler = characterDataHandler;
3146 if (charDataHandler) {
3147 if (MUST_CONVERT(enc, s)) {
3148 for (;;) {
3149 ICHAR *dataPtr = (ICHAR *)dataBuf;
3150 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
3151 *eventEndPP = next;
3152 charDataHandler(handlerArg, dataBuf,
3153 (int)(dataPtr - (ICHAR *)dataBuf));
3154 if (s == next)
3155 break;
3156 *eventPP = s;
3159 else
3160 charDataHandler(handlerArg,
3161 (XML_Char *)s,
3162 (int)((XML_Char *)next - (XML_Char *)s));
3164 else if (defaultHandler)
3165 reportDefault(parser, enc, s, next);
3167 break;
3168 case XML_TOK_INVALID:
3169 *eventPP = next;
3170 return XML_ERROR_INVALID_TOKEN;
3171 case XML_TOK_PARTIAL_CHAR:
3172 if (haveMore) {
3173 *nextPtr = s;
3174 return XML_ERROR_NONE;
3176 return XML_ERROR_PARTIAL_CHAR;
3177 case XML_TOK_PARTIAL:
3178 case XML_TOK_NONE:
3179 if (haveMore) {
3180 *nextPtr = s;
3181 return XML_ERROR_NONE;
3183 return XML_ERROR_UNCLOSED_CDATA_SECTION;
3184 default:
3185 *eventPP = next;
3186 return XML_ERROR_UNEXPECTED_STATE;
3189 *eventPP = s = next;
3190 switch (ps_parsing) {
3191 case XML_SUSPENDED:
3192 *nextPtr = next;
3193 return XML_ERROR_NONE;
3194 case XML_FINISHED:
3195 return XML_ERROR_ABORTED;
3196 default: ;
3199 /* not reached */
3202 #ifdef XML_DTD
3204 /* The idea here is to avoid using stack for each IGNORE section when
3205 the whole file is parsed with one call.
3207 static enum XML_Error PTRCALL
3208 ignoreSectionProcessor(XML_Parser parser,
3209 const char *start,
3210 const char *end,
3211 const char **endPtr)
3213 enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
3214 endPtr, (XML_Bool)!ps_finalBuffer);
3215 if (result != XML_ERROR_NONE)
3216 return result;
3217 if (start) {
3218 processor = prologProcessor;
3219 return prologProcessor(parser, start, end, endPtr);
3221 return result;
3224 /* startPtr gets set to non-null is the section is closed, and to null
3225 if the section is not yet closed.
3227 static enum XML_Error
3228 doIgnoreSection(XML_Parser parser,
3229 const ENCODING *enc,
3230 const char **startPtr,
3231 const char *end,
3232 const char **nextPtr,
3233 XML_Bool haveMore)
3235 const char *next;
3236 int tok;
3237 const char *s = *startPtr;
3238 const char **eventPP;
3239 const char **eventEndPP;
3240 if (enc == encoding) {
3241 eventPP = &eventPtr;
3242 *eventPP = s;
3243 eventEndPP = &eventEndPtr;
3245 else {
3246 eventPP = &(openInternalEntities->internalEventPtr);
3247 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3249 *eventPP = s;
3250 *startPtr = NULL;
3251 tok = XmlIgnoreSectionTok(enc, s, end, &next);
3252 *eventEndPP = next;
3253 switch (tok) {
3254 case XML_TOK_IGNORE_SECT:
3255 if (defaultHandler)
3256 reportDefault(parser, enc, s, next);
3257 *startPtr = next;
3258 *nextPtr = next;
3259 if (ps_parsing == XML_FINISHED)
3260 return XML_ERROR_ABORTED;
3261 else
3262 return XML_ERROR_NONE;
3263 case XML_TOK_INVALID:
3264 *eventPP = next;
3265 return XML_ERROR_INVALID_TOKEN;
3266 case XML_TOK_PARTIAL_CHAR:
3267 if (haveMore) {
3268 *nextPtr = s;
3269 return XML_ERROR_NONE;
3271 return XML_ERROR_PARTIAL_CHAR;
3272 case XML_TOK_PARTIAL:
3273 case XML_TOK_NONE:
3274 if (haveMore) {
3275 *nextPtr = s;
3276 return XML_ERROR_NONE;
3278 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3279 default:
3280 *eventPP = next;
3281 return XML_ERROR_UNEXPECTED_STATE;
3283 /* not reached */
3286 #endif /* XML_DTD */
3288 static enum XML_Error
3289 initializeEncoding(XML_Parser parser)
3291 const char *s;
3292 #ifdef XML_UNICODE
3293 char encodingBuf[128];
3294 if (!protocolEncodingName)
3295 s = NULL;
3296 else {
3297 int i;
3298 for (i = 0; protocolEncodingName[i]; i++) {
3299 if (i == sizeof(encodingBuf) - 1
3300 || (protocolEncodingName[i] & ~0x7f) != 0) {
3301 encodingBuf[0] = '\0';
3302 break;
3304 encodingBuf[i] = (char)protocolEncodingName[i];
3306 encodingBuf[i] = '\0';
3307 s = encodingBuf;
3309 #else
3310 s = protocolEncodingName;
3311 #endif
3312 if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
3313 return XML_ERROR_NONE;
3314 return handleUnknownEncoding(parser, protocolEncodingName);
3317 static enum XML_Error
3318 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
3319 const char *s, const char *next)
3321 const char *encodingName = NULL;
3322 const XML_Char *storedEncName = NULL;
3323 const ENCODING *newEncoding = NULL;
3324 const char *version = NULL;
3325 const char *versionend;
3326 const XML_Char *storedversion = NULL;
3327 int standalone = -1;
3328 if (!(ns
3329 ? XmlParseXmlDeclNS
3330 : XmlParseXmlDecl)(isGeneralTextEntity,
3331 encoding,
3333 next,
3334 &eventPtr,
3335 &version,
3336 &versionend,
3337 &encodingName,
3338 &newEncoding,
3339 &standalone)) {
3340 if (isGeneralTextEntity)
3341 return XML_ERROR_TEXT_DECL;
3342 else
3343 return XML_ERROR_XML_DECL;
3345 if (!isGeneralTextEntity && standalone == 1) {
3346 _dtd->standalone = XML_TRUE;
3347 #ifdef XML_DTD
3348 if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
3349 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
3350 #endif /* XML_DTD */
3352 if (xmlDeclHandler) {
3353 if (encodingName != NULL) {
3354 storedEncName = poolStoreString(&temp2Pool,
3355 encoding,
3356 encodingName,
3357 encodingName
3358 + XmlNameLength(encoding, encodingName));
3359 if (!storedEncName)
3360 return XML_ERROR_NO_MEMORY;
3361 poolFinish(&temp2Pool);
3363 if (version) {
3364 storedversion = poolStoreString(&temp2Pool,
3365 encoding,
3366 version,
3367 versionend - encoding->minBytesPerChar);
3368 if (!storedversion)
3369 return XML_ERROR_NO_MEMORY;
3371 xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
3373 else if (defaultHandler)
3374 reportDefault(parser, encoding, s, next);
3375 if (protocolEncodingName == NULL) {
3376 if (newEncoding) {
3377 if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
3378 eventPtr = encodingName;
3379 return XML_ERROR_INCORRECT_ENCODING;
3381 encoding = newEncoding;
3383 else if (encodingName) {
3384 enum XML_Error result;
3385 if (!storedEncName) {
3386 storedEncName = poolStoreString(
3387 &temp2Pool, encoding, encodingName,
3388 encodingName + XmlNameLength(encoding, encodingName));
3389 if (!storedEncName)
3390 return XML_ERROR_NO_MEMORY;
3392 result = handleUnknownEncoding(parser, storedEncName);
3393 poolClear(&temp2Pool);
3394 if (result == XML_ERROR_UNKNOWN_ENCODING)
3395 eventPtr = encodingName;
3396 return result;
3400 if (storedEncName || storedversion)
3401 poolClear(&temp2Pool);
3403 return XML_ERROR_NONE;
3406 static enum XML_Error
3407 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
3409 if (unknownEncodingHandler) {
3410 XML_Encoding info;
3411 int i;
3412 for (i = 0; i < 256; i++)
3413 info.map[i] = -1;
3414 info.convert = NULL;
3415 info.data = NULL;
3416 info.release = NULL;
3417 if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
3418 &info)) {
3419 ENCODING *enc;
3420 unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
3421 if (!unknownEncodingMem) {
3422 if (info.release)
3423 info.release(info.data);
3424 return XML_ERROR_NO_MEMORY;
3426 enc = (ns
3427 ? XmlInitUnknownEncodingNS
3428 : XmlInitUnknownEncoding)(unknownEncodingMem,
3429 info.map,
3430 info.convert,
3431 info.data);
3432 if (enc) {
3433 unknownEncodingData = info.data;
3434 unknownEncodingRelease = info.release;
3435 encoding = enc;
3436 return XML_ERROR_NONE;
3439 if (info.release != NULL)
3440 info.release(info.data);
3442 return XML_ERROR_UNKNOWN_ENCODING;
3445 static enum XML_Error PTRCALL
3446 prologInitProcessor(XML_Parser parser,
3447 const char *s,
3448 const char *end,
3449 const char **nextPtr)
3451 enum XML_Error result = initializeEncoding(parser);
3452 if (result != XML_ERROR_NONE)
3453 return result;
3454 processor = prologProcessor;
3455 return prologProcessor(parser, s, end, nextPtr);
3458 #ifdef XML_DTD
3460 static enum XML_Error PTRCALL
3461 externalParEntInitProcessor(XML_Parser parser,
3462 const char *s,
3463 const char *end,
3464 const char **nextPtr)
3466 enum XML_Error result = initializeEncoding(parser);
3467 if (result != XML_ERROR_NONE)
3468 return result;
3470 /* we know now that XML_Parse(Buffer) has been called,
3471 so we consider the external parameter entity read */
3472 _dtd->paramEntityRead = XML_TRUE;
3474 if (prologState.inEntityValue) {
3475 processor = entityValueInitProcessor;
3476 return entityValueInitProcessor(parser, s, end, nextPtr);
3478 else {
3479 processor = externalParEntProcessor;
3480 return externalParEntProcessor(parser, s, end, nextPtr);
3484 static enum XML_Error PTRCALL
3485 entityValueInitProcessor(XML_Parser parser,
3486 const char *s,
3487 const char *end,
3488 const char **nextPtr)
3490 int tok;
3491 const char *start = s;
3492 const char *next = start;
3493 eventPtr = start;
3495 for (;;) {
3496 tok = XmlPrologTok(encoding, start, end, &next);
3497 eventEndPtr = next;
3498 if (tok <= 0) {
3499 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3500 *nextPtr = s;
3501 return XML_ERROR_NONE;
3503 switch (tok) {
3504 case XML_TOK_INVALID:
3505 return XML_ERROR_INVALID_TOKEN;
3506 case XML_TOK_PARTIAL:
3507 return XML_ERROR_UNCLOSED_TOKEN;
3508 case XML_TOK_PARTIAL_CHAR:
3509 return XML_ERROR_PARTIAL_CHAR;
3510 case XML_TOK_NONE: /* start == end */
3511 default:
3512 break;
3514 /* found end of entity value - can store it now */
3515 return storeEntityValue(parser, encoding, s, end);
3517 else if (tok == XML_TOK_XML_DECL) {
3518 enum XML_Error result;
3519 result = processXmlDecl(parser, 0, start, next);
3520 if (result != XML_ERROR_NONE)
3521 return result;
3522 switch (ps_parsing) {
3523 case XML_SUSPENDED:
3524 *nextPtr = next;
3525 return XML_ERROR_NONE;
3526 case XML_FINISHED:
3527 return XML_ERROR_ABORTED;
3528 default:
3529 *nextPtr = next;
3531 /* stop scanning for text declaration - we found one */
3532 processor = entityValueProcessor;
3533 return entityValueProcessor(parser, next, end, nextPtr);
3535 /* If we are at the end of the buffer, this would cause XmlPrologTok to
3536 return XML_TOK_NONE on the next call, which would then cause the
3537 function to exit with *nextPtr set to s - that is what we want for other
3538 tokens, but not for the BOM - we would rather like to skip it;
3539 then, when this routine is entered the next time, XmlPrologTok will
3540 return XML_TOK_INVALID, since the BOM is still in the buffer
3542 else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
3543 *nextPtr = next;
3544 return XML_ERROR_NONE;
3546 start = next;
3547 eventPtr = start;
3551 static enum XML_Error PTRCALL
3552 externalParEntProcessor(XML_Parser parser,
3553 const char *s,
3554 const char *end,
3555 const char **nextPtr)
3557 const char *next = s;
3558 int tok;
3560 tok = XmlPrologTok(encoding, s, end, &next);
3561 if (tok <= 0) {
3562 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3563 *nextPtr = s;
3564 return XML_ERROR_NONE;
3566 switch (tok) {
3567 case XML_TOK_INVALID:
3568 return XML_ERROR_INVALID_TOKEN;
3569 case XML_TOK_PARTIAL:
3570 return XML_ERROR_UNCLOSED_TOKEN;
3571 case XML_TOK_PARTIAL_CHAR:
3572 return XML_ERROR_PARTIAL_CHAR;
3573 case XML_TOK_NONE: /* start == end */
3574 default:
3575 break;
3578 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
3579 However, when parsing an external subset, doProlog will not accept a BOM
3580 as valid, and report a syntax error, so we have to skip the BOM
3582 else if (tok == XML_TOK_BOM) {
3583 s = next;
3584 tok = XmlPrologTok(encoding, s, end, &next);
3587 processor = prologProcessor;
3588 return doProlog(parser, encoding, s, end, tok, next,
3589 nextPtr, (XML_Bool)!ps_finalBuffer);
3592 static enum XML_Error PTRCALL
3593 entityValueProcessor(XML_Parser parser,
3594 const char *s,
3595 const char *end,
3596 const char **nextPtr)
3598 const char *start = s;
3599 const char *next = s;
3600 const ENCODING *enc = encoding;
3601 int tok;
3603 for (;;) {
3604 tok = XmlPrologTok(enc, start, end, &next);
3605 if (tok <= 0) {
3606 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3607 *nextPtr = s;
3608 return XML_ERROR_NONE;
3610 switch (tok) {
3611 case XML_TOK_INVALID:
3612 return XML_ERROR_INVALID_TOKEN;
3613 case XML_TOK_PARTIAL:
3614 return XML_ERROR_UNCLOSED_TOKEN;
3615 case XML_TOK_PARTIAL_CHAR:
3616 return XML_ERROR_PARTIAL_CHAR;
3617 case XML_TOK_NONE: /* start == end */
3618 default:
3619 break;
3621 /* found end of entity value - can store it now */
3622 return storeEntityValue(parser, enc, s, end);
3624 start = next;
3628 #endif /* XML_DTD */
3630 static enum XML_Error PTRCALL
3631 prologProcessor(XML_Parser parser,
3632 const char *s,
3633 const char *end,
3634 const char **nextPtr)
3636 const char *next = s;
3637 int tok = XmlPrologTok(encoding, s, end, &next);
3638 return doProlog(parser, encoding, s, end, tok, next,
3639 nextPtr, (XML_Bool)!ps_finalBuffer);
3642 static enum XML_Error
3643 doProlog(XML_Parser parser,
3644 const ENCODING *enc,
3645 const char *s,
3646 const char *end,
3647 int tok,
3648 const char *next,
3649 const char **nextPtr,
3650 XML_Bool haveMore)
3652 #ifdef XML_DTD
3653 static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
3654 #endif /* XML_DTD */
3655 static const XML_Char atypeCDATA[] =
3656 { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
3657 static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
3658 static const XML_Char atypeIDREF[] =
3659 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
3660 static const XML_Char atypeIDREFS[] =
3661 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
3662 static const XML_Char atypeENTITY[] =
3663 { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
3664 static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
3665 ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
3666 static const XML_Char atypeNMTOKEN[] = {
3667 ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
3668 static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
3669 ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
3670 static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
3671 ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
3672 static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
3673 static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
3675 /* save one level of indirection */
3676 DTD * const dtd = _dtd;
3678 const char **eventPP;
3679 const char **eventEndPP;
3680 enum XML_Content_Quant quant;
3682 if (enc == encoding) {
3683 eventPP = &eventPtr;
3684 eventEndPP = &eventEndPtr;
3686 else {
3687 eventPP = &(openInternalEntities->internalEventPtr);
3688 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3691 for (;;) {
3692 int role;
3693 XML_Bool handleDefault = XML_TRUE;
3694 *eventPP = s;
3695 *eventEndPP = next;
3696 if (tok <= 0) {
3697 if (haveMore && tok != XML_TOK_INVALID) {
3698 *nextPtr = s;
3699 return XML_ERROR_NONE;
3701 switch (tok) {
3702 case XML_TOK_INVALID:
3703 *eventPP = next;
3704 return XML_ERROR_INVALID_TOKEN;
3705 case XML_TOK_PARTIAL:
3706 return XML_ERROR_UNCLOSED_TOKEN;
3707 case XML_TOK_PARTIAL_CHAR:
3708 return XML_ERROR_PARTIAL_CHAR;
3709 case XML_TOK_NONE:
3710 #ifdef XML_DTD
3711 /* for internal PE NOT referenced between declarations */
3712 if (enc != encoding && !openInternalEntities->betweenDecl) {
3713 *nextPtr = s;
3714 return XML_ERROR_NONE;
3716 /* WFC: PE Between Declarations - must check that PE contains
3717 complete markup, not only for external PEs, but also for
3718 internal PEs if the reference occurs between declarations.
3720 if (isParamEntity || enc != encoding) {
3721 if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
3722 == XML_ROLE_ERROR)
3723 return XML_ERROR_INCOMPLETE_PE;
3724 *nextPtr = s;
3725 return XML_ERROR_NONE;
3727 #endif /* XML_DTD */
3728 return XML_ERROR_NO_ELEMENTS;
3729 default:
3730 tok = -tok;
3731 next = end;
3732 break;
3735 role = XmlTokenRole(&prologState, tok, s, next, enc);
3736 switch (role) {
3737 case XML_ROLE_XML_DECL:
3739 enum XML_Error result = processXmlDecl(parser, 0, s, next);
3740 if (result != XML_ERROR_NONE)
3741 return result;
3742 enc = encoding;
3743 handleDefault = XML_FALSE;
3745 break;
3746 case XML_ROLE_DOCTYPE_NAME:
3747 if (startDoctypeDeclHandler) {
3748 doctypeName = poolStoreString(&tempPool, enc, s, next);
3749 if (!doctypeName)
3750 return XML_ERROR_NO_MEMORY;
3751 poolFinish(&tempPool);
3752 doctypePubid = NULL;
3753 handleDefault = XML_FALSE;
3755 doctypeSysid = NULL; /* always initialize to NULL */
3756 break;
3757 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
3758 if (startDoctypeDeclHandler) {
3759 startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
3760 doctypePubid, 1);
3761 doctypeName = NULL;
3762 poolClear(&tempPool);
3763 handleDefault = XML_FALSE;
3765 break;
3766 #ifdef XML_DTD
3767 case XML_ROLE_TEXT_DECL:
3769 enum XML_Error result = processXmlDecl(parser, 1, s, next);
3770 if (result != XML_ERROR_NONE)
3771 return result;
3772 enc = encoding;
3773 handleDefault = XML_FALSE;
3775 break;
3776 #endif /* XML_DTD */
3777 case XML_ROLE_DOCTYPE_PUBLIC_ID:
3778 #ifdef XML_DTD
3779 useForeignDTD = XML_FALSE;
3780 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
3781 externalSubsetName,
3782 sizeof(ENTITY));
3783 if (!declEntity)
3784 return XML_ERROR_NO_MEMORY;
3785 #endif /* XML_DTD */
3786 dtd->hasParamEntityRefs = XML_TRUE;
3787 if (startDoctypeDeclHandler) {
3788 if (!XmlIsPublicId(enc, s, next, eventPP))
3789 return XML_ERROR_PUBLICID;
3790 doctypePubid = poolStoreString(&tempPool, enc,
3791 s + enc->minBytesPerChar,
3792 next - enc->minBytesPerChar);
3793 if (!doctypePubid)
3794 return XML_ERROR_NO_MEMORY;
3795 normalizePublicId((XML_Char *)doctypePubid);
3796 poolFinish(&tempPool);
3797 handleDefault = XML_FALSE;
3798 goto alreadyChecked;
3800 /* fall through */
3801 case XML_ROLE_ENTITY_PUBLIC_ID:
3802 if (!XmlIsPublicId(enc, s, next, eventPP))
3803 return XML_ERROR_PUBLICID;
3804 alreadyChecked:
3805 if (dtd->keepProcessing && declEntity) {
3806 XML_Char *tem = poolStoreString(&dtd->pool,
3807 enc,
3808 s + enc->minBytesPerChar,
3809 next - enc->minBytesPerChar);
3810 if (!tem)
3811 return XML_ERROR_NO_MEMORY;
3812 normalizePublicId(tem);
3813 declEntity->publicId = tem;
3814 poolFinish(&dtd->pool);
3815 if (entityDeclHandler)
3816 handleDefault = XML_FALSE;
3818 break;
3819 case XML_ROLE_DOCTYPE_CLOSE:
3820 if (doctypeName) {
3821 startDoctypeDeclHandler(handlerArg, doctypeName,
3822 doctypeSysid, doctypePubid, 0);
3823 poolClear(&tempPool);
3824 handleDefault = XML_FALSE;
3826 /* doctypeSysid will be non-NULL in the case of a previous
3827 XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
3828 was not set, indicating an external subset
3830 #ifdef XML_DTD
3831 if (doctypeSysid || useForeignDTD) {
3832 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3833 dtd->hasParamEntityRefs = XML_TRUE;
3834 if (paramEntityParsing && externalEntityRefHandler) {
3835 ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
3836 externalSubsetName,
3837 sizeof(ENTITY));
3838 if (!entity)
3839 return XML_ERROR_NO_MEMORY;
3840 if (useForeignDTD)
3841 entity->base = curBase;
3842 dtd->paramEntityRead = XML_FALSE;
3843 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3845 entity->base,
3846 entity->systemId,
3847 entity->publicId))
3848 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3849 if (dtd->paramEntityRead) {
3850 if (!dtd->standalone &&
3851 notStandaloneHandler &&
3852 !notStandaloneHandler(handlerArg))
3853 return XML_ERROR_NOT_STANDALONE;
3855 /* if we didn't read the foreign DTD then this means that there
3856 is no external subset and we must reset dtd->hasParamEntityRefs
3858 else if (!doctypeSysid)
3859 dtd->hasParamEntityRefs = hadParamEntityRefs;
3860 /* end of DTD - no need to update dtd->keepProcessing */
3862 useForeignDTD = XML_FALSE;
3864 #endif /* XML_DTD */
3865 if (endDoctypeDeclHandler) {
3866 endDoctypeDeclHandler(handlerArg);
3867 handleDefault = XML_FALSE;
3869 break;
3870 case XML_ROLE_INSTANCE_START:
3871 #ifdef XML_DTD
3872 /* if there is no DOCTYPE declaration then now is the
3873 last chance to read the foreign DTD
3875 if (useForeignDTD) {
3876 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3877 dtd->hasParamEntityRefs = XML_TRUE;
3878 if (paramEntityParsing && externalEntityRefHandler) {
3879 ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
3880 externalSubsetName,
3881 sizeof(ENTITY));
3882 if (!entity)
3883 return XML_ERROR_NO_MEMORY;
3884 entity->base = curBase;
3885 dtd->paramEntityRead = XML_FALSE;
3886 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3888 entity->base,
3889 entity->systemId,
3890 entity->publicId))
3891 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3892 if (dtd->paramEntityRead) {
3893 if (!dtd->standalone &&
3894 notStandaloneHandler &&
3895 !notStandaloneHandler(handlerArg))
3896 return XML_ERROR_NOT_STANDALONE;
3898 /* if we didn't read the foreign DTD then this means that there
3899 is no external subset and we must reset dtd->hasParamEntityRefs
3901 else
3902 dtd->hasParamEntityRefs = hadParamEntityRefs;
3903 /* end of DTD - no need to update dtd->keepProcessing */
3906 #endif /* XML_DTD */
3907 processor = contentProcessor;
3908 return contentProcessor(parser, s, end, nextPtr);
3909 case XML_ROLE_ATTLIST_ELEMENT_NAME:
3910 declElementType = getElementType(parser, enc, s, next);
3911 if (!declElementType)
3912 return XML_ERROR_NO_MEMORY;
3913 goto checkAttListDeclHandler;
3914 case XML_ROLE_ATTRIBUTE_NAME:
3915 declAttributeId = getAttributeId(parser, enc, s, next);
3916 if (!declAttributeId)
3917 return XML_ERROR_NO_MEMORY;
3918 declAttributeIsCdata = XML_FALSE;
3919 declAttributeType = NULL;
3920 declAttributeIsId = XML_FALSE;
3921 goto checkAttListDeclHandler;
3922 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
3923 declAttributeIsCdata = XML_TRUE;
3924 declAttributeType = atypeCDATA;
3925 goto checkAttListDeclHandler;
3926 case XML_ROLE_ATTRIBUTE_TYPE_ID:
3927 declAttributeIsId = XML_TRUE;
3928 declAttributeType = atypeID;
3929 goto checkAttListDeclHandler;
3930 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
3931 declAttributeType = atypeIDREF;
3932 goto checkAttListDeclHandler;
3933 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
3934 declAttributeType = atypeIDREFS;
3935 goto checkAttListDeclHandler;
3936 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
3937 declAttributeType = atypeENTITY;
3938 goto checkAttListDeclHandler;
3939 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
3940 declAttributeType = atypeENTITIES;
3941 goto checkAttListDeclHandler;
3942 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
3943 declAttributeType = atypeNMTOKEN;
3944 goto checkAttListDeclHandler;
3945 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
3946 declAttributeType = atypeNMTOKENS;
3947 checkAttListDeclHandler:
3948 if (dtd->keepProcessing && attlistDeclHandler)
3949 handleDefault = XML_FALSE;
3950 break;
3951 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
3952 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
3953 if (dtd->keepProcessing && attlistDeclHandler) {
3954 const XML_Char *prefix;
3955 if (declAttributeType) {
3956 prefix = enumValueSep;
3958 else {
3959 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
3960 ? notationPrefix
3961 : enumValueStart);
3963 if (!poolAppendString(&tempPool, prefix))
3964 return XML_ERROR_NO_MEMORY;
3965 if (!poolAppend(&tempPool, enc, s, next))
3966 return XML_ERROR_NO_MEMORY;
3967 declAttributeType = tempPool.start;
3968 handleDefault = XML_FALSE;
3970 break;
3971 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
3972 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
3973 if (dtd->keepProcessing) {
3974 if (!defineAttribute(declElementType, declAttributeId,
3975 declAttributeIsCdata, declAttributeIsId,
3976 0, parser))
3977 return XML_ERROR_NO_MEMORY;
3978 if (attlistDeclHandler && declAttributeType) {
3979 if (*declAttributeType == XML_T(ASCII_LPAREN)
3980 || (*declAttributeType == XML_T(ASCII_N)
3981 && declAttributeType[1] == XML_T(ASCII_O))) {
3982 /* Enumerated or Notation type */
3983 if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
3984 || !poolAppendChar(&tempPool, XML_T('\0')))
3985 return XML_ERROR_NO_MEMORY;
3986 declAttributeType = tempPool.start;
3987 poolFinish(&tempPool);
3989 *eventEndPP = s;
3990 attlistDeclHandler(handlerArg, declElementType->name,
3991 declAttributeId->name, declAttributeType,
3992 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
3993 poolClear(&tempPool);
3994 handleDefault = XML_FALSE;
3997 break;
3998 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
3999 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
4000 if (dtd->keepProcessing) {
4001 const XML_Char *attVal;
4002 enum XML_Error result =
4003 storeAttributeValue(parser, enc, declAttributeIsCdata,
4004 s + enc->minBytesPerChar,
4005 next - enc->minBytesPerChar,
4006 &dtd->pool);
4007 if (result)
4008 return result;
4009 attVal = poolStart(&dtd->pool);
4010 poolFinish(&dtd->pool);
4011 /* ID attributes aren't allowed to have a default */
4012 if (!defineAttribute(declElementType, declAttributeId,
4013 declAttributeIsCdata, XML_FALSE, attVal, parser))
4014 return XML_ERROR_NO_MEMORY;
4015 if (attlistDeclHandler && declAttributeType) {
4016 if (*declAttributeType == XML_T(ASCII_LPAREN)
4017 || (*declAttributeType == XML_T(ASCII_N)
4018 && declAttributeType[1] == XML_T(ASCII_O))) {
4019 /* Enumerated or Notation type */
4020 if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4021 || !poolAppendChar(&tempPool, XML_T('\0')))
4022 return XML_ERROR_NO_MEMORY;
4023 declAttributeType = tempPool.start;
4024 poolFinish(&tempPool);
4026 *eventEndPP = s;
4027 attlistDeclHandler(handlerArg, declElementType->name,
4028 declAttributeId->name, declAttributeType,
4029 attVal,
4030 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
4031 poolClear(&tempPool);
4032 handleDefault = XML_FALSE;
4035 break;
4036 case XML_ROLE_ENTITY_VALUE:
4037 if (dtd->keepProcessing) {
4038 enum XML_Error result = storeEntityValue(parser, enc,
4039 s + enc->minBytesPerChar,
4040 next - enc->minBytesPerChar);
4041 if (declEntity) {
4042 declEntity->textPtr = poolStart(&dtd->entityValuePool);
4043 declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
4044 poolFinish(&dtd->entityValuePool);
4045 if (entityDeclHandler) {
4046 *eventEndPP = s;
4047 entityDeclHandler(handlerArg,
4048 declEntity->name,
4049 declEntity->is_param,
4050 declEntity->textPtr,
4051 declEntity->textLen,
4052 curBase, 0, 0, 0);
4053 handleDefault = XML_FALSE;
4056 else
4057 poolDiscard(&dtd->entityValuePool);
4058 if (result != XML_ERROR_NONE)
4059 return result;
4061 break;
4062 case XML_ROLE_DOCTYPE_SYSTEM_ID:
4063 #ifdef XML_DTD
4064 useForeignDTD = XML_FALSE;
4065 #endif /* XML_DTD */
4066 dtd->hasParamEntityRefs = XML_TRUE;
4067 if (startDoctypeDeclHandler) {
4068 doctypeSysid = poolStoreString(&tempPool, enc,
4069 s + enc->minBytesPerChar,
4070 next - enc->minBytesPerChar);
4071 if (doctypeSysid == NULL)
4072 return XML_ERROR_NO_MEMORY;
4073 poolFinish(&tempPool);
4074 handleDefault = XML_FALSE;
4076 #ifdef XML_DTD
4077 else
4078 /* use externalSubsetName to make doctypeSysid non-NULL
4079 for the case where no startDoctypeDeclHandler is set */
4080 doctypeSysid = externalSubsetName;
4081 #endif /* XML_DTD */
4082 if (!dtd->standalone
4083 #ifdef XML_DTD
4084 && !paramEntityParsing
4085 #endif /* XML_DTD */
4086 && notStandaloneHandler
4087 && !notStandaloneHandler(handlerArg))
4088 return XML_ERROR_NOT_STANDALONE;
4089 #ifndef XML_DTD
4090 break;
4091 #else /* XML_DTD */
4092 if (!declEntity) {
4093 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
4094 externalSubsetName,
4095 sizeof(ENTITY));
4096 if (!declEntity)
4097 return XML_ERROR_NO_MEMORY;
4098 declEntity->publicId = NULL;
4100 /* fall through */
4101 #endif /* XML_DTD */
4102 case XML_ROLE_ENTITY_SYSTEM_ID:
4103 if (dtd->keepProcessing && declEntity) {
4104 declEntity->systemId = poolStoreString(&dtd->pool, enc,
4105 s + enc->minBytesPerChar,
4106 next - enc->minBytesPerChar);
4107 if (!declEntity->systemId)
4108 return XML_ERROR_NO_MEMORY;
4109 declEntity->base = curBase;
4110 poolFinish(&dtd->pool);
4111 if (entityDeclHandler)
4112 handleDefault = XML_FALSE;
4114 break;
4115 case XML_ROLE_ENTITY_COMPLETE:
4116 if (dtd->keepProcessing && declEntity && entityDeclHandler) {
4117 *eventEndPP = s;
4118 entityDeclHandler(handlerArg,
4119 declEntity->name,
4120 declEntity->is_param,
4121 0,0,
4122 declEntity->base,
4123 declEntity->systemId,
4124 declEntity->publicId,
4126 handleDefault = XML_FALSE;
4128 break;
4129 case XML_ROLE_ENTITY_NOTATION_NAME:
4130 if (dtd->keepProcessing && declEntity) {
4131 declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
4132 if (!declEntity->notation)
4133 return XML_ERROR_NO_MEMORY;
4134 poolFinish(&dtd->pool);
4135 if (unparsedEntityDeclHandler) {
4136 *eventEndPP = s;
4137 unparsedEntityDeclHandler(handlerArg,
4138 declEntity->name,
4139 declEntity->base,
4140 declEntity->systemId,
4141 declEntity->publicId,
4142 declEntity->notation);
4143 handleDefault = XML_FALSE;
4145 else if (entityDeclHandler) {
4146 *eventEndPP = s;
4147 entityDeclHandler(handlerArg,
4148 declEntity->name,
4149 0,0,0,
4150 declEntity->base,
4151 declEntity->systemId,
4152 declEntity->publicId,
4153 declEntity->notation);
4154 handleDefault = XML_FALSE;
4157 break;
4158 case XML_ROLE_GENERAL_ENTITY_NAME:
4160 if (XmlPredefinedEntityName(enc, s, next)) {
4161 declEntity = NULL;
4162 break;
4164 if (dtd->keepProcessing) {
4165 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4166 if (!name)
4167 return XML_ERROR_NO_MEMORY;
4168 declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
4169 sizeof(ENTITY));
4170 if (!declEntity)
4171 return XML_ERROR_NO_MEMORY;
4172 if (declEntity->name != name) {
4173 poolDiscard(&dtd->pool);
4174 declEntity = NULL;
4176 else {
4177 poolFinish(&dtd->pool);
4178 declEntity->publicId = NULL;
4179 declEntity->is_param = XML_FALSE;
4180 /* if we have a parent parser or are reading an internal parameter
4181 entity, then the entity declaration is not considered "internal"
4183 declEntity->is_internal = !(parentParser || openInternalEntities);
4184 if (entityDeclHandler)
4185 handleDefault = XML_FALSE;
4188 else {
4189 poolDiscard(&dtd->pool);
4190 declEntity = NULL;
4193 break;
4194 case XML_ROLE_PARAM_ENTITY_NAME:
4195 #ifdef XML_DTD
4196 if (dtd->keepProcessing) {
4197 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4198 if (!name)
4199 return XML_ERROR_NO_MEMORY;
4200 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
4201 name, sizeof(ENTITY));
4202 if (!declEntity)
4203 return XML_ERROR_NO_MEMORY;
4204 if (declEntity->name != name) {
4205 poolDiscard(&dtd->pool);
4206 declEntity = NULL;
4208 else {
4209 poolFinish(&dtd->pool);
4210 declEntity->publicId = NULL;
4211 declEntity->is_param = XML_TRUE;
4212 /* if we have a parent parser or are reading an internal parameter
4213 entity, then the entity declaration is not considered "internal"
4215 declEntity->is_internal = !(parentParser || openInternalEntities);
4216 if (entityDeclHandler)
4217 handleDefault = XML_FALSE;
4220 else {
4221 poolDiscard(&dtd->pool);
4222 declEntity = NULL;
4224 #else /* not XML_DTD */
4225 declEntity = NULL;
4226 #endif /* XML_DTD */
4227 break;
4228 case XML_ROLE_NOTATION_NAME:
4229 declNotationPublicId = NULL;
4230 declNotationName = NULL;
4231 if (notationDeclHandler) {
4232 declNotationName = poolStoreString(&tempPool, enc, s, next);
4233 if (!declNotationName)
4234 return XML_ERROR_NO_MEMORY;
4235 poolFinish(&tempPool);
4236 handleDefault = XML_FALSE;
4238 break;
4239 case XML_ROLE_NOTATION_PUBLIC_ID:
4240 if (!XmlIsPublicId(enc, s, next, eventPP))
4241 return XML_ERROR_PUBLICID;
4242 if (declNotationName) { /* means notationDeclHandler != NULL */
4243 XML_Char *tem = poolStoreString(&tempPool,
4244 enc,
4245 s + enc->minBytesPerChar,
4246 next - enc->minBytesPerChar);
4247 if (!tem)
4248 return XML_ERROR_NO_MEMORY;
4249 normalizePublicId(tem);
4250 declNotationPublicId = tem;
4251 poolFinish(&tempPool);
4252 handleDefault = XML_FALSE;
4254 break;
4255 case XML_ROLE_NOTATION_SYSTEM_ID:
4256 if (declNotationName && notationDeclHandler) {
4257 const XML_Char *systemId
4258 = poolStoreString(&tempPool, enc,
4259 s + enc->minBytesPerChar,
4260 next - enc->minBytesPerChar);
4261 if (!systemId)
4262 return XML_ERROR_NO_MEMORY;
4263 *eventEndPP = s;
4264 notationDeclHandler(handlerArg,
4265 declNotationName,
4266 curBase,
4267 systemId,
4268 declNotationPublicId);
4269 handleDefault = XML_FALSE;
4271 poolClear(&tempPool);
4272 break;
4273 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
4274 if (declNotationPublicId && notationDeclHandler) {
4275 *eventEndPP = s;
4276 notationDeclHandler(handlerArg,
4277 declNotationName,
4278 curBase,
4280 declNotationPublicId);
4281 handleDefault = XML_FALSE;
4283 poolClear(&tempPool);
4284 break;
4285 case XML_ROLE_ERROR:
4286 switch (tok) {
4287 case XML_TOK_PARAM_ENTITY_REF:
4288 /* PE references in internal subset are
4289 not allowed within declarations. */
4290 return XML_ERROR_PARAM_ENTITY_REF;
4291 case XML_TOK_XML_DECL:
4292 return XML_ERROR_MISPLACED_XML_PI;
4293 default:
4294 return XML_ERROR_SYNTAX;
4296 #ifdef XML_DTD
4297 case XML_ROLE_IGNORE_SECT:
4299 enum XML_Error result;
4300 if (defaultHandler)
4301 reportDefault(parser, enc, s, next);
4302 handleDefault = XML_FALSE;
4303 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
4304 if (result != XML_ERROR_NONE)
4305 return result;
4306 else if (!next) {
4307 processor = ignoreSectionProcessor;
4308 return result;
4311 break;
4312 #endif /* XML_DTD */
4313 case XML_ROLE_GROUP_OPEN:
4314 if (prologState.level >= groupSize) {
4315 if (groupSize) {
4316 char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
4317 if (temp == NULL)
4318 return XML_ERROR_NO_MEMORY;
4319 groupConnector = temp;
4320 if (dtd->scaffIndex) {
4321 int *temp = (int *)REALLOC(dtd->scaffIndex,
4322 groupSize * sizeof(int));
4323 if (temp == NULL)
4324 return XML_ERROR_NO_MEMORY;
4325 dtd->scaffIndex = temp;
4328 else {
4329 groupConnector = (char *)MALLOC(groupSize = 32);
4330 if (!groupConnector)
4331 return XML_ERROR_NO_MEMORY;
4334 groupConnector[prologState.level] = 0;
4335 if (dtd->in_eldecl) {
4336 int myindex = nextScaffoldPart(parser);
4337 if (myindex < 0)
4338 return XML_ERROR_NO_MEMORY;
4339 dtd->scaffIndex[dtd->scaffLevel] = myindex;
4340 dtd->scaffLevel++;
4341 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
4342 if (elementDeclHandler)
4343 handleDefault = XML_FALSE;
4345 break;
4346 case XML_ROLE_GROUP_SEQUENCE:
4347 if (groupConnector[prologState.level] == ASCII_PIPE)
4348 return XML_ERROR_SYNTAX;
4349 groupConnector[prologState.level] = ASCII_COMMA;
4350 if (dtd->in_eldecl && elementDeclHandler)
4351 handleDefault = XML_FALSE;
4352 break;
4353 case XML_ROLE_GROUP_CHOICE:
4354 if (groupConnector[prologState.level] == ASCII_COMMA)
4355 return XML_ERROR_SYNTAX;
4356 if (dtd->in_eldecl
4357 && !groupConnector[prologState.level]
4358 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4359 != XML_CTYPE_MIXED)
4361 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4362 = XML_CTYPE_CHOICE;
4363 if (elementDeclHandler)
4364 handleDefault = XML_FALSE;
4366 groupConnector[prologState.level] = ASCII_PIPE;
4367 break;
4368 case XML_ROLE_PARAM_ENTITY_REF:
4369 #ifdef XML_DTD
4370 case XML_ROLE_INNER_PARAM_ENTITY_REF:
4371 dtd->hasParamEntityRefs = XML_TRUE;
4372 if (!paramEntityParsing)
4373 dtd->keepProcessing = dtd->standalone;
4374 else {
4375 const XML_Char *name;
4376 ENTITY *entity;
4377 name = poolStoreString(&dtd->pool, enc,
4378 s + enc->minBytesPerChar,
4379 next - enc->minBytesPerChar);
4380 if (!name)
4381 return XML_ERROR_NO_MEMORY;
4382 entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
4383 poolDiscard(&dtd->pool);
4384 /* first, determine if a check for an existing declaration is needed;
4385 if yes, check that the entity exists, and that it is internal,
4386 otherwise call the skipped entity handler
4388 if (prologState.documentEntity &&
4389 (dtd->standalone
4390 ? !openInternalEntities
4391 : !dtd->hasParamEntityRefs)) {
4392 if (!entity)
4393 return XML_ERROR_UNDEFINED_ENTITY;
4394 else if (!entity->is_internal)
4395 return XML_ERROR_ENTITY_DECLARED_IN_PE;
4397 else if (!entity) {
4398 dtd->keepProcessing = dtd->standalone;
4399 /* cannot report skipped entities in declarations */
4400 if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
4401 skippedEntityHandler(handlerArg, name, 1);
4402 handleDefault = XML_FALSE;
4404 break;
4406 if (entity->open)
4407 return XML_ERROR_RECURSIVE_ENTITY_REF;
4408 if (entity->textPtr) {
4409 enum XML_Error result;
4410 XML_Bool betweenDecl =
4411 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
4412 result = processInternalEntity(parser, entity, betweenDecl);
4413 if (result != XML_ERROR_NONE)
4414 return result;
4415 handleDefault = XML_FALSE;
4416 break;
4418 if (externalEntityRefHandler) {
4419 dtd->paramEntityRead = XML_FALSE;
4420 entity->open = XML_TRUE;
4421 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4423 entity->base,
4424 entity->systemId,
4425 entity->publicId)) {
4426 entity->open = XML_FALSE;
4427 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4429 entity->open = XML_FALSE;
4430 handleDefault = XML_FALSE;
4431 if (!dtd->paramEntityRead) {
4432 dtd->keepProcessing = dtd->standalone;
4433 break;
4436 else {
4437 dtd->keepProcessing = dtd->standalone;
4438 break;
4441 #endif /* XML_DTD */
4442 if (!dtd->standalone &&
4443 notStandaloneHandler &&
4444 !notStandaloneHandler(handlerArg))
4445 return XML_ERROR_NOT_STANDALONE;
4446 break;
4448 /* Element declaration stuff */
4450 case XML_ROLE_ELEMENT_NAME:
4451 if (elementDeclHandler) {
4452 declElementType = getElementType(parser, enc, s, next);
4453 if (!declElementType)
4454 return XML_ERROR_NO_MEMORY;
4455 dtd->scaffLevel = 0;
4456 dtd->scaffCount = 0;
4457 dtd->in_eldecl = XML_TRUE;
4458 handleDefault = XML_FALSE;
4460 break;
4462 case XML_ROLE_CONTENT_ANY:
4463 case XML_ROLE_CONTENT_EMPTY:
4464 if (dtd->in_eldecl) {
4465 if (elementDeclHandler) {
4466 XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
4467 if (!content)
4468 return XML_ERROR_NO_MEMORY;
4469 content->quant = XML_CQUANT_NONE;
4470 content->name = NULL;
4471 content->numchildren = 0;
4472 content->children = NULL;
4473 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
4474 XML_CTYPE_ANY :
4475 XML_CTYPE_EMPTY);
4476 *eventEndPP = s;
4477 elementDeclHandler(handlerArg, declElementType->name, content);
4478 handleDefault = XML_FALSE;
4480 dtd->in_eldecl = XML_FALSE;
4482 break;
4484 case XML_ROLE_CONTENT_PCDATA:
4485 if (dtd->in_eldecl) {
4486 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4487 = XML_CTYPE_MIXED;
4488 if (elementDeclHandler)
4489 handleDefault = XML_FALSE;
4491 break;
4493 case XML_ROLE_CONTENT_ELEMENT:
4494 quant = XML_CQUANT_NONE;
4495 goto elementContent;
4496 case XML_ROLE_CONTENT_ELEMENT_OPT:
4497 quant = XML_CQUANT_OPT;
4498 goto elementContent;
4499 case XML_ROLE_CONTENT_ELEMENT_REP:
4500 quant = XML_CQUANT_REP;
4501 goto elementContent;
4502 case XML_ROLE_CONTENT_ELEMENT_PLUS:
4503 quant = XML_CQUANT_PLUS;
4504 elementContent:
4505 if (dtd->in_eldecl) {
4506 ELEMENT_TYPE *el;
4507 const XML_Char *name;
4508 int nameLen;
4509 const char *nxt = (quant == XML_CQUANT_NONE
4510 ? next
4511 : next - enc->minBytesPerChar);
4512 int myindex = nextScaffoldPart(parser);
4513 if (myindex < 0)
4514 return XML_ERROR_NO_MEMORY;
4515 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
4516 dtd->scaffold[myindex].quant = quant;
4517 el = getElementType(parser, enc, s, nxt);
4518 if (!el)
4519 return XML_ERROR_NO_MEMORY;
4520 name = el->name;
4521 dtd->scaffold[myindex].name = name;
4522 nameLen = 0;
4523 for (; name[nameLen++]; );
4524 dtd->contentStringLen += nameLen;
4525 if (elementDeclHandler)
4526 handleDefault = XML_FALSE;
4528 break;
4530 case XML_ROLE_GROUP_CLOSE:
4531 quant = XML_CQUANT_NONE;
4532 goto closeGroup;
4533 case XML_ROLE_GROUP_CLOSE_OPT:
4534 quant = XML_CQUANT_OPT;
4535 goto closeGroup;
4536 case XML_ROLE_GROUP_CLOSE_REP:
4537 quant = XML_CQUANT_REP;
4538 goto closeGroup;
4539 case XML_ROLE_GROUP_CLOSE_PLUS:
4540 quant = XML_CQUANT_PLUS;
4541 closeGroup:
4542 if (dtd->in_eldecl) {
4543 if (elementDeclHandler)
4544 handleDefault = XML_FALSE;
4545 dtd->scaffLevel--;
4546 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
4547 if (dtd->scaffLevel == 0) {
4548 if (!handleDefault) {
4549 XML_Content *model = build_model(parser);
4550 if (!model)
4551 return XML_ERROR_NO_MEMORY;
4552 *eventEndPP = s;
4553 elementDeclHandler(handlerArg, declElementType->name, model);
4555 dtd->in_eldecl = XML_FALSE;
4556 dtd->contentStringLen = 0;
4559 break;
4560 /* End element declaration stuff */
4562 case XML_ROLE_PI:
4563 if (!reportProcessingInstruction(parser, enc, s, next))
4564 return XML_ERROR_NO_MEMORY;
4565 handleDefault = XML_FALSE;
4566 break;
4567 case XML_ROLE_COMMENT:
4568 if (!reportComment(parser, enc, s, next))
4569 return XML_ERROR_NO_MEMORY;
4570 handleDefault = XML_FALSE;
4571 break;
4572 case XML_ROLE_NONE:
4573 switch (tok) {
4574 case XML_TOK_BOM:
4575 handleDefault = XML_FALSE;
4576 break;
4578 break;
4579 case XML_ROLE_DOCTYPE_NONE:
4580 if (startDoctypeDeclHandler)
4581 handleDefault = XML_FALSE;
4582 break;
4583 case XML_ROLE_ENTITY_NONE:
4584 if (dtd->keepProcessing && entityDeclHandler)
4585 handleDefault = XML_FALSE;
4586 break;
4587 case XML_ROLE_NOTATION_NONE:
4588 if (notationDeclHandler)
4589 handleDefault = XML_FALSE;
4590 break;
4591 case XML_ROLE_ATTLIST_NONE:
4592 if (dtd->keepProcessing && attlistDeclHandler)
4593 handleDefault = XML_FALSE;
4594 break;
4595 case XML_ROLE_ELEMENT_NONE:
4596 if (elementDeclHandler)
4597 handleDefault = XML_FALSE;
4598 break;
4599 } /* end of big switch */
4601 if (handleDefault && defaultHandler)
4602 reportDefault(parser, enc, s, next);
4604 switch (ps_parsing) {
4605 case XML_SUSPENDED:
4606 *nextPtr = next;
4607 return XML_ERROR_NONE;
4608 case XML_FINISHED:
4609 return XML_ERROR_ABORTED;
4610 default:
4611 s = next;
4612 tok = XmlPrologTok(enc, s, end, &next);
4615 /* not reached */
4618 static enum XML_Error PTRCALL
4619 epilogProcessor(XML_Parser parser,
4620 const char *s,
4621 const char *end,
4622 const char **nextPtr)
4624 processor = epilogProcessor;
4625 eventPtr = s;
4626 for (;;) {
4627 const char *next = NULL;
4628 int tok = XmlPrologTok(encoding, s, end, &next);
4629 eventEndPtr = next;
4630 switch (tok) {
4631 /* report partial linebreak - it might be the last token */
4632 case -XML_TOK_PROLOG_S:
4633 if (defaultHandler) {
4634 reportDefault(parser, encoding, s, next);
4635 if (ps_parsing == XML_FINISHED)
4636 return XML_ERROR_ABORTED;
4638 *nextPtr = next;
4639 return XML_ERROR_NONE;
4640 case XML_TOK_NONE:
4641 *nextPtr = s;
4642 return XML_ERROR_NONE;
4643 case XML_TOK_PROLOG_S:
4644 if (defaultHandler)
4645 reportDefault(parser, encoding, s, next);
4646 break;
4647 case XML_TOK_PI:
4648 if (!reportProcessingInstruction(parser, encoding, s, next))
4649 return XML_ERROR_NO_MEMORY;
4650 break;
4651 case XML_TOK_COMMENT:
4652 if (!reportComment(parser, encoding, s, next))
4653 return XML_ERROR_NO_MEMORY;
4654 break;
4655 case XML_TOK_INVALID:
4656 eventPtr = next;
4657 return XML_ERROR_INVALID_TOKEN;
4658 case XML_TOK_PARTIAL:
4659 if (!ps_finalBuffer) {
4660 *nextPtr = s;
4661 return XML_ERROR_NONE;
4663 return XML_ERROR_UNCLOSED_TOKEN;
4664 case XML_TOK_PARTIAL_CHAR:
4665 if (!ps_finalBuffer) {
4666 *nextPtr = s;
4667 return XML_ERROR_NONE;
4669 return XML_ERROR_PARTIAL_CHAR;
4670 default:
4671 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
4673 eventPtr = s = next;
4674 switch (ps_parsing) {
4675 case XML_SUSPENDED:
4676 *nextPtr = next;
4677 return XML_ERROR_NONE;
4678 case XML_FINISHED:
4679 return XML_ERROR_ABORTED;
4680 default: ;
4685 static enum XML_Error
4686 processInternalEntity(XML_Parser parser, ENTITY *entity,
4687 XML_Bool betweenDecl)
4689 const char *textStart, *textEnd;
4690 const char *next;
4691 enum XML_Error result;
4692 OPEN_INTERNAL_ENTITY *openEntity;
4694 if (freeInternalEntities) {
4695 openEntity = freeInternalEntities;
4696 freeInternalEntities = openEntity->next;
4698 else {
4699 openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
4700 if (!openEntity)
4701 return XML_ERROR_NO_MEMORY;
4703 entity->open = XML_TRUE;
4704 entity->processed = 0;
4705 openEntity->next = openInternalEntities;
4706 openInternalEntities = openEntity;
4707 openEntity->entity = entity;
4708 openEntity->startTagLevel = tagLevel;
4709 openEntity->betweenDecl = betweenDecl;
4710 openEntity->internalEventPtr = NULL;
4711 openEntity->internalEventEndPtr = NULL;
4712 textStart = (char *)entity->textPtr;
4713 textEnd = (char *)(entity->textPtr + entity->textLen);
4715 #ifdef XML_DTD
4716 if (entity->is_param) {
4717 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4718 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4719 next, &next, XML_FALSE);
4721 else
4722 #endif /* XML_DTD */
4723 result = doContent(parser, tagLevel, internalEncoding, textStart,
4724 textEnd, &next, XML_FALSE);
4726 if (result == XML_ERROR_NONE) {
4727 if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4728 entity->processed = (int)(next - textStart);
4729 processor = internalEntityProcessor;
4731 else {
4732 entity->open = XML_FALSE;
4733 openInternalEntities = openEntity->next;
4734 /* put openEntity back in list of free instances */
4735 openEntity->next = freeInternalEntities;
4736 freeInternalEntities = openEntity;
4739 return result;
4742 static enum XML_Error PTRCALL
4743 internalEntityProcessor(XML_Parser parser,
4744 const char *s,
4745 const char *end,
4746 const char **nextPtr)
4748 ENTITY *entity;
4749 const char *textStart, *textEnd;
4750 const char *next;
4751 enum XML_Error result;
4752 OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
4753 if (!openEntity)
4754 return XML_ERROR_UNEXPECTED_STATE;
4756 entity = openEntity->entity;
4757 textStart = ((char *)entity->textPtr) + entity->processed;
4758 textEnd = (char *)(entity->textPtr + entity->textLen);
4760 #ifdef XML_DTD
4761 if (entity->is_param) {
4762 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4763 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4764 next, &next, XML_FALSE);
4766 else
4767 #endif /* XML_DTD */
4768 result = doContent(parser, openEntity->startTagLevel, internalEncoding,
4769 textStart, textEnd, &next, XML_FALSE);
4771 if (result != XML_ERROR_NONE)
4772 return result;
4773 else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4774 entity->processed = (int)(next - (char *)entity->textPtr);
4775 return result;
4777 else {
4778 entity->open = XML_FALSE;
4779 openInternalEntities = openEntity->next;
4780 /* put openEntity back in list of free instances */
4781 openEntity->next = freeInternalEntities;
4782 freeInternalEntities = openEntity;
4785 #ifdef XML_DTD
4786 if (entity->is_param) {
4787 int tok;
4788 processor = prologProcessor;
4789 tok = XmlPrologTok(encoding, s, end, &next);
4790 return doProlog(parser, encoding, s, end, tok, next, nextPtr,
4791 (XML_Bool)!ps_finalBuffer);
4793 else
4794 #endif /* XML_DTD */
4796 processor = contentProcessor;
4797 /* see externalEntityContentProcessor vs contentProcessor */
4798 return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
4799 nextPtr, (XML_Bool)!ps_finalBuffer);
4803 static enum XML_Error PTRCALL
4804 errorProcessor(XML_Parser parser,
4805 const char *s,
4806 const char *end,
4807 const char **nextPtr)
4809 return errorCode;
4812 static enum XML_Error
4813 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4814 const char *ptr, const char *end,
4815 STRING_POOL *pool)
4817 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
4818 end, pool);
4819 if (result)
4820 return result;
4821 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
4822 poolChop(pool);
4823 if (!poolAppendChar(pool, XML_T('\0')))
4824 return XML_ERROR_NO_MEMORY;
4825 return XML_ERROR_NONE;
4828 static enum XML_Error
4829 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4830 const char *ptr, const char *end,
4831 STRING_POOL *pool)
4833 DTD * const dtd = _dtd; /* save one level of indirection */
4834 for (;;) {
4835 const char *next;
4836 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
4837 switch (tok) {
4838 case XML_TOK_NONE:
4839 return XML_ERROR_NONE;
4840 case XML_TOK_INVALID:
4841 if (enc == encoding)
4842 eventPtr = next;
4843 return XML_ERROR_INVALID_TOKEN;
4844 case XML_TOK_PARTIAL:
4845 if (enc == encoding)
4846 eventPtr = ptr;
4847 return XML_ERROR_INVALID_TOKEN;
4848 case XML_TOK_CHAR_REF:
4850 XML_Char buf[XML_ENCODE_MAX];
4851 int i;
4852 int n = XmlCharRefNumber(enc, ptr);
4853 if (n < 0) {
4854 if (enc == encoding)
4855 eventPtr = ptr;
4856 return XML_ERROR_BAD_CHAR_REF;
4858 if (!isCdata
4859 && n == 0x20 /* space */
4860 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4861 break;
4862 n = XmlEncode(n, (ICHAR *)buf);
4863 if (!n) {
4864 if (enc == encoding)
4865 eventPtr = ptr;
4866 return XML_ERROR_BAD_CHAR_REF;
4868 for (i = 0; i < n; i++) {
4869 if (!poolAppendChar(pool, buf[i]))
4870 return XML_ERROR_NO_MEMORY;
4873 break;
4874 case XML_TOK_DATA_CHARS:
4875 if (!poolAppend(pool, enc, ptr, next))
4876 return XML_ERROR_NO_MEMORY;
4877 break;
4878 case XML_TOK_TRAILING_CR:
4879 next = ptr + enc->minBytesPerChar;
4880 /* fall through */
4881 case XML_TOK_ATTRIBUTE_VALUE_S:
4882 case XML_TOK_DATA_NEWLINE:
4883 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4884 break;
4885 if (!poolAppendChar(pool, 0x20))
4886 return XML_ERROR_NO_MEMORY;
4887 break;
4888 case XML_TOK_ENTITY_REF:
4890 const XML_Char *name;
4891 ENTITY *entity;
4892 char checkEntityDecl;
4893 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
4894 ptr + enc->minBytesPerChar,
4895 next - enc->minBytesPerChar);
4896 if (ch) {
4897 if (!poolAppendChar(pool, ch))
4898 return XML_ERROR_NO_MEMORY;
4899 break;
4901 name = poolStoreString(&temp2Pool, enc,
4902 ptr + enc->minBytesPerChar,
4903 next - enc->minBytesPerChar);
4904 if (!name)
4905 return XML_ERROR_NO_MEMORY;
4906 entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
4907 poolDiscard(&temp2Pool);
4908 /* First, determine if a check for an existing declaration is needed;
4909 if yes, check that the entity exists, and that it is internal.
4911 if (pool == &dtd->pool) /* are we called from prolog? */
4912 checkEntityDecl =
4913 #ifdef XML_DTD
4914 prologState.documentEntity &&
4915 #endif /* XML_DTD */
4916 (dtd->standalone
4917 ? !openInternalEntities
4918 : !dtd->hasParamEntityRefs);
4919 else /* if (pool == &tempPool): we are called from content */
4920 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
4921 if (checkEntityDecl) {
4922 if (!entity)
4923 return XML_ERROR_UNDEFINED_ENTITY;
4924 else if (!entity->is_internal)
4925 return XML_ERROR_ENTITY_DECLARED_IN_PE;
4927 else if (!entity) {
4928 /* Cannot report skipped entity here - see comments on
4929 skippedEntityHandler.
4930 if (skippedEntityHandler)
4931 skippedEntityHandler(handlerArg, name, 0);
4933 /* Cannot call the default handler because this would be
4934 out of sync with the call to the startElementHandler.
4935 if ((pool == &tempPool) && defaultHandler)
4936 reportDefault(parser, enc, ptr, next);
4938 break;
4940 if (entity->open) {
4941 if (enc == encoding)
4942 eventPtr = ptr;
4943 return XML_ERROR_RECURSIVE_ENTITY_REF;
4945 if (entity->notation) {
4946 if (enc == encoding)
4947 eventPtr = ptr;
4948 return XML_ERROR_BINARY_ENTITY_REF;
4950 if (!entity->textPtr) {
4951 if (enc == encoding)
4952 eventPtr = ptr;
4953 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
4955 else {
4956 enum XML_Error result;
4957 const XML_Char *textEnd = entity->textPtr + entity->textLen;
4958 entity->open = XML_TRUE;
4959 result = appendAttributeValue(parser, internalEncoding, isCdata,
4960 (char *)entity->textPtr,
4961 (char *)textEnd, pool);
4962 entity->open = XML_FALSE;
4963 if (result)
4964 return result;
4967 break;
4968 default:
4969 if (enc == encoding)
4970 eventPtr = ptr;
4971 return XML_ERROR_UNEXPECTED_STATE;
4973 ptr = next;
4975 /* not reached */
4978 static enum XML_Error
4979 storeEntityValue(XML_Parser parser,
4980 const ENCODING *enc,
4981 const char *entityTextPtr,
4982 const char *entityTextEnd)
4984 DTD * const dtd = _dtd; /* save one level of indirection */
4985 STRING_POOL *pool = &(dtd->entityValuePool);
4986 enum XML_Error result = XML_ERROR_NONE;
4987 #ifdef XML_DTD
4988 int oldInEntityValue = prologState.inEntityValue;
4989 prologState.inEntityValue = 1;
4990 #endif /* XML_DTD */
4991 /* never return Null for the value argument in EntityDeclHandler,
4992 since this would indicate an external entity; therefore we
4993 have to make sure that entityValuePool.start is not null */
4994 if (!pool->blocks) {
4995 if (!poolGrow(pool))
4996 return XML_ERROR_NO_MEMORY;
4999 for (;;) {
5000 const char *next;
5001 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
5002 switch (tok) {
5003 case XML_TOK_PARAM_ENTITY_REF:
5004 #ifdef XML_DTD
5005 if (isParamEntity || enc != encoding) {
5006 const XML_Char *name;
5007 ENTITY *entity;
5008 name = poolStoreString(&tempPool, enc,
5009 entityTextPtr + enc->minBytesPerChar,
5010 next - enc->minBytesPerChar);
5011 if (!name) {
5012 result = XML_ERROR_NO_MEMORY;
5013 goto endEntityValue;
5015 entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
5016 poolDiscard(&tempPool);
5017 if (!entity) {
5018 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5019 /* cannot report skipped entity here - see comments on
5020 skippedEntityHandler
5021 if (skippedEntityHandler)
5022 skippedEntityHandler(handlerArg, name, 0);
5024 dtd->keepProcessing = dtd->standalone;
5025 goto endEntityValue;
5027 if (entity->open) {
5028 if (enc == encoding)
5029 eventPtr = entityTextPtr;
5030 result = XML_ERROR_RECURSIVE_ENTITY_REF;
5031 goto endEntityValue;
5033 if (entity->systemId) {
5034 if (externalEntityRefHandler) {
5035 dtd->paramEntityRead = XML_FALSE;
5036 entity->open = XML_TRUE;
5037 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
5039 entity->base,
5040 entity->systemId,
5041 entity->publicId)) {
5042 entity->open = XML_FALSE;
5043 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5044 goto endEntityValue;
5046 entity->open = XML_FALSE;
5047 if (!dtd->paramEntityRead)
5048 dtd->keepProcessing = dtd->standalone;
5050 else
5051 dtd->keepProcessing = dtd->standalone;
5053 else {
5054 entity->open = XML_TRUE;
5055 result = storeEntityValue(parser,
5056 internalEncoding,
5057 (char *)entity->textPtr,
5058 (char *)(entity->textPtr
5059 + entity->textLen));
5060 entity->open = XML_FALSE;
5061 if (result)
5062 goto endEntityValue;
5064 break;
5066 #endif /* XML_DTD */
5067 /* In the internal subset, PE references are not legal
5068 within markup declarations, e.g entity values in this case. */
5069 eventPtr = entityTextPtr;
5070 result = XML_ERROR_PARAM_ENTITY_REF;
5071 goto endEntityValue;
5072 case XML_TOK_NONE:
5073 result = XML_ERROR_NONE;
5074 goto endEntityValue;
5075 case XML_TOK_ENTITY_REF:
5076 case XML_TOK_DATA_CHARS:
5077 if (!poolAppend(pool, enc, entityTextPtr, next)) {
5078 result = XML_ERROR_NO_MEMORY;
5079 goto endEntityValue;
5081 break;
5082 case XML_TOK_TRAILING_CR:
5083 next = entityTextPtr + enc->minBytesPerChar;
5084 /* fall through */
5085 case XML_TOK_DATA_NEWLINE:
5086 if (pool->end == pool->ptr && !poolGrow(pool)) {
5087 result = XML_ERROR_NO_MEMORY;
5088 goto endEntityValue;
5090 *(pool->ptr)++ = 0xA;
5091 break;
5092 case XML_TOK_CHAR_REF:
5094 XML_Char buf[XML_ENCODE_MAX];
5095 int i;
5096 int n = XmlCharRefNumber(enc, entityTextPtr);
5097 if (n < 0) {
5098 if (enc == encoding)
5099 eventPtr = entityTextPtr;
5100 result = XML_ERROR_BAD_CHAR_REF;
5101 goto endEntityValue;
5103 n = XmlEncode(n, (ICHAR *)buf);
5104 if (!n) {
5105 if (enc == encoding)
5106 eventPtr = entityTextPtr;
5107 result = XML_ERROR_BAD_CHAR_REF;
5108 goto endEntityValue;
5110 for (i = 0; i < n; i++) {
5111 if (pool->end == pool->ptr && !poolGrow(pool)) {
5112 result = XML_ERROR_NO_MEMORY;
5113 goto endEntityValue;
5115 *(pool->ptr)++ = buf[i];
5118 break;
5119 case XML_TOK_PARTIAL:
5120 if (enc == encoding)
5121 eventPtr = entityTextPtr;
5122 result = XML_ERROR_INVALID_TOKEN;
5123 goto endEntityValue;
5124 case XML_TOK_INVALID:
5125 if (enc == encoding)
5126 eventPtr = next;
5127 result = XML_ERROR_INVALID_TOKEN;
5128 goto endEntityValue;
5129 default:
5130 if (enc == encoding)
5131 eventPtr = entityTextPtr;
5132 result = XML_ERROR_UNEXPECTED_STATE;
5133 goto endEntityValue;
5135 entityTextPtr = next;
5137 endEntityValue:
5138 #ifdef XML_DTD
5139 prologState.inEntityValue = oldInEntityValue;
5140 #endif /* XML_DTD */
5141 return result;
5144 static void FASTCALL
5145 normalizeLines(XML_Char *s)
5147 XML_Char *p;
5148 for (;; s++) {
5149 if (*s == XML_T('\0'))
5150 return;
5151 if (*s == 0xD)
5152 break;
5154 p = s;
5155 do {
5156 if (*s == 0xD) {
5157 *p++ = 0xA;
5158 if (*++s == 0xA)
5159 s++;
5161 else
5162 *p++ = *s++;
5163 } while (*s);
5164 *p = XML_T('\0');
5167 static int
5168 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5169 const char *start, const char *end)
5171 const XML_Char *target;
5172 XML_Char *data;
5173 const char *tem;
5174 if (!processingInstructionHandler) {
5175 if (defaultHandler)
5176 reportDefault(parser, enc, start, end);
5177 return 1;
5179 start += enc->minBytesPerChar * 2;
5180 tem = start + XmlNameLength(enc, start);
5181 target = poolStoreString(&tempPool, enc, start, tem);
5182 if (!target)
5183 return 0;
5184 poolFinish(&tempPool);
5185 data = poolStoreString(&tempPool, enc,
5186 XmlSkipS(enc, tem),
5187 end - enc->minBytesPerChar*2);
5188 if (!data)
5189 return 0;
5190 normalizeLines(data);
5191 processingInstructionHandler(handlerArg, target, data);
5192 poolClear(&tempPool);
5193 return 1;
5196 static int
5197 reportComment(XML_Parser parser, const ENCODING *enc,
5198 const char *start, const char *end)
5200 XML_Char *data;
5201 if (!commentHandler) {
5202 if (defaultHandler)
5203 reportDefault(parser, enc, start, end);
5204 return 1;
5206 data = poolStoreString(&tempPool,
5207 enc,
5208 start + enc->minBytesPerChar * 4,
5209 end - enc->minBytesPerChar * 3);
5210 if (!data)
5211 return 0;
5212 normalizeLines(data);
5213 commentHandler(handlerArg, data);
5214 poolClear(&tempPool);
5215 return 1;
5218 static void
5219 reportDefault(XML_Parser parser, const ENCODING *enc,
5220 const char *s, const char *end)
5222 if (MUST_CONVERT(enc, s)) {
5223 const char **eventPP;
5224 const char **eventEndPP;
5225 if (enc == encoding) {
5226 eventPP = &eventPtr;
5227 eventEndPP = &eventEndPtr;
5229 else {
5230 eventPP = &(openInternalEntities->internalEventPtr);
5231 eventEndPP = &(openInternalEntities->internalEventEndPtr);
5233 do {
5234 ICHAR *dataPtr = (ICHAR *)dataBuf;
5235 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
5236 *eventEndPP = s;
5237 defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
5238 *eventPP = s;
5239 } while (s != end);
5241 else
5242 defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
5246 static int
5247 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
5248 XML_Bool isId, const XML_Char *value, XML_Parser parser)
5250 DEFAULT_ATTRIBUTE *att;
5251 if (value || isId) {
5252 /* The handling of default attributes gets messed up if we have
5253 a default which duplicates a non-default. */
5254 int i;
5255 for (i = 0; i < type->nDefaultAtts; i++)
5256 if (attId == type->defaultAtts[i].id)
5257 return 1;
5258 if (isId && !type->idAtt && !attId->xmlns)
5259 type->idAtt = attId;
5261 if (type->nDefaultAtts == type->allocDefaultAtts) {
5262 if (type->allocDefaultAtts == 0) {
5263 type->allocDefaultAtts = 8;
5264 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
5265 * sizeof(DEFAULT_ATTRIBUTE));
5266 if (!type->defaultAtts)
5267 return 0;
5269 else {
5270 DEFAULT_ATTRIBUTE *temp;
5271 int count = type->allocDefaultAtts * 2;
5272 temp = (DEFAULT_ATTRIBUTE *)
5273 REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
5274 if (temp == NULL)
5275 return 0;
5276 type->allocDefaultAtts = count;
5277 type->defaultAtts = temp;
5280 att = type->defaultAtts + type->nDefaultAtts;
5281 att->id = attId;
5282 att->value = value;
5283 att->isCdata = isCdata;
5284 if (!isCdata)
5285 attId->maybeTokenized = XML_TRUE;
5286 type->nDefaultAtts += 1;
5287 return 1;
5290 static int
5291 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
5293 DTD * const dtd = _dtd; /* save one level of indirection */
5294 const XML_Char *name;
5295 for (name = elementType->name; *name; name++) {
5296 if (*name == XML_T(ASCII_COLON)) {
5297 PREFIX *prefix;
5298 const XML_Char *s;
5299 for (s = elementType->name; s != name; s++) {
5300 if (!poolAppendChar(&dtd->pool, *s))
5301 return 0;
5303 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5304 return 0;
5305 prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
5306 sizeof(PREFIX));
5307 if (!prefix)
5308 return 0;
5309 if (prefix->name == poolStart(&dtd->pool))
5310 poolFinish(&dtd->pool);
5311 else
5312 poolDiscard(&dtd->pool);
5313 elementType->prefix = prefix;
5317 return 1;
5320 static ATTRIBUTE_ID *
5321 getAttributeId(XML_Parser parser, const ENCODING *enc,
5322 const char *start, const char *end)
5324 DTD * const dtd = _dtd; /* save one level of indirection */
5325 ATTRIBUTE_ID *id;
5326 const XML_Char *name;
5327 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5328 return NULL;
5329 name = poolStoreString(&dtd->pool, enc, start, end);
5330 if (!name)
5331 return NULL;
5332 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
5333 ++name;
5334 id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
5335 if (!id)
5336 return NULL;
5337 if (id->name != name)
5338 poolDiscard(&dtd->pool);
5339 else {
5340 poolFinish(&dtd->pool);
5341 if (!ns)
5343 else if (name[0] == XML_T(ASCII_x)
5344 && name[1] == XML_T(ASCII_m)
5345 && name[2] == XML_T(ASCII_l)
5346 && name[3] == XML_T(ASCII_n)
5347 && name[4] == XML_T(ASCII_s)
5348 && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
5349 if (name[5] == XML_T('\0'))
5350 id->prefix = &dtd->defaultPrefix;
5351 else
5352 id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
5353 id->xmlns = XML_TRUE;
5355 else {
5356 int i;
5357 for (i = 0; name[i]; i++) {
5358 /* attributes without prefix are *not* in the default namespace */
5359 if (name[i] == XML_T(ASCII_COLON)) {
5360 int j;
5361 for (j = 0; j < i; j++) {
5362 if (!poolAppendChar(&dtd->pool, name[j]))
5363 return NULL;
5365 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5366 return NULL;
5367 id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
5368 sizeof(PREFIX));
5369 if (id->prefix->name == poolStart(&dtd->pool))
5370 poolFinish(&dtd->pool);
5371 else
5372 poolDiscard(&dtd->pool);
5373 break;
5378 return id;
5381 #define CONTEXT_SEP XML_T(ASCII_FF)
5383 static const XML_Char *
5384 getContext(XML_Parser parser)
5386 DTD * const dtd = _dtd; /* save one level of indirection */
5387 HASH_TABLE_ITER iter;
5388 XML_Bool needSep = XML_FALSE;
5390 if (dtd->defaultPrefix.binding) {
5391 int i;
5392 int len;
5393 if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
5394 return NULL;
5395 len = dtd->defaultPrefix.binding->uriLen;
5396 if (namespaceSeparator)
5397 len--;
5398 for (i = 0; i < len; i++)
5399 if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
5400 return NULL;
5401 needSep = XML_TRUE;
5404 hashTableIterInit(&iter, &(dtd->prefixes));
5405 for (;;) {
5406 int i;
5407 int len;
5408 const XML_Char *s;
5409 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
5410 if (!prefix)
5411 break;
5412 if (!prefix->binding)
5413 continue;
5414 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5415 return NULL;
5416 for (s = prefix->name; *s; s++)
5417 if (!poolAppendChar(&tempPool, *s))
5418 return NULL;
5419 if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
5420 return NULL;
5421 len = prefix->binding->uriLen;
5422 if (namespaceSeparator)
5423 len--;
5424 for (i = 0; i < len; i++)
5425 if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
5426 return NULL;
5427 needSep = XML_TRUE;
5431 hashTableIterInit(&iter, &(dtd->generalEntities));
5432 for (;;) {
5433 const XML_Char *s;
5434 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
5435 if (!e)
5436 break;
5437 if (!e->open)
5438 continue;
5439 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5440 return NULL;
5441 for (s = e->name; *s; s++)
5442 if (!poolAppendChar(&tempPool, *s))
5443 return 0;
5444 needSep = XML_TRUE;
5447 if (!poolAppendChar(&tempPool, XML_T('\0')))
5448 return NULL;
5449 return tempPool.start;
5452 static XML_Bool
5453 setContext(XML_Parser parser, const XML_Char *context)
5455 DTD * const dtd = _dtd; /* save one level of indirection */
5456 const XML_Char *s = context;
5458 while (*context != XML_T('\0')) {
5459 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
5460 ENTITY *e;
5461 if (!poolAppendChar(&tempPool, XML_T('\0')))
5462 return XML_FALSE;
5463 e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
5464 if (e)
5465 e->open = XML_TRUE;
5466 if (*s != XML_T('\0'))
5467 s++;
5468 context = s;
5469 poolDiscard(&tempPool);
5471 else if (*s == XML_T(ASCII_EQUALS)) {
5472 PREFIX *prefix;
5473 if (poolLength(&tempPool) == 0)
5474 prefix = &dtd->defaultPrefix;
5475 else {
5476 if (!poolAppendChar(&tempPool, XML_T('\0')))
5477 return XML_FALSE;
5478 prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
5479 sizeof(PREFIX));
5480 if (!prefix)
5481 return XML_FALSE;
5482 if (prefix->name == poolStart(&tempPool)) {
5483 prefix->name = poolCopyString(&dtd->pool, prefix->name);
5484 if (!prefix->name)
5485 return XML_FALSE;
5487 poolDiscard(&tempPool);
5489 for (context = s + 1;
5490 *context != CONTEXT_SEP && *context != XML_T('\0');
5491 context++)
5492 if (!poolAppendChar(&tempPool, *context))
5493 return XML_FALSE;
5494 if (!poolAppendChar(&tempPool, XML_T('\0')))
5495 return XML_FALSE;
5496 if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
5497 &inheritedBindings) != XML_ERROR_NONE)
5498 return XML_FALSE;
5499 poolDiscard(&tempPool);
5500 if (*context != XML_T('\0'))
5501 ++context;
5502 s = context;
5504 else {
5505 if (!poolAppendChar(&tempPool, *s))
5506 return XML_FALSE;
5507 s++;
5510 return XML_TRUE;
5513 static void FASTCALL
5514 normalizePublicId(XML_Char *publicId)
5516 XML_Char *p = publicId;
5517 XML_Char *s;
5518 for (s = publicId; *s; s++) {
5519 switch (*s) {
5520 case 0x20:
5521 case 0xD:
5522 case 0xA:
5523 if (p != publicId && p[-1] != 0x20)
5524 *p++ = 0x20;
5525 break;
5526 default:
5527 *p++ = *s;
5530 if (p != publicId && p[-1] == 0x20)
5531 --p;
5532 *p = XML_T('\0');
5535 static DTD *
5536 dtdCreate(const XML_Memory_Handling_Suite *ms)
5538 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
5539 if (p == NULL)
5540 return p;
5541 poolInit(&(p->pool), ms);
5542 poolInit(&(p->entityValuePool), ms);
5543 hashTableInit(&(p->generalEntities), ms);
5544 hashTableInit(&(p->elementTypes), ms);
5545 hashTableInit(&(p->attributeIds), ms);
5546 hashTableInit(&(p->prefixes), ms);
5547 #ifdef XML_DTD
5548 p->paramEntityRead = XML_FALSE;
5549 hashTableInit(&(p->paramEntities), ms);
5550 #endif /* XML_DTD */
5551 p->defaultPrefix.name = NULL;
5552 p->defaultPrefix.binding = NULL;
5554 p->in_eldecl = XML_FALSE;
5555 p->scaffIndex = NULL;
5556 p->scaffold = NULL;
5557 p->scaffLevel = 0;
5558 p->scaffSize = 0;
5559 p->scaffCount = 0;
5560 p->contentStringLen = 0;
5562 p->keepProcessing = XML_TRUE;
5563 p->hasParamEntityRefs = XML_FALSE;
5564 p->standalone = XML_FALSE;
5565 return p;
5568 static void
5569 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
5571 HASH_TABLE_ITER iter;
5572 hashTableIterInit(&iter, &(p->elementTypes));
5573 for (;;) {
5574 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5575 if (!e)
5576 break;
5577 if (e->allocDefaultAtts != 0)
5578 ms->free_fcn(e->defaultAtts);
5580 hashTableClear(&(p->generalEntities));
5581 #ifdef XML_DTD
5582 p->paramEntityRead = XML_FALSE;
5583 hashTableClear(&(p->paramEntities));
5584 #endif /* XML_DTD */
5585 hashTableClear(&(p->elementTypes));
5586 hashTableClear(&(p->attributeIds));
5587 hashTableClear(&(p->prefixes));
5588 poolClear(&(p->pool));
5589 poolClear(&(p->entityValuePool));
5590 p->defaultPrefix.name = NULL;
5591 p->defaultPrefix.binding = NULL;
5593 p->in_eldecl = XML_FALSE;
5595 ms->free_fcn(p->scaffIndex);
5596 p->scaffIndex = NULL;
5597 ms->free_fcn(p->scaffold);
5598 p->scaffold = NULL;
5600 p->scaffLevel = 0;
5601 p->scaffSize = 0;
5602 p->scaffCount = 0;
5603 p->contentStringLen = 0;
5605 p->keepProcessing = XML_TRUE;
5606 p->hasParamEntityRefs = XML_FALSE;
5607 p->standalone = XML_FALSE;
5610 static void
5611 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
5613 HASH_TABLE_ITER iter;
5614 hashTableIterInit(&iter, &(p->elementTypes));
5615 for (;;) {
5616 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5617 if (!e)
5618 break;
5619 if (e->allocDefaultAtts != 0)
5620 ms->free_fcn(e->defaultAtts);
5622 hashTableDestroy(&(p->generalEntities));
5623 #ifdef XML_DTD
5624 hashTableDestroy(&(p->paramEntities));
5625 #endif /* XML_DTD */
5626 hashTableDestroy(&(p->elementTypes));
5627 hashTableDestroy(&(p->attributeIds));
5628 hashTableDestroy(&(p->prefixes));
5629 poolDestroy(&(p->pool));
5630 poolDestroy(&(p->entityValuePool));
5631 if (isDocEntity) {
5632 ms->free_fcn(p->scaffIndex);
5633 ms->free_fcn(p->scaffold);
5635 ms->free_fcn(p);
5638 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
5639 The new DTD has already been initialized.
5641 static int
5642 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
5644 HASH_TABLE_ITER iter;
5646 /* Copy the prefix table. */
5648 hashTableIterInit(&iter, &(oldDtd->prefixes));
5649 for (;;) {
5650 const XML_Char *name;
5651 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
5652 if (!oldP)
5653 break;
5654 name = poolCopyString(&(newDtd->pool), oldP->name);
5655 if (!name)
5656 return 0;
5657 if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
5658 return 0;
5661 hashTableIterInit(&iter, &(oldDtd->attributeIds));
5663 /* Copy the attribute id table. */
5665 for (;;) {
5666 ATTRIBUTE_ID *newA;
5667 const XML_Char *name;
5668 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
5670 if (!oldA)
5671 break;
5672 /* Remember to allocate the scratch byte before the name. */
5673 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
5674 return 0;
5675 name = poolCopyString(&(newDtd->pool), oldA->name);
5676 if (!name)
5677 return 0;
5678 ++name;
5679 newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
5680 sizeof(ATTRIBUTE_ID));
5681 if (!newA)
5682 return 0;
5683 newA->maybeTokenized = oldA->maybeTokenized;
5684 if (oldA->prefix) {
5685 newA->xmlns = oldA->xmlns;
5686 if (oldA->prefix == &oldDtd->defaultPrefix)
5687 newA->prefix = &newDtd->defaultPrefix;
5688 else
5689 newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
5690 oldA->prefix->name, 0);
5694 /* Copy the element type table. */
5696 hashTableIterInit(&iter, &(oldDtd->elementTypes));
5698 for (;;) {
5699 int i;
5700 ELEMENT_TYPE *newE;
5701 const XML_Char *name;
5702 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5703 if (!oldE)
5704 break;
5705 name = poolCopyString(&(newDtd->pool), oldE->name);
5706 if (!name)
5707 return 0;
5708 newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
5709 sizeof(ELEMENT_TYPE));
5710 if (!newE)
5711 return 0;
5712 if (oldE->nDefaultAtts) {
5713 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
5714 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
5715 if (!newE->defaultAtts) {
5716 ms->free_fcn(newE);
5717 return 0;
5720 if (oldE->idAtt)
5721 newE->idAtt = (ATTRIBUTE_ID *)
5722 lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
5723 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
5724 if (oldE->prefix)
5725 newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
5726 oldE->prefix->name, 0);
5727 for (i = 0; i < newE->nDefaultAtts; i++) {
5728 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
5729 lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
5730 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
5731 if (oldE->defaultAtts[i].value) {
5732 newE->defaultAtts[i].value
5733 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
5734 if (!newE->defaultAtts[i].value)
5735 return 0;
5737 else
5738 newE->defaultAtts[i].value = NULL;
5742 /* Copy the entity tables. */
5743 if (!copyEntityTable(&(newDtd->generalEntities),
5744 &(newDtd->pool),
5745 &(oldDtd->generalEntities)))
5746 return 0;
5748 #ifdef XML_DTD
5749 if (!copyEntityTable(&(newDtd->paramEntities),
5750 &(newDtd->pool),
5751 &(oldDtd->paramEntities)))
5752 return 0;
5753 newDtd->paramEntityRead = oldDtd->paramEntityRead;
5754 #endif /* XML_DTD */
5756 newDtd->keepProcessing = oldDtd->keepProcessing;
5757 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
5758 newDtd->standalone = oldDtd->standalone;
5760 /* Don't want deep copying for scaffolding */
5761 newDtd->in_eldecl = oldDtd->in_eldecl;
5762 newDtd->scaffold = oldDtd->scaffold;
5763 newDtd->contentStringLen = oldDtd->contentStringLen;
5764 newDtd->scaffSize = oldDtd->scaffSize;
5765 newDtd->scaffLevel = oldDtd->scaffLevel;
5766 newDtd->scaffIndex = oldDtd->scaffIndex;
5768 return 1;
5769 } /* End dtdCopy */
5771 static int
5772 copyEntityTable(HASH_TABLE *newTable,
5773 STRING_POOL *newPool,
5774 const HASH_TABLE *oldTable)
5776 HASH_TABLE_ITER iter;
5777 const XML_Char *cachedOldBase = NULL;
5778 const XML_Char *cachedNewBase = NULL;
5780 hashTableIterInit(&iter, oldTable);
5782 for (;;) {
5783 ENTITY *newE;
5784 const XML_Char *name;
5785 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
5786 if (!oldE)
5787 break;
5788 name = poolCopyString(newPool, oldE->name);
5789 if (!name)
5790 return 0;
5791 newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
5792 if (!newE)
5793 return 0;
5794 if (oldE->systemId) {
5795 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
5796 if (!tem)
5797 return 0;
5798 newE->systemId = tem;
5799 if (oldE->base) {
5800 if (oldE->base == cachedOldBase)
5801 newE->base = cachedNewBase;
5802 else {
5803 cachedOldBase = oldE->base;
5804 tem = poolCopyString(newPool, cachedOldBase);
5805 if (!tem)
5806 return 0;
5807 cachedNewBase = newE->base = tem;
5810 if (oldE->publicId) {
5811 tem = poolCopyString(newPool, oldE->publicId);
5812 if (!tem)
5813 return 0;
5814 newE->publicId = tem;
5817 else {
5818 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
5819 oldE->textLen);
5820 if (!tem)
5821 return 0;
5822 newE->textPtr = tem;
5823 newE->textLen = oldE->textLen;
5825 if (oldE->notation) {
5826 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
5827 if (!tem)
5828 return 0;
5829 newE->notation = tem;
5831 newE->is_param = oldE->is_param;
5832 newE->is_internal = oldE->is_internal;
5834 return 1;
5837 #define INIT_POWER 6
5839 static XML_Bool FASTCALL
5840 keyeq(KEY s1, KEY s2)
5842 for (; *s1 == *s2; s1++, s2++)
5843 if (*s1 == 0)
5844 return XML_TRUE;
5845 return XML_FALSE;
5848 static unsigned long FASTCALL
5849 hash(KEY s)
5851 unsigned long h = 0;
5852 while (*s)
5853 h = CHAR_HASH(h, *s++);
5854 return h;
5857 static NAMED *
5858 lookup(HASH_TABLE *table, KEY name, size_t createSize)
5860 size_t i;
5861 if (table->size == 0) {
5862 size_t tsize;
5863 if (!createSize)
5864 return NULL;
5865 table->power = INIT_POWER;
5866 /* table->size is a power of 2 */
5867 table->size = (size_t)1 << INIT_POWER;
5868 tsize = table->size * sizeof(NAMED *);
5869 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
5870 if (!table->v) {
5871 table->size = 0;
5872 return NULL;
5874 memset(table->v, 0, tsize);
5875 i = hash(name) & ((unsigned long)table->size - 1);
5877 else {
5878 unsigned long h = hash(name);
5879 unsigned long mask = (unsigned long)table->size - 1;
5880 unsigned char step = 0;
5881 i = h & mask;
5882 while (table->v[i]) {
5883 if (keyeq(name, table->v[i]->name))
5884 return table->v[i];
5885 if (!step)
5886 step = PROBE_STEP(h, mask, table->power);
5887 i < step ? (i += table->size - step) : (i -= step);
5889 if (!createSize)
5890 return NULL;
5892 /* check for overflow (table is half full) */
5893 if (table->used >> (table->power - 1)) {
5894 unsigned char newPower = table->power + 1;
5895 size_t newSize = (size_t)1 << newPower;
5896 unsigned long newMask = (unsigned long)newSize - 1;
5897 size_t tsize = newSize * sizeof(NAMED *);
5898 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
5899 if (!newV)
5900 return NULL;
5901 memset(newV, 0, tsize);
5902 for (i = 0; i < table->size; i++)
5903 if (table->v[i]) {
5904 unsigned long newHash = hash(table->v[i]->name);
5905 size_t j = newHash & newMask;
5906 step = 0;
5907 while (newV[j]) {
5908 if (!step)
5909 step = PROBE_STEP(newHash, newMask, newPower);
5910 j < step ? (j += newSize - step) : (j -= step);
5912 newV[j] = table->v[i];
5914 table->mem->free_fcn(table->v);
5915 table->v = newV;
5916 table->power = newPower;
5917 table->size = newSize;
5918 i = h & newMask;
5919 step = 0;
5920 while (table->v[i]) {
5921 if (!step)
5922 step = PROBE_STEP(h, newMask, newPower);
5923 i < step ? (i += newSize - step) : (i -= step);
5927 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
5928 if (!table->v[i])
5929 return NULL;
5930 memset(table->v[i], 0, createSize);
5931 table->v[i]->name = name;
5932 (table->used)++;
5933 return table->v[i];
5936 static void FASTCALL
5937 hashTableClear(HASH_TABLE *table)
5939 size_t i;
5940 for (i = 0; i < table->size; i++) {
5941 table->mem->free_fcn(table->v[i]);
5942 table->v[i] = NULL;
5944 table->used = 0;
5947 static void FASTCALL
5948 hashTableDestroy(HASH_TABLE *table)
5950 size_t i;
5951 for (i = 0; i < table->size; i++)
5952 table->mem->free_fcn(table->v[i]);
5953 table->mem->free_fcn(table->v);
5956 static void FASTCALL
5957 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
5959 p->power = 0;
5960 p->size = 0;
5961 p->used = 0;
5962 p->v = NULL;
5963 p->mem = ms;
5966 static void FASTCALL
5967 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
5969 iter->p = table->v;
5970 iter->end = iter->p + table->size;
5973 static NAMED * FASTCALL
5974 hashTableIterNext(HASH_TABLE_ITER *iter)
5976 while (iter->p != iter->end) {
5977 NAMED *tem = *(iter->p)++;
5978 if (tem)
5979 return tem;
5981 return NULL;
5984 static void FASTCALL
5985 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
5987 pool->blocks = NULL;
5988 pool->freeBlocks = NULL;
5989 pool->start = NULL;
5990 pool->ptr = NULL;
5991 pool->end = NULL;
5992 pool->mem = ms;
5995 static void FASTCALL
5996 poolClear(STRING_POOL *pool)
5998 if (!pool->freeBlocks)
5999 pool->freeBlocks = pool->blocks;
6000 else {
6001 BLOCK *p = pool->blocks;
6002 while (p) {
6003 BLOCK *tem = p->next;
6004 p->next = pool->freeBlocks;
6005 pool->freeBlocks = p;
6006 p = tem;
6009 pool->blocks = NULL;
6010 pool->start = NULL;
6011 pool->ptr = NULL;
6012 pool->end = NULL;
6015 static void FASTCALL
6016 poolDestroy(STRING_POOL *pool)
6018 BLOCK *p = pool->blocks;
6019 while (p) {
6020 BLOCK *tem = p->next;
6021 pool->mem->free_fcn(p);
6022 p = tem;
6024 p = pool->freeBlocks;
6025 while (p) {
6026 BLOCK *tem = p->next;
6027 pool->mem->free_fcn(p);
6028 p = tem;
6032 static XML_Char *
6033 poolAppend(STRING_POOL *pool, const ENCODING *enc,
6034 const char *ptr, const char *end)
6036 if (!pool->ptr && !poolGrow(pool))
6037 return NULL;
6038 for (;;) {
6039 XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6040 if (ptr == end)
6041 break;
6042 if (!poolGrow(pool))
6043 return NULL;
6045 return pool->start;
6048 static const XML_Char * FASTCALL
6049 poolCopyString(STRING_POOL *pool, const XML_Char *s)
6051 do {
6052 if (!poolAppendChar(pool, *s))
6053 return NULL;
6054 } while (*s++);
6055 s = pool->start;
6056 poolFinish(pool);
6057 return s;
6060 static const XML_Char *
6061 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
6063 if (!pool->ptr && !poolGrow(pool))
6064 return NULL;
6065 for (; n > 0; --n, s++) {
6066 if (!poolAppendChar(pool, *s))
6067 return NULL;
6069 s = pool->start;
6070 poolFinish(pool);
6071 return s;
6074 static const XML_Char * FASTCALL
6075 poolAppendString(STRING_POOL *pool, const XML_Char *s)
6077 while (*s) {
6078 if (!poolAppendChar(pool, *s))
6079 return NULL;
6080 s++;
6082 return pool->start;
6085 static XML_Char *
6086 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
6087 const char *ptr, const char *end)
6089 if (!poolAppend(pool, enc, ptr, end))
6090 return NULL;
6091 if (pool->ptr == pool->end && !poolGrow(pool))
6092 return NULL;
6093 *(pool->ptr)++ = 0;
6094 return pool->start;
6097 static XML_Bool FASTCALL
6098 poolGrow(STRING_POOL *pool)
6100 if (pool->freeBlocks) {
6101 if (pool->start == 0) {
6102 pool->blocks = pool->freeBlocks;
6103 pool->freeBlocks = pool->freeBlocks->next;
6104 pool->blocks->next = NULL;
6105 pool->start = pool->blocks->s;
6106 pool->end = pool->start + pool->blocks->size;
6107 pool->ptr = pool->start;
6108 return XML_TRUE;
6110 if (pool->end - pool->start < pool->freeBlocks->size) {
6111 BLOCK *tem = pool->freeBlocks->next;
6112 pool->freeBlocks->next = pool->blocks;
6113 pool->blocks = pool->freeBlocks;
6114 pool->freeBlocks = tem;
6115 memcpy(pool->blocks->s, pool->start,
6116 (pool->end - pool->start) * sizeof(XML_Char));
6117 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6118 pool->start = pool->blocks->s;
6119 pool->end = pool->start + pool->blocks->size;
6120 return XML_TRUE;
6123 if (pool->blocks && pool->start == pool->blocks->s) {
6124 int blockSize = (int)(pool->end - pool->start)*2;
6125 pool->blocks = (BLOCK *)
6126 pool->mem->realloc_fcn(pool->blocks,
6127 (offsetof(BLOCK, s)
6128 + blockSize * sizeof(XML_Char)));
6129 if (pool->blocks == NULL)
6130 return XML_FALSE;
6131 pool->blocks->size = blockSize;
6132 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6133 pool->start = pool->blocks->s;
6134 pool->end = pool->start + blockSize;
6136 else {
6137 BLOCK *tem;
6138 int blockSize = (int)(pool->end - pool->start);
6139 if (blockSize < INIT_BLOCK_SIZE)
6140 blockSize = INIT_BLOCK_SIZE;
6141 else
6142 blockSize *= 2;
6143 tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
6144 + blockSize * sizeof(XML_Char));
6145 if (!tem)
6146 return XML_FALSE;
6147 tem->size = blockSize;
6148 tem->next = pool->blocks;
6149 pool->blocks = tem;
6150 if (pool->ptr != pool->start)
6151 memcpy(tem->s, pool->start,
6152 (pool->ptr - pool->start) * sizeof(XML_Char));
6153 pool->ptr = tem->s + (pool->ptr - pool->start);
6154 pool->start = tem->s;
6155 pool->end = tem->s + blockSize;
6157 return XML_TRUE;
6160 static int FASTCALL
6161 nextScaffoldPart(XML_Parser parser)
6163 DTD * const dtd = _dtd; /* save one level of indirection */
6164 CONTENT_SCAFFOLD * me;
6165 int next;
6167 if (!dtd->scaffIndex) {
6168 dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
6169 if (!dtd->scaffIndex)
6170 return -1;
6171 dtd->scaffIndex[0] = 0;
6174 if (dtd->scaffCount >= dtd->scaffSize) {
6175 CONTENT_SCAFFOLD *temp;
6176 if (dtd->scaffold) {
6177 temp = (CONTENT_SCAFFOLD *)
6178 REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
6179 if (temp == NULL)
6180 return -1;
6181 dtd->scaffSize *= 2;
6183 else {
6184 temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
6185 * sizeof(CONTENT_SCAFFOLD));
6186 if (temp == NULL)
6187 return -1;
6188 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
6190 dtd->scaffold = temp;
6192 next = dtd->scaffCount++;
6193 me = &dtd->scaffold[next];
6194 if (dtd->scaffLevel) {
6195 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
6196 if (parent->lastchild) {
6197 dtd->scaffold[parent->lastchild].nextsib = next;
6199 if (!parent->childcnt)
6200 parent->firstchild = next;
6201 parent->lastchild = next;
6202 parent->childcnt++;
6204 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
6205 return next;
6208 static void
6209 build_node(XML_Parser parser,
6210 int src_node,
6211 XML_Content *dest,
6212 XML_Content **contpos,
6213 XML_Char **strpos)
6215 DTD * const dtd = _dtd; /* save one level of indirection */
6216 dest->type = dtd->scaffold[src_node].type;
6217 dest->quant = dtd->scaffold[src_node].quant;
6218 if (dest->type == XML_CTYPE_NAME) {
6219 const XML_Char *src;
6220 dest->name = *strpos;
6221 src = dtd->scaffold[src_node].name;
6222 for (;;) {
6223 *(*strpos)++ = *src;
6224 if (!*src)
6225 break;
6226 src++;
6228 dest->numchildren = 0;
6229 dest->children = NULL;
6231 else {
6232 unsigned int i;
6233 int cn;
6234 dest->numchildren = dtd->scaffold[src_node].childcnt;
6235 dest->children = *contpos;
6236 *contpos += dest->numchildren;
6237 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
6238 i < dest->numchildren;
6239 i++, cn = dtd->scaffold[cn].nextsib) {
6240 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
6242 dest->name = NULL;
6246 static XML_Content *
6247 build_model (XML_Parser parser)
6249 DTD * const dtd = _dtd; /* save one level of indirection */
6250 XML_Content *ret;
6251 XML_Content *cpos;
6252 XML_Char * str;
6253 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
6254 + (dtd->contentStringLen * sizeof(XML_Char)));
6256 ret = (XML_Content *)MALLOC(allocsize);
6257 if (!ret)
6258 return NULL;
6260 str = (XML_Char *) (&ret[dtd->scaffCount]);
6261 cpos = &ret[1];
6263 build_node(parser, 0, ret, &cpos, &str);
6264 return ret;
6267 static ELEMENT_TYPE *
6268 getElementType(XML_Parser parser,
6269 const ENCODING *enc,
6270 const char *ptr,
6271 const char *end)
6273 DTD * const dtd = _dtd; /* save one level of indirection */
6274 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
6275 ELEMENT_TYPE *ret;
6277 if (!name)
6278 return NULL;
6279 ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
6280 if (!ret)
6281 return NULL;
6282 if (ret->name != name)
6283 poolDiscard(&dtd->pool);
6284 else {
6285 poolFinish(&dtd->pool);
6286 if (!setElementTypePrefix(parser, ret))
6287 return NULL;
6289 return ret;