Drop main() prototype. Syncs with NetBSD-8
[minix.git] / external / mit / expat / dist / lib / xmlparse.c
blobf35aa36ba8a7fce3bae90f31b20354435b15d2f2
1 /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
2 See the file COPYING for copying permission.
3 */
5 #include <stddef.h>
6 #include <string.h> /* memset(), memcpy() */
7 #include <assert.h>
8 #include <limits.h> /* UINT_MAX */
9 #include <time.h> /* time() */
11 #define XML_BUILDING_EXPAT 1
13 #ifdef COMPILED_FROM_DSP
14 #include "winconfig.h"
15 #elif defined(MACOS_CLASSIC)
16 #include "macconfig.h"
17 #elif defined(__amigaos__)
18 #include "amigaconfig.h"
19 #elif defined(__WATCOMC__)
20 #include "watcomconfig.h"
21 #elif defined(HAVE_EXPAT_CONFIG_H)
22 #include <expat_config.h>
23 #endif /* ndef COMPILED_FROM_DSP */
25 #include "ascii.h"
26 #include "expat.h"
28 #ifdef XML_UNICODE
29 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
30 #define XmlConvert XmlUtf16Convert
31 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
32 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
33 #define XmlEncode XmlUtf16Encode
34 /* Using pointer subtraction to convert to integer type. */
35 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
36 typedef unsigned short ICHAR;
37 #else
38 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
39 #define XmlConvert XmlUtf8Convert
40 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
41 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
42 #define XmlEncode XmlUtf8Encode
43 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
44 typedef char ICHAR;
45 #endif
48 #ifndef XML_NS
50 #define XmlInitEncodingNS XmlInitEncoding
51 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
52 #undef XmlGetInternalEncodingNS
53 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
54 #define XmlParseXmlDeclNS XmlParseXmlDecl
56 #endif
58 #ifdef XML_UNICODE
60 #ifdef XML_UNICODE_WCHAR_T
61 #define XML_T(x) (const wchar_t)x
62 #define XML_L(x) L ## x
63 #else
64 #define XML_T(x) (const unsigned short)x
65 #define XML_L(x) x
66 #endif
68 #else
70 #define XML_T(x) x
71 #define XML_L(x) x
73 #endif
75 /* Round up n to be a multiple of sz, where sz is a power of 2. */
76 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
78 /* Handle the case where memmove() doesn't exist. */
79 #ifndef HAVE_MEMMOVE
80 #ifdef HAVE_BCOPY
81 #define memmove(d,s,l) bcopy((s),(d),(l))
82 #else
83 #error memmove does not exist on this platform, nor is a substitute available
84 #endif /* HAVE_BCOPY */
85 #endif /* HAVE_MEMMOVE */
87 #include "internal.h"
88 #include "xmltok.h"
89 #include "xmlrole.h"
91 typedef const XML_Char *KEY;
93 typedef struct {
94 KEY name;
95 } NAMED;
97 typedef struct {
98 NAMED **v;
99 unsigned char power;
100 size_t size;
101 size_t used;
102 const XML_Memory_Handling_Suite *mem;
103 } HASH_TABLE;
105 /* Basic character hash algorithm, taken from Python's string hash:
106 h = h * 1000003 ^ character, the constant being a prime number.
109 #ifdef XML_UNICODE
110 #define CHAR_HASH(h, c) \
111 (((h) * 0xF4243) ^ (unsigned short)(c))
112 #else
113 #define CHAR_HASH(h, c) \
114 (((h) * 0xF4243) ^ (unsigned char)(c))
115 #endif
117 /* For probing (after a collision) we need a step size relative prime
118 to the hash table size, which is a power of 2. We use double-hashing,
119 since we can calculate a second hash value cheaply by taking those bits
120 of the first hash value that were discarded (masked out) when the table
121 index was calculated: index = hash & mask, where mask = table->size - 1.
122 We limit the maximum step size to table->size / 4 (mask >> 2) and make
123 it odd, since odd numbers are always relative prime to a power of 2.
125 #define SECOND_HASH(hash, mask, power) \
126 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
127 #define PROBE_STEP(hash, mask, power) \
128 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
130 typedef struct {
131 NAMED **p;
132 NAMED **end;
133 } HASH_TABLE_ITER;
135 #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
136 #define INIT_DATA_BUF_SIZE 1024
137 #define INIT_ATTS_SIZE 16
138 #define INIT_ATTS_VERSION 0xFFFFFFFF
139 #define INIT_BLOCK_SIZE 1024
140 #define INIT_BUFFER_SIZE 1024
142 #define EXPAND_SPARE 24
144 typedef struct binding {
145 struct prefix *prefix;
146 struct binding *nextTagBinding;
147 struct binding *prevPrefixBinding;
148 const struct attribute_id *attId;
149 XML_Char *uri;
150 int uriLen;
151 int uriAlloc;
152 } BINDING;
154 typedef struct prefix {
155 const XML_Char *name;
156 BINDING *binding;
157 } PREFIX;
159 typedef struct {
160 const XML_Char *str;
161 const XML_Char *localPart;
162 const XML_Char *prefix;
163 int strLen;
164 int uriLen;
165 int prefixLen;
166 } TAG_NAME;
168 /* TAG represents an open element.
169 The name of the element is stored in both the document and API
170 encodings. The memory buffer 'buf' is a separately-allocated
171 memory area which stores the name. During the XML_Parse()/
172 XMLParseBuffer() when the element is open, the memory for the 'raw'
173 version of the name (in the document encoding) is shared with the
174 document buffer. If the element is open across calls to
175 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
176 contain the 'raw' name as well.
178 A parser re-uses these structures, maintaining a list of allocated
179 TAG objects in a free list.
181 typedef struct tag {
182 struct tag *parent; /* parent of this element */
183 const char *rawName; /* tagName in the original encoding */
184 int rawNameLength;
185 TAG_NAME name; /* tagName in the API encoding */
186 char *buf; /* buffer for name components */
187 char *bufEnd; /* end of the buffer */
188 BINDING *bindings;
189 } TAG;
191 typedef struct {
192 const XML_Char *name;
193 const XML_Char *textPtr;
194 int textLen; /* length in XML_Chars */
195 int processed; /* # of processed bytes - when suspended */
196 const XML_Char *systemId;
197 const XML_Char *base;
198 const XML_Char *publicId;
199 const XML_Char *notation;
200 XML_Bool open;
201 XML_Bool is_param;
202 XML_Bool is_internal; /* true if declared in internal subset outside PE */
203 } ENTITY;
205 typedef struct {
206 enum XML_Content_Type type;
207 enum XML_Content_Quant quant;
208 const XML_Char * name;
209 int firstchild;
210 int lastchild;
211 int childcnt;
212 int nextsib;
213 } CONTENT_SCAFFOLD;
215 #define INIT_SCAFFOLD_ELEMENTS 32
217 typedef struct block {
218 struct block *next;
219 int size;
220 XML_Char s[1];
221 } BLOCK;
223 typedef struct {
224 BLOCK *blocks;
225 BLOCK *freeBlocks;
226 const XML_Char *end;
227 XML_Char *ptr;
228 XML_Char *start;
229 const XML_Memory_Handling_Suite *mem;
230 } STRING_POOL;
232 /* The XML_Char before the name is used to determine whether
233 an attribute has been specified. */
234 typedef struct attribute_id {
235 XML_Char *name;
236 PREFIX *prefix;
237 XML_Bool maybeTokenized;
238 XML_Bool xmlns;
239 } ATTRIBUTE_ID;
241 typedef struct {
242 const ATTRIBUTE_ID *id;
243 XML_Bool isCdata;
244 const XML_Char *value;
245 } DEFAULT_ATTRIBUTE;
247 typedef struct {
248 unsigned long version;
249 unsigned long hash;
250 const XML_Char *uriName;
251 } NS_ATT;
253 typedef struct {
254 const XML_Char *name;
255 PREFIX *prefix;
256 const ATTRIBUTE_ID *idAtt;
257 int nDefaultAtts;
258 int allocDefaultAtts;
259 DEFAULT_ATTRIBUTE *defaultAtts;
260 } ELEMENT_TYPE;
262 typedef struct {
263 HASH_TABLE generalEntities;
264 HASH_TABLE elementTypes;
265 HASH_TABLE attributeIds;
266 HASH_TABLE prefixes;
267 STRING_POOL pool;
268 STRING_POOL entityValuePool;
269 /* false once a parameter entity reference has been skipped */
270 XML_Bool keepProcessing;
271 /* true once an internal or external PE reference has been encountered;
272 this includes the reference to an external subset */
273 XML_Bool hasParamEntityRefs;
274 XML_Bool standalone;
275 #ifdef XML_DTD
276 /* indicates if external PE has been read */
277 XML_Bool paramEntityRead;
278 HASH_TABLE paramEntities;
279 #endif /* XML_DTD */
280 PREFIX defaultPrefix;
281 /* === scaffolding for building content model === */
282 XML_Bool in_eldecl;
283 CONTENT_SCAFFOLD *scaffold;
284 unsigned contentStringLen;
285 unsigned scaffSize;
286 unsigned scaffCount;
287 int scaffLevel;
288 int *scaffIndex;
289 } DTD;
291 typedef struct open_internal_entity {
292 const char *internalEventPtr;
293 const char *internalEventEndPtr;
294 struct open_internal_entity *next;
295 ENTITY *entity;
296 int startTagLevel;
297 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
298 } OPEN_INTERNAL_ENTITY;
300 typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
301 const char *start,
302 const char *end,
303 const char **endPtr);
305 static Processor prologProcessor;
306 static Processor prologInitProcessor;
307 static Processor contentProcessor;
308 static Processor cdataSectionProcessor;
309 #ifdef XML_DTD
310 static Processor ignoreSectionProcessor;
311 static Processor externalParEntProcessor;
312 static Processor externalParEntInitProcessor;
313 static Processor entityValueProcessor;
314 static Processor entityValueInitProcessor;
315 #endif /* XML_DTD */
316 static Processor epilogProcessor;
317 static Processor errorProcessor;
318 static Processor externalEntityInitProcessor;
319 static Processor externalEntityInitProcessor2;
320 static Processor externalEntityInitProcessor3;
321 static Processor externalEntityContentProcessor;
322 static Processor internalEntityProcessor;
324 static enum XML_Error
325 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
326 static enum XML_Error
327 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
328 const char *s, const char *next);
329 static enum XML_Error
330 initializeEncoding(XML_Parser parser);
331 static enum XML_Error
332 doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
333 const char *end, int tok, const char *next, const char **nextPtr,
334 XML_Bool haveMore);
335 static enum XML_Error
336 processInternalEntity(XML_Parser parser, ENTITY *entity,
337 XML_Bool betweenDecl);
338 static enum XML_Error
339 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
340 const char *start, const char *end, const char **endPtr,
341 XML_Bool haveMore);
342 static enum XML_Error
343 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
344 const char *end, const char **nextPtr, XML_Bool haveMore);
345 #ifdef XML_DTD
346 static enum XML_Error
347 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
348 const char *end, const char **nextPtr, XML_Bool haveMore);
349 #endif /* XML_DTD */
351 static enum XML_Error
352 storeAtts(XML_Parser parser, const ENCODING *, const char *s,
353 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
354 static enum XML_Error
355 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
356 const XML_Char *uri, BINDING **bindingsPtr);
357 static int
358 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
359 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
360 static enum XML_Error
361 storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
362 const char *, const char *, STRING_POOL *);
363 static enum XML_Error
364 appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
365 const char *, const char *, STRING_POOL *);
366 static ATTRIBUTE_ID *
367 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
368 const char *end);
369 static int
370 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
371 static enum XML_Error
372 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
373 const char *end);
374 static int
375 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
376 const char *start, const char *end);
377 static int
378 reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
379 const char *end);
380 static void
381 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
382 const char *end);
384 static const XML_Char * getContext(XML_Parser parser);
385 static XML_Bool
386 setContext(XML_Parser parser, const XML_Char *context);
388 static void FASTCALL normalizePublicId(XML_Char *s);
390 static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
391 /* do not call if parentParser != NULL */
392 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
393 static void
394 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
395 static int
396 dtdCopy(XML_Parser oldParser,
397 DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
398 static int
399 copyEntityTable(XML_Parser oldParser,
400 HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
401 static NAMED *
402 lookup(XML_Parser parser, 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 unsigned long generate_hash_secret_salt(void);
436 static XML_Bool startParsing(XML_Parser parser);
438 static XML_Parser
439 parserCreate(const XML_Char *encodingName,
440 const XML_Memory_Handling_Suite *memsuite,
441 const XML_Char *nameSep,
442 DTD *dtd);
444 static void
445 parserInit(XML_Parser parser, const XML_Char *encodingName);
447 #define poolStart(pool) ((pool)->start)
448 #define poolEnd(pool) ((pool)->ptr)
449 #define poolLength(pool) ((pool)->ptr - (pool)->start)
450 #define poolChop(pool) ((void)--(pool->ptr))
451 #define poolLastChar(pool) (((pool)->ptr)[-1])
452 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
453 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
454 #define poolAppendChar(pool, c) \
455 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
456 ? 0 \
457 : ((*((pool)->ptr)++ = c), 1))
459 struct XML_ParserStruct {
460 /* The first member must be userData so that the XML_GetUserData
461 macro works. */
462 void *m_userData;
463 void *m_handlerArg;
464 char *m_buffer;
465 const XML_Memory_Handling_Suite m_mem;
466 /* first character to be parsed */
467 const char *m_bufferPtr;
468 /* past last character to be parsed */
469 char *m_bufferEnd;
470 /* allocated end of buffer */
471 const char *m_bufferLim;
472 XML_Index m_parseEndByteIndex;
473 const char *m_parseEndPtr;
474 XML_Char *m_dataBuf;
475 XML_Char *m_dataBufEnd;
476 XML_StartElementHandler m_startElementHandler;
477 XML_EndElementHandler m_endElementHandler;
478 XML_CharacterDataHandler m_characterDataHandler;
479 XML_ProcessingInstructionHandler m_processingInstructionHandler;
480 XML_CommentHandler m_commentHandler;
481 XML_StartCdataSectionHandler m_startCdataSectionHandler;
482 XML_EndCdataSectionHandler m_endCdataSectionHandler;
483 XML_DefaultHandler m_defaultHandler;
484 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
485 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
486 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
487 XML_NotationDeclHandler m_notationDeclHandler;
488 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
489 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
490 XML_NotStandaloneHandler m_notStandaloneHandler;
491 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
492 XML_Parser m_externalEntityRefHandlerArg;
493 XML_SkippedEntityHandler m_skippedEntityHandler;
494 XML_UnknownEncodingHandler m_unknownEncodingHandler;
495 XML_ElementDeclHandler m_elementDeclHandler;
496 XML_AttlistDeclHandler m_attlistDeclHandler;
497 XML_EntityDeclHandler m_entityDeclHandler;
498 XML_XmlDeclHandler m_xmlDeclHandler;
499 const ENCODING *m_encoding;
500 INIT_ENCODING m_initEncoding;
501 const ENCODING *m_internalEncoding;
502 const XML_Char *m_protocolEncodingName;
503 XML_Bool m_ns;
504 XML_Bool m_ns_triplets;
505 void *m_unknownEncodingMem;
506 void *m_unknownEncodingData;
507 void *m_unknownEncodingHandlerData;
508 void (XMLCALL *m_unknownEncodingRelease)(void *);
509 PROLOG_STATE m_prologState;
510 Processor *m_processor;
511 enum XML_Error m_errorCode;
512 const char *m_eventPtr;
513 const char *m_eventEndPtr;
514 const char *m_positionPtr;
515 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
516 OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
517 XML_Bool m_defaultExpandInternalEntities;
518 int m_tagLevel;
519 ENTITY *m_declEntity;
520 const XML_Char *m_doctypeName;
521 const XML_Char *m_doctypeSysid;
522 const XML_Char *m_doctypePubid;
523 const XML_Char *m_declAttributeType;
524 const XML_Char *m_declNotationName;
525 const XML_Char *m_declNotationPublicId;
526 ELEMENT_TYPE *m_declElementType;
527 ATTRIBUTE_ID *m_declAttributeId;
528 XML_Bool m_declAttributeIsCdata;
529 XML_Bool m_declAttributeIsId;
530 DTD *m_dtd;
531 const XML_Char *m_curBase;
532 TAG *m_tagStack;
533 TAG *m_freeTagList;
534 BINDING *m_inheritedBindings;
535 BINDING *m_freeBindingList;
536 int m_attsSize;
537 int m_nSpecifiedAtts;
538 int m_idAttIndex;
539 ATTRIBUTE *m_atts;
540 NS_ATT *m_nsAtts;
541 unsigned long m_nsAttsVersion;
542 unsigned char m_nsAttsPower;
543 #ifdef XML_ATTR_INFO
544 XML_AttrInfo *m_attInfo;
545 #endif
546 POSITION m_position;
547 STRING_POOL m_tempPool;
548 STRING_POOL m_temp2Pool;
549 char *m_groupConnector;
550 unsigned int m_groupSize;
551 XML_Char m_namespaceSeparator;
552 XML_Parser m_parentParser;
553 XML_ParsingStatus m_parsingStatus;
554 #ifdef XML_DTD
555 XML_Bool m_isParamEntity;
556 XML_Bool m_useForeignDTD;
557 enum XML_ParamEntityParsing m_paramEntityParsing;
558 #endif
559 unsigned long m_hash_secret_salt;
562 #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
563 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
564 #define FREE(p) (parser->m_mem.free_fcn((p)))
566 #define userData (parser->m_userData)
567 #define handlerArg (parser->m_handlerArg)
568 #define startElementHandler (parser->m_startElementHandler)
569 #define endElementHandler (parser->m_endElementHandler)
570 #define characterDataHandler (parser->m_characterDataHandler)
571 #define processingInstructionHandler \
572 (parser->m_processingInstructionHandler)
573 #define commentHandler (parser->m_commentHandler)
574 #define startCdataSectionHandler \
575 (parser->m_startCdataSectionHandler)
576 #define endCdataSectionHandler (parser->m_endCdataSectionHandler)
577 #define defaultHandler (parser->m_defaultHandler)
578 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
579 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
580 #define unparsedEntityDeclHandler \
581 (parser->m_unparsedEntityDeclHandler)
582 #define notationDeclHandler (parser->m_notationDeclHandler)
583 #define startNamespaceDeclHandler \
584 (parser->m_startNamespaceDeclHandler)
585 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
586 #define notStandaloneHandler (parser->m_notStandaloneHandler)
587 #define externalEntityRefHandler \
588 (parser->m_externalEntityRefHandler)
589 #define externalEntityRefHandlerArg \
590 (parser->m_externalEntityRefHandlerArg)
591 #define internalEntityRefHandler \
592 (parser->m_internalEntityRefHandler)
593 #define skippedEntityHandler (parser->m_skippedEntityHandler)
594 #define unknownEncodingHandler (parser->m_unknownEncodingHandler)
595 #define elementDeclHandler (parser->m_elementDeclHandler)
596 #define attlistDeclHandler (parser->m_attlistDeclHandler)
597 #define entityDeclHandler (parser->m_entityDeclHandler)
598 #define xmlDeclHandler (parser->m_xmlDeclHandler)
599 #define encoding (parser->m_encoding)
600 #define initEncoding (parser->m_initEncoding)
601 #define internalEncoding (parser->m_internalEncoding)
602 #define unknownEncodingMem (parser->m_unknownEncodingMem)
603 #define unknownEncodingData (parser->m_unknownEncodingData)
604 #define unknownEncodingHandlerData \
605 (parser->m_unknownEncodingHandlerData)
606 #define unknownEncodingRelease (parser->m_unknownEncodingRelease)
607 #define protocolEncodingName (parser->m_protocolEncodingName)
608 #define ns (parser->m_ns)
609 #define ns_triplets (parser->m_ns_triplets)
610 #define prologState (parser->m_prologState)
611 #define processor (parser->m_processor)
612 #define errorCode (parser->m_errorCode)
613 #define eventPtr (parser->m_eventPtr)
614 #define eventEndPtr (parser->m_eventEndPtr)
615 #define positionPtr (parser->m_positionPtr)
616 #define position (parser->m_position)
617 #define openInternalEntities (parser->m_openInternalEntities)
618 #define freeInternalEntities (parser->m_freeInternalEntities)
619 #define defaultExpandInternalEntities \
620 (parser->m_defaultExpandInternalEntities)
621 #define tagLevel (parser->m_tagLevel)
622 #define buffer (parser->m_buffer)
623 #define bufferPtr (parser->m_bufferPtr)
624 #define bufferEnd (parser->m_bufferEnd)
625 #define parseEndByteIndex (parser->m_parseEndByteIndex)
626 #define parseEndPtr (parser->m_parseEndPtr)
627 #define bufferLim (parser->m_bufferLim)
628 #define dataBuf (parser->m_dataBuf)
629 #define dataBufEnd (parser->m_dataBufEnd)
630 #define _dtd (parser->m_dtd)
631 #define curBase (parser->m_curBase)
632 #define declEntity (parser->m_declEntity)
633 #define doctypeName (parser->m_doctypeName)
634 #define doctypeSysid (parser->m_doctypeSysid)
635 #define doctypePubid (parser->m_doctypePubid)
636 #define declAttributeType (parser->m_declAttributeType)
637 #define declNotationName (parser->m_declNotationName)
638 #define declNotationPublicId (parser->m_declNotationPublicId)
639 #define declElementType (parser->m_declElementType)
640 #define declAttributeId (parser->m_declAttributeId)
641 #define declAttributeIsCdata (parser->m_declAttributeIsCdata)
642 #define declAttributeIsId (parser->m_declAttributeIsId)
643 #define freeTagList (parser->m_freeTagList)
644 #define freeBindingList (parser->m_freeBindingList)
645 #define inheritedBindings (parser->m_inheritedBindings)
646 #define tagStack (parser->m_tagStack)
647 #define atts (parser->m_atts)
648 #define attsSize (parser->m_attsSize)
649 #define nSpecifiedAtts (parser->m_nSpecifiedAtts)
650 #define idAttIndex (parser->m_idAttIndex)
651 #define nsAtts (parser->m_nsAtts)
652 #define nsAttsVersion (parser->m_nsAttsVersion)
653 #define nsAttsPower (parser->m_nsAttsPower)
654 #define attInfo (parser->m_attInfo)
655 #define tempPool (parser->m_tempPool)
656 #define temp2Pool (parser->m_temp2Pool)
657 #define groupConnector (parser->m_groupConnector)
658 #define groupSize (parser->m_groupSize)
659 #define namespaceSeparator (parser->m_namespaceSeparator)
660 #define parentParser (parser->m_parentParser)
661 #define ps_parsing (parser->m_parsingStatus.parsing)
662 #define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
663 #ifdef XML_DTD
664 #define isParamEntity (parser->m_isParamEntity)
665 #define useForeignDTD (parser->m_useForeignDTD)
666 #define paramEntityParsing (parser->m_paramEntityParsing)
667 #endif /* XML_DTD */
668 #define hash_secret_salt (parser->m_hash_secret_salt)
670 XML_Parser XMLCALL
671 XML_ParserCreate(const XML_Char *encodingName)
673 return XML_ParserCreate_MM(encodingName, NULL, NULL);
676 XML_Parser XMLCALL
677 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
679 XML_Char tmp[2];
680 *tmp = nsSep;
681 return XML_ParserCreate_MM(encodingName, NULL, tmp);
684 static const XML_Char implicitContext[] = {
685 ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
686 ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
687 ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
688 ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
689 ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
690 ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
693 static unsigned long
694 generate_hash_secret_salt(void)
696 unsigned int seed = time(NULL) % UINT_MAX;
697 srand(seed);
698 return rand();
701 static XML_Bool /* only valid for root parser */
702 startParsing(XML_Parser parser)
704 /* hash functions must be initialized before setContext() is called */
705 if (hash_secret_salt == 0)
706 hash_secret_salt = generate_hash_secret_salt();
707 if (ns) {
708 /* implicit context only set for root parser, since child
709 parsers (i.e. external entity parsers) will inherit it
711 return setContext(parser, implicitContext);
713 return XML_TRUE;
716 XML_Parser XMLCALL
717 XML_ParserCreate_MM(const XML_Char *encodingName,
718 const XML_Memory_Handling_Suite *memsuite,
719 const XML_Char *nameSep)
721 return parserCreate(encodingName, memsuite, nameSep, NULL);
724 static XML_Parser
725 parserCreate(const XML_Char *encodingName,
726 const XML_Memory_Handling_Suite *memsuite,
727 const XML_Char *nameSep,
728 DTD *dtd)
730 XML_Parser parser;
732 if (memsuite) {
733 XML_Memory_Handling_Suite *mtemp;
734 parser = (XML_Parser)
735 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
736 if (parser != NULL) {
737 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
738 mtemp->malloc_fcn = memsuite->malloc_fcn;
739 mtemp->realloc_fcn = memsuite->realloc_fcn;
740 mtemp->free_fcn = memsuite->free_fcn;
743 else {
744 XML_Memory_Handling_Suite *mtemp;
745 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
746 if (parser != NULL) {
747 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
748 mtemp->malloc_fcn = malloc;
749 mtemp->realloc_fcn = realloc;
750 mtemp->free_fcn = free;
754 if (!parser)
755 return parser;
757 buffer = NULL;
758 bufferLim = NULL;
760 attsSize = INIT_ATTS_SIZE;
761 atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
762 if (atts == NULL) {
763 FREE(parser);
764 return NULL;
766 #ifdef XML_ATTR_INFO
767 attInfo = (XML_AttrInfo*)MALLOC(attsSize * sizeof(XML_AttrInfo));
768 if (attInfo == NULL) {
769 FREE(atts);
770 FREE(parser);
771 return NULL;
773 #endif
774 dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
775 if (dataBuf == NULL) {
776 FREE(atts);
777 #ifdef XML_ATTR_INFO
778 FREE(attInfo);
779 #endif
780 FREE(parser);
781 return NULL;
783 dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
785 if (dtd)
786 _dtd = dtd;
787 else {
788 _dtd = dtdCreate(&parser->m_mem);
789 if (_dtd == NULL) {
790 FREE(dataBuf);
791 FREE(atts);
792 #ifdef XML_ATTR_INFO
793 FREE(attInfo);
794 #endif
795 FREE(parser);
796 return NULL;
800 freeBindingList = NULL;
801 freeTagList = NULL;
802 freeInternalEntities = NULL;
804 groupSize = 0;
805 groupConnector = NULL;
807 unknownEncodingHandler = NULL;
808 unknownEncodingHandlerData = NULL;
810 namespaceSeparator = ASCII_EXCL;
811 ns = XML_FALSE;
812 ns_triplets = XML_FALSE;
814 nsAtts = NULL;
815 nsAttsVersion = 0;
816 nsAttsPower = 0;
818 poolInit(&tempPool, &(parser->m_mem));
819 poolInit(&temp2Pool, &(parser->m_mem));
820 parserInit(parser, encodingName);
822 if (encodingName && !protocolEncodingName) {
823 XML_ParserFree(parser);
824 return NULL;
827 if (nameSep) {
828 ns = XML_TRUE;
829 internalEncoding = XmlGetInternalEncodingNS();
830 namespaceSeparator = *nameSep;
832 else {
833 internalEncoding = XmlGetInternalEncoding();
836 return parser;
839 static void
840 parserInit(XML_Parser parser, const XML_Char *encodingName)
842 processor = prologInitProcessor;
843 XmlPrologStateInit(&prologState);
844 protocolEncodingName = (encodingName != NULL
845 ? poolCopyString(&tempPool, encodingName)
846 : NULL);
847 curBase = NULL;
848 XmlInitEncoding(&initEncoding, &encoding, 0);
849 userData = NULL;
850 handlerArg = NULL;
851 startElementHandler = NULL;
852 endElementHandler = NULL;
853 characterDataHandler = NULL;
854 processingInstructionHandler = NULL;
855 commentHandler = NULL;
856 startCdataSectionHandler = NULL;
857 endCdataSectionHandler = NULL;
858 defaultHandler = NULL;
859 startDoctypeDeclHandler = NULL;
860 endDoctypeDeclHandler = NULL;
861 unparsedEntityDeclHandler = NULL;
862 notationDeclHandler = NULL;
863 startNamespaceDeclHandler = NULL;
864 endNamespaceDeclHandler = NULL;
865 notStandaloneHandler = NULL;
866 externalEntityRefHandler = NULL;
867 externalEntityRefHandlerArg = parser;
868 skippedEntityHandler = NULL;
869 elementDeclHandler = NULL;
870 attlistDeclHandler = NULL;
871 entityDeclHandler = NULL;
872 xmlDeclHandler = NULL;
873 bufferPtr = buffer;
874 bufferEnd = buffer;
875 parseEndByteIndex = 0;
876 parseEndPtr = NULL;
877 declElementType = NULL;
878 declAttributeId = NULL;
879 declEntity = NULL;
880 doctypeName = NULL;
881 doctypeSysid = NULL;
882 doctypePubid = NULL;
883 declAttributeType = NULL;
884 declNotationName = NULL;
885 declNotationPublicId = NULL;
886 declAttributeIsCdata = XML_FALSE;
887 declAttributeIsId = XML_FALSE;
888 memset(&position, 0, sizeof(POSITION));
889 errorCode = XML_ERROR_NONE;
890 eventPtr = NULL;
891 eventEndPtr = NULL;
892 positionPtr = NULL;
893 openInternalEntities = NULL;
894 defaultExpandInternalEntities = XML_TRUE;
895 tagLevel = 0;
896 tagStack = NULL;
897 inheritedBindings = NULL;
898 nSpecifiedAtts = 0;
899 unknownEncodingMem = NULL;
900 unknownEncodingRelease = NULL;
901 unknownEncodingData = NULL;
902 parentParser = NULL;
903 ps_parsing = XML_INITIALIZED;
904 #ifdef XML_DTD
905 isParamEntity = XML_FALSE;
906 useForeignDTD = XML_FALSE;
907 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
908 #endif
909 hash_secret_salt = 0;
912 /* moves list of bindings to freeBindingList */
913 static void FASTCALL
914 moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
916 while (bindings) {
917 BINDING *b = bindings;
918 bindings = bindings->nextTagBinding;
919 b->nextTagBinding = freeBindingList;
920 freeBindingList = b;
924 XML_Bool XMLCALL
925 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
927 TAG *tStk;
928 OPEN_INTERNAL_ENTITY *openEntityList;
929 if (parentParser)
930 return XML_FALSE;
931 /* move tagStack to freeTagList */
932 tStk = tagStack;
933 while (tStk) {
934 TAG *tag = tStk;
935 tStk = tStk->parent;
936 tag->parent = freeTagList;
937 moveToFreeBindingList(parser, tag->bindings);
938 tag->bindings = NULL;
939 freeTagList = tag;
941 /* move openInternalEntities to freeInternalEntities */
942 openEntityList = openInternalEntities;
943 while (openEntityList) {
944 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
945 openEntityList = openEntity->next;
946 openEntity->next = freeInternalEntities;
947 freeInternalEntities = openEntity;
949 moveToFreeBindingList(parser, inheritedBindings);
950 FREE(unknownEncodingMem);
951 if (unknownEncodingRelease)
952 unknownEncodingRelease(unknownEncodingData);
953 poolClear(&tempPool);
954 poolClear(&temp2Pool);
955 parserInit(parser, encodingName);
956 dtdReset(_dtd, &parser->m_mem);
957 return XML_TRUE;
960 enum XML_Status XMLCALL
961 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
963 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
964 XXX There's no way for the caller to determine which of the
965 XXX possible error cases caused the XML_STATUS_ERROR return.
967 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
968 return XML_STATUS_ERROR;
969 if (encodingName == NULL)
970 protocolEncodingName = NULL;
971 else {
972 protocolEncodingName = poolCopyString(&tempPool, encodingName);
973 if (!protocolEncodingName)
974 return XML_STATUS_ERROR;
976 return XML_STATUS_OK;
979 XML_Parser XMLCALL
980 XML_ExternalEntityParserCreate(XML_Parser oldParser,
981 const XML_Char *context,
982 const XML_Char *encodingName)
984 XML_Parser parser = oldParser;
985 DTD *newDtd = NULL;
986 DTD *oldDtd = _dtd;
987 XML_StartElementHandler oldStartElementHandler = startElementHandler;
988 XML_EndElementHandler oldEndElementHandler = endElementHandler;
989 XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
990 XML_ProcessingInstructionHandler oldProcessingInstructionHandler
991 = processingInstructionHandler;
992 XML_CommentHandler oldCommentHandler = commentHandler;
993 XML_StartCdataSectionHandler oldStartCdataSectionHandler
994 = startCdataSectionHandler;
995 XML_EndCdataSectionHandler oldEndCdataSectionHandler
996 = endCdataSectionHandler;
997 XML_DefaultHandler oldDefaultHandler = defaultHandler;
998 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
999 = unparsedEntityDeclHandler;
1000 XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
1001 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
1002 = startNamespaceDeclHandler;
1003 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
1004 = endNamespaceDeclHandler;
1005 XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
1006 XML_ExternalEntityRefHandler oldExternalEntityRefHandler
1007 = externalEntityRefHandler;
1008 XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
1009 XML_UnknownEncodingHandler oldUnknownEncodingHandler
1010 = unknownEncodingHandler;
1011 XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
1012 XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
1013 XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
1014 XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
1015 ELEMENT_TYPE * oldDeclElementType = declElementType;
1017 void *oldUserData = userData;
1018 void *oldHandlerArg = handlerArg;
1019 XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
1020 XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
1021 #ifdef XML_DTD
1022 enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
1023 int oldInEntityValue = prologState.inEntityValue;
1024 #endif
1025 XML_Bool oldns_triplets = ns_triplets;
1026 /* Note that the new parser shares the same hash secret as the old
1027 parser, so that dtdCopy and copyEntityTable can lookup values
1028 from hash tables associated with either parser without us having
1029 to worry which hash secrets each table has.
1031 unsigned long oldhash_secret_salt = hash_secret_salt;
1033 #ifdef XML_DTD
1034 if (!context)
1035 newDtd = oldDtd;
1036 #endif /* XML_DTD */
1038 /* Note that the magical uses of the pre-processor to make field
1039 access look more like C++ require that `parser' be overwritten
1040 here. This makes this function more painful to follow than it
1041 would be otherwise.
1043 if (ns) {
1044 XML_Char tmp[2];
1045 *tmp = namespaceSeparator;
1046 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
1048 else {
1049 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1052 if (!parser)
1053 return NULL;
1055 startElementHandler = oldStartElementHandler;
1056 endElementHandler = oldEndElementHandler;
1057 characterDataHandler = oldCharacterDataHandler;
1058 processingInstructionHandler = oldProcessingInstructionHandler;
1059 commentHandler = oldCommentHandler;
1060 startCdataSectionHandler = oldStartCdataSectionHandler;
1061 endCdataSectionHandler = oldEndCdataSectionHandler;
1062 defaultHandler = oldDefaultHandler;
1063 unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1064 notationDeclHandler = oldNotationDeclHandler;
1065 startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1066 endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1067 notStandaloneHandler = oldNotStandaloneHandler;
1068 externalEntityRefHandler = oldExternalEntityRefHandler;
1069 skippedEntityHandler = oldSkippedEntityHandler;
1070 unknownEncodingHandler = oldUnknownEncodingHandler;
1071 elementDeclHandler = oldElementDeclHandler;
1072 attlistDeclHandler = oldAttlistDeclHandler;
1073 entityDeclHandler = oldEntityDeclHandler;
1074 xmlDeclHandler = oldXmlDeclHandler;
1075 declElementType = oldDeclElementType;
1076 userData = oldUserData;
1077 if (oldUserData == oldHandlerArg)
1078 handlerArg = userData;
1079 else
1080 handlerArg = parser;
1081 if (oldExternalEntityRefHandlerArg != oldParser)
1082 externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1083 defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1084 ns_triplets = oldns_triplets;
1085 hash_secret_salt = oldhash_secret_salt;
1086 parentParser = oldParser;
1087 #ifdef XML_DTD
1088 paramEntityParsing = oldParamEntityParsing;
1089 prologState.inEntityValue = oldInEntityValue;
1090 if (context) {
1091 #endif /* XML_DTD */
1092 if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem)
1093 || !setContext(parser, context)) {
1094 XML_ParserFree(parser);
1095 return NULL;
1097 processor = externalEntityInitProcessor;
1098 #ifdef XML_DTD
1100 else {
1101 /* The DTD instance referenced by _dtd is shared between the document's
1102 root parser and external PE parsers, therefore one does not need to
1103 call setContext. In addition, one also *must* not call setContext,
1104 because this would overwrite existing prefix->binding pointers in
1105 _dtd with ones that get destroyed with the external PE parser.
1106 This would leave those prefixes with dangling pointers.
1108 isParamEntity = XML_TRUE;
1109 XmlPrologStateInitExternalEntity(&prologState);
1110 processor = externalParEntInitProcessor;
1112 #endif /* XML_DTD */
1113 return parser;
1116 static void FASTCALL
1117 destroyBindings(BINDING *bindings, XML_Parser parser)
1119 for (;;) {
1120 BINDING *b = bindings;
1121 if (!b)
1122 break;
1123 bindings = b->nextTagBinding;
1124 FREE(b->uri);
1125 FREE(b);
1129 void XMLCALL
1130 XML_ParserFree(XML_Parser parser)
1132 TAG *tagList;
1133 OPEN_INTERNAL_ENTITY *entityList;
1134 if (parser == NULL)
1135 return;
1136 /* free tagStack and freeTagList */
1137 tagList = tagStack;
1138 for (;;) {
1139 TAG *p;
1140 if (tagList == NULL) {
1141 if (freeTagList == NULL)
1142 break;
1143 tagList = freeTagList;
1144 freeTagList = NULL;
1146 p = tagList;
1147 tagList = tagList->parent;
1148 FREE(p->buf);
1149 destroyBindings(p->bindings, parser);
1150 FREE(p);
1152 /* free openInternalEntities and freeInternalEntities */
1153 entityList = openInternalEntities;
1154 for (;;) {
1155 OPEN_INTERNAL_ENTITY *openEntity;
1156 if (entityList == NULL) {
1157 if (freeInternalEntities == NULL)
1158 break;
1159 entityList = freeInternalEntities;
1160 freeInternalEntities = NULL;
1162 openEntity = entityList;
1163 entityList = entityList->next;
1164 FREE(openEntity);
1167 destroyBindings(freeBindingList, parser);
1168 destroyBindings(inheritedBindings, parser);
1169 poolDestroy(&tempPool);
1170 poolDestroy(&temp2Pool);
1171 #ifdef XML_DTD
1172 /* external parameter entity parsers share the DTD structure
1173 parser->m_dtd with the root parser, so we must not destroy it
1175 if (!isParamEntity && _dtd)
1176 #else
1177 if (_dtd)
1178 #endif /* XML_DTD */
1179 dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
1180 FREE((void *)atts);
1181 #ifdef XML_ATTR_INFO
1182 FREE((void *)attInfo);
1183 #endif
1184 FREE(groupConnector);
1185 FREE(buffer);
1186 FREE(dataBuf);
1187 FREE(nsAtts);
1188 FREE(unknownEncodingMem);
1189 if (unknownEncodingRelease)
1190 unknownEncodingRelease(unknownEncodingData);
1191 FREE(parser);
1194 void XMLCALL
1195 XML_UseParserAsHandlerArg(XML_Parser parser)
1197 handlerArg = parser;
1200 enum XML_Error XMLCALL
1201 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
1203 #ifdef XML_DTD
1204 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1205 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1206 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
1207 useForeignDTD = useDTD;
1208 return XML_ERROR_NONE;
1209 #else
1210 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1211 #endif
1214 void XMLCALL
1215 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
1217 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1218 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1219 return;
1220 ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
1223 void XMLCALL
1224 XML_SetUserData(XML_Parser parser, void *p)
1226 if (handlerArg == userData)
1227 handlerArg = userData = p;
1228 else
1229 userData = p;
1232 enum XML_Status XMLCALL
1233 XML_SetBase(XML_Parser parser, const XML_Char *p)
1235 if (p) {
1236 p = poolCopyString(&_dtd->pool, p);
1237 if (!p)
1238 return XML_STATUS_ERROR;
1239 curBase = p;
1241 else
1242 curBase = NULL;
1243 return XML_STATUS_OK;
1246 const XML_Char * XMLCALL
1247 XML_GetBase(XML_Parser parser)
1249 return curBase;
1252 int XMLCALL
1253 XML_GetSpecifiedAttributeCount(XML_Parser parser)
1255 return nSpecifiedAtts;
1258 int XMLCALL
1259 XML_GetIdAttributeIndex(XML_Parser parser)
1261 return idAttIndex;
1264 #ifdef XML_ATTR_INFO
1265 const XML_AttrInfo * XMLCALL
1266 XML_GetAttributeInfo(XML_Parser parser)
1268 return attInfo;
1270 #endif
1272 void XMLCALL
1273 XML_SetElementHandler(XML_Parser parser,
1274 XML_StartElementHandler start,
1275 XML_EndElementHandler end)
1277 startElementHandler = start;
1278 endElementHandler = end;
1281 void XMLCALL
1282 XML_SetStartElementHandler(XML_Parser parser,
1283 XML_StartElementHandler start) {
1284 startElementHandler = start;
1287 void XMLCALL
1288 XML_SetEndElementHandler(XML_Parser parser,
1289 XML_EndElementHandler end) {
1290 endElementHandler = end;
1293 void XMLCALL
1294 XML_SetCharacterDataHandler(XML_Parser parser,
1295 XML_CharacterDataHandler handler)
1297 characterDataHandler = handler;
1300 void XMLCALL
1301 XML_SetProcessingInstructionHandler(XML_Parser parser,
1302 XML_ProcessingInstructionHandler handler)
1304 processingInstructionHandler = handler;
1307 void XMLCALL
1308 XML_SetCommentHandler(XML_Parser parser,
1309 XML_CommentHandler handler)
1311 commentHandler = handler;
1314 void XMLCALL
1315 XML_SetCdataSectionHandler(XML_Parser parser,
1316 XML_StartCdataSectionHandler start,
1317 XML_EndCdataSectionHandler end)
1319 startCdataSectionHandler = start;
1320 endCdataSectionHandler = end;
1323 void XMLCALL
1324 XML_SetStartCdataSectionHandler(XML_Parser parser,
1325 XML_StartCdataSectionHandler start) {
1326 startCdataSectionHandler = start;
1329 void XMLCALL
1330 XML_SetEndCdataSectionHandler(XML_Parser parser,
1331 XML_EndCdataSectionHandler end) {
1332 endCdataSectionHandler = end;
1335 void XMLCALL
1336 XML_SetDefaultHandler(XML_Parser parser,
1337 XML_DefaultHandler handler)
1339 defaultHandler = handler;
1340 defaultExpandInternalEntities = XML_FALSE;
1343 void XMLCALL
1344 XML_SetDefaultHandlerExpand(XML_Parser parser,
1345 XML_DefaultHandler handler)
1347 defaultHandler = handler;
1348 defaultExpandInternalEntities = XML_TRUE;
1351 void XMLCALL
1352 XML_SetDoctypeDeclHandler(XML_Parser parser,
1353 XML_StartDoctypeDeclHandler start,
1354 XML_EndDoctypeDeclHandler end)
1356 startDoctypeDeclHandler = start;
1357 endDoctypeDeclHandler = end;
1360 void XMLCALL
1361 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1362 XML_StartDoctypeDeclHandler start) {
1363 startDoctypeDeclHandler = start;
1366 void XMLCALL
1367 XML_SetEndDoctypeDeclHandler(XML_Parser parser,
1368 XML_EndDoctypeDeclHandler end) {
1369 endDoctypeDeclHandler = end;
1372 void XMLCALL
1373 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1374 XML_UnparsedEntityDeclHandler handler)
1376 unparsedEntityDeclHandler = handler;
1379 void XMLCALL
1380 XML_SetNotationDeclHandler(XML_Parser parser,
1381 XML_NotationDeclHandler handler)
1383 notationDeclHandler = handler;
1386 void XMLCALL
1387 XML_SetNamespaceDeclHandler(XML_Parser parser,
1388 XML_StartNamespaceDeclHandler start,
1389 XML_EndNamespaceDeclHandler end)
1391 startNamespaceDeclHandler = start;
1392 endNamespaceDeclHandler = end;
1395 void XMLCALL
1396 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1397 XML_StartNamespaceDeclHandler start) {
1398 startNamespaceDeclHandler = start;
1401 void XMLCALL
1402 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1403 XML_EndNamespaceDeclHandler end) {
1404 endNamespaceDeclHandler = end;
1407 void XMLCALL
1408 XML_SetNotStandaloneHandler(XML_Parser parser,
1409 XML_NotStandaloneHandler handler)
1411 notStandaloneHandler = handler;
1414 void XMLCALL
1415 XML_SetExternalEntityRefHandler(XML_Parser parser,
1416 XML_ExternalEntityRefHandler handler)
1418 externalEntityRefHandler = handler;
1421 void XMLCALL
1422 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
1424 if (arg)
1425 externalEntityRefHandlerArg = (XML_Parser)arg;
1426 else
1427 externalEntityRefHandlerArg = parser;
1430 void XMLCALL
1431 XML_SetSkippedEntityHandler(XML_Parser parser,
1432 XML_SkippedEntityHandler handler)
1434 skippedEntityHandler = handler;
1437 void XMLCALL
1438 XML_SetUnknownEncodingHandler(XML_Parser parser,
1439 XML_UnknownEncodingHandler handler,
1440 void *data)
1442 unknownEncodingHandler = handler;
1443 unknownEncodingHandlerData = data;
1446 void XMLCALL
1447 XML_SetElementDeclHandler(XML_Parser parser,
1448 XML_ElementDeclHandler eldecl)
1450 elementDeclHandler = eldecl;
1453 void XMLCALL
1454 XML_SetAttlistDeclHandler(XML_Parser parser,
1455 XML_AttlistDeclHandler attdecl)
1457 attlistDeclHandler = attdecl;
1460 void XMLCALL
1461 XML_SetEntityDeclHandler(XML_Parser parser,
1462 XML_EntityDeclHandler handler)
1464 entityDeclHandler = handler;
1467 void XMLCALL
1468 XML_SetXmlDeclHandler(XML_Parser parser,
1469 XML_XmlDeclHandler handler) {
1470 xmlDeclHandler = handler;
1473 int XMLCALL
1474 XML_SetParamEntityParsing(XML_Parser parser,
1475 enum XML_ParamEntityParsing peParsing)
1477 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1478 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1479 return 0;
1480 #ifdef XML_DTD
1481 paramEntityParsing = peParsing;
1482 return 1;
1483 #else
1484 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1485 #endif
1488 int XMLCALL
1489 XML_SetHashSalt(XML_Parser parser,
1490 unsigned long hash_salt)
1492 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1493 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1494 return 0;
1495 hash_secret_salt = hash_salt;
1496 return 1;
1499 enum XML_Status XMLCALL
1500 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
1502 switch (ps_parsing) {
1503 case XML_SUSPENDED:
1504 errorCode = XML_ERROR_SUSPENDED;
1505 return XML_STATUS_ERROR;
1506 case XML_FINISHED:
1507 errorCode = XML_ERROR_FINISHED;
1508 return XML_STATUS_ERROR;
1509 case XML_INITIALIZED:
1510 if (parentParser == NULL && !startParsing(parser)) {
1511 errorCode = XML_ERROR_NO_MEMORY;
1512 return XML_STATUS_ERROR;
1514 default:
1515 ps_parsing = XML_PARSING;
1518 if (len == 0) {
1519 ps_finalBuffer = (XML_Bool)isFinal;
1520 if (!isFinal)
1521 return XML_STATUS_OK;
1522 positionPtr = bufferPtr;
1523 parseEndPtr = bufferEnd;
1525 /* If data are left over from last buffer, and we now know that these
1526 data are the final chunk of input, then we have to check them again
1527 to detect errors based on that fact.
1529 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
1531 if (errorCode == XML_ERROR_NONE) {
1532 switch (ps_parsing) {
1533 case XML_SUSPENDED:
1534 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1535 positionPtr = bufferPtr;
1536 return XML_STATUS_SUSPENDED;
1537 case XML_INITIALIZED:
1538 case XML_PARSING:
1539 ps_parsing = XML_FINISHED;
1540 /* fall through */
1541 default:
1542 return XML_STATUS_OK;
1545 eventEndPtr = eventPtr;
1546 processor = errorProcessor;
1547 return XML_STATUS_ERROR;
1549 #ifndef XML_CONTEXT_BYTES
1550 else if (bufferPtr == bufferEnd) {
1551 const char *end;
1552 int nLeftOver;
1553 enum XML_Error result;
1554 parseEndByteIndex += len;
1555 positionPtr = s;
1556 ps_finalBuffer = (XML_Bool)isFinal;
1558 errorCode = processor(parser, s, parseEndPtr = s + len, &end);
1560 if (errorCode != XML_ERROR_NONE) {
1561 eventEndPtr = eventPtr;
1562 processor = errorProcessor;
1563 return XML_STATUS_ERROR;
1565 else {
1566 switch (ps_parsing) {
1567 case XML_SUSPENDED:
1568 result = XML_STATUS_SUSPENDED;
1569 break;
1570 case XML_INITIALIZED:
1571 case XML_PARSING:
1572 if (isFinal) {
1573 ps_parsing = XML_FINISHED;
1574 return XML_STATUS_OK;
1576 /* fall through */
1577 default:
1578 result = XML_STATUS_OK;
1582 XmlUpdatePosition(encoding, positionPtr, end, &position);
1583 nLeftOver = s + len - end;
1584 if (nLeftOver) {
1585 if (buffer == NULL || nLeftOver > bufferLim - buffer) {
1586 /* FIXME avoid integer overflow */
1587 char *temp;
1588 temp = (buffer == NULL
1589 ? (char *)MALLOC(len * 2)
1590 : (char *)REALLOC(buffer, len * 2));
1591 if (temp == NULL) {
1592 errorCode = XML_ERROR_NO_MEMORY;
1593 eventPtr = eventEndPtr = NULL;
1594 processor = errorProcessor;
1595 return XML_STATUS_ERROR;
1597 buffer = temp;
1598 bufferLim = buffer + len * 2;
1600 memcpy(buffer, end, nLeftOver);
1602 bufferPtr = buffer;
1603 bufferEnd = buffer + nLeftOver;
1604 positionPtr = bufferPtr;
1605 parseEndPtr = bufferEnd;
1606 eventPtr = bufferPtr;
1607 eventEndPtr = bufferPtr;
1608 return result;
1610 #endif /* not defined XML_CONTEXT_BYTES */
1611 else {
1612 void *buff = XML_GetBuffer(parser, len);
1613 if (buff == NULL)
1614 return XML_STATUS_ERROR;
1615 else {
1616 memcpy(buff, s, len);
1617 return XML_ParseBuffer(parser, len, isFinal);
1622 enum XML_Status XMLCALL
1623 XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
1625 const char *start;
1626 enum XML_Status result = XML_STATUS_OK;
1628 switch (ps_parsing) {
1629 case XML_SUSPENDED:
1630 errorCode = XML_ERROR_SUSPENDED;
1631 return XML_STATUS_ERROR;
1632 case XML_FINISHED:
1633 errorCode = XML_ERROR_FINISHED;
1634 return XML_STATUS_ERROR;
1635 case XML_INITIALIZED:
1636 if (parentParser == NULL && !startParsing(parser)) {
1637 errorCode = XML_ERROR_NO_MEMORY;
1638 return XML_STATUS_ERROR;
1640 default:
1641 ps_parsing = XML_PARSING;
1644 start = bufferPtr;
1645 positionPtr = start;
1646 bufferEnd += len;
1647 parseEndPtr = bufferEnd;
1648 parseEndByteIndex += len;
1649 ps_finalBuffer = (XML_Bool)isFinal;
1651 errorCode = processor(parser, start, parseEndPtr, &bufferPtr);
1653 if (errorCode != XML_ERROR_NONE) {
1654 eventEndPtr = eventPtr;
1655 processor = errorProcessor;
1656 return XML_STATUS_ERROR;
1658 else {
1659 switch (ps_parsing) {
1660 case XML_SUSPENDED:
1661 result = XML_STATUS_SUSPENDED;
1662 break;
1663 case XML_INITIALIZED:
1664 case XML_PARSING:
1665 if (isFinal) {
1666 ps_parsing = XML_FINISHED;
1667 return result;
1669 default: ; /* should not happen */
1673 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1674 positionPtr = bufferPtr;
1675 return result;
1678 void * XMLCALL
1679 XML_GetBuffer(XML_Parser parser, int len)
1681 switch (ps_parsing) {
1682 case XML_SUSPENDED:
1683 errorCode = XML_ERROR_SUSPENDED;
1684 return NULL;
1685 case XML_FINISHED:
1686 errorCode = XML_ERROR_FINISHED;
1687 return NULL;
1688 default: ;
1691 if (len > bufferLim - bufferEnd) {
1692 /* FIXME avoid integer overflow */
1693 int neededSize = len + (int)(bufferEnd - bufferPtr);
1694 #ifdef XML_CONTEXT_BYTES
1695 int keep = (int)(bufferPtr - buffer);
1697 if (keep > XML_CONTEXT_BYTES)
1698 keep = XML_CONTEXT_BYTES;
1699 neededSize += keep;
1700 #endif /* defined XML_CONTEXT_BYTES */
1701 if (neededSize <= bufferLim - buffer) {
1702 #ifdef XML_CONTEXT_BYTES
1703 if (keep < bufferPtr - buffer) {
1704 int offset = (int)(bufferPtr - buffer) - keep;
1705 memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
1706 bufferEnd -= offset;
1707 bufferPtr -= offset;
1709 #else
1710 memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
1711 bufferEnd = buffer + (bufferEnd - bufferPtr);
1712 bufferPtr = buffer;
1713 #endif /* not defined XML_CONTEXT_BYTES */
1715 else {
1716 char *newBuf;
1717 int bufferSize = (int)(bufferLim - bufferPtr);
1718 if (bufferSize == 0)
1719 bufferSize = INIT_BUFFER_SIZE;
1720 do {
1721 bufferSize *= 2;
1722 } while (bufferSize < neededSize);
1723 newBuf = (char *)MALLOC(bufferSize);
1724 if (newBuf == 0) {
1725 errorCode = XML_ERROR_NO_MEMORY;
1726 return NULL;
1728 bufferLim = newBuf + bufferSize;
1729 #ifdef XML_CONTEXT_BYTES
1730 if (bufferPtr) {
1731 int keep = (int)(bufferPtr - buffer);
1732 if (keep > XML_CONTEXT_BYTES)
1733 keep = XML_CONTEXT_BYTES;
1734 memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
1735 FREE(buffer);
1736 buffer = newBuf;
1737 bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
1738 bufferPtr = buffer + keep;
1740 else {
1741 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1742 bufferPtr = buffer = newBuf;
1744 #else
1745 if (bufferPtr) {
1746 memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
1747 FREE(buffer);
1749 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1750 bufferPtr = buffer = newBuf;
1751 #endif /* not defined XML_CONTEXT_BYTES */
1753 eventPtr = eventEndPtr = NULL;
1754 positionPtr = NULL;
1756 return bufferEnd;
1759 enum XML_Status XMLCALL
1760 XML_StopParser(XML_Parser parser, XML_Bool resumable)
1762 switch (ps_parsing) {
1763 case XML_SUSPENDED:
1764 if (resumable) {
1765 errorCode = XML_ERROR_SUSPENDED;
1766 return XML_STATUS_ERROR;
1768 ps_parsing = XML_FINISHED;
1769 break;
1770 case XML_FINISHED:
1771 errorCode = XML_ERROR_FINISHED;
1772 return XML_STATUS_ERROR;
1773 default:
1774 if (resumable) {
1775 #ifdef XML_DTD
1776 if (isParamEntity) {
1777 errorCode = XML_ERROR_SUSPEND_PE;
1778 return XML_STATUS_ERROR;
1780 #endif
1781 ps_parsing = XML_SUSPENDED;
1783 else
1784 ps_parsing = XML_FINISHED;
1786 return XML_STATUS_OK;
1789 enum XML_Status XMLCALL
1790 XML_ResumeParser(XML_Parser parser)
1792 enum XML_Status result = XML_STATUS_OK;
1794 if (ps_parsing != XML_SUSPENDED) {
1795 errorCode = XML_ERROR_NOT_SUSPENDED;
1796 return XML_STATUS_ERROR;
1798 ps_parsing = XML_PARSING;
1800 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
1802 if (errorCode != XML_ERROR_NONE) {
1803 eventEndPtr = eventPtr;
1804 processor = errorProcessor;
1805 return XML_STATUS_ERROR;
1807 else {
1808 switch (ps_parsing) {
1809 case XML_SUSPENDED:
1810 result = XML_STATUS_SUSPENDED;
1811 break;
1812 case XML_INITIALIZED:
1813 case XML_PARSING:
1814 if (ps_finalBuffer) {
1815 ps_parsing = XML_FINISHED;
1816 return result;
1818 default: ;
1822 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1823 positionPtr = bufferPtr;
1824 return result;
1827 void XMLCALL
1828 XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
1830 assert(status != NULL);
1831 *status = parser->m_parsingStatus;
1834 enum XML_Error XMLCALL
1835 XML_GetErrorCode(XML_Parser parser)
1837 return errorCode;
1840 XML_Index XMLCALL
1841 XML_GetCurrentByteIndex(XML_Parser parser)
1843 if (eventPtr)
1844 return parseEndByteIndex - (parseEndPtr - eventPtr);
1845 return -1;
1848 int XMLCALL
1849 XML_GetCurrentByteCount(XML_Parser parser)
1851 if (eventEndPtr && eventPtr)
1852 return (int)(eventEndPtr - eventPtr);
1853 return 0;
1856 const char * XMLCALL
1857 XML_GetInputContext(XML_Parser parser, int *offset, int *size)
1859 #ifdef XML_CONTEXT_BYTES
1860 if (eventPtr && buffer) {
1861 *offset = (int)(eventPtr - buffer);
1862 *size = (int)(bufferEnd - buffer);
1863 return buffer;
1865 #endif /* defined XML_CONTEXT_BYTES */
1866 return (char *) 0;
1869 XML_Size XMLCALL
1870 XML_GetCurrentLineNumber(XML_Parser parser)
1872 if (eventPtr && eventPtr >= positionPtr) {
1873 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1874 positionPtr = eventPtr;
1876 return position.lineNumber + 1;
1879 XML_Size XMLCALL
1880 XML_GetCurrentColumnNumber(XML_Parser parser)
1882 if (eventPtr && eventPtr >= positionPtr) {
1883 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1884 positionPtr = eventPtr;
1886 return position.columnNumber;
1889 void XMLCALL
1890 XML_FreeContentModel(XML_Parser parser, XML_Content *model)
1892 FREE(model);
1895 void * XMLCALL
1896 XML_MemMalloc(XML_Parser parser, size_t size)
1898 return MALLOC(size);
1901 void * XMLCALL
1902 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
1904 return REALLOC(ptr, size);
1907 void XMLCALL
1908 XML_MemFree(XML_Parser parser, void *ptr)
1910 FREE(ptr);
1913 void XMLCALL
1914 XML_DefaultCurrent(XML_Parser parser)
1916 if (defaultHandler) {
1917 if (openInternalEntities)
1918 reportDefault(parser,
1919 internalEncoding,
1920 openInternalEntities->internalEventPtr,
1921 openInternalEntities->internalEventEndPtr);
1922 else
1923 reportDefault(parser, encoding, eventPtr, eventEndPtr);
1927 const XML_LChar * XMLCALL
1928 XML_ErrorString(enum XML_Error code)
1930 static const XML_LChar* const message[] = {
1932 XML_L("out of memory"),
1933 XML_L("syntax error"),
1934 XML_L("no element found"),
1935 XML_L("not well-formed (invalid token)"),
1936 XML_L("unclosed token"),
1937 XML_L("partial character"),
1938 XML_L("mismatched tag"),
1939 XML_L("duplicate attribute"),
1940 XML_L("junk after document element"),
1941 XML_L("illegal parameter entity reference"),
1942 XML_L("undefined entity"),
1943 XML_L("recursive entity reference"),
1944 XML_L("asynchronous entity"),
1945 XML_L("reference to invalid character number"),
1946 XML_L("reference to binary entity"),
1947 XML_L("reference to external entity in attribute"),
1948 XML_L("XML or text declaration not at start of entity"),
1949 XML_L("unknown encoding"),
1950 XML_L("encoding specified in XML declaration is incorrect"),
1951 XML_L("unclosed CDATA section"),
1952 XML_L("error in processing external entity reference"),
1953 XML_L("document is not standalone"),
1954 XML_L("unexpected parser state - please send a bug report"),
1955 XML_L("entity declared in parameter entity"),
1956 XML_L("requested feature requires XML_DTD support in Expat"),
1957 XML_L("cannot change setting once parsing has begun"),
1958 XML_L("unbound prefix"),
1959 XML_L("must not undeclare prefix"),
1960 XML_L("incomplete markup in parameter entity"),
1961 XML_L("XML declaration not well-formed"),
1962 XML_L("text declaration not well-formed"),
1963 XML_L("illegal character(s) in public id"),
1964 XML_L("parser suspended"),
1965 XML_L("parser not suspended"),
1966 XML_L("parsing aborted"),
1967 XML_L("parsing finished"),
1968 XML_L("cannot suspend in external parameter entity"),
1969 XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
1970 XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
1971 XML_L("prefix must not be bound to one of the reserved namespace names")
1973 if (code > 0 && code < sizeof(message)/sizeof(message[0]))
1974 return message[code];
1975 return NULL;
1978 const XML_LChar * XMLCALL
1979 XML_ExpatVersion(void) {
1981 /* V1 is used to string-ize the version number. However, it would
1982 string-ize the actual version macro *names* unless we get them
1983 substituted before being passed to V1. CPP is defined to expand
1984 a macro, then rescan for more expansions. Thus, we use V2 to expand
1985 the version macros, then CPP will expand the resulting V1() macro
1986 with the correct numerals. */
1987 /* ### I'm assuming cpp is portable in this respect... */
1989 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
1990 #define V2(a,b,c) XML_L("expat_")V1(a,b,c)
1992 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
1994 #undef V1
1995 #undef V2
1998 XML_Expat_Version XMLCALL
1999 XML_ExpatVersionInfo(void)
2001 XML_Expat_Version version;
2003 version.major = XML_MAJOR_VERSION;
2004 version.minor = XML_MINOR_VERSION;
2005 version.micro = XML_MICRO_VERSION;
2007 return version;
2010 const XML_Feature * XMLCALL
2011 XML_GetFeatureList(void)
2013 static const XML_Feature features[] = {
2014 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
2015 sizeof(XML_Char)},
2016 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
2017 sizeof(XML_LChar)},
2018 #ifdef XML_UNICODE
2019 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
2020 #endif
2021 #ifdef XML_UNICODE_WCHAR_T
2022 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
2023 #endif
2024 #ifdef XML_DTD
2025 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
2026 #endif
2027 #ifdef XML_CONTEXT_BYTES
2028 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
2029 XML_CONTEXT_BYTES},
2030 #endif
2031 #ifdef XML_MIN_SIZE
2032 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
2033 #endif
2034 #ifdef XML_NS
2035 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
2036 #endif
2037 #ifdef XML_LARGE_SIZE
2038 {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
2039 #endif
2040 #ifdef XML_ATTR_INFO
2041 {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
2042 #endif
2043 {XML_FEATURE_END, NULL, 0}
2046 return features;
2049 /* Initially tag->rawName always points into the parse buffer;
2050 for those TAG instances opened while the current parse buffer was
2051 processed, and not yet closed, we need to store tag->rawName in a more
2052 permanent location, since the parse buffer is about to be discarded.
2054 static XML_Bool
2055 storeRawNames(XML_Parser parser)
2057 TAG *tag = tagStack;
2058 while (tag) {
2059 int bufSize;
2060 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
2061 char *rawNameBuf = tag->buf + nameLen;
2062 /* Stop if already stored. Since tagStack is a stack, we can stop
2063 at the first entry that has already been copied; everything
2064 below it in the stack is already been accounted for in a
2065 previous call to this function.
2067 if (tag->rawName == rawNameBuf)
2068 break;
2069 /* For re-use purposes we need to ensure that the
2070 size of tag->buf is a multiple of sizeof(XML_Char).
2072 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
2073 if (bufSize > tag->bufEnd - tag->buf) {
2074 char *temp = (char *)REALLOC(tag->buf, bufSize);
2075 if (temp == NULL)
2076 return XML_FALSE;
2077 /* if tag->name.str points to tag->buf (only when namespace
2078 processing is off) then we have to update it
2080 if (tag->name.str == (XML_Char *)tag->buf)
2081 tag->name.str = (XML_Char *)temp;
2082 /* if tag->name.localPart is set (when namespace processing is on)
2083 then update it as well, since it will always point into tag->buf
2085 if (tag->name.localPart)
2086 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
2087 (XML_Char *)tag->buf);
2088 tag->buf = temp;
2089 tag->bufEnd = temp + bufSize;
2090 rawNameBuf = temp + nameLen;
2092 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2093 tag->rawName = rawNameBuf;
2094 tag = tag->parent;
2096 return XML_TRUE;
2099 static enum XML_Error PTRCALL
2100 contentProcessor(XML_Parser parser,
2101 const char *start,
2102 const char *end,
2103 const char **endPtr)
2105 enum XML_Error result = doContent(parser, 0, encoding, start, end,
2106 endPtr, (XML_Bool)!ps_finalBuffer);
2107 if (result == XML_ERROR_NONE) {
2108 if (!storeRawNames(parser))
2109 return XML_ERROR_NO_MEMORY;
2111 return result;
2114 static enum XML_Error PTRCALL
2115 externalEntityInitProcessor(XML_Parser parser,
2116 const char *start,
2117 const char *end,
2118 const char **endPtr)
2120 enum XML_Error result = initializeEncoding(parser);
2121 if (result != XML_ERROR_NONE)
2122 return result;
2123 processor = externalEntityInitProcessor2;
2124 return externalEntityInitProcessor2(parser, start, end, endPtr);
2127 static enum XML_Error PTRCALL
2128 externalEntityInitProcessor2(XML_Parser parser,
2129 const char *start,
2130 const char *end,
2131 const char **endPtr)
2133 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2134 int tok = XmlContentTok(encoding, start, end, &next);
2135 switch (tok) {
2136 case XML_TOK_BOM:
2137 /* If we are at the end of the buffer, this would cause the next stage,
2138 i.e. externalEntityInitProcessor3, to pass control directly to
2139 doContent (by detecting XML_TOK_NONE) without processing any xml text
2140 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2142 if (next == end && !ps_finalBuffer) {
2143 *endPtr = next;
2144 return XML_ERROR_NONE;
2146 start = next;
2147 break;
2148 case XML_TOK_PARTIAL:
2149 if (!ps_finalBuffer) {
2150 *endPtr = start;
2151 return XML_ERROR_NONE;
2153 eventPtr = start;
2154 return XML_ERROR_UNCLOSED_TOKEN;
2155 case XML_TOK_PARTIAL_CHAR:
2156 if (!ps_finalBuffer) {
2157 *endPtr = start;
2158 return XML_ERROR_NONE;
2160 eventPtr = start;
2161 return XML_ERROR_PARTIAL_CHAR;
2163 processor = externalEntityInitProcessor3;
2164 return externalEntityInitProcessor3(parser, start, end, endPtr);
2167 static enum XML_Error PTRCALL
2168 externalEntityInitProcessor3(XML_Parser parser,
2169 const char *start,
2170 const char *end,
2171 const char **endPtr)
2173 int tok;
2174 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2175 eventPtr = start;
2176 tok = XmlContentTok(encoding, start, end, &next);
2177 eventEndPtr = next;
2179 switch (tok) {
2180 case XML_TOK_XML_DECL:
2182 enum XML_Error result;
2183 result = processXmlDecl(parser, 1, start, next);
2184 if (result != XML_ERROR_NONE)
2185 return result;
2186 switch (ps_parsing) {
2187 case XML_SUSPENDED:
2188 *endPtr = next;
2189 return XML_ERROR_NONE;
2190 case XML_FINISHED:
2191 return XML_ERROR_ABORTED;
2192 default:
2193 start = next;
2196 break;
2197 case XML_TOK_PARTIAL:
2198 if (!ps_finalBuffer) {
2199 *endPtr = start;
2200 return XML_ERROR_NONE;
2202 return XML_ERROR_UNCLOSED_TOKEN;
2203 case XML_TOK_PARTIAL_CHAR:
2204 if (!ps_finalBuffer) {
2205 *endPtr = start;
2206 return XML_ERROR_NONE;
2208 return XML_ERROR_PARTIAL_CHAR;
2210 processor = externalEntityContentProcessor;
2211 tagLevel = 1;
2212 return externalEntityContentProcessor(parser, start, end, endPtr);
2215 static enum XML_Error PTRCALL
2216 externalEntityContentProcessor(XML_Parser parser,
2217 const char *start,
2218 const char *end,
2219 const char **endPtr)
2221 enum XML_Error result = doContent(parser, 1, encoding, start, end,
2222 endPtr, (XML_Bool)!ps_finalBuffer);
2223 if (result == XML_ERROR_NONE) {
2224 if (!storeRawNames(parser))
2225 return XML_ERROR_NO_MEMORY;
2227 return result;
2230 static enum XML_Error
2231 doContent(XML_Parser parser,
2232 int startTagLevel,
2233 const ENCODING *enc,
2234 const char *s,
2235 const char *end,
2236 const char **nextPtr,
2237 XML_Bool haveMore)
2239 /* save one level of indirection */
2240 DTD * const dtd = _dtd;
2242 const char **eventPP;
2243 const char **eventEndPP;
2244 if (enc == encoding) {
2245 eventPP = &eventPtr;
2246 eventEndPP = &eventEndPtr;
2248 else {
2249 eventPP = &(openInternalEntities->internalEventPtr);
2250 eventEndPP = &(openInternalEntities->internalEventEndPtr);
2252 *eventPP = s;
2254 for (;;) {
2255 const char *next = s; /* XmlContentTok doesn't always set the last arg */
2256 int tok = XmlContentTok(enc, s, end, &next);
2257 *eventEndPP = next;
2258 switch (tok) {
2259 case XML_TOK_TRAILING_CR:
2260 if (haveMore) {
2261 *nextPtr = s;
2262 return XML_ERROR_NONE;
2264 *eventEndPP = end;
2265 if (characterDataHandler) {
2266 XML_Char c = 0xA;
2267 characterDataHandler(handlerArg, &c, 1);
2269 else if (defaultHandler)
2270 reportDefault(parser, enc, s, end);
2271 /* We are at the end of the final buffer, should we check for
2272 XML_SUSPENDED, XML_FINISHED?
2274 if (startTagLevel == 0)
2275 return XML_ERROR_NO_ELEMENTS;
2276 if (tagLevel != startTagLevel)
2277 return XML_ERROR_ASYNC_ENTITY;
2278 *nextPtr = end;
2279 return XML_ERROR_NONE;
2280 case XML_TOK_NONE:
2281 if (haveMore) {
2282 *nextPtr = s;
2283 return XML_ERROR_NONE;
2285 if (startTagLevel > 0) {
2286 if (tagLevel != startTagLevel)
2287 return XML_ERROR_ASYNC_ENTITY;
2288 *nextPtr = s;
2289 return XML_ERROR_NONE;
2291 return XML_ERROR_NO_ELEMENTS;
2292 case XML_TOK_INVALID:
2293 *eventPP = next;
2294 return XML_ERROR_INVALID_TOKEN;
2295 case XML_TOK_PARTIAL:
2296 if (haveMore) {
2297 *nextPtr = s;
2298 return XML_ERROR_NONE;
2300 return XML_ERROR_UNCLOSED_TOKEN;
2301 case XML_TOK_PARTIAL_CHAR:
2302 if (haveMore) {
2303 *nextPtr = s;
2304 return XML_ERROR_NONE;
2306 return XML_ERROR_PARTIAL_CHAR;
2307 case XML_TOK_ENTITY_REF:
2309 const XML_Char *name;
2310 ENTITY *entity;
2311 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
2312 s + enc->minBytesPerChar,
2313 next - enc->minBytesPerChar);
2314 if (ch) {
2315 if (characterDataHandler)
2316 characterDataHandler(handlerArg, &ch, 1);
2317 else if (defaultHandler)
2318 reportDefault(parser, enc, s, next);
2319 break;
2321 name = poolStoreString(&dtd->pool, enc,
2322 s + enc->minBytesPerChar,
2323 next - enc->minBytesPerChar);
2324 if (!name)
2325 return XML_ERROR_NO_MEMORY;
2326 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
2327 poolDiscard(&dtd->pool);
2328 /* First, determine if a check for an existing declaration is needed;
2329 if yes, check that the entity exists, and that it is internal,
2330 otherwise call the skipped entity or default handler.
2332 if (!dtd->hasParamEntityRefs || dtd->standalone) {
2333 if (!entity)
2334 return XML_ERROR_UNDEFINED_ENTITY;
2335 else if (!entity->is_internal)
2336 return XML_ERROR_ENTITY_DECLARED_IN_PE;
2338 else if (!entity) {
2339 if (skippedEntityHandler)
2340 skippedEntityHandler(handlerArg, name, 0);
2341 else if (defaultHandler)
2342 reportDefault(parser, enc, s, next);
2343 break;
2345 if (entity->open)
2346 return XML_ERROR_RECURSIVE_ENTITY_REF;
2347 if (entity->notation)
2348 return XML_ERROR_BINARY_ENTITY_REF;
2349 if (entity->textPtr) {
2350 enum XML_Error result;
2351 if (!defaultExpandInternalEntities) {
2352 if (skippedEntityHandler)
2353 skippedEntityHandler(handlerArg, entity->name, 0);
2354 else if (defaultHandler)
2355 reportDefault(parser, enc, s, next);
2356 break;
2358 result = processInternalEntity(parser, entity, XML_FALSE);
2359 if (result != XML_ERROR_NONE)
2360 return result;
2362 else if (externalEntityRefHandler) {
2363 const XML_Char *context;
2364 entity->open = XML_TRUE;
2365 context = getContext(parser);
2366 entity->open = XML_FALSE;
2367 if (!context)
2368 return XML_ERROR_NO_MEMORY;
2369 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
2370 context,
2371 entity->base,
2372 entity->systemId,
2373 entity->publicId))
2374 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2375 poolDiscard(&tempPool);
2377 else if (defaultHandler)
2378 reportDefault(parser, enc, s, next);
2379 break;
2381 case XML_TOK_START_TAG_NO_ATTS:
2382 /* fall through */
2383 case XML_TOK_START_TAG_WITH_ATTS:
2385 TAG *tag;
2386 enum XML_Error result;
2387 XML_Char *toPtr;
2388 if (freeTagList) {
2389 tag = freeTagList;
2390 freeTagList = freeTagList->parent;
2392 else {
2393 tag = (TAG *)MALLOC(sizeof(TAG));
2394 if (!tag)
2395 return XML_ERROR_NO_MEMORY;
2396 tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
2397 if (!tag->buf) {
2398 FREE(tag);
2399 return XML_ERROR_NO_MEMORY;
2401 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2403 tag->bindings = NULL;
2404 tag->parent = tagStack;
2405 tagStack = tag;
2406 tag->name.localPart = NULL;
2407 tag->name.prefix = NULL;
2408 tag->rawName = s + enc->minBytesPerChar;
2409 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
2410 ++tagLevel;
2412 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2413 const char *fromPtr = tag->rawName;
2414 toPtr = (XML_Char *)tag->buf;
2415 for (;;) {
2416 int bufSize;
2417 int convLen;
2418 XmlConvert(enc,
2419 &fromPtr, rawNameEnd,
2420 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
2421 convLen = (int)(toPtr - (XML_Char *)tag->buf);
2422 if (fromPtr == rawNameEnd) {
2423 tag->name.strLen = convLen;
2424 break;
2426 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2428 char *temp = (char *)REALLOC(tag->buf, bufSize);
2429 if (temp == NULL)
2430 return XML_ERROR_NO_MEMORY;
2431 tag->buf = temp;
2432 tag->bufEnd = temp + bufSize;
2433 toPtr = (XML_Char *)temp + convLen;
2437 tag->name.str = (XML_Char *)tag->buf;
2438 *toPtr = XML_T('\0');
2439 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2440 if (result)
2441 return result;
2442 if (startElementHandler)
2443 startElementHandler(handlerArg, tag->name.str,
2444 (const XML_Char **)atts);
2445 else if (defaultHandler)
2446 reportDefault(parser, enc, s, next);
2447 poolClear(&tempPool);
2448 break;
2450 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2451 /* fall through */
2452 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
2454 const char *rawName = s + enc->minBytesPerChar;
2455 enum XML_Error result;
2456 BINDING *bindings = NULL;
2457 XML_Bool noElmHandlers = XML_TRUE;
2458 TAG_NAME name;
2459 name.str = poolStoreString(&tempPool, enc, rawName,
2460 rawName + XmlNameLength(enc, rawName));
2461 if (!name.str)
2462 return XML_ERROR_NO_MEMORY;
2463 poolFinish(&tempPool);
2464 result = storeAtts(parser, enc, s, &name, &bindings);
2465 if (result)
2466 return result;
2467 poolFinish(&tempPool);
2468 if (startElementHandler) {
2469 startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
2470 noElmHandlers = XML_FALSE;
2472 if (endElementHandler) {
2473 if (startElementHandler)
2474 *eventPP = *eventEndPP;
2475 endElementHandler(handlerArg, name.str);
2476 noElmHandlers = XML_FALSE;
2478 if (noElmHandlers && defaultHandler)
2479 reportDefault(parser, enc, s, next);
2480 poolClear(&tempPool);
2481 while (bindings) {
2482 BINDING *b = bindings;
2483 if (endNamespaceDeclHandler)
2484 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2485 bindings = bindings->nextTagBinding;
2486 b->nextTagBinding = freeBindingList;
2487 freeBindingList = b;
2488 b->prefix->binding = b->prevPrefixBinding;
2491 if (tagLevel == 0)
2492 return epilogProcessor(parser, next, end, nextPtr);
2493 break;
2494 case XML_TOK_END_TAG:
2495 if (tagLevel == startTagLevel)
2496 return XML_ERROR_ASYNC_ENTITY;
2497 else {
2498 int len;
2499 const char *rawName;
2500 TAG *tag = tagStack;
2501 tagStack = tag->parent;
2502 tag->parent = freeTagList;
2503 freeTagList = tag;
2504 rawName = s + enc->minBytesPerChar*2;
2505 len = XmlNameLength(enc, rawName);
2506 if (len != tag->rawNameLength
2507 || memcmp(tag->rawName, rawName, len) != 0) {
2508 *eventPP = rawName;
2509 return XML_ERROR_TAG_MISMATCH;
2511 --tagLevel;
2512 if (endElementHandler) {
2513 const XML_Char *localPart;
2514 const XML_Char *prefix;
2515 XML_Char *uri;
2516 localPart = tag->name.localPart;
2517 if (ns && localPart) {
2518 /* localPart and prefix may have been overwritten in
2519 tag->name.str, since this points to the binding->uri
2520 buffer which gets re-used; so we have to add them again
2522 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2523 /* don't need to check for space - already done in storeAtts() */
2524 while (*localPart) *uri++ = *localPart++;
2525 prefix = (XML_Char *)tag->name.prefix;
2526 if (ns_triplets && prefix) {
2527 *uri++ = namespaceSeparator;
2528 while (*prefix) *uri++ = *prefix++;
2530 *uri = XML_T('\0');
2532 endElementHandler(handlerArg, tag->name.str);
2534 else if (defaultHandler)
2535 reportDefault(parser, enc, s, next);
2536 while (tag->bindings) {
2537 BINDING *b = tag->bindings;
2538 if (endNamespaceDeclHandler)
2539 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2540 tag->bindings = tag->bindings->nextTagBinding;
2541 b->nextTagBinding = freeBindingList;
2542 freeBindingList = b;
2543 b->prefix->binding = b->prevPrefixBinding;
2545 if (tagLevel == 0)
2546 return epilogProcessor(parser, next, end, nextPtr);
2548 break;
2549 case XML_TOK_CHAR_REF:
2551 int n = XmlCharRefNumber(enc, s);
2552 if (n < 0)
2553 return XML_ERROR_BAD_CHAR_REF;
2554 if (characterDataHandler) {
2555 XML_Char buf[XML_ENCODE_MAX];
2556 characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
2558 else if (defaultHandler)
2559 reportDefault(parser, enc, s, next);
2561 break;
2562 case XML_TOK_XML_DECL:
2563 return XML_ERROR_MISPLACED_XML_PI;
2564 case XML_TOK_DATA_NEWLINE:
2565 if (characterDataHandler) {
2566 XML_Char c = 0xA;
2567 characterDataHandler(handlerArg, &c, 1);
2569 else if (defaultHandler)
2570 reportDefault(parser, enc, s, next);
2571 break;
2572 case XML_TOK_CDATA_SECT_OPEN:
2574 enum XML_Error result;
2575 if (startCdataSectionHandler)
2576 startCdataSectionHandler(handlerArg);
2577 #if 0
2578 /* Suppose you doing a transformation on a document that involves
2579 changing only the character data. You set up a defaultHandler
2580 and a characterDataHandler. The defaultHandler simply copies
2581 characters through. The characterDataHandler does the
2582 transformation and writes the characters out escaping them as
2583 necessary. This case will fail to work if we leave out the
2584 following two lines (because & and < inside CDATA sections will
2585 be incorrectly escaped).
2587 However, now we have a start/endCdataSectionHandler, so it seems
2588 easier to let the user deal with this.
2590 else if (characterDataHandler)
2591 characterDataHandler(handlerArg, dataBuf, 0);
2592 #endif
2593 else if (defaultHandler)
2594 reportDefault(parser, enc, s, next);
2595 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
2596 if (result != XML_ERROR_NONE)
2597 return result;
2598 else if (!next) {
2599 processor = cdataSectionProcessor;
2600 return result;
2603 break;
2604 case XML_TOK_TRAILING_RSQB:
2605 if (haveMore) {
2606 *nextPtr = s;
2607 return XML_ERROR_NONE;
2609 if (characterDataHandler) {
2610 if (MUST_CONVERT(enc, s)) {
2611 ICHAR *dataPtr = (ICHAR *)dataBuf;
2612 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
2613 characterDataHandler(handlerArg, dataBuf,
2614 (int)(dataPtr - (ICHAR *)dataBuf));
2616 else
2617 characterDataHandler(handlerArg,
2618 (XML_Char *)s,
2619 (int)((XML_Char *)end - (XML_Char *)s));
2621 else if (defaultHandler)
2622 reportDefault(parser, enc, s, end);
2623 /* We are at the end of the final buffer, should we check for
2624 XML_SUSPENDED, XML_FINISHED?
2626 if (startTagLevel == 0) {
2627 *eventPP = end;
2628 return XML_ERROR_NO_ELEMENTS;
2630 if (tagLevel != startTagLevel) {
2631 *eventPP = end;
2632 return XML_ERROR_ASYNC_ENTITY;
2634 *nextPtr = end;
2635 return XML_ERROR_NONE;
2636 case XML_TOK_DATA_CHARS:
2638 XML_CharacterDataHandler charDataHandler = characterDataHandler;
2639 if (charDataHandler) {
2640 if (MUST_CONVERT(enc, s)) {
2641 for (;;) {
2642 ICHAR *dataPtr = (ICHAR *)dataBuf;
2643 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
2644 *eventEndPP = s;
2645 charDataHandler(handlerArg, dataBuf,
2646 (int)(dataPtr - (ICHAR *)dataBuf));
2647 if (s == next)
2648 break;
2649 *eventPP = s;
2652 else
2653 charDataHandler(handlerArg,
2654 (XML_Char *)s,
2655 (int)((XML_Char *)next - (XML_Char *)s));
2657 else if (defaultHandler)
2658 reportDefault(parser, enc, s, next);
2660 break;
2661 case XML_TOK_PI:
2662 if (!reportProcessingInstruction(parser, enc, s, next))
2663 return XML_ERROR_NO_MEMORY;
2664 break;
2665 case XML_TOK_COMMENT:
2666 if (!reportComment(parser, enc, s, next))
2667 return XML_ERROR_NO_MEMORY;
2668 break;
2669 default:
2670 if (defaultHandler)
2671 reportDefault(parser, enc, s, next);
2672 break;
2674 *eventPP = s = next;
2675 switch (ps_parsing) {
2676 case XML_SUSPENDED:
2677 *nextPtr = next;
2678 return XML_ERROR_NONE;
2679 case XML_FINISHED:
2680 return XML_ERROR_ABORTED;
2681 default: ;
2684 /* not reached */
2687 /* Precondition: all arguments must be non-NULL;
2688 Purpose:
2689 - normalize attributes
2690 - check attributes for well-formedness
2691 - generate namespace aware attribute names (URI, prefix)
2692 - build list of attributes for startElementHandler
2693 - default attributes
2694 - process namespace declarations (check and report them)
2695 - generate namespace aware element name (URI, prefix)
2697 static enum XML_Error
2698 storeAtts(XML_Parser parser, const ENCODING *enc,
2699 const char *attStr, TAG_NAME *tagNamePtr,
2700 BINDING **bindingsPtr)
2702 DTD * const dtd = _dtd; /* save one level of indirection */
2703 ELEMENT_TYPE *elementType;
2704 int nDefaultAtts;
2705 const XML_Char **appAtts; /* the attribute list for the application */
2706 int attIndex = 0;
2707 int prefixLen;
2708 int i;
2709 int n;
2710 XML_Char *uri;
2711 int nPrefixes = 0;
2712 BINDING *binding;
2713 const XML_Char *localPart;
2715 /* lookup the element type name */
2716 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
2717 if (!elementType) {
2718 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
2719 if (!name)
2720 return XML_ERROR_NO_MEMORY;
2721 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
2722 sizeof(ELEMENT_TYPE));
2723 if (!elementType)
2724 return XML_ERROR_NO_MEMORY;
2725 if (ns && !setElementTypePrefix(parser, elementType))
2726 return XML_ERROR_NO_MEMORY;
2728 nDefaultAtts = elementType->nDefaultAtts;
2730 /* get the attributes from the tokenizer */
2731 n = XmlGetAttributes(enc, attStr, attsSize, atts);
2732 if (n + nDefaultAtts > attsSize) {
2733 int oldAttsSize = attsSize;
2734 ATTRIBUTE *temp;
2735 #ifdef XML_ATTR_INFO
2736 XML_AttrInfo *temp2;
2737 #endif
2738 attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
2739 temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
2740 if (temp == NULL)
2741 return XML_ERROR_NO_MEMORY;
2742 atts = temp;
2743 #ifdef XML_ATTR_INFO
2744 temp2 = (XML_AttrInfo *)REALLOC((void *)attInfo, attsSize * sizeof(XML_AttrInfo));
2745 if (temp2 == NULL)
2746 return XML_ERROR_NO_MEMORY;
2747 attInfo = temp2;
2748 #endif
2749 if (n > oldAttsSize)
2750 XmlGetAttributes(enc, attStr, n, atts);
2753 appAtts = (const XML_Char **)atts;
2754 for (i = 0; i < n; i++) {
2755 ATTRIBUTE *currAtt = &atts[i];
2756 #ifdef XML_ATTR_INFO
2757 XML_AttrInfo *currAttInfo = &attInfo[i];
2758 #endif
2759 /* add the name and value to the attribute list */
2760 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
2761 currAtt->name
2762 + XmlNameLength(enc, currAtt->name));
2763 if (!attId)
2764 return XML_ERROR_NO_MEMORY;
2765 #ifdef XML_ATTR_INFO
2766 currAttInfo->nameStart = parseEndByteIndex - (parseEndPtr - currAtt->name);
2767 currAttInfo->nameEnd = currAttInfo->nameStart +
2768 XmlNameLength(enc, currAtt->name);
2769 currAttInfo->valueStart = parseEndByteIndex -
2770 (parseEndPtr - currAtt->valuePtr);
2771 currAttInfo->valueEnd = parseEndByteIndex - (parseEndPtr - currAtt->valueEnd);
2772 #endif
2773 /* Detect duplicate attributes by their QNames. This does not work when
2774 namespace processing is turned on and different prefixes for the same
2775 namespace are used. For this case we have a check further down.
2777 if ((attId->name)[-1]) {
2778 if (enc == encoding)
2779 eventPtr = atts[i].name;
2780 return XML_ERROR_DUPLICATE_ATTRIBUTE;
2782 (attId->name)[-1] = 1;
2783 appAtts[attIndex++] = attId->name;
2784 if (!atts[i].normalized) {
2785 enum XML_Error result;
2786 XML_Bool isCdata = XML_TRUE;
2788 /* figure out whether declared as other than CDATA */
2789 if (attId->maybeTokenized) {
2790 int j;
2791 for (j = 0; j < nDefaultAtts; j++) {
2792 if (attId == elementType->defaultAtts[j].id) {
2793 isCdata = elementType->defaultAtts[j].isCdata;
2794 break;
2799 /* normalize the attribute value */
2800 result = storeAttributeValue(parser, enc, isCdata,
2801 atts[i].valuePtr, atts[i].valueEnd,
2802 &tempPool);
2803 if (result)
2804 return result;
2805 appAtts[attIndex] = poolStart(&tempPool);
2806 poolFinish(&tempPool);
2808 else {
2809 /* the value did not need normalizing */
2810 appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
2811 atts[i].valueEnd);
2812 if (appAtts[attIndex] == 0)
2813 return XML_ERROR_NO_MEMORY;
2814 poolFinish(&tempPool);
2816 /* handle prefixed attribute names */
2817 if (attId->prefix) {
2818 if (attId->xmlns) {
2819 /* deal with namespace declarations here */
2820 enum XML_Error result = addBinding(parser, attId->prefix, attId,
2821 appAtts[attIndex], bindingsPtr);
2822 if (result)
2823 return result;
2824 --attIndex;
2826 else {
2827 /* deal with other prefixed names later */
2828 attIndex++;
2829 nPrefixes++;
2830 (attId->name)[-1] = 2;
2833 else
2834 attIndex++;
2837 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
2838 nSpecifiedAtts = attIndex;
2839 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
2840 for (i = 0; i < attIndex; i += 2)
2841 if (appAtts[i] == elementType->idAtt->name) {
2842 idAttIndex = i;
2843 break;
2846 else
2847 idAttIndex = -1;
2849 /* do attribute defaulting */
2850 for (i = 0; i < nDefaultAtts; i++) {
2851 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
2852 if (!(da->id->name)[-1] && da->value) {
2853 if (da->id->prefix) {
2854 if (da->id->xmlns) {
2855 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
2856 da->value, bindingsPtr);
2857 if (result)
2858 return result;
2860 else {
2861 (da->id->name)[-1] = 2;
2862 nPrefixes++;
2863 appAtts[attIndex++] = da->id->name;
2864 appAtts[attIndex++] = da->value;
2867 else {
2868 (da->id->name)[-1] = 1;
2869 appAtts[attIndex++] = da->id->name;
2870 appAtts[attIndex++] = da->value;
2874 appAtts[attIndex] = 0;
2876 /* expand prefixed attribute names, check for duplicates,
2877 and clear flags that say whether attributes were specified */
2878 i = 0;
2879 if (nPrefixes) {
2880 int j; /* hash table index */
2881 unsigned long version = nsAttsVersion;
2882 int nsAttsSize = (int)1 << nsAttsPower;
2883 /* size of hash table must be at least 2 * (# of prefixed attributes) */
2884 if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */
2885 NS_ATT *temp;
2886 /* hash table size must also be a power of 2 and >= 8 */
2887 while (nPrefixes >> nsAttsPower++);
2888 if (nsAttsPower < 3)
2889 nsAttsPower = 3;
2890 nsAttsSize = (int)1 << nsAttsPower;
2891 temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
2892 if (!temp)
2893 return XML_ERROR_NO_MEMORY;
2894 nsAtts = temp;
2895 version = 0; /* force re-initialization of nsAtts hash table */
2897 /* using a version flag saves us from initializing nsAtts every time */
2898 if (!version) { /* initialize version flags when version wraps around */
2899 version = INIT_ATTS_VERSION;
2900 for (j = nsAttsSize; j != 0; )
2901 nsAtts[--j].version = version;
2903 nsAttsVersion = --version;
2905 /* expand prefixed names and check for duplicates */
2906 for (; i < attIndex; i += 2) {
2907 const XML_Char *s = appAtts[i];
2908 if (s[-1] == 2) { /* prefixed */
2909 ATTRIBUTE_ID *id;
2910 const BINDING *b;
2911 unsigned long uriHash = hash_secret_salt;
2912 ((XML_Char *)s)[-1] = 0; /* clear flag */
2913 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
2914 b = id->prefix->binding;
2915 if (!b)
2916 return XML_ERROR_UNBOUND_PREFIX;
2918 /* as we expand the name we also calculate its hash value */
2919 for (j = 0; j < b->uriLen; j++) {
2920 const XML_Char c = b->uri[j];
2921 if (!poolAppendChar(&tempPool, c))
2922 return XML_ERROR_NO_MEMORY;
2923 uriHash = CHAR_HASH(uriHash, c);
2925 while (*s++ != XML_T(ASCII_COLON))
2927 do { /* copies null terminator */
2928 const XML_Char c = *s;
2929 if (!poolAppendChar(&tempPool, *s))
2930 return XML_ERROR_NO_MEMORY;
2931 uriHash = CHAR_HASH(uriHash, c);
2932 } while (*s++);
2934 { /* Check hash table for duplicate of expanded name (uriName).
2935 Derived from code in lookup(parser, HASH_TABLE *table, ...).
2937 unsigned char step = 0;
2938 unsigned long mask = nsAttsSize - 1;
2939 j = uriHash & mask; /* index into hash table */
2940 while (nsAtts[j].version == version) {
2941 /* for speed we compare stored hash values first */
2942 if (uriHash == nsAtts[j].hash) {
2943 const XML_Char *s1 = poolStart(&tempPool);
2944 const XML_Char *s2 = nsAtts[j].uriName;
2945 /* s1 is null terminated, but not s2 */
2946 for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
2947 if (*s1 == 0)
2948 return XML_ERROR_DUPLICATE_ATTRIBUTE;
2950 if (!step)
2951 step = PROBE_STEP(uriHash, mask, nsAttsPower);
2952 j < step ? (j += nsAttsSize - step) : (j -= step);
2956 if (ns_triplets) { /* append namespace separator and prefix */
2957 tempPool.ptr[-1] = namespaceSeparator;
2958 s = b->prefix->name;
2959 do {
2960 if (!poolAppendChar(&tempPool, *s))
2961 return XML_ERROR_NO_MEMORY;
2962 } while (*s++);
2965 /* store expanded name in attribute list */
2966 s = poolStart(&tempPool);
2967 poolFinish(&tempPool);
2968 appAtts[i] = s;
2970 /* fill empty slot with new version, uriName and hash value */
2971 nsAtts[j].version = version;
2972 nsAtts[j].hash = uriHash;
2973 nsAtts[j].uriName = s;
2975 if (!--nPrefixes) {
2976 i += 2;
2977 break;
2980 else /* not prefixed */
2981 ((XML_Char *)s)[-1] = 0; /* clear flag */
2984 /* clear flags for the remaining attributes */
2985 for (; i < attIndex; i += 2)
2986 ((XML_Char *)(appAtts[i]))[-1] = 0;
2987 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
2988 binding->attId->name[-1] = 0;
2990 if (!ns)
2991 return XML_ERROR_NONE;
2993 /* expand the element type name */
2994 if (elementType->prefix) {
2995 binding = elementType->prefix->binding;
2996 if (!binding)
2997 return XML_ERROR_UNBOUND_PREFIX;
2998 localPart = tagNamePtr->str;
2999 while (*localPart++ != XML_T(ASCII_COLON))
3002 else if (dtd->defaultPrefix.binding) {
3003 binding = dtd->defaultPrefix.binding;
3004 localPart = tagNamePtr->str;
3006 else
3007 return XML_ERROR_NONE;
3008 prefixLen = 0;
3009 if (ns_triplets && binding->prefix->name) {
3010 for (; binding->prefix->name[prefixLen++];)
3011 ; /* prefixLen includes null terminator */
3013 tagNamePtr->localPart = localPart;
3014 tagNamePtr->uriLen = binding->uriLen;
3015 tagNamePtr->prefix = binding->prefix->name;
3016 tagNamePtr->prefixLen = prefixLen;
3017 for (i = 0; localPart[i++];)
3018 ; /* i includes null terminator */
3019 n = i + binding->uriLen + prefixLen;
3020 if (n > binding->uriAlloc) {
3021 TAG *p;
3022 uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
3023 if (!uri)
3024 return XML_ERROR_NO_MEMORY;
3025 binding->uriAlloc = n + EXPAND_SPARE;
3026 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
3027 for (p = tagStack; p; p = p->parent)
3028 if (p->name.str == binding->uri)
3029 p->name.str = uri;
3030 FREE(binding->uri);
3031 binding->uri = uri;
3033 /* if namespaceSeparator != '\0' then uri includes it already */
3034 uri = binding->uri + binding->uriLen;
3035 memcpy(uri, localPart, i * sizeof(XML_Char));
3036 /* we always have a namespace separator between localPart and prefix */
3037 if (prefixLen) {
3038 uri += i - 1;
3039 *uri = namespaceSeparator; /* replace null terminator */
3040 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
3042 tagNamePtr->str = binding->uri;
3043 return XML_ERROR_NONE;
3046 /* addBinding() overwrites the value of prefix->binding without checking.
3047 Therefore one must keep track of the old value outside of addBinding().
3049 static enum XML_Error
3050 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
3051 const XML_Char *uri, BINDING **bindingsPtr)
3053 static const XML_Char xmlNamespace[] = {
3054 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3055 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
3056 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
3057 ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
3058 ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
3059 ASCII_e, '\0'
3061 static const int xmlLen =
3062 (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
3063 static const XML_Char xmlnsNamespace[] = {
3064 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3065 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
3066 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
3067 ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
3068 ASCII_SLASH, '\0'
3070 static const int xmlnsLen =
3071 (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
3073 XML_Bool mustBeXML = XML_FALSE;
3074 XML_Bool isXML = XML_TRUE;
3075 XML_Bool isXMLNS = XML_TRUE;
3077 BINDING *b;
3078 int len;
3080 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
3081 if (*uri == XML_T('\0') && prefix->name)
3082 return XML_ERROR_UNDECLARING_PREFIX;
3084 if (prefix->name
3085 && prefix->name[0] == XML_T(ASCII_x)
3086 && prefix->name[1] == XML_T(ASCII_m)
3087 && prefix->name[2] == XML_T(ASCII_l)) {
3089 /* Not allowed to bind xmlns */
3090 if (prefix->name[3] == XML_T(ASCII_n)
3091 && prefix->name[4] == XML_T(ASCII_s)
3092 && prefix->name[5] == XML_T('\0'))
3093 return XML_ERROR_RESERVED_PREFIX_XMLNS;
3095 if (prefix->name[3] == XML_T('\0'))
3096 mustBeXML = XML_TRUE;
3099 for (len = 0; uri[len]; len++) {
3100 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
3101 isXML = XML_FALSE;
3103 if (!mustBeXML && isXMLNS
3104 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3105 isXMLNS = XML_FALSE;
3107 isXML = isXML && len == xmlLen;
3108 isXMLNS = isXMLNS && len == xmlnsLen;
3110 if (mustBeXML != isXML)
3111 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3112 : XML_ERROR_RESERVED_NAMESPACE_URI;
3114 if (isXMLNS)
3115 return XML_ERROR_RESERVED_NAMESPACE_URI;
3117 if (namespaceSeparator)
3118 len++;
3119 if (freeBindingList) {
3120 b = freeBindingList;
3121 if (len > b->uriAlloc) {
3122 XML_Char *temp = (XML_Char *)REALLOC(b->uri,
3123 sizeof(XML_Char) * (len + EXPAND_SPARE));
3124 if (temp == NULL)
3125 return XML_ERROR_NO_MEMORY;
3126 b->uri = temp;
3127 b->uriAlloc = len + EXPAND_SPARE;
3129 freeBindingList = b->nextTagBinding;
3131 else {
3132 b = (BINDING *)MALLOC(sizeof(BINDING));
3133 if (!b)
3134 return XML_ERROR_NO_MEMORY;
3135 b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
3136 if (!b->uri) {
3137 FREE(b);
3138 return XML_ERROR_NO_MEMORY;
3140 b->uriAlloc = len + EXPAND_SPARE;
3142 b->uriLen = len;
3143 memcpy(b->uri, uri, len * sizeof(XML_Char));
3144 if (namespaceSeparator)
3145 b->uri[len - 1] = namespaceSeparator;
3146 b->prefix = prefix;
3147 b->attId = attId;
3148 b->prevPrefixBinding = prefix->binding;
3149 /* NULL binding when default namespace undeclared */
3150 if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
3151 prefix->binding = NULL;
3152 else
3153 prefix->binding = b;
3154 b->nextTagBinding = *bindingsPtr;
3155 *bindingsPtr = b;
3156 /* if attId == NULL then we are not starting a namespace scope */
3157 if (attId && startNamespaceDeclHandler)
3158 startNamespaceDeclHandler(handlerArg, prefix->name,
3159 prefix->binding ? uri : 0);
3160 return XML_ERROR_NONE;
3163 /* The idea here is to avoid using stack for each CDATA section when
3164 the whole file is parsed with one call.
3166 static enum XML_Error PTRCALL
3167 cdataSectionProcessor(XML_Parser parser,
3168 const char *start,
3169 const char *end,
3170 const char **endPtr)
3172 enum XML_Error result = doCdataSection(parser, encoding, &start, end,
3173 endPtr, (XML_Bool)!ps_finalBuffer);
3174 if (result != XML_ERROR_NONE)
3175 return result;
3176 if (start) {
3177 if (parentParser) { /* we are parsing an external entity */
3178 processor = externalEntityContentProcessor;
3179 return externalEntityContentProcessor(parser, start, end, endPtr);
3181 else {
3182 processor = contentProcessor;
3183 return contentProcessor(parser, start, end, endPtr);
3186 return result;
3189 /* startPtr gets set to non-null if the section is closed, and to null if
3190 the section is not yet closed.
3192 static enum XML_Error
3193 doCdataSection(XML_Parser parser,
3194 const ENCODING *enc,
3195 const char **startPtr,
3196 const char *end,
3197 const char **nextPtr,
3198 XML_Bool haveMore)
3200 const char *s = *startPtr;
3201 const char **eventPP;
3202 const char **eventEndPP;
3203 if (enc == encoding) {
3204 eventPP = &eventPtr;
3205 *eventPP = s;
3206 eventEndPP = &eventEndPtr;
3208 else {
3209 eventPP = &(openInternalEntities->internalEventPtr);
3210 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3212 *eventPP = s;
3213 *startPtr = NULL;
3215 for (;;) {
3216 const char *next;
3217 int tok = XmlCdataSectionTok(enc, s, end, &next);
3218 *eventEndPP = next;
3219 switch (tok) {
3220 case XML_TOK_CDATA_SECT_CLOSE:
3221 if (endCdataSectionHandler)
3222 endCdataSectionHandler(handlerArg);
3223 #if 0
3224 /* see comment under XML_TOK_CDATA_SECT_OPEN */
3225 else if (characterDataHandler)
3226 characterDataHandler(handlerArg, dataBuf, 0);
3227 #endif
3228 else if (defaultHandler)
3229 reportDefault(parser, enc, s, next);
3230 *startPtr = next;
3231 *nextPtr = next;
3232 if (ps_parsing == XML_FINISHED)
3233 return XML_ERROR_ABORTED;
3234 else
3235 return XML_ERROR_NONE;
3236 case XML_TOK_DATA_NEWLINE:
3237 if (characterDataHandler) {
3238 XML_Char c = 0xA;
3239 characterDataHandler(handlerArg, &c, 1);
3241 else if (defaultHandler)
3242 reportDefault(parser, enc, s, next);
3243 break;
3244 case XML_TOK_DATA_CHARS:
3246 XML_CharacterDataHandler charDataHandler = characterDataHandler;
3247 if (charDataHandler) {
3248 if (MUST_CONVERT(enc, s)) {
3249 for (;;) {
3250 ICHAR *dataPtr = (ICHAR *)dataBuf;
3251 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
3252 *eventEndPP = next;
3253 charDataHandler(handlerArg, dataBuf,
3254 (int)(dataPtr - (ICHAR *)dataBuf));
3255 if (s == next)
3256 break;
3257 *eventPP = s;
3260 else
3261 charDataHandler(handlerArg,
3262 (XML_Char *)s,
3263 (int)((XML_Char *)next - (XML_Char *)s));
3265 else if (defaultHandler)
3266 reportDefault(parser, enc, s, next);
3268 break;
3269 case XML_TOK_INVALID:
3270 *eventPP = next;
3271 return XML_ERROR_INVALID_TOKEN;
3272 case XML_TOK_PARTIAL_CHAR:
3273 if (haveMore) {
3274 *nextPtr = s;
3275 return XML_ERROR_NONE;
3277 return XML_ERROR_PARTIAL_CHAR;
3278 case XML_TOK_PARTIAL:
3279 case XML_TOK_NONE:
3280 if (haveMore) {
3281 *nextPtr = s;
3282 return XML_ERROR_NONE;
3284 return XML_ERROR_UNCLOSED_CDATA_SECTION;
3285 default:
3286 *eventPP = next;
3287 return XML_ERROR_UNEXPECTED_STATE;
3290 *eventPP = s = next;
3291 switch (ps_parsing) {
3292 case XML_SUSPENDED:
3293 *nextPtr = next;
3294 return XML_ERROR_NONE;
3295 case XML_FINISHED:
3296 return XML_ERROR_ABORTED;
3297 default: ;
3300 /* not reached */
3303 #ifdef XML_DTD
3305 /* The idea here is to avoid using stack for each IGNORE section when
3306 the whole file is parsed with one call.
3308 static enum XML_Error PTRCALL
3309 ignoreSectionProcessor(XML_Parser parser,
3310 const char *start,
3311 const char *end,
3312 const char **endPtr)
3314 enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
3315 endPtr, (XML_Bool)!ps_finalBuffer);
3316 if (result != XML_ERROR_NONE)
3317 return result;
3318 if (start) {
3319 processor = prologProcessor;
3320 return prologProcessor(parser, start, end, endPtr);
3322 return result;
3325 /* startPtr gets set to non-null is the section is closed, and to null
3326 if the section is not yet closed.
3328 static enum XML_Error
3329 doIgnoreSection(XML_Parser parser,
3330 const ENCODING *enc,
3331 const char **startPtr,
3332 const char *end,
3333 const char **nextPtr,
3334 XML_Bool haveMore)
3336 const char *next;
3337 int tok;
3338 const char *s = *startPtr;
3339 const char **eventPP;
3340 const char **eventEndPP;
3341 if (enc == encoding) {
3342 eventPP = &eventPtr;
3343 *eventPP = s;
3344 eventEndPP = &eventEndPtr;
3346 else {
3347 eventPP = &(openInternalEntities->internalEventPtr);
3348 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3350 *eventPP = s;
3351 *startPtr = NULL;
3352 tok = XmlIgnoreSectionTok(enc, s, end, &next);
3353 *eventEndPP = next;
3354 switch (tok) {
3355 case XML_TOK_IGNORE_SECT:
3356 if (defaultHandler)
3357 reportDefault(parser, enc, s, next);
3358 *startPtr = next;
3359 *nextPtr = next;
3360 if (ps_parsing == XML_FINISHED)
3361 return XML_ERROR_ABORTED;
3362 else
3363 return XML_ERROR_NONE;
3364 case XML_TOK_INVALID:
3365 *eventPP = next;
3366 return XML_ERROR_INVALID_TOKEN;
3367 case XML_TOK_PARTIAL_CHAR:
3368 if (haveMore) {
3369 *nextPtr = s;
3370 return XML_ERROR_NONE;
3372 return XML_ERROR_PARTIAL_CHAR;
3373 case XML_TOK_PARTIAL:
3374 case XML_TOK_NONE:
3375 if (haveMore) {
3376 *nextPtr = s;
3377 return XML_ERROR_NONE;
3379 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3380 default:
3381 *eventPP = next;
3382 return XML_ERROR_UNEXPECTED_STATE;
3384 /* not reached */
3387 #endif /* XML_DTD */
3389 static enum XML_Error
3390 initializeEncoding(XML_Parser parser)
3392 const char *s;
3393 #ifdef XML_UNICODE
3394 char encodingBuf[128];
3395 if (!protocolEncodingName)
3396 s = NULL;
3397 else {
3398 int i;
3399 for (i = 0; protocolEncodingName[i]; i++) {
3400 if (i == sizeof(encodingBuf) - 1
3401 || (protocolEncodingName[i] & ~0x7f) != 0) {
3402 encodingBuf[0] = '\0';
3403 break;
3405 encodingBuf[i] = (char)protocolEncodingName[i];
3407 encodingBuf[i] = '\0';
3408 s = encodingBuf;
3410 #else
3411 s = protocolEncodingName;
3412 #endif
3413 if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
3414 return XML_ERROR_NONE;
3415 return handleUnknownEncoding(parser, protocolEncodingName);
3418 static enum XML_Error
3419 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
3420 const char *s, const char *next)
3422 const char *encodingName = NULL;
3423 const XML_Char *storedEncName = NULL;
3424 const ENCODING *newEncoding = NULL;
3425 const char *version = NULL;
3426 const char *versionend;
3427 const XML_Char *storedversion = NULL;
3428 int standalone = -1;
3429 if (!(ns
3430 ? XmlParseXmlDeclNS
3431 : XmlParseXmlDecl)(isGeneralTextEntity,
3432 encoding,
3434 next,
3435 &eventPtr,
3436 &version,
3437 &versionend,
3438 &encodingName,
3439 &newEncoding,
3440 &standalone)) {
3441 if (isGeneralTextEntity)
3442 return XML_ERROR_TEXT_DECL;
3443 else
3444 return XML_ERROR_XML_DECL;
3446 if (!isGeneralTextEntity && standalone == 1) {
3447 _dtd->standalone = XML_TRUE;
3448 #ifdef XML_DTD
3449 if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
3450 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
3451 #endif /* XML_DTD */
3453 if (xmlDeclHandler) {
3454 if (encodingName != NULL) {
3455 storedEncName = poolStoreString(&temp2Pool,
3456 encoding,
3457 encodingName,
3458 encodingName
3459 + XmlNameLength(encoding, encodingName));
3460 if (!storedEncName)
3461 return XML_ERROR_NO_MEMORY;
3462 poolFinish(&temp2Pool);
3464 if (version) {
3465 storedversion = poolStoreString(&temp2Pool,
3466 encoding,
3467 version,
3468 versionend - encoding->minBytesPerChar);
3469 if (!storedversion)
3470 return XML_ERROR_NO_MEMORY;
3472 xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
3474 else if (defaultHandler)
3475 reportDefault(parser, encoding, s, next);
3476 if (protocolEncodingName == NULL) {
3477 if (newEncoding) {
3478 if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
3479 eventPtr = encodingName;
3480 return XML_ERROR_INCORRECT_ENCODING;
3482 encoding = newEncoding;
3484 else if (encodingName) {
3485 enum XML_Error result;
3486 if (!storedEncName) {
3487 storedEncName = poolStoreString(
3488 &temp2Pool, encoding, encodingName,
3489 encodingName + XmlNameLength(encoding, encodingName));
3490 if (!storedEncName)
3491 return XML_ERROR_NO_MEMORY;
3493 result = handleUnknownEncoding(parser, storedEncName);
3494 poolClear(&temp2Pool);
3495 if (result == XML_ERROR_UNKNOWN_ENCODING)
3496 eventPtr = encodingName;
3497 return result;
3501 if (storedEncName || storedversion)
3502 poolClear(&temp2Pool);
3504 return XML_ERROR_NONE;
3507 static enum XML_Error
3508 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
3510 if (unknownEncodingHandler) {
3511 XML_Encoding info;
3512 int i;
3513 for (i = 0; i < 256; i++)
3514 info.map[i] = -1;
3515 info.convert = NULL;
3516 info.data = NULL;
3517 info.release = NULL;
3518 if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
3519 &info)) {
3520 ENCODING *enc;
3521 unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
3522 if (!unknownEncodingMem) {
3523 if (info.release)
3524 info.release(info.data);
3525 return XML_ERROR_NO_MEMORY;
3527 enc = (ns
3528 ? XmlInitUnknownEncodingNS
3529 : XmlInitUnknownEncoding)(unknownEncodingMem,
3530 info.map,
3531 info.convert,
3532 info.data);
3533 if (enc) {
3534 unknownEncodingData = info.data;
3535 unknownEncodingRelease = info.release;
3536 encoding = enc;
3537 return XML_ERROR_NONE;
3540 if (info.release != NULL)
3541 info.release(info.data);
3543 return XML_ERROR_UNKNOWN_ENCODING;
3546 static enum XML_Error PTRCALL
3547 prologInitProcessor(XML_Parser parser,
3548 const char *s,
3549 const char *end,
3550 const char **nextPtr)
3552 enum XML_Error result = initializeEncoding(parser);
3553 if (result != XML_ERROR_NONE)
3554 return result;
3555 processor = prologProcessor;
3556 return prologProcessor(parser, s, end, nextPtr);
3559 #ifdef XML_DTD
3561 static enum XML_Error PTRCALL
3562 externalParEntInitProcessor(XML_Parser parser,
3563 const char *s,
3564 const char *end,
3565 const char **nextPtr)
3567 enum XML_Error result = initializeEncoding(parser);
3568 if (result != XML_ERROR_NONE)
3569 return result;
3571 /* we know now that XML_Parse(Buffer) has been called,
3572 so we consider the external parameter entity read */
3573 _dtd->paramEntityRead = XML_TRUE;
3575 if (prologState.inEntityValue) {
3576 processor = entityValueInitProcessor;
3577 return entityValueInitProcessor(parser, s, end, nextPtr);
3579 else {
3580 processor = externalParEntProcessor;
3581 return externalParEntProcessor(parser, s, end, nextPtr);
3585 static enum XML_Error PTRCALL
3586 entityValueInitProcessor(XML_Parser parser,
3587 const char *s,
3588 const char *end,
3589 const char **nextPtr)
3591 int tok;
3592 const char *start = s;
3593 const char *next = start;
3594 eventPtr = start;
3596 for (;;) {
3597 tok = XmlPrologTok(encoding, start, end, &next);
3598 eventEndPtr = next;
3599 if (tok <= 0) {
3600 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3601 *nextPtr = s;
3602 return XML_ERROR_NONE;
3604 switch (tok) {
3605 case XML_TOK_INVALID:
3606 return XML_ERROR_INVALID_TOKEN;
3607 case XML_TOK_PARTIAL:
3608 return XML_ERROR_UNCLOSED_TOKEN;
3609 case XML_TOK_PARTIAL_CHAR:
3610 return XML_ERROR_PARTIAL_CHAR;
3611 case XML_TOK_NONE: /* start == end */
3612 default:
3613 break;
3615 /* found end of entity value - can store it now */
3616 return storeEntityValue(parser, encoding, s, end);
3618 else if (tok == XML_TOK_XML_DECL) {
3619 enum XML_Error result;
3620 result = processXmlDecl(parser, 0, start, next);
3621 if (result != XML_ERROR_NONE)
3622 return result;
3623 switch (ps_parsing) {
3624 case XML_SUSPENDED:
3625 *nextPtr = next;
3626 return XML_ERROR_NONE;
3627 case XML_FINISHED:
3628 return XML_ERROR_ABORTED;
3629 default:
3630 *nextPtr = next;
3632 /* stop scanning for text declaration - we found one */
3633 processor = entityValueProcessor;
3634 return entityValueProcessor(parser, next, end, nextPtr);
3636 /* If we are at the end of the buffer, this would cause XmlPrologTok to
3637 return XML_TOK_NONE on the next call, which would then cause the
3638 function to exit with *nextPtr set to s - that is what we want for other
3639 tokens, but not for the BOM - we would rather like to skip it;
3640 then, when this routine is entered the next time, XmlPrologTok will
3641 return XML_TOK_INVALID, since the BOM is still in the buffer
3643 else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
3644 *nextPtr = next;
3645 return XML_ERROR_NONE;
3647 start = next;
3648 eventPtr = start;
3652 static enum XML_Error PTRCALL
3653 externalParEntProcessor(XML_Parser parser,
3654 const char *s,
3655 const char *end,
3656 const char **nextPtr)
3658 const char *next = s;
3659 int tok;
3661 tok = XmlPrologTok(encoding, s, end, &next);
3662 if (tok <= 0) {
3663 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3664 *nextPtr = s;
3665 return XML_ERROR_NONE;
3667 switch (tok) {
3668 case XML_TOK_INVALID:
3669 return XML_ERROR_INVALID_TOKEN;
3670 case XML_TOK_PARTIAL:
3671 return XML_ERROR_UNCLOSED_TOKEN;
3672 case XML_TOK_PARTIAL_CHAR:
3673 return XML_ERROR_PARTIAL_CHAR;
3674 case XML_TOK_NONE: /* start == end */
3675 default:
3676 break;
3679 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
3680 However, when parsing an external subset, doProlog will not accept a BOM
3681 as valid, and report a syntax error, so we have to skip the BOM
3683 else if (tok == XML_TOK_BOM) {
3684 s = next;
3685 tok = XmlPrologTok(encoding, s, end, &next);
3688 processor = prologProcessor;
3689 return doProlog(parser, encoding, s, end, tok, next,
3690 nextPtr, (XML_Bool)!ps_finalBuffer);
3693 static enum XML_Error PTRCALL
3694 entityValueProcessor(XML_Parser parser,
3695 const char *s,
3696 const char *end,
3697 const char **nextPtr)
3699 const char *start = s;
3700 const char *next = s;
3701 const ENCODING *enc = encoding;
3702 int tok;
3704 for (;;) {
3705 tok = XmlPrologTok(enc, start, end, &next);
3706 if (tok <= 0) {
3707 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3708 *nextPtr = s;
3709 return XML_ERROR_NONE;
3711 switch (tok) {
3712 case XML_TOK_INVALID:
3713 return XML_ERROR_INVALID_TOKEN;
3714 case XML_TOK_PARTIAL:
3715 return XML_ERROR_UNCLOSED_TOKEN;
3716 case XML_TOK_PARTIAL_CHAR:
3717 return XML_ERROR_PARTIAL_CHAR;
3718 case XML_TOK_NONE: /* start == end */
3719 default:
3720 break;
3722 /* found end of entity value - can store it now */
3723 return storeEntityValue(parser, enc, s, end);
3725 start = next;
3729 #endif /* XML_DTD */
3731 static enum XML_Error PTRCALL
3732 prologProcessor(XML_Parser parser,
3733 const char *s,
3734 const char *end,
3735 const char **nextPtr)
3737 const char *next = s;
3738 int tok = XmlPrologTok(encoding, s, end, &next);
3739 return doProlog(parser, encoding, s, end, tok, next,
3740 nextPtr, (XML_Bool)!ps_finalBuffer);
3743 static enum XML_Error
3744 doProlog(XML_Parser parser,
3745 const ENCODING *enc,
3746 const char *s,
3747 const char *end,
3748 int tok,
3749 const char *next,
3750 const char **nextPtr,
3751 XML_Bool haveMore)
3753 #ifdef XML_DTD
3754 static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
3755 #endif /* XML_DTD */
3756 static const XML_Char atypeCDATA[] =
3757 { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
3758 static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
3759 static const XML_Char atypeIDREF[] =
3760 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
3761 static const XML_Char atypeIDREFS[] =
3762 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
3763 static const XML_Char atypeENTITY[] =
3764 { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
3765 static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
3766 ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
3767 static const XML_Char atypeNMTOKEN[] = {
3768 ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
3769 static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
3770 ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
3771 static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
3772 ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
3773 static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
3774 static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
3776 /* save one level of indirection */
3777 DTD * const dtd = _dtd;
3779 const char **eventPP;
3780 const char **eventEndPP;
3781 enum XML_Content_Quant quant;
3783 if (enc == encoding) {
3784 eventPP = &eventPtr;
3785 eventEndPP = &eventEndPtr;
3787 else {
3788 eventPP = &(openInternalEntities->internalEventPtr);
3789 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3792 for (;;) {
3793 int role;
3794 XML_Bool handleDefault = XML_TRUE;
3795 *eventPP = s;
3796 *eventEndPP = next;
3797 if (tok <= 0) {
3798 if (haveMore && tok != XML_TOK_INVALID) {
3799 *nextPtr = s;
3800 return XML_ERROR_NONE;
3802 switch (tok) {
3803 case XML_TOK_INVALID:
3804 *eventPP = next;
3805 return XML_ERROR_INVALID_TOKEN;
3806 case XML_TOK_PARTIAL:
3807 return XML_ERROR_UNCLOSED_TOKEN;
3808 case XML_TOK_PARTIAL_CHAR:
3809 return XML_ERROR_PARTIAL_CHAR;
3810 case -XML_TOK_PROLOG_S:
3811 tok = -tok;
3812 break;
3813 case XML_TOK_NONE:
3814 #ifdef XML_DTD
3815 /* for internal PE NOT referenced between declarations */
3816 if (enc != encoding && !openInternalEntities->betweenDecl) {
3817 *nextPtr = s;
3818 return XML_ERROR_NONE;
3820 /* WFC: PE Between Declarations - must check that PE contains
3821 complete markup, not only for external PEs, but also for
3822 internal PEs if the reference occurs between declarations.
3824 if (isParamEntity || enc != encoding) {
3825 if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
3826 == XML_ROLE_ERROR)
3827 return XML_ERROR_INCOMPLETE_PE;
3828 *nextPtr = s;
3829 return XML_ERROR_NONE;
3831 #endif /* XML_DTD */
3832 return XML_ERROR_NO_ELEMENTS;
3833 default:
3834 tok = -tok;
3835 next = end;
3836 break;
3839 role = XmlTokenRole(&prologState, tok, s, next, enc);
3840 switch (role) {
3841 case XML_ROLE_XML_DECL:
3843 enum XML_Error result = processXmlDecl(parser, 0, s, next);
3844 if (result != XML_ERROR_NONE)
3845 return result;
3846 enc = encoding;
3847 handleDefault = XML_FALSE;
3849 break;
3850 case XML_ROLE_DOCTYPE_NAME:
3851 if (startDoctypeDeclHandler) {
3852 doctypeName = poolStoreString(&tempPool, enc, s, next);
3853 if (!doctypeName)
3854 return XML_ERROR_NO_MEMORY;
3855 poolFinish(&tempPool);
3856 doctypePubid = NULL;
3857 handleDefault = XML_FALSE;
3859 doctypeSysid = NULL; /* always initialize to NULL */
3860 break;
3861 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
3862 if (startDoctypeDeclHandler) {
3863 startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
3864 doctypePubid, 1);
3865 doctypeName = NULL;
3866 poolClear(&tempPool);
3867 handleDefault = XML_FALSE;
3869 break;
3870 #ifdef XML_DTD
3871 case XML_ROLE_TEXT_DECL:
3873 enum XML_Error result = processXmlDecl(parser, 1, s, next);
3874 if (result != XML_ERROR_NONE)
3875 return result;
3876 enc = encoding;
3877 handleDefault = XML_FALSE;
3879 break;
3880 #endif /* XML_DTD */
3881 case XML_ROLE_DOCTYPE_PUBLIC_ID:
3882 #ifdef XML_DTD
3883 useForeignDTD = XML_FALSE;
3884 declEntity = (ENTITY *)lookup(parser,
3885 &dtd->paramEntities,
3886 externalSubsetName,
3887 sizeof(ENTITY));
3888 if (!declEntity)
3889 return XML_ERROR_NO_MEMORY;
3890 #endif /* XML_DTD */
3891 dtd->hasParamEntityRefs = XML_TRUE;
3892 if (startDoctypeDeclHandler) {
3893 XML_Char *pubId;
3894 if (!XmlIsPublicId(enc, s, next, eventPP))
3895 return XML_ERROR_PUBLICID;
3896 pubId = poolStoreString(&tempPool, enc,
3897 s + enc->minBytesPerChar,
3898 next - enc->minBytesPerChar);
3899 if (!pubId)
3900 return XML_ERROR_NO_MEMORY;
3901 normalizePublicId(pubId);
3902 poolFinish(&tempPool);
3903 doctypePubid = pubId;
3904 handleDefault = XML_FALSE;
3905 goto alreadyChecked;
3907 /* fall through */
3908 case XML_ROLE_ENTITY_PUBLIC_ID:
3909 if (!XmlIsPublicId(enc, s, next, eventPP))
3910 return XML_ERROR_PUBLICID;
3911 alreadyChecked:
3912 if (dtd->keepProcessing && declEntity) {
3913 XML_Char *tem = poolStoreString(&dtd->pool,
3914 enc,
3915 s + enc->minBytesPerChar,
3916 next - enc->minBytesPerChar);
3917 if (!tem)
3918 return XML_ERROR_NO_MEMORY;
3919 normalizePublicId(tem);
3920 declEntity->publicId = tem;
3921 poolFinish(&dtd->pool);
3922 if (entityDeclHandler)
3923 handleDefault = XML_FALSE;
3925 break;
3926 case XML_ROLE_DOCTYPE_CLOSE:
3927 if (doctypeName) {
3928 startDoctypeDeclHandler(handlerArg, doctypeName,
3929 doctypeSysid, doctypePubid, 0);
3930 poolClear(&tempPool);
3931 handleDefault = XML_FALSE;
3933 /* doctypeSysid will be non-NULL in the case of a previous
3934 XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
3935 was not set, indicating an external subset
3937 #ifdef XML_DTD
3938 if (doctypeSysid || useForeignDTD) {
3939 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3940 dtd->hasParamEntityRefs = XML_TRUE;
3941 if (paramEntityParsing && externalEntityRefHandler) {
3942 ENTITY *entity = (ENTITY *)lookup(parser,
3943 &dtd->paramEntities,
3944 externalSubsetName,
3945 sizeof(ENTITY));
3946 if (!entity)
3947 return XML_ERROR_NO_MEMORY;
3948 if (useForeignDTD)
3949 entity->base = curBase;
3950 dtd->paramEntityRead = XML_FALSE;
3951 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3953 entity->base,
3954 entity->systemId,
3955 entity->publicId))
3956 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3957 if (dtd->paramEntityRead) {
3958 if (!dtd->standalone &&
3959 notStandaloneHandler &&
3960 !notStandaloneHandler(handlerArg))
3961 return XML_ERROR_NOT_STANDALONE;
3963 /* if we didn't read the foreign DTD then this means that there
3964 is no external subset and we must reset dtd->hasParamEntityRefs
3966 else if (!doctypeSysid)
3967 dtd->hasParamEntityRefs = hadParamEntityRefs;
3968 /* end of DTD - no need to update dtd->keepProcessing */
3970 useForeignDTD = XML_FALSE;
3972 #endif /* XML_DTD */
3973 if (endDoctypeDeclHandler) {
3974 endDoctypeDeclHandler(handlerArg);
3975 handleDefault = XML_FALSE;
3977 break;
3978 case XML_ROLE_INSTANCE_START:
3979 #ifdef XML_DTD
3980 /* if there is no DOCTYPE declaration then now is the
3981 last chance to read the foreign DTD
3983 if (useForeignDTD) {
3984 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3985 dtd->hasParamEntityRefs = XML_TRUE;
3986 if (paramEntityParsing && externalEntityRefHandler) {
3987 ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
3988 externalSubsetName,
3989 sizeof(ENTITY));
3990 if (!entity)
3991 return XML_ERROR_NO_MEMORY;
3992 entity->base = curBase;
3993 dtd->paramEntityRead = XML_FALSE;
3994 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3996 entity->base,
3997 entity->systemId,
3998 entity->publicId))
3999 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4000 if (dtd->paramEntityRead) {
4001 if (!dtd->standalone &&
4002 notStandaloneHandler &&
4003 !notStandaloneHandler(handlerArg))
4004 return XML_ERROR_NOT_STANDALONE;
4006 /* if we didn't read the foreign DTD then this means that there
4007 is no external subset and we must reset dtd->hasParamEntityRefs
4009 else
4010 dtd->hasParamEntityRefs = hadParamEntityRefs;
4011 /* end of DTD - no need to update dtd->keepProcessing */
4014 #endif /* XML_DTD */
4015 processor = contentProcessor;
4016 return contentProcessor(parser, s, end, nextPtr);
4017 case XML_ROLE_ATTLIST_ELEMENT_NAME:
4018 declElementType = getElementType(parser, enc, s, next);
4019 if (!declElementType)
4020 return XML_ERROR_NO_MEMORY;
4021 goto checkAttListDeclHandler;
4022 case XML_ROLE_ATTRIBUTE_NAME:
4023 declAttributeId = getAttributeId(parser, enc, s, next);
4024 if (!declAttributeId)
4025 return XML_ERROR_NO_MEMORY;
4026 declAttributeIsCdata = XML_FALSE;
4027 declAttributeType = NULL;
4028 declAttributeIsId = XML_FALSE;
4029 goto checkAttListDeclHandler;
4030 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
4031 declAttributeIsCdata = XML_TRUE;
4032 declAttributeType = atypeCDATA;
4033 goto checkAttListDeclHandler;
4034 case XML_ROLE_ATTRIBUTE_TYPE_ID:
4035 declAttributeIsId = XML_TRUE;
4036 declAttributeType = atypeID;
4037 goto checkAttListDeclHandler;
4038 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
4039 declAttributeType = atypeIDREF;
4040 goto checkAttListDeclHandler;
4041 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
4042 declAttributeType = atypeIDREFS;
4043 goto checkAttListDeclHandler;
4044 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
4045 declAttributeType = atypeENTITY;
4046 goto checkAttListDeclHandler;
4047 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
4048 declAttributeType = atypeENTITIES;
4049 goto checkAttListDeclHandler;
4050 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
4051 declAttributeType = atypeNMTOKEN;
4052 goto checkAttListDeclHandler;
4053 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
4054 declAttributeType = atypeNMTOKENS;
4055 checkAttListDeclHandler:
4056 if (dtd->keepProcessing && attlistDeclHandler)
4057 handleDefault = XML_FALSE;
4058 break;
4059 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
4060 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
4061 if (dtd->keepProcessing && attlistDeclHandler) {
4062 const XML_Char *prefix;
4063 if (declAttributeType) {
4064 prefix = enumValueSep;
4066 else {
4067 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
4068 ? notationPrefix
4069 : enumValueStart);
4071 if (!poolAppendString(&tempPool, prefix))
4072 return XML_ERROR_NO_MEMORY;
4073 if (!poolAppend(&tempPool, enc, s, next))
4074 return XML_ERROR_NO_MEMORY;
4075 declAttributeType = tempPool.start;
4076 handleDefault = XML_FALSE;
4078 break;
4079 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
4080 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
4081 if (dtd->keepProcessing) {
4082 if (!defineAttribute(declElementType, declAttributeId,
4083 declAttributeIsCdata, declAttributeIsId,
4084 0, parser))
4085 return XML_ERROR_NO_MEMORY;
4086 if (attlistDeclHandler && declAttributeType) {
4087 if (*declAttributeType == XML_T(ASCII_LPAREN)
4088 || (*declAttributeType == XML_T(ASCII_N)
4089 && declAttributeType[1] == XML_T(ASCII_O))) {
4090 /* Enumerated or Notation type */
4091 if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4092 || !poolAppendChar(&tempPool, XML_T('\0')))
4093 return XML_ERROR_NO_MEMORY;
4094 declAttributeType = tempPool.start;
4095 poolFinish(&tempPool);
4097 *eventEndPP = s;
4098 attlistDeclHandler(handlerArg, declElementType->name,
4099 declAttributeId->name, declAttributeType,
4100 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
4101 poolClear(&tempPool);
4102 handleDefault = XML_FALSE;
4105 break;
4106 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
4107 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
4108 if (dtd->keepProcessing) {
4109 const XML_Char *attVal;
4110 enum XML_Error result =
4111 storeAttributeValue(parser, enc, declAttributeIsCdata,
4112 s + enc->minBytesPerChar,
4113 next - enc->minBytesPerChar,
4114 &dtd->pool);
4115 if (result)
4116 return result;
4117 attVal = poolStart(&dtd->pool);
4118 poolFinish(&dtd->pool);
4119 /* ID attributes aren't allowed to have a default */
4120 if (!defineAttribute(declElementType, declAttributeId,
4121 declAttributeIsCdata, XML_FALSE, attVal, parser))
4122 return XML_ERROR_NO_MEMORY;
4123 if (attlistDeclHandler && declAttributeType) {
4124 if (*declAttributeType == XML_T(ASCII_LPAREN)
4125 || (*declAttributeType == XML_T(ASCII_N)
4126 && declAttributeType[1] == XML_T(ASCII_O))) {
4127 /* Enumerated or Notation type */
4128 if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4129 || !poolAppendChar(&tempPool, XML_T('\0')))
4130 return XML_ERROR_NO_MEMORY;
4131 declAttributeType = tempPool.start;
4132 poolFinish(&tempPool);
4134 *eventEndPP = s;
4135 attlistDeclHandler(handlerArg, declElementType->name,
4136 declAttributeId->name, declAttributeType,
4137 attVal,
4138 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
4139 poolClear(&tempPool);
4140 handleDefault = XML_FALSE;
4143 break;
4144 case XML_ROLE_ENTITY_VALUE:
4145 if (dtd->keepProcessing) {
4146 enum XML_Error result = storeEntityValue(parser, enc,
4147 s + enc->minBytesPerChar,
4148 next - enc->minBytesPerChar);
4149 if (declEntity) {
4150 declEntity->textPtr = poolStart(&dtd->entityValuePool);
4151 declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
4152 poolFinish(&dtd->entityValuePool);
4153 if (entityDeclHandler) {
4154 *eventEndPP = s;
4155 entityDeclHandler(handlerArg,
4156 declEntity->name,
4157 declEntity->is_param,
4158 declEntity->textPtr,
4159 declEntity->textLen,
4160 curBase, 0, 0, 0);
4161 handleDefault = XML_FALSE;
4164 else
4165 poolDiscard(&dtd->entityValuePool);
4166 if (result != XML_ERROR_NONE)
4167 return result;
4169 break;
4170 case XML_ROLE_DOCTYPE_SYSTEM_ID:
4171 #ifdef XML_DTD
4172 useForeignDTD = XML_FALSE;
4173 #endif /* XML_DTD */
4174 dtd->hasParamEntityRefs = XML_TRUE;
4175 if (startDoctypeDeclHandler) {
4176 doctypeSysid = poolStoreString(&tempPool, enc,
4177 s + enc->minBytesPerChar,
4178 next - enc->minBytesPerChar);
4179 if (doctypeSysid == NULL)
4180 return XML_ERROR_NO_MEMORY;
4181 poolFinish(&tempPool);
4182 handleDefault = XML_FALSE;
4184 #ifdef XML_DTD
4185 else
4186 /* use externalSubsetName to make doctypeSysid non-NULL
4187 for the case where no startDoctypeDeclHandler is set */
4188 doctypeSysid = externalSubsetName;
4189 #endif /* XML_DTD */
4190 if (!dtd->standalone
4191 #ifdef XML_DTD
4192 && !paramEntityParsing
4193 #endif /* XML_DTD */
4194 && notStandaloneHandler
4195 && !notStandaloneHandler(handlerArg))
4196 return XML_ERROR_NOT_STANDALONE;
4197 #ifndef XML_DTD
4198 break;
4199 #else /* XML_DTD */
4200 if (!declEntity) {
4201 declEntity = (ENTITY *)lookup(parser,
4202 &dtd->paramEntities,
4203 externalSubsetName,
4204 sizeof(ENTITY));
4205 if (!declEntity)
4206 return XML_ERROR_NO_MEMORY;
4207 declEntity->publicId = NULL;
4209 /* fall through */
4210 #endif /* XML_DTD */
4211 case XML_ROLE_ENTITY_SYSTEM_ID:
4212 if (dtd->keepProcessing && declEntity) {
4213 declEntity->systemId = poolStoreString(&dtd->pool, enc,
4214 s + enc->minBytesPerChar,
4215 next - enc->minBytesPerChar);
4216 if (!declEntity->systemId)
4217 return XML_ERROR_NO_MEMORY;
4218 declEntity->base = curBase;
4219 poolFinish(&dtd->pool);
4220 if (entityDeclHandler)
4221 handleDefault = XML_FALSE;
4223 break;
4224 case XML_ROLE_ENTITY_COMPLETE:
4225 if (dtd->keepProcessing && declEntity && entityDeclHandler) {
4226 *eventEndPP = s;
4227 entityDeclHandler(handlerArg,
4228 declEntity->name,
4229 declEntity->is_param,
4230 0,0,
4231 declEntity->base,
4232 declEntity->systemId,
4233 declEntity->publicId,
4235 handleDefault = XML_FALSE;
4237 break;
4238 case XML_ROLE_ENTITY_NOTATION_NAME:
4239 if (dtd->keepProcessing && declEntity) {
4240 declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
4241 if (!declEntity->notation)
4242 return XML_ERROR_NO_MEMORY;
4243 poolFinish(&dtd->pool);
4244 if (unparsedEntityDeclHandler) {
4245 *eventEndPP = s;
4246 unparsedEntityDeclHandler(handlerArg,
4247 declEntity->name,
4248 declEntity->base,
4249 declEntity->systemId,
4250 declEntity->publicId,
4251 declEntity->notation);
4252 handleDefault = XML_FALSE;
4254 else if (entityDeclHandler) {
4255 *eventEndPP = s;
4256 entityDeclHandler(handlerArg,
4257 declEntity->name,
4258 0,0,0,
4259 declEntity->base,
4260 declEntity->systemId,
4261 declEntity->publicId,
4262 declEntity->notation);
4263 handleDefault = XML_FALSE;
4266 break;
4267 case XML_ROLE_GENERAL_ENTITY_NAME:
4269 if (XmlPredefinedEntityName(enc, s, next)) {
4270 declEntity = NULL;
4271 break;
4273 if (dtd->keepProcessing) {
4274 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4275 if (!name)
4276 return XML_ERROR_NO_MEMORY;
4277 declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
4278 sizeof(ENTITY));
4279 if (!declEntity)
4280 return XML_ERROR_NO_MEMORY;
4281 if (declEntity->name != name) {
4282 poolDiscard(&dtd->pool);
4283 declEntity = NULL;
4285 else {
4286 poolFinish(&dtd->pool);
4287 declEntity->publicId = NULL;
4288 declEntity->is_param = XML_FALSE;
4289 /* if we have a parent parser or are reading an internal parameter
4290 entity, then the entity declaration is not considered "internal"
4292 declEntity->is_internal = !(parentParser || openInternalEntities);
4293 if (entityDeclHandler)
4294 handleDefault = XML_FALSE;
4297 else {
4298 poolDiscard(&dtd->pool);
4299 declEntity = NULL;
4302 break;
4303 case XML_ROLE_PARAM_ENTITY_NAME:
4304 #ifdef XML_DTD
4305 if (dtd->keepProcessing) {
4306 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4307 if (!name)
4308 return XML_ERROR_NO_MEMORY;
4309 declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4310 name, sizeof(ENTITY));
4311 if (!declEntity)
4312 return XML_ERROR_NO_MEMORY;
4313 if (declEntity->name != name) {
4314 poolDiscard(&dtd->pool);
4315 declEntity = NULL;
4317 else {
4318 poolFinish(&dtd->pool);
4319 declEntity->publicId = NULL;
4320 declEntity->is_param = XML_TRUE;
4321 /* if we have a parent parser or are reading an internal parameter
4322 entity, then the entity declaration is not considered "internal"
4324 declEntity->is_internal = !(parentParser || openInternalEntities);
4325 if (entityDeclHandler)
4326 handleDefault = XML_FALSE;
4329 else {
4330 poolDiscard(&dtd->pool);
4331 declEntity = NULL;
4333 #else /* not XML_DTD */
4334 declEntity = NULL;
4335 #endif /* XML_DTD */
4336 break;
4337 case XML_ROLE_NOTATION_NAME:
4338 declNotationPublicId = NULL;
4339 declNotationName = NULL;
4340 if (notationDeclHandler) {
4341 declNotationName = poolStoreString(&tempPool, enc, s, next);
4342 if (!declNotationName)
4343 return XML_ERROR_NO_MEMORY;
4344 poolFinish(&tempPool);
4345 handleDefault = XML_FALSE;
4347 break;
4348 case XML_ROLE_NOTATION_PUBLIC_ID:
4349 if (!XmlIsPublicId(enc, s, next, eventPP))
4350 return XML_ERROR_PUBLICID;
4351 if (declNotationName) { /* means notationDeclHandler != NULL */
4352 XML_Char *tem = poolStoreString(&tempPool,
4353 enc,
4354 s + enc->minBytesPerChar,
4355 next - enc->minBytesPerChar);
4356 if (!tem)
4357 return XML_ERROR_NO_MEMORY;
4358 normalizePublicId(tem);
4359 declNotationPublicId = tem;
4360 poolFinish(&tempPool);
4361 handleDefault = XML_FALSE;
4363 break;
4364 case XML_ROLE_NOTATION_SYSTEM_ID:
4365 if (declNotationName && notationDeclHandler) {
4366 const XML_Char *systemId
4367 = poolStoreString(&tempPool, enc,
4368 s + enc->minBytesPerChar,
4369 next - enc->minBytesPerChar);
4370 if (!systemId)
4371 return XML_ERROR_NO_MEMORY;
4372 *eventEndPP = s;
4373 notationDeclHandler(handlerArg,
4374 declNotationName,
4375 curBase,
4376 systemId,
4377 declNotationPublicId);
4378 handleDefault = XML_FALSE;
4380 poolClear(&tempPool);
4381 break;
4382 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
4383 if (declNotationPublicId && notationDeclHandler) {
4384 *eventEndPP = s;
4385 notationDeclHandler(handlerArg,
4386 declNotationName,
4387 curBase,
4389 declNotationPublicId);
4390 handleDefault = XML_FALSE;
4392 poolClear(&tempPool);
4393 break;
4394 case XML_ROLE_ERROR:
4395 switch (tok) {
4396 case XML_TOK_PARAM_ENTITY_REF:
4397 /* PE references in internal subset are
4398 not allowed within declarations. */
4399 return XML_ERROR_PARAM_ENTITY_REF;
4400 case XML_TOK_XML_DECL:
4401 return XML_ERROR_MISPLACED_XML_PI;
4402 default:
4403 return XML_ERROR_SYNTAX;
4405 #ifdef XML_DTD
4406 case XML_ROLE_IGNORE_SECT:
4408 enum XML_Error result;
4409 if (defaultHandler)
4410 reportDefault(parser, enc, s, next);
4411 handleDefault = XML_FALSE;
4412 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
4413 if (result != XML_ERROR_NONE)
4414 return result;
4415 else if (!next) {
4416 processor = ignoreSectionProcessor;
4417 return result;
4420 break;
4421 #endif /* XML_DTD */
4422 case XML_ROLE_GROUP_OPEN:
4423 if (prologState.level >= groupSize) {
4424 if (groupSize) {
4425 char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
4426 if (temp == NULL)
4427 return XML_ERROR_NO_MEMORY;
4428 groupConnector = temp;
4429 if (dtd->scaffIndex) {
4430 int *temp = (int *)REALLOC(dtd->scaffIndex,
4431 groupSize * sizeof(int));
4432 if (temp == NULL)
4433 return XML_ERROR_NO_MEMORY;
4434 dtd->scaffIndex = temp;
4437 else {
4438 groupConnector = (char *)MALLOC(groupSize = 32);
4439 if (!groupConnector)
4440 return XML_ERROR_NO_MEMORY;
4443 groupConnector[prologState.level] = 0;
4444 if (dtd->in_eldecl) {
4445 int myindex = nextScaffoldPart(parser);
4446 if (myindex < 0)
4447 return XML_ERROR_NO_MEMORY;
4448 dtd->scaffIndex[dtd->scaffLevel] = myindex;
4449 dtd->scaffLevel++;
4450 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
4451 if (elementDeclHandler)
4452 handleDefault = XML_FALSE;
4454 break;
4455 case XML_ROLE_GROUP_SEQUENCE:
4456 if (groupConnector[prologState.level] == ASCII_PIPE)
4457 return XML_ERROR_SYNTAX;
4458 groupConnector[prologState.level] = ASCII_COMMA;
4459 if (dtd->in_eldecl && elementDeclHandler)
4460 handleDefault = XML_FALSE;
4461 break;
4462 case XML_ROLE_GROUP_CHOICE:
4463 if (groupConnector[prologState.level] == ASCII_COMMA)
4464 return XML_ERROR_SYNTAX;
4465 if (dtd->in_eldecl
4466 && !groupConnector[prologState.level]
4467 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4468 != XML_CTYPE_MIXED)
4470 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4471 = XML_CTYPE_CHOICE;
4472 if (elementDeclHandler)
4473 handleDefault = XML_FALSE;
4475 groupConnector[prologState.level] = ASCII_PIPE;
4476 break;
4477 case XML_ROLE_PARAM_ENTITY_REF:
4478 #ifdef XML_DTD
4479 case XML_ROLE_INNER_PARAM_ENTITY_REF:
4480 dtd->hasParamEntityRefs = XML_TRUE;
4481 if (!paramEntityParsing)
4482 dtd->keepProcessing = dtd->standalone;
4483 else {
4484 const XML_Char *name;
4485 ENTITY *entity;
4486 name = poolStoreString(&dtd->pool, enc,
4487 s + enc->minBytesPerChar,
4488 next - enc->minBytesPerChar);
4489 if (!name)
4490 return XML_ERROR_NO_MEMORY;
4491 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
4492 poolDiscard(&dtd->pool);
4493 /* first, determine if a check for an existing declaration is needed;
4494 if yes, check that the entity exists, and that it is internal,
4495 otherwise call the skipped entity handler
4497 if (prologState.documentEntity &&
4498 (dtd->standalone
4499 ? !openInternalEntities
4500 : !dtd->hasParamEntityRefs)) {
4501 if (!entity)
4502 return XML_ERROR_UNDEFINED_ENTITY;
4503 else if (!entity->is_internal)
4504 return XML_ERROR_ENTITY_DECLARED_IN_PE;
4506 else if (!entity) {
4507 dtd->keepProcessing = dtd->standalone;
4508 /* cannot report skipped entities in declarations */
4509 if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
4510 skippedEntityHandler(handlerArg, name, 1);
4511 handleDefault = XML_FALSE;
4513 break;
4515 if (entity->open)
4516 return XML_ERROR_RECURSIVE_ENTITY_REF;
4517 if (entity->textPtr) {
4518 enum XML_Error result;
4519 XML_Bool betweenDecl =
4520 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
4521 result = processInternalEntity(parser, entity, betweenDecl);
4522 if (result != XML_ERROR_NONE)
4523 return result;
4524 handleDefault = XML_FALSE;
4525 break;
4527 if (externalEntityRefHandler) {
4528 dtd->paramEntityRead = XML_FALSE;
4529 entity->open = XML_TRUE;
4530 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4532 entity->base,
4533 entity->systemId,
4534 entity->publicId)) {
4535 entity->open = XML_FALSE;
4536 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4538 entity->open = XML_FALSE;
4539 handleDefault = XML_FALSE;
4540 if (!dtd->paramEntityRead) {
4541 dtd->keepProcessing = dtd->standalone;
4542 break;
4545 else {
4546 dtd->keepProcessing = dtd->standalone;
4547 break;
4550 #endif /* XML_DTD */
4551 if (!dtd->standalone &&
4552 notStandaloneHandler &&
4553 !notStandaloneHandler(handlerArg))
4554 return XML_ERROR_NOT_STANDALONE;
4555 break;
4557 /* Element declaration stuff */
4559 case XML_ROLE_ELEMENT_NAME:
4560 if (elementDeclHandler) {
4561 declElementType = getElementType(parser, enc, s, next);
4562 if (!declElementType)
4563 return XML_ERROR_NO_MEMORY;
4564 dtd->scaffLevel = 0;
4565 dtd->scaffCount = 0;
4566 dtd->in_eldecl = XML_TRUE;
4567 handleDefault = XML_FALSE;
4569 break;
4571 case XML_ROLE_CONTENT_ANY:
4572 case XML_ROLE_CONTENT_EMPTY:
4573 if (dtd->in_eldecl) {
4574 if (elementDeclHandler) {
4575 XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
4576 if (!content)
4577 return XML_ERROR_NO_MEMORY;
4578 content->quant = XML_CQUANT_NONE;
4579 content->name = NULL;
4580 content->numchildren = 0;
4581 content->children = NULL;
4582 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
4583 XML_CTYPE_ANY :
4584 XML_CTYPE_EMPTY);
4585 *eventEndPP = s;
4586 elementDeclHandler(handlerArg, declElementType->name, content);
4587 handleDefault = XML_FALSE;
4589 dtd->in_eldecl = XML_FALSE;
4591 break;
4593 case XML_ROLE_CONTENT_PCDATA:
4594 if (dtd->in_eldecl) {
4595 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4596 = XML_CTYPE_MIXED;
4597 if (elementDeclHandler)
4598 handleDefault = XML_FALSE;
4600 break;
4602 case XML_ROLE_CONTENT_ELEMENT:
4603 quant = XML_CQUANT_NONE;
4604 goto elementContent;
4605 case XML_ROLE_CONTENT_ELEMENT_OPT:
4606 quant = XML_CQUANT_OPT;
4607 goto elementContent;
4608 case XML_ROLE_CONTENT_ELEMENT_REP:
4609 quant = XML_CQUANT_REP;
4610 goto elementContent;
4611 case XML_ROLE_CONTENT_ELEMENT_PLUS:
4612 quant = XML_CQUANT_PLUS;
4613 elementContent:
4614 if (dtd->in_eldecl) {
4615 ELEMENT_TYPE *el;
4616 const XML_Char *name;
4617 int nameLen;
4618 const char *nxt = (quant == XML_CQUANT_NONE
4619 ? next
4620 : next - enc->minBytesPerChar);
4621 int myindex = nextScaffoldPart(parser);
4622 if (myindex < 0)
4623 return XML_ERROR_NO_MEMORY;
4624 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
4625 dtd->scaffold[myindex].quant = quant;
4626 el = getElementType(parser, enc, s, nxt);
4627 if (!el)
4628 return XML_ERROR_NO_MEMORY;
4629 name = el->name;
4630 dtd->scaffold[myindex].name = name;
4631 nameLen = 0;
4632 for (; name[nameLen++]; );
4633 dtd->contentStringLen += nameLen;
4634 if (elementDeclHandler)
4635 handleDefault = XML_FALSE;
4637 break;
4639 case XML_ROLE_GROUP_CLOSE:
4640 quant = XML_CQUANT_NONE;
4641 goto closeGroup;
4642 case XML_ROLE_GROUP_CLOSE_OPT:
4643 quant = XML_CQUANT_OPT;
4644 goto closeGroup;
4645 case XML_ROLE_GROUP_CLOSE_REP:
4646 quant = XML_CQUANT_REP;
4647 goto closeGroup;
4648 case XML_ROLE_GROUP_CLOSE_PLUS:
4649 quant = XML_CQUANT_PLUS;
4650 closeGroup:
4651 if (dtd->in_eldecl) {
4652 if (elementDeclHandler)
4653 handleDefault = XML_FALSE;
4654 dtd->scaffLevel--;
4655 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
4656 if (dtd->scaffLevel == 0) {
4657 if (!handleDefault) {
4658 XML_Content *model = build_model(parser);
4659 if (!model)
4660 return XML_ERROR_NO_MEMORY;
4661 *eventEndPP = s;
4662 elementDeclHandler(handlerArg, declElementType->name, model);
4664 dtd->in_eldecl = XML_FALSE;
4665 dtd->contentStringLen = 0;
4668 break;
4669 /* End element declaration stuff */
4671 case XML_ROLE_PI:
4672 if (!reportProcessingInstruction(parser, enc, s, next))
4673 return XML_ERROR_NO_MEMORY;
4674 handleDefault = XML_FALSE;
4675 break;
4676 case XML_ROLE_COMMENT:
4677 if (!reportComment(parser, enc, s, next))
4678 return XML_ERROR_NO_MEMORY;
4679 handleDefault = XML_FALSE;
4680 break;
4681 case XML_ROLE_NONE:
4682 switch (tok) {
4683 case XML_TOK_BOM:
4684 handleDefault = XML_FALSE;
4685 break;
4687 break;
4688 case XML_ROLE_DOCTYPE_NONE:
4689 if (startDoctypeDeclHandler)
4690 handleDefault = XML_FALSE;
4691 break;
4692 case XML_ROLE_ENTITY_NONE:
4693 if (dtd->keepProcessing && entityDeclHandler)
4694 handleDefault = XML_FALSE;
4695 break;
4696 case XML_ROLE_NOTATION_NONE:
4697 if (notationDeclHandler)
4698 handleDefault = XML_FALSE;
4699 break;
4700 case XML_ROLE_ATTLIST_NONE:
4701 if (dtd->keepProcessing && attlistDeclHandler)
4702 handleDefault = XML_FALSE;
4703 break;
4704 case XML_ROLE_ELEMENT_NONE:
4705 if (elementDeclHandler)
4706 handleDefault = XML_FALSE;
4707 break;
4708 } /* end of big switch */
4710 if (handleDefault && defaultHandler)
4711 reportDefault(parser, enc, s, next);
4713 switch (ps_parsing) {
4714 case XML_SUSPENDED:
4715 *nextPtr = next;
4716 return XML_ERROR_NONE;
4717 case XML_FINISHED:
4718 return XML_ERROR_ABORTED;
4719 default:
4720 s = next;
4721 tok = XmlPrologTok(enc, s, end, &next);
4724 /* not reached */
4727 static enum XML_Error PTRCALL
4728 epilogProcessor(XML_Parser parser,
4729 const char *s,
4730 const char *end,
4731 const char **nextPtr)
4733 processor = epilogProcessor;
4734 eventPtr = s;
4735 for (;;) {
4736 const char *next = NULL;
4737 int tok = XmlPrologTok(encoding, s, end, &next);
4738 eventEndPtr = next;
4739 switch (tok) {
4740 /* report partial linebreak - it might be the last token */
4741 case -XML_TOK_PROLOG_S:
4742 if (defaultHandler) {
4743 reportDefault(parser, encoding, s, next);
4744 if (ps_parsing == XML_FINISHED)
4745 return XML_ERROR_ABORTED;
4747 *nextPtr = next;
4748 return XML_ERROR_NONE;
4749 case XML_TOK_NONE:
4750 *nextPtr = s;
4751 return XML_ERROR_NONE;
4752 case XML_TOK_PROLOG_S:
4753 if (defaultHandler)
4754 reportDefault(parser, encoding, s, next);
4755 break;
4756 case XML_TOK_PI:
4757 if (!reportProcessingInstruction(parser, encoding, s, next))
4758 return XML_ERROR_NO_MEMORY;
4759 break;
4760 case XML_TOK_COMMENT:
4761 if (!reportComment(parser, encoding, s, next))
4762 return XML_ERROR_NO_MEMORY;
4763 break;
4764 case XML_TOK_INVALID:
4765 eventPtr = next;
4766 return XML_ERROR_INVALID_TOKEN;
4767 case XML_TOK_PARTIAL:
4768 if (!ps_finalBuffer) {
4769 *nextPtr = s;
4770 return XML_ERROR_NONE;
4772 return XML_ERROR_UNCLOSED_TOKEN;
4773 case XML_TOK_PARTIAL_CHAR:
4774 if (!ps_finalBuffer) {
4775 *nextPtr = s;
4776 return XML_ERROR_NONE;
4778 return XML_ERROR_PARTIAL_CHAR;
4779 default:
4780 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
4782 eventPtr = s = next;
4783 switch (ps_parsing) {
4784 case XML_SUSPENDED:
4785 *nextPtr = next;
4786 return XML_ERROR_NONE;
4787 case XML_FINISHED:
4788 return XML_ERROR_ABORTED;
4789 default: ;
4794 static enum XML_Error
4795 processInternalEntity(XML_Parser parser, ENTITY *entity,
4796 XML_Bool betweenDecl)
4798 const char *textStart, *textEnd;
4799 const char *next;
4800 enum XML_Error result;
4801 OPEN_INTERNAL_ENTITY *openEntity;
4803 if (freeInternalEntities) {
4804 openEntity = freeInternalEntities;
4805 freeInternalEntities = openEntity->next;
4807 else {
4808 openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
4809 if (!openEntity)
4810 return XML_ERROR_NO_MEMORY;
4812 entity->open = XML_TRUE;
4813 entity->processed = 0;
4814 openEntity->next = openInternalEntities;
4815 openInternalEntities = openEntity;
4816 openEntity->entity = entity;
4817 openEntity->startTagLevel = tagLevel;
4818 openEntity->betweenDecl = betweenDecl;
4819 openEntity->internalEventPtr = NULL;
4820 openEntity->internalEventEndPtr = NULL;
4821 textStart = (char *)entity->textPtr;
4822 textEnd = (char *)(entity->textPtr + entity->textLen);
4824 #ifdef XML_DTD
4825 if (entity->is_param) {
4826 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4827 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4828 next, &next, XML_FALSE);
4830 else
4831 #endif /* XML_DTD */
4832 result = doContent(parser, tagLevel, internalEncoding, textStart,
4833 textEnd, &next, XML_FALSE);
4835 if (result == XML_ERROR_NONE) {
4836 if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4837 entity->processed = (int)(next - textStart);
4838 processor = internalEntityProcessor;
4840 else {
4841 entity->open = XML_FALSE;
4842 openInternalEntities = openEntity->next;
4843 /* put openEntity back in list of free instances */
4844 openEntity->next = freeInternalEntities;
4845 freeInternalEntities = openEntity;
4848 return result;
4851 static enum XML_Error PTRCALL
4852 internalEntityProcessor(XML_Parser parser,
4853 const char *s,
4854 const char *end,
4855 const char **nextPtr)
4857 ENTITY *entity;
4858 const char *textStart, *textEnd;
4859 const char *next;
4860 enum XML_Error result;
4861 OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
4862 if (!openEntity)
4863 return XML_ERROR_UNEXPECTED_STATE;
4865 entity = openEntity->entity;
4866 textStart = ((char *)entity->textPtr) + entity->processed;
4867 textEnd = (char *)(entity->textPtr + entity->textLen);
4869 #ifdef XML_DTD
4870 if (entity->is_param) {
4871 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4872 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4873 next, &next, XML_FALSE);
4875 else
4876 #endif /* XML_DTD */
4877 result = doContent(parser, openEntity->startTagLevel, internalEncoding,
4878 textStart, textEnd, &next, XML_FALSE);
4880 if (result != XML_ERROR_NONE)
4881 return result;
4882 else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4883 entity->processed = (int)(next - (char *)entity->textPtr);
4884 return result;
4886 else {
4887 entity->open = XML_FALSE;
4888 openInternalEntities = openEntity->next;
4889 /* put openEntity back in list of free instances */
4890 openEntity->next = freeInternalEntities;
4891 freeInternalEntities = openEntity;
4894 #ifdef XML_DTD
4895 if (entity->is_param) {
4896 int tok;
4897 processor = prologProcessor;
4898 tok = XmlPrologTok(encoding, s, end, &next);
4899 return doProlog(parser, encoding, s, end, tok, next, nextPtr,
4900 (XML_Bool)!ps_finalBuffer);
4902 else
4903 #endif /* XML_DTD */
4905 processor = contentProcessor;
4906 /* see externalEntityContentProcessor vs contentProcessor */
4907 return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
4908 nextPtr, (XML_Bool)!ps_finalBuffer);
4912 static enum XML_Error PTRCALL
4913 errorProcessor(XML_Parser parser,
4914 const char *s,
4915 const char *end,
4916 const char **nextPtr)
4918 return errorCode;
4921 static enum XML_Error
4922 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4923 const char *ptr, const char *end,
4924 STRING_POOL *pool)
4926 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
4927 end, pool);
4928 if (result)
4929 return result;
4930 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
4931 poolChop(pool);
4932 if (!poolAppendChar(pool, XML_T('\0')))
4933 return XML_ERROR_NO_MEMORY;
4934 return XML_ERROR_NONE;
4937 static enum XML_Error
4938 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4939 const char *ptr, const char *end,
4940 STRING_POOL *pool)
4942 DTD * const dtd = _dtd; /* save one level of indirection */
4943 for (;;) {
4944 const char *next;
4945 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
4946 switch (tok) {
4947 case XML_TOK_NONE:
4948 return XML_ERROR_NONE;
4949 case XML_TOK_INVALID:
4950 if (enc == encoding)
4951 eventPtr = next;
4952 return XML_ERROR_INVALID_TOKEN;
4953 case XML_TOK_PARTIAL:
4954 if (enc == encoding)
4955 eventPtr = ptr;
4956 return XML_ERROR_INVALID_TOKEN;
4957 case XML_TOK_CHAR_REF:
4959 XML_Char buf[XML_ENCODE_MAX];
4960 int i;
4961 int n = XmlCharRefNumber(enc, ptr);
4962 if (n < 0) {
4963 if (enc == encoding)
4964 eventPtr = ptr;
4965 return XML_ERROR_BAD_CHAR_REF;
4967 if (!isCdata
4968 && n == 0x20 /* space */
4969 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4970 break;
4971 n = XmlEncode(n, (ICHAR *)buf);
4972 if (!n) {
4973 if (enc == encoding)
4974 eventPtr = ptr;
4975 return XML_ERROR_BAD_CHAR_REF;
4977 for (i = 0; i < n; i++) {
4978 if (!poolAppendChar(pool, buf[i]))
4979 return XML_ERROR_NO_MEMORY;
4982 break;
4983 case XML_TOK_DATA_CHARS:
4984 if (!poolAppend(pool, enc, ptr, next))
4985 return XML_ERROR_NO_MEMORY;
4986 break;
4987 case XML_TOK_TRAILING_CR:
4988 next = ptr + enc->minBytesPerChar;
4989 /* fall through */
4990 case XML_TOK_ATTRIBUTE_VALUE_S:
4991 case XML_TOK_DATA_NEWLINE:
4992 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4993 break;
4994 if (!poolAppendChar(pool, 0x20))
4995 return XML_ERROR_NO_MEMORY;
4996 break;
4997 case XML_TOK_ENTITY_REF:
4999 const XML_Char *name;
5000 ENTITY *entity;
5001 char checkEntityDecl;
5002 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
5003 ptr + enc->minBytesPerChar,
5004 next - enc->minBytesPerChar);
5005 if (ch) {
5006 if (!poolAppendChar(pool, ch))
5007 return XML_ERROR_NO_MEMORY;
5008 break;
5010 name = poolStoreString(&temp2Pool, enc,
5011 ptr + enc->minBytesPerChar,
5012 next - enc->minBytesPerChar);
5013 if (!name)
5014 return XML_ERROR_NO_MEMORY;
5015 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
5016 poolDiscard(&temp2Pool);
5017 /* First, determine if a check for an existing declaration is needed;
5018 if yes, check that the entity exists, and that it is internal.
5020 if (pool == &dtd->pool) /* are we called from prolog? */
5021 checkEntityDecl =
5022 #ifdef XML_DTD
5023 prologState.documentEntity &&
5024 #endif /* XML_DTD */
5025 (dtd->standalone
5026 ? !openInternalEntities
5027 : !dtd->hasParamEntityRefs);
5028 else /* if (pool == &tempPool): we are called from content */
5029 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
5030 if (checkEntityDecl) {
5031 if (!entity)
5032 return XML_ERROR_UNDEFINED_ENTITY;
5033 else if (!entity->is_internal)
5034 return XML_ERROR_ENTITY_DECLARED_IN_PE;
5036 else if (!entity) {
5037 /* Cannot report skipped entity here - see comments on
5038 skippedEntityHandler.
5039 if (skippedEntityHandler)
5040 skippedEntityHandler(handlerArg, name, 0);
5042 /* Cannot call the default handler because this would be
5043 out of sync with the call to the startElementHandler.
5044 if ((pool == &tempPool) && defaultHandler)
5045 reportDefault(parser, enc, ptr, next);
5047 break;
5049 if (entity->open) {
5050 if (enc == encoding)
5051 eventPtr = ptr;
5052 return XML_ERROR_RECURSIVE_ENTITY_REF;
5054 if (entity->notation) {
5055 if (enc == encoding)
5056 eventPtr = ptr;
5057 return XML_ERROR_BINARY_ENTITY_REF;
5059 if (!entity->textPtr) {
5060 if (enc == encoding)
5061 eventPtr = ptr;
5062 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
5064 else {
5065 enum XML_Error result;
5066 const XML_Char *textEnd = entity->textPtr + entity->textLen;
5067 entity->open = XML_TRUE;
5068 result = appendAttributeValue(parser, internalEncoding, isCdata,
5069 (char *)entity->textPtr,
5070 (char *)textEnd, pool);
5071 entity->open = XML_FALSE;
5072 if (result)
5073 return result;
5076 break;
5077 default:
5078 if (enc == encoding)
5079 eventPtr = ptr;
5080 return XML_ERROR_UNEXPECTED_STATE;
5082 ptr = next;
5084 /* not reached */
5087 static enum XML_Error
5088 storeEntityValue(XML_Parser parser,
5089 const ENCODING *enc,
5090 const char *entityTextPtr,
5091 const char *entityTextEnd)
5093 DTD * const dtd = _dtd; /* save one level of indirection */
5094 STRING_POOL *pool = &(dtd->entityValuePool);
5095 enum XML_Error result = XML_ERROR_NONE;
5096 #ifdef XML_DTD
5097 int oldInEntityValue = prologState.inEntityValue;
5098 prologState.inEntityValue = 1;
5099 #endif /* XML_DTD */
5100 /* never return Null for the value argument in EntityDeclHandler,
5101 since this would indicate an external entity; therefore we
5102 have to make sure that entityValuePool.start is not null */
5103 if (!pool->blocks) {
5104 if (!poolGrow(pool))
5105 return XML_ERROR_NO_MEMORY;
5108 for (;;) {
5109 const char *next;
5110 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
5111 switch (tok) {
5112 case XML_TOK_PARAM_ENTITY_REF:
5113 #ifdef XML_DTD
5114 if (isParamEntity || enc != encoding) {
5115 const XML_Char *name;
5116 ENTITY *entity;
5117 name = poolStoreString(&tempPool, enc,
5118 entityTextPtr + enc->minBytesPerChar,
5119 next - enc->minBytesPerChar);
5120 if (!name) {
5121 result = XML_ERROR_NO_MEMORY;
5122 goto endEntityValue;
5124 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
5125 poolDiscard(&tempPool);
5126 if (!entity) {
5127 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5128 /* cannot report skipped entity here - see comments on
5129 skippedEntityHandler
5130 if (skippedEntityHandler)
5131 skippedEntityHandler(handlerArg, name, 0);
5133 dtd->keepProcessing = dtd->standalone;
5134 goto endEntityValue;
5136 if (entity->open) {
5137 if (enc == encoding)
5138 eventPtr = entityTextPtr;
5139 result = XML_ERROR_RECURSIVE_ENTITY_REF;
5140 goto endEntityValue;
5142 if (entity->systemId) {
5143 if (externalEntityRefHandler) {
5144 dtd->paramEntityRead = XML_FALSE;
5145 entity->open = XML_TRUE;
5146 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
5148 entity->base,
5149 entity->systemId,
5150 entity->publicId)) {
5151 entity->open = XML_FALSE;
5152 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5153 goto endEntityValue;
5155 entity->open = XML_FALSE;
5156 if (!dtd->paramEntityRead)
5157 dtd->keepProcessing = dtd->standalone;
5159 else
5160 dtd->keepProcessing = dtd->standalone;
5162 else {
5163 entity->open = XML_TRUE;
5164 result = storeEntityValue(parser,
5165 internalEncoding,
5166 (char *)entity->textPtr,
5167 (char *)(entity->textPtr
5168 + entity->textLen));
5169 entity->open = XML_FALSE;
5170 if (result)
5171 goto endEntityValue;
5173 break;
5175 #endif /* XML_DTD */
5176 /* In the internal subset, PE references are not legal
5177 within markup declarations, e.g entity values in this case. */
5178 eventPtr = entityTextPtr;
5179 result = XML_ERROR_PARAM_ENTITY_REF;
5180 goto endEntityValue;
5181 case XML_TOK_NONE:
5182 result = XML_ERROR_NONE;
5183 goto endEntityValue;
5184 case XML_TOK_ENTITY_REF:
5185 case XML_TOK_DATA_CHARS:
5186 if (!poolAppend(pool, enc, entityTextPtr, next)) {
5187 result = XML_ERROR_NO_MEMORY;
5188 goto endEntityValue;
5190 break;
5191 case XML_TOK_TRAILING_CR:
5192 next = entityTextPtr + enc->minBytesPerChar;
5193 /* fall through */
5194 case XML_TOK_DATA_NEWLINE:
5195 if (pool->end == pool->ptr && !poolGrow(pool)) {
5196 result = XML_ERROR_NO_MEMORY;
5197 goto endEntityValue;
5199 *(pool->ptr)++ = 0xA;
5200 break;
5201 case XML_TOK_CHAR_REF:
5203 XML_Char buf[XML_ENCODE_MAX];
5204 int i;
5205 int n = XmlCharRefNumber(enc, entityTextPtr);
5206 if (n < 0) {
5207 if (enc == encoding)
5208 eventPtr = entityTextPtr;
5209 result = XML_ERROR_BAD_CHAR_REF;
5210 goto endEntityValue;
5212 n = XmlEncode(n, (ICHAR *)buf);
5213 if (!n) {
5214 if (enc == encoding)
5215 eventPtr = entityTextPtr;
5216 result = XML_ERROR_BAD_CHAR_REF;
5217 goto endEntityValue;
5219 for (i = 0; i < n; i++) {
5220 if (pool->end == pool->ptr && !poolGrow(pool)) {
5221 result = XML_ERROR_NO_MEMORY;
5222 goto endEntityValue;
5224 *(pool->ptr)++ = buf[i];
5227 break;
5228 case XML_TOK_PARTIAL:
5229 if (enc == encoding)
5230 eventPtr = entityTextPtr;
5231 result = XML_ERROR_INVALID_TOKEN;
5232 goto endEntityValue;
5233 case XML_TOK_INVALID:
5234 if (enc == encoding)
5235 eventPtr = next;
5236 result = XML_ERROR_INVALID_TOKEN;
5237 goto endEntityValue;
5238 default:
5239 if (enc == encoding)
5240 eventPtr = entityTextPtr;
5241 result = XML_ERROR_UNEXPECTED_STATE;
5242 goto endEntityValue;
5244 entityTextPtr = next;
5246 endEntityValue:
5247 #ifdef XML_DTD
5248 prologState.inEntityValue = oldInEntityValue;
5249 #endif /* XML_DTD */
5250 return result;
5253 static void FASTCALL
5254 normalizeLines(XML_Char *s)
5256 XML_Char *p;
5257 for (;; s++) {
5258 if (*s == XML_T('\0'))
5259 return;
5260 if (*s == 0xD)
5261 break;
5263 p = s;
5264 do {
5265 if (*s == 0xD) {
5266 *p++ = 0xA;
5267 if (*++s == 0xA)
5268 s++;
5270 else
5271 *p++ = *s++;
5272 } while (*s);
5273 *p = XML_T('\0');
5276 static int
5277 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5278 const char *start, const char *end)
5280 const XML_Char *target;
5281 XML_Char *data;
5282 const char *tem;
5283 if (!processingInstructionHandler) {
5284 if (defaultHandler)
5285 reportDefault(parser, enc, start, end);
5286 return 1;
5288 start += enc->minBytesPerChar * 2;
5289 tem = start + XmlNameLength(enc, start);
5290 target = poolStoreString(&tempPool, enc, start, tem);
5291 if (!target)
5292 return 0;
5293 poolFinish(&tempPool);
5294 data = poolStoreString(&tempPool, enc,
5295 XmlSkipS(enc, tem),
5296 end - enc->minBytesPerChar*2);
5297 if (!data)
5298 return 0;
5299 normalizeLines(data);
5300 processingInstructionHandler(handlerArg, target, data);
5301 poolClear(&tempPool);
5302 return 1;
5305 static int
5306 reportComment(XML_Parser parser, const ENCODING *enc,
5307 const char *start, const char *end)
5309 XML_Char *data;
5310 if (!commentHandler) {
5311 if (defaultHandler)
5312 reportDefault(parser, enc, start, end);
5313 return 1;
5315 data = poolStoreString(&tempPool,
5316 enc,
5317 start + enc->minBytesPerChar * 4,
5318 end - enc->minBytesPerChar * 3);
5319 if (!data)
5320 return 0;
5321 normalizeLines(data);
5322 commentHandler(handlerArg, data);
5323 poolClear(&tempPool);
5324 return 1;
5327 static void
5328 reportDefault(XML_Parser parser, const ENCODING *enc,
5329 const char *s, const char *end)
5331 if (MUST_CONVERT(enc, s)) {
5332 const char **eventPP;
5333 const char **eventEndPP;
5334 if (enc == encoding) {
5335 eventPP = &eventPtr;
5336 eventEndPP = &eventEndPtr;
5338 else {
5339 eventPP = &(openInternalEntities->internalEventPtr);
5340 eventEndPP = &(openInternalEntities->internalEventEndPtr);
5342 do {
5343 ICHAR *dataPtr = (ICHAR *)dataBuf;
5344 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
5345 *eventEndPP = s;
5346 defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
5347 *eventPP = s;
5348 } while (s != end);
5350 else
5351 defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
5355 static int
5356 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
5357 XML_Bool isId, const XML_Char *value, XML_Parser parser)
5359 DEFAULT_ATTRIBUTE *att;
5360 if (value || isId) {
5361 /* The handling of default attributes gets messed up if we have
5362 a default which duplicates a non-default. */
5363 int i;
5364 for (i = 0; i < type->nDefaultAtts; i++)
5365 if (attId == type->defaultAtts[i].id)
5366 return 1;
5367 if (isId && !type->idAtt && !attId->xmlns)
5368 type->idAtt = attId;
5370 if (type->nDefaultAtts == type->allocDefaultAtts) {
5371 if (type->allocDefaultAtts == 0) {
5372 type->allocDefaultAtts = 8;
5373 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
5374 * sizeof(DEFAULT_ATTRIBUTE));
5375 if (!type->defaultAtts)
5376 return 0;
5378 else {
5379 DEFAULT_ATTRIBUTE *temp;
5380 int count = type->allocDefaultAtts * 2;
5381 temp = (DEFAULT_ATTRIBUTE *)
5382 REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
5383 if (temp == NULL)
5384 return 0;
5385 type->allocDefaultAtts = count;
5386 type->defaultAtts = temp;
5389 att = type->defaultAtts + type->nDefaultAtts;
5390 att->id = attId;
5391 att->value = value;
5392 att->isCdata = isCdata;
5393 if (!isCdata)
5394 attId->maybeTokenized = XML_TRUE;
5395 type->nDefaultAtts += 1;
5396 return 1;
5399 static int
5400 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
5402 DTD * const dtd = _dtd; /* save one level of indirection */
5403 const XML_Char *name;
5404 for (name = elementType->name; *name; name++) {
5405 if (*name == XML_T(ASCII_COLON)) {
5406 PREFIX *prefix;
5407 const XML_Char *s;
5408 for (s = elementType->name; s != name; s++) {
5409 if (!poolAppendChar(&dtd->pool, *s))
5410 return 0;
5412 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5413 return 0;
5414 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
5415 sizeof(PREFIX));
5416 if (!prefix)
5417 return 0;
5418 if (prefix->name == poolStart(&dtd->pool))
5419 poolFinish(&dtd->pool);
5420 else
5421 poolDiscard(&dtd->pool);
5422 elementType->prefix = prefix;
5426 return 1;
5429 static ATTRIBUTE_ID *
5430 getAttributeId(XML_Parser parser, const ENCODING *enc,
5431 const char *start, const char *end)
5433 DTD * const dtd = _dtd; /* save one level of indirection */
5434 ATTRIBUTE_ID *id;
5435 const XML_Char *name;
5436 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5437 return NULL;
5438 name = poolStoreString(&dtd->pool, enc, start, end);
5439 if (!name)
5440 return NULL;
5441 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
5442 ++name;
5443 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
5444 if (!id)
5445 return NULL;
5446 if (id->name != name)
5447 poolDiscard(&dtd->pool);
5448 else {
5449 poolFinish(&dtd->pool);
5450 if (!ns)
5452 else if (name[0] == XML_T(ASCII_x)
5453 && name[1] == XML_T(ASCII_m)
5454 && name[2] == XML_T(ASCII_l)
5455 && name[3] == XML_T(ASCII_n)
5456 && name[4] == XML_T(ASCII_s)
5457 && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
5458 if (name[5] == XML_T('\0'))
5459 id->prefix = &dtd->defaultPrefix;
5460 else
5461 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
5462 id->xmlns = XML_TRUE;
5464 else {
5465 int i;
5466 for (i = 0; name[i]; i++) {
5467 /* attributes without prefix are *not* in the default namespace */
5468 if (name[i] == XML_T(ASCII_COLON)) {
5469 int j;
5470 for (j = 0; j < i; j++) {
5471 if (!poolAppendChar(&dtd->pool, name[j]))
5472 return NULL;
5474 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5475 return NULL;
5476 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
5477 sizeof(PREFIX));
5478 if (id->prefix->name == poolStart(&dtd->pool))
5479 poolFinish(&dtd->pool);
5480 else
5481 poolDiscard(&dtd->pool);
5482 break;
5487 return id;
5490 #define CONTEXT_SEP XML_T(ASCII_FF)
5492 static const XML_Char *
5493 getContext(XML_Parser parser)
5495 DTD * const dtd = _dtd; /* save one level of indirection */
5496 HASH_TABLE_ITER iter;
5497 XML_Bool needSep = XML_FALSE;
5499 if (dtd->defaultPrefix.binding) {
5500 int i;
5501 int len;
5502 if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
5503 return NULL;
5504 len = dtd->defaultPrefix.binding->uriLen;
5505 if (namespaceSeparator)
5506 len--;
5507 for (i = 0; i < len; i++)
5508 if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
5509 return NULL;
5510 needSep = XML_TRUE;
5513 hashTableIterInit(&iter, &(dtd->prefixes));
5514 for (;;) {
5515 int i;
5516 int len;
5517 const XML_Char *s;
5518 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
5519 if (!prefix)
5520 break;
5521 if (!prefix->binding)
5522 continue;
5523 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5524 return NULL;
5525 for (s = prefix->name; *s; s++)
5526 if (!poolAppendChar(&tempPool, *s))
5527 return NULL;
5528 if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
5529 return NULL;
5530 len = prefix->binding->uriLen;
5531 if (namespaceSeparator)
5532 len--;
5533 for (i = 0; i < len; i++)
5534 if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
5535 return NULL;
5536 needSep = XML_TRUE;
5540 hashTableIterInit(&iter, &(dtd->generalEntities));
5541 for (;;) {
5542 const XML_Char *s;
5543 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
5544 if (!e)
5545 break;
5546 if (!e->open)
5547 continue;
5548 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5549 return NULL;
5550 for (s = e->name; *s; s++)
5551 if (!poolAppendChar(&tempPool, *s))
5552 return 0;
5553 needSep = XML_TRUE;
5556 if (!poolAppendChar(&tempPool, XML_T('\0')))
5557 return NULL;
5558 return tempPool.start;
5561 static XML_Bool
5562 setContext(XML_Parser parser, const XML_Char *context)
5564 DTD * const dtd = _dtd; /* save one level of indirection */
5565 const XML_Char *s = context;
5567 while (*context != XML_T('\0')) {
5568 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
5569 ENTITY *e;
5570 if (!poolAppendChar(&tempPool, XML_T('\0')))
5571 return XML_FALSE;
5572 e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0);
5573 if (e)
5574 e->open = XML_TRUE;
5575 if (*s != XML_T('\0'))
5576 s++;
5577 context = s;
5578 poolDiscard(&tempPool);
5580 else if (*s == XML_T(ASCII_EQUALS)) {
5581 PREFIX *prefix;
5582 if (poolLength(&tempPool) == 0)
5583 prefix = &dtd->defaultPrefix;
5584 else {
5585 if (!poolAppendChar(&tempPool, XML_T('\0')))
5586 return XML_FALSE;
5587 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool),
5588 sizeof(PREFIX));
5589 if (!prefix)
5590 return XML_FALSE;
5591 if (prefix->name == poolStart(&tempPool)) {
5592 prefix->name = poolCopyString(&dtd->pool, prefix->name);
5593 if (!prefix->name)
5594 return XML_FALSE;
5596 poolDiscard(&tempPool);
5598 for (context = s + 1;
5599 *context != CONTEXT_SEP && *context != XML_T('\0');
5600 context++)
5601 if (!poolAppendChar(&tempPool, *context))
5602 return XML_FALSE;
5603 if (!poolAppendChar(&tempPool, XML_T('\0')))
5604 return XML_FALSE;
5605 if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
5606 &inheritedBindings) != XML_ERROR_NONE)
5607 return XML_FALSE;
5608 poolDiscard(&tempPool);
5609 if (*context != XML_T('\0'))
5610 ++context;
5611 s = context;
5613 else {
5614 if (!poolAppendChar(&tempPool, *s))
5615 return XML_FALSE;
5616 s++;
5619 return XML_TRUE;
5622 static void FASTCALL
5623 normalizePublicId(XML_Char *publicId)
5625 XML_Char *p = publicId;
5626 XML_Char *s;
5627 for (s = publicId; *s; s++) {
5628 switch (*s) {
5629 case 0x20:
5630 case 0xD:
5631 case 0xA:
5632 if (p != publicId && p[-1] != 0x20)
5633 *p++ = 0x20;
5634 break;
5635 default:
5636 *p++ = *s;
5639 if (p != publicId && p[-1] == 0x20)
5640 --p;
5641 *p = XML_T('\0');
5644 static DTD *
5645 dtdCreate(const XML_Memory_Handling_Suite *ms)
5647 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
5648 if (p == NULL)
5649 return p;
5650 poolInit(&(p->pool), ms);
5651 poolInit(&(p->entityValuePool), ms);
5652 hashTableInit(&(p->generalEntities), ms);
5653 hashTableInit(&(p->elementTypes), ms);
5654 hashTableInit(&(p->attributeIds), ms);
5655 hashTableInit(&(p->prefixes), ms);
5656 #ifdef XML_DTD
5657 p->paramEntityRead = XML_FALSE;
5658 hashTableInit(&(p->paramEntities), ms);
5659 #endif /* XML_DTD */
5660 p->defaultPrefix.name = NULL;
5661 p->defaultPrefix.binding = NULL;
5663 p->in_eldecl = XML_FALSE;
5664 p->scaffIndex = NULL;
5665 p->scaffold = NULL;
5666 p->scaffLevel = 0;
5667 p->scaffSize = 0;
5668 p->scaffCount = 0;
5669 p->contentStringLen = 0;
5671 p->keepProcessing = XML_TRUE;
5672 p->hasParamEntityRefs = XML_FALSE;
5673 p->standalone = XML_FALSE;
5674 return p;
5677 static void
5678 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
5680 HASH_TABLE_ITER iter;
5681 hashTableIterInit(&iter, &(p->elementTypes));
5682 for (;;) {
5683 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5684 if (!e)
5685 break;
5686 if (e->allocDefaultAtts != 0)
5687 ms->free_fcn(e->defaultAtts);
5689 hashTableClear(&(p->generalEntities));
5690 #ifdef XML_DTD
5691 p->paramEntityRead = XML_FALSE;
5692 hashTableClear(&(p->paramEntities));
5693 #endif /* XML_DTD */
5694 hashTableClear(&(p->elementTypes));
5695 hashTableClear(&(p->attributeIds));
5696 hashTableClear(&(p->prefixes));
5697 poolClear(&(p->pool));
5698 poolClear(&(p->entityValuePool));
5699 p->defaultPrefix.name = NULL;
5700 p->defaultPrefix.binding = NULL;
5702 p->in_eldecl = XML_FALSE;
5704 ms->free_fcn(p->scaffIndex);
5705 p->scaffIndex = NULL;
5706 ms->free_fcn(p->scaffold);
5707 p->scaffold = NULL;
5709 p->scaffLevel = 0;
5710 p->scaffSize = 0;
5711 p->scaffCount = 0;
5712 p->contentStringLen = 0;
5714 p->keepProcessing = XML_TRUE;
5715 p->hasParamEntityRefs = XML_FALSE;
5716 p->standalone = XML_FALSE;
5719 static void
5720 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
5722 HASH_TABLE_ITER iter;
5723 hashTableIterInit(&iter, &(p->elementTypes));
5724 for (;;) {
5725 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5726 if (!e)
5727 break;
5728 if (e->allocDefaultAtts != 0)
5729 ms->free_fcn(e->defaultAtts);
5731 hashTableDestroy(&(p->generalEntities));
5732 #ifdef XML_DTD
5733 hashTableDestroy(&(p->paramEntities));
5734 #endif /* XML_DTD */
5735 hashTableDestroy(&(p->elementTypes));
5736 hashTableDestroy(&(p->attributeIds));
5737 hashTableDestroy(&(p->prefixes));
5738 poolDestroy(&(p->pool));
5739 poolDestroy(&(p->entityValuePool));
5740 if (isDocEntity) {
5741 ms->free_fcn(p->scaffIndex);
5742 ms->free_fcn(p->scaffold);
5744 ms->free_fcn(p);
5747 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
5748 The new DTD has already been initialized.
5750 static int
5751 dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
5753 HASH_TABLE_ITER iter;
5755 /* Copy the prefix table. */
5757 hashTableIterInit(&iter, &(oldDtd->prefixes));
5758 for (;;) {
5759 const XML_Char *name;
5760 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
5761 if (!oldP)
5762 break;
5763 name = poolCopyString(&(newDtd->pool), oldP->name);
5764 if (!name)
5765 return 0;
5766 if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
5767 return 0;
5770 hashTableIterInit(&iter, &(oldDtd->attributeIds));
5772 /* Copy the attribute id table. */
5774 for (;;) {
5775 ATTRIBUTE_ID *newA;
5776 const XML_Char *name;
5777 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
5779 if (!oldA)
5780 break;
5781 /* Remember to allocate the scratch byte before the name. */
5782 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
5783 return 0;
5784 name = poolCopyString(&(newDtd->pool), oldA->name);
5785 if (!name)
5786 return 0;
5787 ++name;
5788 newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
5789 sizeof(ATTRIBUTE_ID));
5790 if (!newA)
5791 return 0;
5792 newA->maybeTokenized = oldA->maybeTokenized;
5793 if (oldA->prefix) {
5794 newA->xmlns = oldA->xmlns;
5795 if (oldA->prefix == &oldDtd->defaultPrefix)
5796 newA->prefix = &newDtd->defaultPrefix;
5797 else
5798 newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
5799 oldA->prefix->name, 0);
5803 /* Copy the element type table. */
5805 hashTableIterInit(&iter, &(oldDtd->elementTypes));
5807 for (;;) {
5808 int i;
5809 ELEMENT_TYPE *newE;
5810 const XML_Char *name;
5811 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5812 if (!oldE)
5813 break;
5814 name = poolCopyString(&(newDtd->pool), oldE->name);
5815 if (!name)
5816 return 0;
5817 newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
5818 sizeof(ELEMENT_TYPE));
5819 if (!newE)
5820 return 0;
5821 if (oldE->nDefaultAtts) {
5822 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
5823 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
5824 if (!newE->defaultAtts) {
5825 ms->free_fcn(newE);
5826 return 0;
5829 if (oldE->idAtt)
5830 newE->idAtt = (ATTRIBUTE_ID *)
5831 lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
5832 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
5833 if (oldE->prefix)
5834 newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
5835 oldE->prefix->name, 0);
5836 for (i = 0; i < newE->nDefaultAtts; i++) {
5837 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
5838 lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
5839 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
5840 if (oldE->defaultAtts[i].value) {
5841 newE->defaultAtts[i].value
5842 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
5843 if (!newE->defaultAtts[i].value)
5844 return 0;
5846 else
5847 newE->defaultAtts[i].value = NULL;
5851 /* Copy the entity tables. */
5852 if (!copyEntityTable(oldParser,
5853 &(newDtd->generalEntities),
5854 &(newDtd->pool),
5855 &(oldDtd->generalEntities)))
5856 return 0;
5858 #ifdef XML_DTD
5859 if (!copyEntityTable(oldParser,
5860 &(newDtd->paramEntities),
5861 &(newDtd->pool),
5862 &(oldDtd->paramEntities)))
5863 return 0;
5864 newDtd->paramEntityRead = oldDtd->paramEntityRead;
5865 #endif /* XML_DTD */
5867 newDtd->keepProcessing = oldDtd->keepProcessing;
5868 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
5869 newDtd->standalone = oldDtd->standalone;
5871 /* Don't want deep copying for scaffolding */
5872 newDtd->in_eldecl = oldDtd->in_eldecl;
5873 newDtd->scaffold = oldDtd->scaffold;
5874 newDtd->contentStringLen = oldDtd->contentStringLen;
5875 newDtd->scaffSize = oldDtd->scaffSize;
5876 newDtd->scaffLevel = oldDtd->scaffLevel;
5877 newDtd->scaffIndex = oldDtd->scaffIndex;
5879 return 1;
5880 } /* End dtdCopy */
5882 static int
5883 copyEntityTable(XML_Parser oldParser,
5884 HASH_TABLE *newTable,
5885 STRING_POOL *newPool,
5886 const HASH_TABLE *oldTable)
5888 HASH_TABLE_ITER iter;
5889 const XML_Char *cachedOldBase = NULL;
5890 const XML_Char *cachedNewBase = NULL;
5892 hashTableIterInit(&iter, oldTable);
5894 for (;;) {
5895 ENTITY *newE;
5896 const XML_Char *name;
5897 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
5898 if (!oldE)
5899 break;
5900 name = poolCopyString(newPool, oldE->name);
5901 if (!name)
5902 return 0;
5903 newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
5904 if (!newE)
5905 return 0;
5906 if (oldE->systemId) {
5907 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
5908 if (!tem)
5909 return 0;
5910 newE->systemId = tem;
5911 if (oldE->base) {
5912 if (oldE->base == cachedOldBase)
5913 newE->base = cachedNewBase;
5914 else {
5915 cachedOldBase = oldE->base;
5916 tem = poolCopyString(newPool, cachedOldBase);
5917 if (!tem)
5918 return 0;
5919 cachedNewBase = newE->base = tem;
5922 if (oldE->publicId) {
5923 tem = poolCopyString(newPool, oldE->publicId);
5924 if (!tem)
5925 return 0;
5926 newE->publicId = tem;
5929 else {
5930 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
5931 oldE->textLen);
5932 if (!tem)
5933 return 0;
5934 newE->textPtr = tem;
5935 newE->textLen = oldE->textLen;
5937 if (oldE->notation) {
5938 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
5939 if (!tem)
5940 return 0;
5941 newE->notation = tem;
5943 newE->is_param = oldE->is_param;
5944 newE->is_internal = oldE->is_internal;
5946 return 1;
5949 #define INIT_POWER 6
5951 static XML_Bool FASTCALL
5952 keyeq(KEY s1, KEY s2)
5954 for (; *s1 == *s2; s1++, s2++)
5955 if (*s1 == 0)
5956 return XML_TRUE;
5957 return XML_FALSE;
5960 static unsigned long FASTCALL
5961 hash(XML_Parser parser, KEY s)
5963 unsigned long h = hash_secret_salt;
5964 while (*s)
5965 h = CHAR_HASH(h, *s++);
5966 return h;
5969 static NAMED *
5970 lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
5972 size_t i;
5973 if (table->size == 0) {
5974 size_t tsize;
5975 if (!createSize)
5976 return NULL;
5977 table->power = INIT_POWER;
5978 /* table->size is a power of 2 */
5979 table->size = (size_t)1 << INIT_POWER;
5980 tsize = table->size * sizeof(NAMED *);
5981 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
5982 if (!table->v) {
5983 table->size = 0;
5984 return NULL;
5986 memset(table->v, 0, tsize);
5987 i = hash(parser, name) & ((unsigned long)table->size - 1);
5989 else {
5990 unsigned long h = hash(parser, name);
5991 unsigned long mask = (unsigned long)table->size - 1;
5992 unsigned char step = 0;
5993 i = h & mask;
5994 while (table->v[i]) {
5995 if (keyeq(name, table->v[i]->name))
5996 return table->v[i];
5997 if (!step)
5998 step = PROBE_STEP(h, mask, table->power);
5999 i < step ? (i += table->size - step) : (i -= step);
6001 if (!createSize)
6002 return NULL;
6004 /* check for overflow (table is half full) */
6005 if (table->used >> (table->power - 1)) {
6006 unsigned char newPower = table->power + 1;
6007 size_t newSize = (size_t)1 << newPower;
6008 unsigned long newMask = (unsigned long)newSize - 1;
6009 size_t tsize = newSize * sizeof(NAMED *);
6010 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
6011 if (!newV)
6012 return NULL;
6013 memset(newV, 0, tsize);
6014 for (i = 0; i < table->size; i++)
6015 if (table->v[i]) {
6016 unsigned long newHash = hash(parser, table->v[i]->name);
6017 size_t j = newHash & newMask;
6018 step = 0;
6019 while (newV[j]) {
6020 if (!step)
6021 step = PROBE_STEP(newHash, newMask, newPower);
6022 j < step ? (j += newSize - step) : (j -= step);
6024 newV[j] = table->v[i];
6026 table->mem->free_fcn(table->v);
6027 table->v = newV;
6028 table->power = newPower;
6029 table->size = newSize;
6030 i = h & newMask;
6031 step = 0;
6032 while (table->v[i]) {
6033 if (!step)
6034 step = PROBE_STEP(h, newMask, newPower);
6035 i < step ? (i += newSize - step) : (i -= step);
6039 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
6040 if (!table->v[i])
6041 return NULL;
6042 memset(table->v[i], 0, createSize);
6043 table->v[i]->name = name;
6044 (table->used)++;
6045 return table->v[i];
6048 static void FASTCALL
6049 hashTableClear(HASH_TABLE *table)
6051 size_t i;
6052 for (i = 0; i < table->size; i++) {
6053 table->mem->free_fcn(table->v[i]);
6054 table->v[i] = NULL;
6056 table->used = 0;
6059 static void FASTCALL
6060 hashTableDestroy(HASH_TABLE *table)
6062 size_t i;
6063 for (i = 0; i < table->size; i++)
6064 table->mem->free_fcn(table->v[i]);
6065 table->mem->free_fcn(table->v);
6068 static void FASTCALL
6069 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
6071 p->power = 0;
6072 p->size = 0;
6073 p->used = 0;
6074 p->v = NULL;
6075 p->mem = ms;
6078 static void FASTCALL
6079 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
6081 iter->p = table->v;
6082 iter->end = iter->p + table->size;
6085 static NAMED * FASTCALL
6086 hashTableIterNext(HASH_TABLE_ITER *iter)
6088 while (iter->p != iter->end) {
6089 NAMED *tem = *(iter->p)++;
6090 if (tem)
6091 return tem;
6093 return NULL;
6096 static void FASTCALL
6097 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
6099 pool->blocks = NULL;
6100 pool->freeBlocks = NULL;
6101 pool->start = NULL;
6102 pool->ptr = NULL;
6103 pool->end = NULL;
6104 pool->mem = ms;
6107 static void FASTCALL
6108 poolClear(STRING_POOL *pool)
6110 if (!pool->freeBlocks)
6111 pool->freeBlocks = pool->blocks;
6112 else {
6113 BLOCK *p = pool->blocks;
6114 while (p) {
6115 BLOCK *tem = p->next;
6116 p->next = pool->freeBlocks;
6117 pool->freeBlocks = p;
6118 p = tem;
6121 pool->blocks = NULL;
6122 pool->start = NULL;
6123 pool->ptr = NULL;
6124 pool->end = NULL;
6127 static void FASTCALL
6128 poolDestroy(STRING_POOL *pool)
6130 BLOCK *p = pool->blocks;
6131 while (p) {
6132 BLOCK *tem = p->next;
6133 pool->mem->free_fcn(p);
6134 p = tem;
6136 p = pool->freeBlocks;
6137 while (p) {
6138 BLOCK *tem = p->next;
6139 pool->mem->free_fcn(p);
6140 p = tem;
6144 static XML_Char *
6145 poolAppend(STRING_POOL *pool, const ENCODING *enc,
6146 const char *ptr, const char *end)
6148 if (!pool->ptr && !poolGrow(pool))
6149 return NULL;
6150 for (;;) {
6151 XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6152 if (ptr == end)
6153 break;
6154 if (!poolGrow(pool))
6155 return NULL;
6157 return pool->start;
6160 static const XML_Char * FASTCALL
6161 poolCopyString(STRING_POOL *pool, const XML_Char *s)
6163 do {
6164 if (!poolAppendChar(pool, *s))
6165 return NULL;
6166 } while (*s++);
6167 s = pool->start;
6168 poolFinish(pool);
6169 return s;
6172 static const XML_Char *
6173 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
6175 if (!pool->ptr && !poolGrow(pool))
6176 return NULL;
6177 for (; n > 0; --n, s++) {
6178 if (!poolAppendChar(pool, *s))
6179 return NULL;
6181 s = pool->start;
6182 poolFinish(pool);
6183 return s;
6186 static const XML_Char * FASTCALL
6187 poolAppendString(STRING_POOL *pool, const XML_Char *s)
6189 while (*s) {
6190 if (!poolAppendChar(pool, *s))
6191 return NULL;
6192 s++;
6194 return pool->start;
6197 static XML_Char *
6198 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
6199 const char *ptr, const char *end)
6201 if (!poolAppend(pool, enc, ptr, end))
6202 return NULL;
6203 if (pool->ptr == pool->end && !poolGrow(pool))
6204 return NULL;
6205 *(pool->ptr)++ = 0;
6206 return pool->start;
6209 static XML_Bool FASTCALL
6210 poolGrow(STRING_POOL *pool)
6212 if (pool->freeBlocks) {
6213 if (pool->start == 0) {
6214 pool->blocks = pool->freeBlocks;
6215 pool->freeBlocks = pool->freeBlocks->next;
6216 pool->blocks->next = NULL;
6217 pool->start = pool->blocks->s;
6218 pool->end = pool->start + pool->blocks->size;
6219 pool->ptr = pool->start;
6220 return XML_TRUE;
6222 if (pool->end - pool->start < pool->freeBlocks->size) {
6223 BLOCK *tem = pool->freeBlocks->next;
6224 pool->freeBlocks->next = pool->blocks;
6225 pool->blocks = pool->freeBlocks;
6226 pool->freeBlocks = tem;
6227 memcpy(pool->blocks->s, pool->start,
6228 (pool->end - pool->start) * sizeof(XML_Char));
6229 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6230 pool->start = pool->blocks->s;
6231 pool->end = pool->start + pool->blocks->size;
6232 return XML_TRUE;
6235 if (pool->blocks && pool->start == pool->blocks->s) {
6236 int blockSize = (int)(pool->end - pool->start)*2;
6237 BLOCK *temp = (BLOCK *)
6238 pool->mem->realloc_fcn(pool->blocks,
6239 (offsetof(BLOCK, s)
6240 + blockSize * sizeof(XML_Char)));
6241 if (temp == NULL)
6242 return XML_FALSE;
6243 pool->blocks = temp;
6244 pool->blocks->size = blockSize;
6245 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6246 pool->start = pool->blocks->s;
6247 pool->end = pool->start + blockSize;
6249 else {
6250 BLOCK *tem;
6251 int blockSize = (int)(pool->end - pool->start);
6252 if (blockSize < INIT_BLOCK_SIZE)
6253 blockSize = INIT_BLOCK_SIZE;
6254 else
6255 blockSize *= 2;
6256 tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
6257 + blockSize * sizeof(XML_Char));
6258 if (!tem)
6259 return XML_FALSE;
6260 tem->size = blockSize;
6261 tem->next = pool->blocks;
6262 pool->blocks = tem;
6263 if (pool->ptr != pool->start)
6264 memcpy(tem->s, pool->start,
6265 (pool->ptr - pool->start) * sizeof(XML_Char));
6266 pool->ptr = tem->s + (pool->ptr - pool->start);
6267 pool->start = tem->s;
6268 pool->end = tem->s + blockSize;
6270 return XML_TRUE;
6273 static int FASTCALL
6274 nextScaffoldPart(XML_Parser parser)
6276 DTD * const dtd = _dtd; /* save one level of indirection */
6277 CONTENT_SCAFFOLD * me;
6278 int next;
6280 if (!dtd->scaffIndex) {
6281 dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
6282 if (!dtd->scaffIndex)
6283 return -1;
6284 dtd->scaffIndex[0] = 0;
6287 if (dtd->scaffCount >= dtd->scaffSize) {
6288 CONTENT_SCAFFOLD *temp;
6289 if (dtd->scaffold) {
6290 temp = (CONTENT_SCAFFOLD *)
6291 REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
6292 if (temp == NULL)
6293 return -1;
6294 dtd->scaffSize *= 2;
6296 else {
6297 temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
6298 * sizeof(CONTENT_SCAFFOLD));
6299 if (temp == NULL)
6300 return -1;
6301 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
6303 dtd->scaffold = temp;
6305 next = dtd->scaffCount++;
6306 me = &dtd->scaffold[next];
6307 if (dtd->scaffLevel) {
6308 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
6309 if (parent->lastchild) {
6310 dtd->scaffold[parent->lastchild].nextsib = next;
6312 if (!parent->childcnt)
6313 parent->firstchild = next;
6314 parent->lastchild = next;
6315 parent->childcnt++;
6317 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
6318 return next;
6321 static void
6322 build_node(XML_Parser parser,
6323 int src_node,
6324 XML_Content *dest,
6325 XML_Content **contpos,
6326 XML_Char **strpos)
6328 DTD * const dtd = _dtd; /* save one level of indirection */
6329 dest->type = dtd->scaffold[src_node].type;
6330 dest->quant = dtd->scaffold[src_node].quant;
6331 if (dest->type == XML_CTYPE_NAME) {
6332 const XML_Char *src;
6333 dest->name = *strpos;
6334 src = dtd->scaffold[src_node].name;
6335 for (;;) {
6336 *(*strpos)++ = *src;
6337 if (!*src)
6338 break;
6339 src++;
6341 dest->numchildren = 0;
6342 dest->children = NULL;
6344 else {
6345 unsigned int i;
6346 int cn;
6347 dest->numchildren = dtd->scaffold[src_node].childcnt;
6348 dest->children = *contpos;
6349 *contpos += dest->numchildren;
6350 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
6351 i < dest->numchildren;
6352 i++, cn = dtd->scaffold[cn].nextsib) {
6353 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
6355 dest->name = NULL;
6359 static XML_Content *
6360 build_model (XML_Parser parser)
6362 DTD * const dtd = _dtd; /* save one level of indirection */
6363 XML_Content *ret;
6364 XML_Content *cpos;
6365 XML_Char * str;
6366 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
6367 + (dtd->contentStringLen * sizeof(XML_Char)));
6369 ret = (XML_Content *)MALLOC(allocsize);
6370 if (!ret)
6371 return NULL;
6373 str = (XML_Char *) (&ret[dtd->scaffCount]);
6374 cpos = &ret[1];
6376 build_node(parser, 0, ret, &cpos, &str);
6377 return ret;
6380 static ELEMENT_TYPE *
6381 getElementType(XML_Parser parser,
6382 const ENCODING *enc,
6383 const char *ptr,
6384 const char *end)
6386 DTD * const dtd = _dtd; /* save one level of indirection */
6387 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
6388 ELEMENT_TYPE *ret;
6390 if (!name)
6391 return NULL;
6392 ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
6393 if (!ret)
6394 return NULL;
6395 if (ret->name != name)
6396 poolDiscard(&dtd->pool);
6397 else {
6398 poolFinish(&dtd->pool);
6399 if (!setElementTypePrefix(parser, ret))
6400 return NULL;
6402 return ret;