Added xmltok_impl.c and xmltok_ns.c to source files.
[mirror-ossqm-expat.git] / lib / xmlparse.c
blob449bd92f323aedcc704f8e1ab12a0652ad30ec7a
1 /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
2 See the file COPYING for copying permission.
3 */
5 #include <stddef.h>
6 #include <string.h> /* memset(), memcpy() */
7 #include <assert.h>
9 #define XML_BUILDING_EXPAT 1
11 #ifdef COMPILED_FROM_DSP
12 #include "winconfig.h"
13 #elif defined(MACOS_CLASSIC)
14 #include "macconfig.h"
15 #elif defined(__amigaos4__)
16 #include "amigaconfig.h"
17 #elif defined(__WATCOMC__)
18 #include "watcomconfig.h"
19 #elif defined(HAVE_EXPAT_CONFIG_H)
20 #include <expat_config.h>
21 #endif /* ndef COMPILED_FROM_DSP */
23 #include "expat.h"
25 #ifdef XML_UNICODE
26 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
27 #define XmlConvert XmlUtf16Convert
28 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
29 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
30 #define XmlEncode XmlUtf16Encode
31 /* Using pointer subtraction to convert to integer type. */
32 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
33 typedef unsigned short ICHAR;
34 #else
35 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
36 #define XmlConvert XmlUtf8Convert
37 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
38 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
39 #define XmlEncode XmlUtf8Encode
40 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
41 typedef char ICHAR;
42 #endif
45 #ifndef XML_NS
47 #define XmlInitEncodingNS XmlInitEncoding
48 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
49 #undef XmlGetInternalEncodingNS
50 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
51 #define XmlParseXmlDeclNS XmlParseXmlDecl
53 #endif
55 #ifdef XML_UNICODE
57 #ifdef XML_UNICODE_WCHAR_T
58 #define XML_T(x) (const wchar_t)x
59 #define XML_L(x) L ## x
60 #else
61 #define XML_T(x) (const unsigned short)x
62 #define XML_L(x) x
63 #endif
65 #else
67 #define XML_T(x) x
68 #define XML_L(x) x
70 #endif
72 /* Round up n to be a multiple of sz, where sz is a power of 2. */
73 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
75 /* Handle the case where memmove() doesn't exist. */
76 #ifndef HAVE_MEMMOVE
77 #ifdef HAVE_BCOPY
78 #define memmove(d,s,l) bcopy((s),(d),(l))
79 #else
80 #error memmove does not exist on this platform, nor is a substitute available
81 #endif /* HAVE_BCOPY */
82 #endif /* HAVE_MEMMOVE */
84 #include "internal.h"
85 #include "xmltok.h"
86 #include "xmlrole.h"
88 typedef const XML_Char *KEY;
90 typedef struct {
91 KEY name;
92 } NAMED;
94 typedef struct {
95 NAMED **v;
96 unsigned char power;
97 size_t size;
98 size_t used;
99 const XML_Memory_Handling_Suite *mem;
100 } HASH_TABLE;
102 /* Basic character hash algorithm, taken from Python's string hash:
103 h = h * 1000003 ^ character, the constant being a prime number.
106 #ifdef XML_UNICODE
107 #define CHAR_HASH(h, c) \
108 (((h) * 0xF4243) ^ (unsigned short)(c))
109 #else
110 #define CHAR_HASH(h, c) \
111 (((h) * 0xF4243) ^ (unsigned char)(c))
112 #endif
114 /* For probing (after a collision) we need a step size relative prime
115 to the hash table size, which is a power of 2. We use double-hashing,
116 since we can calculate a second hash value cheaply by taking those bits
117 of the first hash value that were discarded (masked out) when the table
118 index was calculated: index = hash & mask, where mask = table->size - 1.
119 We limit the maximum step size to table->size / 4 (mask >> 2) and make
120 it odd, since odd numbers are always relative prime to a power of 2.
122 #define SECOND_HASH(hash, mask, power) \
123 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
124 #define PROBE_STEP(hash, mask, power) \
125 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
127 typedef struct {
128 NAMED **p;
129 NAMED **end;
130 } HASH_TABLE_ITER;
132 #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
133 #define INIT_DATA_BUF_SIZE 1024
134 #define INIT_ATTS_SIZE 16
135 #define INIT_ATTS_VERSION 0xFFFFFFFF
136 #define INIT_BLOCK_SIZE 1024
137 #define INIT_BUFFER_SIZE 1024
139 #define EXPAND_SPARE 24
141 typedef struct binding {
142 struct prefix *prefix;
143 struct binding *nextTagBinding;
144 struct binding *prevPrefixBinding;
145 const struct attribute_id *attId;
146 XML_Char *uri;
147 int uriLen;
148 int uriAlloc;
149 } BINDING;
151 typedef struct prefix {
152 const XML_Char *name;
153 BINDING *binding;
154 } PREFIX;
156 typedef struct {
157 const XML_Char *str;
158 const XML_Char *localPart;
159 const XML_Char *prefix;
160 int strLen;
161 int uriLen;
162 int prefixLen;
163 } TAG_NAME;
165 /* TAG represents an open element.
166 The name of the element is stored in both the document and API
167 encodings. The memory buffer 'buf' is a separately-allocated
168 memory area which stores the name. During the XML_Parse()/
169 XMLParseBuffer() when the element is open, the memory for the 'raw'
170 version of the name (in the document encoding) is shared with the
171 document buffer. If the element is open across calls to
172 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
173 contain the 'raw' name as well.
175 A parser re-uses these structures, maintaining a list of allocated
176 TAG objects in a free list.
178 typedef struct tag {
179 struct tag *parent; /* parent of this element */
180 const char *rawName; /* tagName in the original encoding */
181 int rawNameLength;
182 TAG_NAME name; /* tagName in the API encoding */
183 char *buf; /* buffer for name components */
184 char *bufEnd; /* end of the buffer */
185 BINDING *bindings;
186 } TAG;
188 typedef struct {
189 const XML_Char *name;
190 const XML_Char *textPtr;
191 int textLen; /* length in XML_Chars */
192 int processed; /* # of processed bytes - when suspended */
193 const XML_Char *systemId;
194 const XML_Char *base;
195 const XML_Char *publicId;
196 const XML_Char *notation;
197 XML_Bool open;
198 XML_Bool is_param;
199 XML_Bool is_internal; /* true if declared in internal subset outside PE */
200 } ENTITY;
202 typedef struct {
203 enum XML_Content_Type type;
204 enum XML_Content_Quant quant;
205 const XML_Char * name;
206 int firstchild;
207 int lastchild;
208 int childcnt;
209 int nextsib;
210 } CONTENT_SCAFFOLD;
212 #define INIT_SCAFFOLD_ELEMENTS 32
214 typedef struct block {
215 struct block *next;
216 int size;
217 XML_Char s[1];
218 } BLOCK;
220 typedef struct {
221 BLOCK *blocks;
222 BLOCK *freeBlocks;
223 const XML_Char *end;
224 XML_Char *ptr;
225 XML_Char *start;
226 const XML_Memory_Handling_Suite *mem;
227 } STRING_POOL;
229 /* The XML_Char before the name is used to determine whether
230 an attribute has been specified. */
231 typedef struct attribute_id {
232 XML_Char *name;
233 PREFIX *prefix;
234 XML_Bool maybeTokenized;
235 XML_Bool xmlns;
236 } ATTRIBUTE_ID;
238 typedef struct {
239 const ATTRIBUTE_ID *id;
240 XML_Bool isCdata;
241 const XML_Char *value;
242 } DEFAULT_ATTRIBUTE;
244 typedef struct {
245 unsigned long version;
246 unsigned long hash;
247 const XML_Char *uriName;
248 } NS_ATT;
250 typedef struct {
251 const XML_Char *name;
252 PREFIX *prefix;
253 const ATTRIBUTE_ID *idAtt;
254 int nDefaultAtts;
255 int allocDefaultAtts;
256 DEFAULT_ATTRIBUTE *defaultAtts;
257 } ELEMENT_TYPE;
259 typedef struct {
260 HASH_TABLE generalEntities;
261 HASH_TABLE elementTypes;
262 HASH_TABLE attributeIds;
263 HASH_TABLE prefixes;
264 STRING_POOL pool;
265 STRING_POOL entityValuePool;
266 /* false once a parameter entity reference has been skipped */
267 XML_Bool keepProcessing;
268 /* true once an internal or external PE reference has been encountered;
269 this includes the reference to an external subset */
270 XML_Bool hasParamEntityRefs;
271 XML_Bool standalone;
272 #ifdef XML_DTD
273 /* indicates if external PE has been read */
274 XML_Bool paramEntityRead;
275 HASH_TABLE paramEntities;
276 #endif /* XML_DTD */
277 PREFIX defaultPrefix;
278 /* === scaffolding for building content model === */
279 XML_Bool in_eldecl;
280 CONTENT_SCAFFOLD *scaffold;
281 unsigned contentStringLen;
282 unsigned scaffSize;
283 unsigned scaffCount;
284 int scaffLevel;
285 int *scaffIndex;
286 } DTD;
288 typedef struct open_internal_entity {
289 const char *internalEventPtr;
290 const char *internalEventEndPtr;
291 struct open_internal_entity *next;
292 ENTITY *entity;
293 int startTagLevel;
294 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
295 } OPEN_INTERNAL_ENTITY;
297 typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
298 const char *start,
299 const char *end,
300 const char **endPtr);
302 static Processor prologProcessor;
303 static Processor prologInitProcessor;
304 static Processor contentProcessor;
305 static Processor cdataSectionProcessor;
306 #ifdef XML_DTD
307 static Processor ignoreSectionProcessor;
308 static Processor externalParEntProcessor;
309 static Processor externalParEntInitProcessor;
310 static Processor entityValueProcessor;
311 static Processor entityValueInitProcessor;
312 #endif /* XML_DTD */
313 static Processor epilogProcessor;
314 static Processor errorProcessor;
315 static Processor externalEntityInitProcessor;
316 static Processor externalEntityInitProcessor2;
317 static Processor externalEntityInitProcessor3;
318 static Processor externalEntityContentProcessor;
319 static Processor internalEntityProcessor;
321 static enum XML_Error
322 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
323 static enum XML_Error
324 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
325 const char *s, const char *next);
326 static enum XML_Error
327 initializeEncoding(XML_Parser parser);
328 static enum XML_Error
329 doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
330 const char *end, int tok, const char *next, const char **nextPtr,
331 XML_Bool haveMore);
332 static enum XML_Error
333 processInternalEntity(XML_Parser parser, ENTITY *entity,
334 XML_Bool betweenDecl);
335 static enum XML_Error
336 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
337 const char *start, const char *end, const char **endPtr,
338 XML_Bool haveMore);
339 static enum XML_Error
340 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
341 const char *end, const char **nextPtr, XML_Bool haveMore);
342 #ifdef XML_DTD
343 static enum XML_Error
344 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
345 const char *end, const char **nextPtr, XML_Bool haveMore);
346 #endif /* XML_DTD */
348 static enum XML_Error
349 storeAtts(XML_Parser parser, const ENCODING *, const char *s,
350 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
351 static enum XML_Error
352 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
353 const XML_Char *uri, BINDING **bindingsPtr);
354 static int
355 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
356 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
357 static enum XML_Error
358 storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
359 const char *, const char *, STRING_POOL *);
360 static enum XML_Error
361 appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
362 const char *, const char *, STRING_POOL *);
363 static ATTRIBUTE_ID *
364 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
365 const char *end);
366 static int
367 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
368 static enum XML_Error
369 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
370 const char *end);
371 static int
372 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
373 const char *start, const char *end);
374 static int
375 reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
376 const char *end);
377 static void
378 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
379 const char *end);
381 static const XML_Char * getContext(XML_Parser parser);
382 static XML_Bool
383 setContext(XML_Parser parser, const XML_Char *context);
385 static void FASTCALL normalizePublicId(XML_Char *s);
387 static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
388 /* do not call if parentParser != NULL */
389 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
390 static void
391 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
392 static int
393 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
394 static int
395 copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
397 static NAMED *
398 lookup(HASH_TABLE *table, KEY name, size_t createSize);
399 static void FASTCALL
400 hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
401 static void FASTCALL hashTableClear(HASH_TABLE *);
402 static void FASTCALL hashTableDestroy(HASH_TABLE *);
403 static void FASTCALL
404 hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
405 static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
407 static void FASTCALL
408 poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
409 static void FASTCALL poolClear(STRING_POOL *);
410 static void FASTCALL poolDestroy(STRING_POOL *);
411 static XML_Char *
412 poolAppend(STRING_POOL *pool, const ENCODING *enc,
413 const char *ptr, const char *end);
414 static XML_Char *
415 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
416 const char *ptr, const char *end);
417 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
418 static const XML_Char * FASTCALL
419 poolCopyString(STRING_POOL *pool, const XML_Char *s);
420 static const XML_Char *
421 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
422 static const XML_Char * FASTCALL
423 poolAppendString(STRING_POOL *pool, const XML_Char *s);
425 static int FASTCALL nextScaffoldPart(XML_Parser parser);
426 static XML_Content * build_model(XML_Parser parser);
427 static ELEMENT_TYPE *
428 getElementType(XML_Parser parser, const ENCODING *enc,
429 const char *ptr, const char *end);
431 static XML_Parser
432 parserCreate(const XML_Char *encodingName,
433 const XML_Memory_Handling_Suite *memsuite,
434 const XML_Char *nameSep,
435 DTD *dtd);
436 static void
437 parserInit(XML_Parser parser, const XML_Char *encodingName);
439 #define poolStart(pool) ((pool)->start)
440 #define poolEnd(pool) ((pool)->ptr)
441 #define poolLength(pool) ((pool)->ptr - (pool)->start)
442 #define poolChop(pool) ((void)--(pool->ptr))
443 #define poolLastChar(pool) (((pool)->ptr)[-1])
444 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
445 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
446 #define poolAppendChar(pool, c) \
447 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
448 ? 0 \
449 : ((*((pool)->ptr)++ = c), 1))
451 struct XML_ParserStruct {
452 /* The first member must be userData so that the XML_GetUserData
453 macro works. */
454 void *m_userData;
455 void *m_handlerArg;
456 char *m_buffer;
457 const XML_Memory_Handling_Suite m_mem;
458 /* first character to be parsed */
459 const char *m_bufferPtr;
460 /* past last character to be parsed */
461 char *m_bufferEnd;
462 /* allocated end of buffer */
463 const char *m_bufferLim;
464 XML_Index m_parseEndByteIndex;
465 const char *m_parseEndPtr;
466 XML_Char *m_dataBuf;
467 XML_Char *m_dataBufEnd;
468 XML_StartElementHandler m_startElementHandler;
469 XML_EndElementHandler m_endElementHandler;
470 XML_CharacterDataHandler m_characterDataHandler;
471 XML_ProcessingInstructionHandler m_processingInstructionHandler;
472 XML_CommentHandler m_commentHandler;
473 XML_StartCdataSectionHandler m_startCdataSectionHandler;
474 XML_EndCdataSectionHandler m_endCdataSectionHandler;
475 XML_DefaultHandler m_defaultHandler;
476 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
477 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
478 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
479 XML_NotationDeclHandler m_notationDeclHandler;
480 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
481 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
482 XML_NotStandaloneHandler m_notStandaloneHandler;
483 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
484 XML_Parser m_externalEntityRefHandlerArg;
485 XML_SkippedEntityHandler m_skippedEntityHandler;
486 XML_UnknownEncodingHandler m_unknownEncodingHandler;
487 XML_ElementDeclHandler m_elementDeclHandler;
488 XML_AttlistDeclHandler m_attlistDeclHandler;
489 XML_EntityDeclHandler m_entityDeclHandler;
490 XML_XmlDeclHandler m_xmlDeclHandler;
491 const ENCODING *m_encoding;
492 INIT_ENCODING m_initEncoding;
493 const ENCODING *m_internalEncoding;
494 const XML_Char *m_protocolEncodingName;
495 XML_Bool m_ns;
496 XML_Bool m_ns_triplets;
497 void *m_unknownEncodingMem;
498 void *m_unknownEncodingData;
499 void *m_unknownEncodingHandlerData;
500 void (XMLCALL *m_unknownEncodingRelease)(void *);
501 PROLOG_STATE m_prologState;
502 Processor *m_processor;
503 enum XML_Error m_errorCode;
504 const char *m_eventPtr;
505 const char *m_eventEndPtr;
506 const char *m_positionPtr;
507 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
508 OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
509 XML_Bool m_defaultExpandInternalEntities;
510 int m_tagLevel;
511 ENTITY *m_declEntity;
512 const XML_Char *m_doctypeName;
513 const XML_Char *m_doctypeSysid;
514 const XML_Char *m_doctypePubid;
515 const XML_Char *m_declAttributeType;
516 const XML_Char *m_declNotationName;
517 const XML_Char *m_declNotationPublicId;
518 ELEMENT_TYPE *m_declElementType;
519 ATTRIBUTE_ID *m_declAttributeId;
520 XML_Bool m_declAttributeIsCdata;
521 XML_Bool m_declAttributeIsId;
522 DTD *m_dtd;
523 const XML_Char *m_curBase;
524 TAG *m_tagStack;
525 TAG *m_freeTagList;
526 BINDING *m_inheritedBindings;
527 BINDING *m_freeBindingList;
528 int m_attsSize;
529 int m_nSpecifiedAtts;
530 int m_idAttIndex;
531 ATTRIBUTE *m_atts;
532 NS_ATT *m_nsAtts;
533 unsigned long m_nsAttsVersion;
534 unsigned char m_nsAttsPower;
535 POSITION m_position;
536 STRING_POOL m_tempPool;
537 STRING_POOL m_temp2Pool;
538 char *m_groupConnector;
539 unsigned int m_groupSize;
540 XML_Char m_namespaceSeparator;
541 XML_Parser m_parentParser;
542 XML_ParsingStatus m_parsingStatus;
543 #ifdef XML_DTD
544 XML_Bool m_isParamEntity;
545 XML_Bool m_useForeignDTD;
546 enum XML_ParamEntityParsing m_paramEntityParsing;
547 #endif
550 #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
551 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
552 #define FREE(p) (parser->m_mem.free_fcn((p)))
554 #define userData (parser->m_userData)
555 #define handlerArg (parser->m_handlerArg)
556 #define startElementHandler (parser->m_startElementHandler)
557 #define endElementHandler (parser->m_endElementHandler)
558 #define characterDataHandler (parser->m_characterDataHandler)
559 #define processingInstructionHandler \
560 (parser->m_processingInstructionHandler)
561 #define commentHandler (parser->m_commentHandler)
562 #define startCdataSectionHandler \
563 (parser->m_startCdataSectionHandler)
564 #define endCdataSectionHandler (parser->m_endCdataSectionHandler)
565 #define defaultHandler (parser->m_defaultHandler)
566 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
567 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
568 #define unparsedEntityDeclHandler \
569 (parser->m_unparsedEntityDeclHandler)
570 #define notationDeclHandler (parser->m_notationDeclHandler)
571 #define startNamespaceDeclHandler \
572 (parser->m_startNamespaceDeclHandler)
573 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
574 #define notStandaloneHandler (parser->m_notStandaloneHandler)
575 #define externalEntityRefHandler \
576 (parser->m_externalEntityRefHandler)
577 #define externalEntityRefHandlerArg \
578 (parser->m_externalEntityRefHandlerArg)
579 #define internalEntityRefHandler \
580 (parser->m_internalEntityRefHandler)
581 #define skippedEntityHandler (parser->m_skippedEntityHandler)
582 #define unknownEncodingHandler (parser->m_unknownEncodingHandler)
583 #define elementDeclHandler (parser->m_elementDeclHandler)
584 #define attlistDeclHandler (parser->m_attlistDeclHandler)
585 #define entityDeclHandler (parser->m_entityDeclHandler)
586 #define xmlDeclHandler (parser->m_xmlDeclHandler)
587 #define encoding (parser->m_encoding)
588 #define initEncoding (parser->m_initEncoding)
589 #define internalEncoding (parser->m_internalEncoding)
590 #define unknownEncodingMem (parser->m_unknownEncodingMem)
591 #define unknownEncodingData (parser->m_unknownEncodingData)
592 #define unknownEncodingHandlerData \
593 (parser->m_unknownEncodingHandlerData)
594 #define unknownEncodingRelease (parser->m_unknownEncodingRelease)
595 #define protocolEncodingName (parser->m_protocolEncodingName)
596 #define ns (parser->m_ns)
597 #define ns_triplets (parser->m_ns_triplets)
598 #define prologState (parser->m_prologState)
599 #define processor (parser->m_processor)
600 #define errorCode (parser->m_errorCode)
601 #define eventPtr (parser->m_eventPtr)
602 #define eventEndPtr (parser->m_eventEndPtr)
603 #define positionPtr (parser->m_positionPtr)
604 #define position (parser->m_position)
605 #define openInternalEntities (parser->m_openInternalEntities)
606 #define freeInternalEntities (parser->m_freeInternalEntities)
607 #define defaultExpandInternalEntities \
608 (parser->m_defaultExpandInternalEntities)
609 #define tagLevel (parser->m_tagLevel)
610 #define buffer (parser->m_buffer)
611 #define bufferPtr (parser->m_bufferPtr)
612 #define bufferEnd (parser->m_bufferEnd)
613 #define parseEndByteIndex (parser->m_parseEndByteIndex)
614 #define parseEndPtr (parser->m_parseEndPtr)
615 #define bufferLim (parser->m_bufferLim)
616 #define dataBuf (parser->m_dataBuf)
617 #define dataBufEnd (parser->m_dataBufEnd)
618 #define _dtd (parser->m_dtd)
619 #define curBase (parser->m_curBase)
620 #define declEntity (parser->m_declEntity)
621 #define doctypeName (parser->m_doctypeName)
622 #define doctypeSysid (parser->m_doctypeSysid)
623 #define doctypePubid (parser->m_doctypePubid)
624 #define declAttributeType (parser->m_declAttributeType)
625 #define declNotationName (parser->m_declNotationName)
626 #define declNotationPublicId (parser->m_declNotationPublicId)
627 #define declElementType (parser->m_declElementType)
628 #define declAttributeId (parser->m_declAttributeId)
629 #define declAttributeIsCdata (parser->m_declAttributeIsCdata)
630 #define declAttributeIsId (parser->m_declAttributeIsId)
631 #define freeTagList (parser->m_freeTagList)
632 #define freeBindingList (parser->m_freeBindingList)
633 #define inheritedBindings (parser->m_inheritedBindings)
634 #define tagStack (parser->m_tagStack)
635 #define atts (parser->m_atts)
636 #define attsSize (parser->m_attsSize)
637 #define nSpecifiedAtts (parser->m_nSpecifiedAtts)
638 #define idAttIndex (parser->m_idAttIndex)
639 #define nsAtts (parser->m_nsAtts)
640 #define nsAttsVersion (parser->m_nsAttsVersion)
641 #define nsAttsPower (parser->m_nsAttsPower)
642 #define tempPool (parser->m_tempPool)
643 #define temp2Pool (parser->m_temp2Pool)
644 #define groupConnector (parser->m_groupConnector)
645 #define groupSize (parser->m_groupSize)
646 #define namespaceSeparator (parser->m_namespaceSeparator)
647 #define parentParser (parser->m_parentParser)
648 #define ps_parsing (parser->m_parsingStatus.parsing)
649 #define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
650 #ifdef XML_DTD
651 #define isParamEntity (parser->m_isParamEntity)
652 #define useForeignDTD (parser->m_useForeignDTD)
653 #define paramEntityParsing (parser->m_paramEntityParsing)
654 #endif /* XML_DTD */
656 XML_Parser XMLCALL
657 XML_ParserCreate(const XML_Char *encodingName)
659 return XML_ParserCreate_MM(encodingName, NULL, NULL);
662 XML_Parser XMLCALL
663 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
665 XML_Char tmp[2];
666 *tmp = nsSep;
667 return XML_ParserCreate_MM(encodingName, NULL, tmp);
670 static const XML_Char implicitContext[] = {
671 'x', 'm', 'l', '=', 'h', 't', 't', 'p', ':', '/', '/',
672 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
673 'X', 'M', 'L', '/', '1', '9', '9', '8', '/',
674 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0'
677 XML_Parser XMLCALL
678 XML_ParserCreate_MM(const XML_Char *encodingName,
679 const XML_Memory_Handling_Suite *memsuite,
680 const XML_Char *nameSep)
682 XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL);
683 if (parser != NULL && ns) {
684 /* implicit context only set for root parser, since child
685 parsers (i.e. external entity parsers) will inherit it
687 if (!setContext(parser, implicitContext)) {
688 XML_ParserFree(parser);
689 return NULL;
692 return parser;
695 static XML_Parser
696 parserCreate(const XML_Char *encodingName,
697 const XML_Memory_Handling_Suite *memsuite,
698 const XML_Char *nameSep,
699 DTD *dtd)
701 XML_Parser parser;
703 if (memsuite) {
704 XML_Memory_Handling_Suite *mtemp;
705 parser = (XML_Parser)
706 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
707 if (parser != NULL) {
708 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
709 mtemp->malloc_fcn = memsuite->malloc_fcn;
710 mtemp->realloc_fcn = memsuite->realloc_fcn;
711 mtemp->free_fcn = memsuite->free_fcn;
714 else {
715 XML_Memory_Handling_Suite *mtemp;
716 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
717 if (parser != NULL) {
718 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
719 mtemp->malloc_fcn = malloc;
720 mtemp->realloc_fcn = realloc;
721 mtemp->free_fcn = free;
725 if (!parser)
726 return parser;
728 buffer = NULL;
729 bufferLim = NULL;
731 attsSize = INIT_ATTS_SIZE;
732 atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
733 if (atts == NULL) {
734 FREE(parser);
735 return NULL;
737 dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
738 if (dataBuf == NULL) {
739 FREE(atts);
740 FREE(parser);
741 return NULL;
743 dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
745 if (dtd)
746 _dtd = dtd;
747 else {
748 _dtd = dtdCreate(&parser->m_mem);
749 if (_dtd == NULL) {
750 FREE(dataBuf);
751 FREE(atts);
752 FREE(parser);
753 return NULL;
757 freeBindingList = NULL;
758 freeTagList = NULL;
759 freeInternalEntities = NULL;
761 groupSize = 0;
762 groupConnector = NULL;
764 unknownEncodingHandler = NULL;
765 unknownEncodingHandlerData = NULL;
767 namespaceSeparator = '!';
768 ns = XML_FALSE;
769 ns_triplets = XML_FALSE;
771 nsAtts = NULL;
772 nsAttsVersion = 0;
773 nsAttsPower = 0;
775 poolInit(&tempPool, &(parser->m_mem));
776 poolInit(&temp2Pool, &(parser->m_mem));
777 parserInit(parser, encodingName);
779 if (encodingName && !protocolEncodingName) {
780 XML_ParserFree(parser);
781 return NULL;
784 if (nameSep) {
785 ns = XML_TRUE;
786 internalEncoding = XmlGetInternalEncodingNS();
787 namespaceSeparator = *nameSep;
789 else {
790 internalEncoding = XmlGetInternalEncoding();
793 return parser;
796 static void
797 parserInit(XML_Parser parser, const XML_Char *encodingName)
799 processor = prologInitProcessor;
800 XmlPrologStateInit(&prologState);
801 protocolEncodingName = (encodingName != NULL
802 ? poolCopyString(&tempPool, encodingName)
803 : NULL);
804 curBase = NULL;
805 XmlInitEncoding(&initEncoding, &encoding, 0);
806 userData = NULL;
807 handlerArg = NULL;
808 startElementHandler = NULL;
809 endElementHandler = NULL;
810 characterDataHandler = NULL;
811 processingInstructionHandler = NULL;
812 commentHandler = NULL;
813 startCdataSectionHandler = NULL;
814 endCdataSectionHandler = NULL;
815 defaultHandler = NULL;
816 startDoctypeDeclHandler = NULL;
817 endDoctypeDeclHandler = NULL;
818 unparsedEntityDeclHandler = NULL;
819 notationDeclHandler = NULL;
820 startNamespaceDeclHandler = NULL;
821 endNamespaceDeclHandler = NULL;
822 notStandaloneHandler = NULL;
823 externalEntityRefHandler = NULL;
824 externalEntityRefHandlerArg = parser;
825 skippedEntityHandler = NULL;
826 elementDeclHandler = NULL;
827 attlistDeclHandler = NULL;
828 entityDeclHandler = NULL;
829 xmlDeclHandler = NULL;
830 bufferPtr = buffer;
831 bufferEnd = buffer;
832 parseEndByteIndex = 0;
833 parseEndPtr = NULL;
834 declElementType = NULL;
835 declAttributeId = NULL;
836 declEntity = NULL;
837 doctypeName = NULL;
838 doctypeSysid = NULL;
839 doctypePubid = NULL;
840 declAttributeType = NULL;
841 declNotationName = NULL;
842 declNotationPublicId = NULL;
843 declAttributeIsCdata = XML_FALSE;
844 declAttributeIsId = XML_FALSE;
845 memset(&position, 0, sizeof(POSITION));
846 errorCode = XML_ERROR_NONE;
847 eventPtr = NULL;
848 eventEndPtr = NULL;
849 positionPtr = NULL;
850 openInternalEntities = NULL;
851 defaultExpandInternalEntities = XML_TRUE;
852 tagLevel = 0;
853 tagStack = NULL;
854 inheritedBindings = NULL;
855 nSpecifiedAtts = 0;
856 unknownEncodingMem = NULL;
857 unknownEncodingRelease = NULL;
858 unknownEncodingData = NULL;
859 parentParser = NULL;
860 ps_parsing = XML_INITIALIZED;
861 #ifdef XML_DTD
862 isParamEntity = XML_FALSE;
863 useForeignDTD = XML_FALSE;
864 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
865 #endif
868 /* moves list of bindings to freeBindingList */
869 static void FASTCALL
870 moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
872 while (bindings) {
873 BINDING *b = bindings;
874 bindings = bindings->nextTagBinding;
875 b->nextTagBinding = freeBindingList;
876 freeBindingList = b;
880 XML_Bool XMLCALL
881 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
883 TAG *tStk;
884 OPEN_INTERNAL_ENTITY *openEntityList;
885 if (parentParser)
886 return XML_FALSE;
887 /* move tagStack to freeTagList */
888 tStk = tagStack;
889 while (tStk) {
890 TAG *tag = tStk;
891 tStk = tStk->parent;
892 tag->parent = freeTagList;
893 moveToFreeBindingList(parser, tag->bindings);
894 tag->bindings = NULL;
895 freeTagList = tag;
897 /* move openInternalEntities to freeInternalEntities */
898 openEntityList = openInternalEntities;
899 while (openEntityList) {
900 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
901 openEntityList = openEntity->next;
902 openEntity->next = freeInternalEntities;
903 freeInternalEntities = openEntity;
905 moveToFreeBindingList(parser, inheritedBindings);
906 FREE(unknownEncodingMem);
907 if (unknownEncodingRelease)
908 unknownEncodingRelease(unknownEncodingData);
909 poolClear(&tempPool);
910 poolClear(&temp2Pool);
911 parserInit(parser, encodingName);
912 dtdReset(_dtd, &parser->m_mem);
913 return setContext(parser, implicitContext);
916 enum XML_Status XMLCALL
917 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
919 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
920 XXX There's no way for the caller to determine which of the
921 XXX possible error cases caused the XML_STATUS_ERROR return.
923 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
924 return XML_STATUS_ERROR;
925 if (encodingName == NULL)
926 protocolEncodingName = NULL;
927 else {
928 protocolEncodingName = poolCopyString(&tempPool, encodingName);
929 if (!protocolEncodingName)
930 return XML_STATUS_ERROR;
932 return XML_STATUS_OK;
935 XML_Parser XMLCALL
936 XML_ExternalEntityParserCreate(XML_Parser oldParser,
937 const XML_Char *context,
938 const XML_Char *encodingName)
940 XML_Parser parser = oldParser;
941 DTD *newDtd = NULL;
942 DTD *oldDtd = _dtd;
943 XML_StartElementHandler oldStartElementHandler = startElementHandler;
944 XML_EndElementHandler oldEndElementHandler = endElementHandler;
945 XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
946 XML_ProcessingInstructionHandler oldProcessingInstructionHandler
947 = processingInstructionHandler;
948 XML_CommentHandler oldCommentHandler = commentHandler;
949 XML_StartCdataSectionHandler oldStartCdataSectionHandler
950 = startCdataSectionHandler;
951 XML_EndCdataSectionHandler oldEndCdataSectionHandler
952 = endCdataSectionHandler;
953 XML_DefaultHandler oldDefaultHandler = defaultHandler;
954 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
955 = unparsedEntityDeclHandler;
956 XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
957 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
958 = startNamespaceDeclHandler;
959 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
960 = endNamespaceDeclHandler;
961 XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
962 XML_ExternalEntityRefHandler oldExternalEntityRefHandler
963 = externalEntityRefHandler;
964 XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
965 XML_UnknownEncodingHandler oldUnknownEncodingHandler
966 = unknownEncodingHandler;
967 XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
968 XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
969 XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
970 XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
971 ELEMENT_TYPE * oldDeclElementType = declElementType;
973 void *oldUserData = userData;
974 void *oldHandlerArg = handlerArg;
975 XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
976 XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
977 #ifdef XML_DTD
978 enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
979 int oldInEntityValue = prologState.inEntityValue;
980 #endif
981 XML_Bool oldns_triplets = ns_triplets;
983 #ifdef XML_DTD
984 if (!context)
985 newDtd = oldDtd;
986 #endif /* XML_DTD */
988 /* Note that the magical uses of the pre-processor to make field
989 access look more like C++ require that `parser' be overwritten
990 here. This makes this function more painful to follow than it
991 would be otherwise.
993 if (ns) {
994 XML_Char tmp[2];
995 *tmp = namespaceSeparator;
996 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
998 else {
999 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1002 if (!parser)
1003 return NULL;
1005 startElementHandler = oldStartElementHandler;
1006 endElementHandler = oldEndElementHandler;
1007 characterDataHandler = oldCharacterDataHandler;
1008 processingInstructionHandler = oldProcessingInstructionHandler;
1009 commentHandler = oldCommentHandler;
1010 startCdataSectionHandler = oldStartCdataSectionHandler;
1011 endCdataSectionHandler = oldEndCdataSectionHandler;
1012 defaultHandler = oldDefaultHandler;
1013 unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1014 notationDeclHandler = oldNotationDeclHandler;
1015 startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1016 endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1017 notStandaloneHandler = oldNotStandaloneHandler;
1018 externalEntityRefHandler = oldExternalEntityRefHandler;
1019 skippedEntityHandler = oldSkippedEntityHandler;
1020 unknownEncodingHandler = oldUnknownEncodingHandler;
1021 elementDeclHandler = oldElementDeclHandler;
1022 attlistDeclHandler = oldAttlistDeclHandler;
1023 entityDeclHandler = oldEntityDeclHandler;
1024 xmlDeclHandler = oldXmlDeclHandler;
1025 declElementType = oldDeclElementType;
1026 userData = oldUserData;
1027 if (oldUserData == oldHandlerArg)
1028 handlerArg = userData;
1029 else
1030 handlerArg = parser;
1031 if (oldExternalEntityRefHandlerArg != oldParser)
1032 externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1033 defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1034 ns_triplets = oldns_triplets;
1035 parentParser = oldParser;
1036 #ifdef XML_DTD
1037 paramEntityParsing = oldParamEntityParsing;
1038 prologState.inEntityValue = oldInEntityValue;
1039 if (context) {
1040 #endif /* XML_DTD */
1041 if (!dtdCopy(_dtd, oldDtd, &parser->m_mem)
1042 || !setContext(parser, context)) {
1043 XML_ParserFree(parser);
1044 return NULL;
1046 processor = externalEntityInitProcessor;
1047 #ifdef XML_DTD
1049 else {
1050 /* The DTD instance referenced by _dtd is shared between the document's
1051 root parser and external PE parsers, therefore one does not need to
1052 call setContext. In addition, one also *must* not call setContext,
1053 because this would overwrite existing prefix->binding pointers in
1054 _dtd with ones that get destroyed with the external PE parser.
1055 This would leave those prefixes with dangling pointers.
1057 isParamEntity = XML_TRUE;
1058 XmlPrologStateInitExternalEntity(&prologState);
1059 processor = externalParEntInitProcessor;
1061 #endif /* XML_DTD */
1062 return parser;
1065 static void FASTCALL
1066 destroyBindings(BINDING *bindings, XML_Parser parser)
1068 for (;;) {
1069 BINDING *b = bindings;
1070 if (!b)
1071 break;
1072 bindings = b->nextTagBinding;
1073 FREE(b->uri);
1074 FREE(b);
1078 void XMLCALL
1079 XML_ParserFree(XML_Parser parser)
1081 TAG *tagList;
1082 OPEN_INTERNAL_ENTITY *entityList;
1083 if (parser == NULL)
1084 return;
1085 /* free tagStack and freeTagList */
1086 tagList = tagStack;
1087 for (;;) {
1088 TAG *p;
1089 if (tagList == NULL) {
1090 if (freeTagList == NULL)
1091 break;
1092 tagList = freeTagList;
1093 freeTagList = NULL;
1095 p = tagList;
1096 tagList = tagList->parent;
1097 FREE(p->buf);
1098 destroyBindings(p->bindings, parser);
1099 FREE(p);
1101 /* free openInternalEntities and freeInternalEntities */
1102 entityList = openInternalEntities;
1103 for (;;) {
1104 OPEN_INTERNAL_ENTITY *openEntity;
1105 if (entityList == NULL) {
1106 if (freeInternalEntities == NULL)
1107 break;
1108 entityList = freeInternalEntities;
1109 freeInternalEntities = NULL;
1111 openEntity = entityList;
1112 entityList = entityList->next;
1113 FREE(openEntity);
1116 destroyBindings(freeBindingList, parser);
1117 destroyBindings(inheritedBindings, parser);
1118 poolDestroy(&tempPool);
1119 poolDestroy(&temp2Pool);
1120 #ifdef XML_DTD
1121 /* external parameter entity parsers share the DTD structure
1122 parser->m_dtd with the root parser, so we must not destroy it
1124 if (!isParamEntity && _dtd)
1125 #else
1126 if (_dtd)
1127 #endif /* XML_DTD */
1128 dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
1129 FREE((void *)atts);
1130 FREE(groupConnector);
1131 FREE(buffer);
1132 FREE(dataBuf);
1133 FREE(nsAtts);
1134 FREE(unknownEncodingMem);
1135 if (unknownEncodingRelease)
1136 unknownEncodingRelease(unknownEncodingData);
1137 FREE(parser);
1140 void XMLCALL
1141 XML_UseParserAsHandlerArg(XML_Parser parser)
1143 handlerArg = parser;
1146 enum XML_Error XMLCALL
1147 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
1149 #ifdef XML_DTD
1150 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1151 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1152 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
1153 useForeignDTD = useDTD;
1154 return XML_ERROR_NONE;
1155 #else
1156 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1157 #endif
1160 void XMLCALL
1161 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
1163 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1164 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1165 return;
1166 ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
1169 void XMLCALL
1170 XML_SetUserData(XML_Parser parser, void *p)
1172 if (handlerArg == userData)
1173 handlerArg = userData = p;
1174 else
1175 userData = p;
1178 enum XML_Status XMLCALL
1179 XML_SetBase(XML_Parser parser, const XML_Char *p)
1181 if (p) {
1182 p = poolCopyString(&_dtd->pool, p);
1183 if (!p)
1184 return XML_STATUS_ERROR;
1185 curBase = p;
1187 else
1188 curBase = NULL;
1189 return XML_STATUS_OK;
1192 const XML_Char * XMLCALL
1193 XML_GetBase(XML_Parser parser)
1195 return curBase;
1198 int XMLCALL
1199 XML_GetSpecifiedAttributeCount(XML_Parser parser)
1201 return nSpecifiedAtts;
1204 int XMLCALL
1205 XML_GetIdAttributeIndex(XML_Parser parser)
1207 return idAttIndex;
1210 void XMLCALL
1211 XML_SetElementHandler(XML_Parser parser,
1212 XML_StartElementHandler start,
1213 XML_EndElementHandler end)
1215 startElementHandler = start;
1216 endElementHandler = end;
1219 void XMLCALL
1220 XML_SetStartElementHandler(XML_Parser parser,
1221 XML_StartElementHandler start) {
1222 startElementHandler = start;
1225 void XMLCALL
1226 XML_SetEndElementHandler(XML_Parser parser,
1227 XML_EndElementHandler end) {
1228 endElementHandler = end;
1231 void XMLCALL
1232 XML_SetCharacterDataHandler(XML_Parser parser,
1233 XML_CharacterDataHandler handler)
1235 characterDataHandler = handler;
1238 void XMLCALL
1239 XML_SetProcessingInstructionHandler(XML_Parser parser,
1240 XML_ProcessingInstructionHandler handler)
1242 processingInstructionHandler = handler;
1245 void XMLCALL
1246 XML_SetCommentHandler(XML_Parser parser,
1247 XML_CommentHandler handler)
1249 commentHandler = handler;
1252 void XMLCALL
1253 XML_SetCdataSectionHandler(XML_Parser parser,
1254 XML_StartCdataSectionHandler start,
1255 XML_EndCdataSectionHandler end)
1257 startCdataSectionHandler = start;
1258 endCdataSectionHandler = end;
1261 void XMLCALL
1262 XML_SetStartCdataSectionHandler(XML_Parser parser,
1263 XML_StartCdataSectionHandler start) {
1264 startCdataSectionHandler = start;
1267 void XMLCALL
1268 XML_SetEndCdataSectionHandler(XML_Parser parser,
1269 XML_EndCdataSectionHandler end) {
1270 endCdataSectionHandler = end;
1273 void XMLCALL
1274 XML_SetDefaultHandler(XML_Parser parser,
1275 XML_DefaultHandler handler)
1277 defaultHandler = handler;
1278 defaultExpandInternalEntities = XML_FALSE;
1281 void XMLCALL
1282 XML_SetDefaultHandlerExpand(XML_Parser parser,
1283 XML_DefaultHandler handler)
1285 defaultHandler = handler;
1286 defaultExpandInternalEntities = XML_TRUE;
1289 void XMLCALL
1290 XML_SetDoctypeDeclHandler(XML_Parser parser,
1291 XML_StartDoctypeDeclHandler start,
1292 XML_EndDoctypeDeclHandler end)
1294 startDoctypeDeclHandler = start;
1295 endDoctypeDeclHandler = end;
1298 void XMLCALL
1299 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1300 XML_StartDoctypeDeclHandler start) {
1301 startDoctypeDeclHandler = start;
1304 void XMLCALL
1305 XML_SetEndDoctypeDeclHandler(XML_Parser parser,
1306 XML_EndDoctypeDeclHandler end) {
1307 endDoctypeDeclHandler = end;
1310 void XMLCALL
1311 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1312 XML_UnparsedEntityDeclHandler handler)
1314 unparsedEntityDeclHandler = handler;
1317 void XMLCALL
1318 XML_SetNotationDeclHandler(XML_Parser parser,
1319 XML_NotationDeclHandler handler)
1321 notationDeclHandler = handler;
1324 void XMLCALL
1325 XML_SetNamespaceDeclHandler(XML_Parser parser,
1326 XML_StartNamespaceDeclHandler start,
1327 XML_EndNamespaceDeclHandler end)
1329 startNamespaceDeclHandler = start;
1330 endNamespaceDeclHandler = end;
1333 void XMLCALL
1334 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1335 XML_StartNamespaceDeclHandler start) {
1336 startNamespaceDeclHandler = start;
1339 void XMLCALL
1340 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1341 XML_EndNamespaceDeclHandler end) {
1342 endNamespaceDeclHandler = end;
1345 void XMLCALL
1346 XML_SetNotStandaloneHandler(XML_Parser parser,
1347 XML_NotStandaloneHandler handler)
1349 notStandaloneHandler = handler;
1352 void XMLCALL
1353 XML_SetExternalEntityRefHandler(XML_Parser parser,
1354 XML_ExternalEntityRefHandler handler)
1356 externalEntityRefHandler = handler;
1359 void XMLCALL
1360 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
1362 if (arg)
1363 externalEntityRefHandlerArg = (XML_Parser)arg;
1364 else
1365 externalEntityRefHandlerArg = parser;
1368 void XMLCALL
1369 XML_SetSkippedEntityHandler(XML_Parser parser,
1370 XML_SkippedEntityHandler handler)
1372 skippedEntityHandler = handler;
1375 void XMLCALL
1376 XML_SetUnknownEncodingHandler(XML_Parser parser,
1377 XML_UnknownEncodingHandler handler,
1378 void *data)
1380 unknownEncodingHandler = handler;
1381 unknownEncodingHandlerData = data;
1384 void XMLCALL
1385 XML_SetElementDeclHandler(XML_Parser parser,
1386 XML_ElementDeclHandler eldecl)
1388 elementDeclHandler = eldecl;
1391 void XMLCALL
1392 XML_SetAttlistDeclHandler(XML_Parser parser,
1393 XML_AttlistDeclHandler attdecl)
1395 attlistDeclHandler = attdecl;
1398 void XMLCALL
1399 XML_SetEntityDeclHandler(XML_Parser parser,
1400 XML_EntityDeclHandler handler)
1402 entityDeclHandler = handler;
1405 void XMLCALL
1406 XML_SetXmlDeclHandler(XML_Parser parser,
1407 XML_XmlDeclHandler handler) {
1408 xmlDeclHandler = handler;
1411 int XMLCALL
1412 XML_SetParamEntityParsing(XML_Parser parser,
1413 enum XML_ParamEntityParsing peParsing)
1415 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1416 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1417 return 0;
1418 #ifdef XML_DTD
1419 paramEntityParsing = peParsing;
1420 return 1;
1421 #else
1422 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1423 #endif
1426 enum XML_Status XMLCALL
1427 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
1429 switch (ps_parsing) {
1430 case XML_SUSPENDED:
1431 errorCode = XML_ERROR_SUSPENDED;
1432 return XML_STATUS_ERROR;
1433 case XML_FINISHED:
1434 errorCode = XML_ERROR_FINISHED;
1435 return XML_STATUS_ERROR;
1436 default:
1437 ps_parsing = XML_PARSING;
1440 if (len == 0) {
1441 ps_finalBuffer = (XML_Bool)isFinal;
1442 if (!isFinal)
1443 return XML_STATUS_OK;
1444 positionPtr = bufferPtr;
1445 parseEndPtr = bufferEnd;
1447 /* If data are left over from last buffer, and we now know that these
1448 data are the final chunk of input, then we have to check them again
1449 to detect errors based on that fact.
1451 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
1453 if (errorCode == XML_ERROR_NONE) {
1454 switch (ps_parsing) {
1455 case XML_SUSPENDED:
1456 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1457 positionPtr = bufferPtr;
1458 return XML_STATUS_SUSPENDED;
1459 case XML_INITIALIZED:
1460 case XML_PARSING:
1461 ps_parsing = XML_FINISHED;
1462 /* fall through */
1463 default:
1464 return XML_STATUS_OK;
1467 eventEndPtr = eventPtr;
1468 processor = errorProcessor;
1469 return XML_STATUS_ERROR;
1471 #ifndef XML_CONTEXT_BYTES
1472 else if (bufferPtr == bufferEnd) {
1473 const char *end;
1474 int nLeftOver;
1475 enum XML_Error result;
1476 parseEndByteIndex += len;
1477 positionPtr = s;
1478 ps_finalBuffer = (XML_Bool)isFinal;
1480 errorCode = processor(parser, s, parseEndPtr = s + len, &end);
1482 if (errorCode != XML_ERROR_NONE) {
1483 eventEndPtr = eventPtr;
1484 processor = errorProcessor;
1485 return XML_STATUS_ERROR;
1487 else {
1488 switch (ps_parsing) {
1489 case XML_SUSPENDED:
1490 result = XML_STATUS_SUSPENDED;
1491 break;
1492 case XML_INITIALIZED:
1493 case XML_PARSING:
1494 result = XML_STATUS_OK;
1495 if (isFinal) {
1496 ps_parsing = XML_FINISHED;
1497 return result;
1502 XmlUpdatePosition(encoding, positionPtr, end, &position);
1503 nLeftOver = s + len - end;
1504 if (nLeftOver) {
1505 if (buffer == NULL || nLeftOver > bufferLim - buffer) {
1506 /* FIXME avoid integer overflow */
1507 char *temp;
1508 temp = (buffer == NULL
1509 ? (char *)MALLOC(len * 2)
1510 : (char *)REALLOC(buffer, len * 2));
1511 if (temp == NULL) {
1512 errorCode = XML_ERROR_NO_MEMORY;
1513 return XML_STATUS_ERROR;
1515 buffer = temp;
1516 if (!buffer) {
1517 errorCode = XML_ERROR_NO_MEMORY;
1518 eventPtr = eventEndPtr = NULL;
1519 processor = errorProcessor;
1520 return XML_STATUS_ERROR;
1522 bufferLim = buffer + len * 2;
1524 memcpy(buffer, end, nLeftOver);
1526 bufferPtr = buffer;
1527 bufferEnd = buffer + nLeftOver;
1528 positionPtr = bufferPtr;
1529 parseEndPtr = bufferEnd;
1530 eventPtr = bufferPtr;
1531 eventEndPtr = bufferPtr;
1532 return result;
1534 #endif /* not defined XML_CONTEXT_BYTES */
1535 else {
1536 void *buff = XML_GetBuffer(parser, len);
1537 if (buff == NULL)
1538 return XML_STATUS_ERROR;
1539 else {
1540 memcpy(buff, s, len);
1541 return XML_ParseBuffer(parser, len, isFinal);
1546 enum XML_Status XMLCALL
1547 XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
1549 const char *start;
1550 enum XML_Status result = XML_STATUS_OK;
1552 switch (ps_parsing) {
1553 case XML_SUSPENDED:
1554 errorCode = XML_ERROR_SUSPENDED;
1555 return XML_STATUS_ERROR;
1556 case XML_FINISHED:
1557 errorCode = XML_ERROR_FINISHED;
1558 return XML_STATUS_ERROR;
1559 default:
1560 ps_parsing = XML_PARSING;
1563 start = bufferPtr;
1564 positionPtr = start;
1565 bufferEnd += len;
1566 parseEndPtr = bufferEnd;
1567 parseEndByteIndex += len;
1568 ps_finalBuffer = (XML_Bool)isFinal;
1570 errorCode = processor(parser, start, parseEndPtr, &bufferPtr);
1572 if (errorCode != XML_ERROR_NONE) {
1573 eventEndPtr = eventPtr;
1574 processor = errorProcessor;
1575 return XML_STATUS_ERROR;
1577 else {
1578 switch (ps_parsing) {
1579 case XML_SUSPENDED:
1580 result = XML_STATUS_SUSPENDED;
1581 break;
1582 case XML_INITIALIZED:
1583 case XML_PARSING:
1584 if (isFinal) {
1585 ps_parsing = XML_FINISHED;
1586 return result;
1588 default: ; /* should not happen */
1592 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1593 positionPtr = bufferPtr;
1594 return result;
1597 void * XMLCALL
1598 XML_GetBuffer(XML_Parser parser, int len)
1600 switch (ps_parsing) {
1601 case XML_SUSPENDED:
1602 errorCode = XML_ERROR_SUSPENDED;
1603 return NULL;
1604 case XML_FINISHED:
1605 errorCode = XML_ERROR_FINISHED;
1606 return NULL;
1607 default: ;
1610 if (len > bufferLim - bufferEnd) {
1611 /* FIXME avoid integer overflow */
1612 int neededSize = len + (int)(bufferEnd - bufferPtr);
1613 #ifdef XML_CONTEXT_BYTES
1614 int keep = (int)(bufferPtr - buffer);
1616 if (keep > XML_CONTEXT_BYTES)
1617 keep = XML_CONTEXT_BYTES;
1618 neededSize += keep;
1619 #endif /* defined XML_CONTEXT_BYTES */
1620 if (neededSize <= bufferLim - buffer) {
1621 #ifdef XML_CONTEXT_BYTES
1622 if (keep < bufferPtr - buffer) {
1623 int offset = (int)(bufferPtr - buffer) - keep;
1624 memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
1625 bufferEnd -= offset;
1626 bufferPtr -= offset;
1628 #else
1629 memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
1630 bufferEnd = buffer + (bufferEnd - bufferPtr);
1631 bufferPtr = buffer;
1632 #endif /* not defined XML_CONTEXT_BYTES */
1634 else {
1635 char *newBuf;
1636 int bufferSize = (int)(bufferLim - bufferPtr);
1637 if (bufferSize == 0)
1638 bufferSize = INIT_BUFFER_SIZE;
1639 do {
1640 bufferSize *= 2;
1641 } while (bufferSize < neededSize);
1642 newBuf = (char *)MALLOC(bufferSize);
1643 if (newBuf == 0) {
1644 errorCode = XML_ERROR_NO_MEMORY;
1645 return NULL;
1647 bufferLim = newBuf + bufferSize;
1648 #ifdef XML_CONTEXT_BYTES
1649 if (bufferPtr) {
1650 int keep = (int)(bufferPtr - buffer);
1651 if (keep > XML_CONTEXT_BYTES)
1652 keep = XML_CONTEXT_BYTES;
1653 memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
1654 FREE(buffer);
1655 buffer = newBuf;
1656 bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
1657 bufferPtr = buffer + keep;
1659 else {
1660 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1661 bufferPtr = buffer = newBuf;
1663 #else
1664 if (bufferPtr) {
1665 memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
1666 FREE(buffer);
1668 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1669 bufferPtr = buffer = newBuf;
1670 #endif /* not defined XML_CONTEXT_BYTES */
1673 return bufferEnd;
1676 enum XML_Status XMLCALL
1677 XML_StopParser(XML_Parser parser, XML_Bool resumable)
1679 switch (ps_parsing) {
1680 case XML_SUSPENDED:
1681 if (resumable) {
1682 errorCode = XML_ERROR_SUSPENDED;
1683 return XML_STATUS_ERROR;
1685 ps_parsing = XML_FINISHED;
1686 break;
1687 case XML_FINISHED:
1688 errorCode = XML_ERROR_FINISHED;
1689 return XML_STATUS_ERROR;
1690 default:
1691 if (resumable) {
1692 #ifdef XML_DTD
1693 if (isParamEntity) {
1694 errorCode = XML_ERROR_SUSPEND_PE;
1695 return XML_STATUS_ERROR;
1697 #endif
1698 ps_parsing = XML_SUSPENDED;
1700 else
1701 ps_parsing = XML_FINISHED;
1703 return XML_STATUS_OK;
1706 enum XML_Status XMLCALL
1707 XML_ResumeParser(XML_Parser parser)
1709 enum XML_Status result = XML_STATUS_OK;
1711 if (ps_parsing != XML_SUSPENDED) {
1712 errorCode = XML_ERROR_NOT_SUSPENDED;
1713 return XML_STATUS_ERROR;
1715 ps_parsing = XML_PARSING;
1717 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
1719 if (errorCode != XML_ERROR_NONE) {
1720 eventEndPtr = eventPtr;
1721 processor = errorProcessor;
1722 return XML_STATUS_ERROR;
1724 else {
1725 switch (ps_parsing) {
1726 case XML_SUSPENDED:
1727 result = XML_STATUS_SUSPENDED;
1728 break;
1729 case XML_INITIALIZED:
1730 case XML_PARSING:
1731 if (ps_finalBuffer) {
1732 ps_parsing = XML_FINISHED;
1733 return result;
1735 default: ;
1739 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1740 positionPtr = bufferPtr;
1741 return result;
1744 void XMLCALL
1745 XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
1747 assert(status != NULL);
1748 *status = parser->m_parsingStatus;
1751 enum XML_Error XMLCALL
1752 XML_GetErrorCode(XML_Parser parser)
1754 return errorCode;
1757 XML_Index XMLCALL
1758 XML_GetCurrentByteIndex(XML_Parser parser)
1760 if (eventPtr)
1761 return parseEndByteIndex - (parseEndPtr - eventPtr);
1762 return -1;
1765 int XMLCALL
1766 XML_GetCurrentByteCount(XML_Parser parser)
1768 if (eventEndPtr && eventPtr)
1769 return (int)(eventEndPtr - eventPtr);
1770 return 0;
1773 const char * XMLCALL
1774 XML_GetInputContext(XML_Parser parser, int *offset, int *size)
1776 #ifdef XML_CONTEXT_BYTES
1777 if (eventPtr && buffer) {
1778 *offset = (int)(eventPtr - buffer);
1779 *size = (int)(bufferEnd - buffer);
1780 return buffer;
1782 #endif /* defined XML_CONTEXT_BYTES */
1783 return (char *) 0;
1786 XML_Size XMLCALL
1787 XML_GetCurrentLineNumber(XML_Parser parser)
1789 if (eventPtr && eventPtr >= positionPtr) {
1790 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1791 positionPtr = eventPtr;
1793 return position.lineNumber + 1;
1796 XML_Size XMLCALL
1797 XML_GetCurrentColumnNumber(XML_Parser parser)
1799 if (eventPtr && eventPtr >= positionPtr) {
1800 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1801 positionPtr = eventPtr;
1803 return position.columnNumber;
1806 void XMLCALL
1807 XML_FreeContentModel(XML_Parser parser, XML_Content *model)
1809 FREE(model);
1812 void * XMLCALL
1813 XML_MemMalloc(XML_Parser parser, size_t size)
1815 return MALLOC(size);
1818 void * XMLCALL
1819 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
1821 return REALLOC(ptr, size);
1824 void XMLCALL
1825 XML_MemFree(XML_Parser parser, void *ptr)
1827 FREE(ptr);
1830 void XMLCALL
1831 XML_DefaultCurrent(XML_Parser parser)
1833 if (defaultHandler) {
1834 if (openInternalEntities)
1835 reportDefault(parser,
1836 internalEncoding,
1837 openInternalEntities->internalEventPtr,
1838 openInternalEntities->internalEventEndPtr);
1839 else
1840 reportDefault(parser, encoding, eventPtr, eventEndPtr);
1844 const XML_LChar * XMLCALL
1845 XML_ErrorString(enum XML_Error code)
1847 static const XML_LChar* const message[] = {
1849 XML_L("out of memory"),
1850 XML_L("syntax error"),
1851 XML_L("no element found"),
1852 XML_L("not well-formed (invalid token)"),
1853 XML_L("unclosed token"),
1854 XML_L("partial character"),
1855 XML_L("mismatched tag"),
1856 XML_L("duplicate attribute"),
1857 XML_L("junk after document element"),
1858 XML_L("illegal parameter entity reference"),
1859 XML_L("undefined entity"),
1860 XML_L("recursive entity reference"),
1861 XML_L("asynchronous entity"),
1862 XML_L("reference to invalid character number"),
1863 XML_L("reference to binary entity"),
1864 XML_L("reference to external entity in attribute"),
1865 XML_L("XML or text declaration not at start of entity"),
1866 XML_L("unknown encoding"),
1867 XML_L("encoding specified in XML declaration is incorrect"),
1868 XML_L("unclosed CDATA section"),
1869 XML_L("error in processing external entity reference"),
1870 XML_L("document is not standalone"),
1871 XML_L("unexpected parser state - please send a bug report"),
1872 XML_L("entity declared in parameter entity"),
1873 XML_L("requested feature requires XML_DTD support in Expat"),
1874 XML_L("cannot change setting once parsing has begun"),
1875 XML_L("unbound prefix"),
1876 XML_L("must not undeclare prefix"),
1877 XML_L("incomplete markup in parameter entity"),
1878 XML_L("XML declaration not well-formed"),
1879 XML_L("text declaration not well-formed"),
1880 XML_L("illegal character(s) in public id"),
1881 XML_L("parser suspended"),
1882 XML_L("parser not suspended"),
1883 XML_L("parsing aborted"),
1884 XML_L("parsing finished"),
1885 XML_L("cannot suspend in external parameter entity"),
1886 XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
1887 XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
1888 XML_L("prefix must not be bound to one of the reserved namespace names")
1890 if (code > 0 && code < sizeof(message)/sizeof(message[0]))
1891 return message[code];
1892 return NULL;
1895 const XML_LChar * XMLCALL
1896 XML_ExpatVersion(void) {
1898 /* V1 is used to string-ize the version number. However, it would
1899 string-ize the actual version macro *names* unless we get them
1900 substituted before being passed to V1. CPP is defined to expand
1901 a macro, then rescan for more expansions. Thus, we use V2 to expand
1902 the version macros, then CPP will expand the resulting V1() macro
1903 with the correct numerals. */
1904 /* ### I'm assuming cpp is portable in this respect... */
1906 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
1907 #define V2(a,b,c) XML_L("expat_")V1(a,b,c)
1909 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
1911 #undef V1
1912 #undef V2
1915 XML_Expat_Version XMLCALL
1916 XML_ExpatVersionInfo(void)
1918 XML_Expat_Version version;
1920 version.major = XML_MAJOR_VERSION;
1921 version.minor = XML_MINOR_VERSION;
1922 version.micro = XML_MICRO_VERSION;
1924 return version;
1927 const XML_Feature * XMLCALL
1928 XML_GetFeatureList(void)
1930 static const XML_Feature features[] = {
1931 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
1932 sizeof(XML_Char)},
1933 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
1934 sizeof(XML_LChar)},
1935 #ifdef XML_UNICODE
1936 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
1937 #endif
1938 #ifdef XML_UNICODE_WCHAR_T
1939 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
1940 #endif
1941 #ifdef XML_DTD
1942 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
1943 #endif
1944 #ifdef XML_CONTEXT_BYTES
1945 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
1946 XML_CONTEXT_BYTES},
1947 #endif
1948 #ifdef XML_MIN_SIZE
1949 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
1950 #endif
1951 #ifdef XML_NS
1952 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
1953 #endif
1954 #ifdef XML_LARGE_SIZE
1955 {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
1956 #endif
1957 {XML_FEATURE_END, NULL, 0}
1960 return features;
1963 /* Initially tag->rawName always points into the parse buffer;
1964 for those TAG instances opened while the current parse buffer was
1965 processed, and not yet closed, we need to store tag->rawName in a more
1966 permanent location, since the parse buffer is about to be discarded.
1968 static XML_Bool
1969 storeRawNames(XML_Parser parser)
1971 TAG *tag = tagStack;
1972 while (tag) {
1973 int bufSize;
1974 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
1975 char *rawNameBuf = tag->buf + nameLen;
1976 /* Stop if already stored. Since tagStack is a stack, we can stop
1977 at the first entry that has already been copied; everything
1978 below it in the stack is already been accounted for in a
1979 previous call to this function.
1981 if (tag->rawName == rawNameBuf)
1982 break;
1983 /* For re-use purposes we need to ensure that the
1984 size of tag->buf is a multiple of sizeof(XML_Char).
1986 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
1987 if (bufSize > tag->bufEnd - tag->buf) {
1988 char *temp = (char *)REALLOC(tag->buf, bufSize);
1989 if (temp == NULL)
1990 return XML_FALSE;
1991 /* if tag->name.str points to tag->buf (only when namespace
1992 processing is off) then we have to update it
1994 if (tag->name.str == (XML_Char *)tag->buf)
1995 tag->name.str = (XML_Char *)temp;
1996 /* if tag->name.localPart is set (when namespace processing is on)
1997 then update it as well, since it will always point into tag->buf
1999 if (tag->name.localPart)
2000 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
2001 (XML_Char *)tag->buf);
2002 tag->buf = temp;
2003 tag->bufEnd = temp + bufSize;
2004 rawNameBuf = temp + nameLen;
2006 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2007 tag->rawName = rawNameBuf;
2008 tag = tag->parent;
2010 return XML_TRUE;
2013 static enum XML_Error PTRCALL
2014 contentProcessor(XML_Parser parser,
2015 const char *start,
2016 const char *end,
2017 const char **endPtr)
2019 enum XML_Error result = doContent(parser, 0, encoding, start, end,
2020 endPtr, (XML_Bool)!ps_finalBuffer);
2021 if (result == XML_ERROR_NONE) {
2022 if (!storeRawNames(parser))
2023 return XML_ERROR_NO_MEMORY;
2025 return result;
2028 static enum XML_Error PTRCALL
2029 externalEntityInitProcessor(XML_Parser parser,
2030 const char *start,
2031 const char *end,
2032 const char **endPtr)
2034 enum XML_Error result = initializeEncoding(parser);
2035 if (result != XML_ERROR_NONE)
2036 return result;
2037 processor = externalEntityInitProcessor2;
2038 return externalEntityInitProcessor2(parser, start, end, endPtr);
2041 static enum XML_Error PTRCALL
2042 externalEntityInitProcessor2(XML_Parser parser,
2043 const char *start,
2044 const char *end,
2045 const char **endPtr)
2047 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2048 int tok = XmlContentTok(encoding, start, end, &next);
2049 switch (tok) {
2050 case XML_TOK_BOM:
2051 /* If we are at the end of the buffer, this would cause the next stage,
2052 i.e. externalEntityInitProcessor3, to pass control directly to
2053 doContent (by detecting XML_TOK_NONE) without processing any xml text
2054 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2056 if (next == end && !ps_finalBuffer) {
2057 *endPtr = next;
2058 return XML_ERROR_NONE;
2060 start = next;
2061 break;
2062 case XML_TOK_PARTIAL:
2063 if (!ps_finalBuffer) {
2064 *endPtr = start;
2065 return XML_ERROR_NONE;
2067 eventPtr = start;
2068 return XML_ERROR_UNCLOSED_TOKEN;
2069 case XML_TOK_PARTIAL_CHAR:
2070 if (!ps_finalBuffer) {
2071 *endPtr = start;
2072 return XML_ERROR_NONE;
2074 eventPtr = start;
2075 return XML_ERROR_PARTIAL_CHAR;
2077 processor = externalEntityInitProcessor3;
2078 return externalEntityInitProcessor3(parser, start, end, endPtr);
2081 static enum XML_Error PTRCALL
2082 externalEntityInitProcessor3(XML_Parser parser,
2083 const char *start,
2084 const char *end,
2085 const char **endPtr)
2087 int tok;
2088 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2089 eventPtr = start;
2090 tok = XmlContentTok(encoding, start, end, &next);
2091 eventEndPtr = next;
2093 switch (tok) {
2094 case XML_TOK_XML_DECL:
2096 enum XML_Error result;
2097 result = processXmlDecl(parser, 1, start, next);
2098 if (result != XML_ERROR_NONE)
2099 return result;
2100 switch (ps_parsing) {
2101 case XML_SUSPENDED:
2102 *endPtr = next;
2103 return XML_ERROR_NONE;
2104 case XML_FINISHED:
2105 return XML_ERROR_ABORTED;
2106 default:
2107 start = next;
2110 break;
2111 case XML_TOK_PARTIAL:
2112 if (!ps_finalBuffer) {
2113 *endPtr = start;
2114 return XML_ERROR_NONE;
2116 return XML_ERROR_UNCLOSED_TOKEN;
2117 case XML_TOK_PARTIAL_CHAR:
2118 if (!ps_finalBuffer) {
2119 *endPtr = start;
2120 return XML_ERROR_NONE;
2122 return XML_ERROR_PARTIAL_CHAR;
2124 processor = externalEntityContentProcessor;
2125 tagLevel = 1;
2126 return externalEntityContentProcessor(parser, start, end, endPtr);
2129 static enum XML_Error PTRCALL
2130 externalEntityContentProcessor(XML_Parser parser,
2131 const char *start,
2132 const char *end,
2133 const char **endPtr)
2135 enum XML_Error result = doContent(parser, 1, encoding, start, end,
2136 endPtr, (XML_Bool)!ps_finalBuffer);
2137 if (result == XML_ERROR_NONE) {
2138 if (!storeRawNames(parser))
2139 return XML_ERROR_NO_MEMORY;
2141 return result;
2144 static enum XML_Error
2145 doContent(XML_Parser parser,
2146 int startTagLevel,
2147 const ENCODING *enc,
2148 const char *s,
2149 const char *end,
2150 const char **nextPtr,
2151 XML_Bool haveMore)
2153 /* save one level of indirection */
2154 DTD * const dtd = _dtd;
2156 const char **eventPP;
2157 const char **eventEndPP;
2158 if (enc == encoding) {
2159 eventPP = &eventPtr;
2160 eventEndPP = &eventEndPtr;
2162 else {
2163 eventPP = &(openInternalEntities->internalEventPtr);
2164 eventEndPP = &(openInternalEntities->internalEventEndPtr);
2166 *eventPP = s;
2168 for (;;) {
2169 const char *next = s; /* XmlContentTok doesn't always set the last arg */
2170 int tok = XmlContentTok(enc, s, end, &next);
2171 *eventEndPP = next;
2172 switch (tok) {
2173 case XML_TOK_TRAILING_CR:
2174 if (haveMore) {
2175 *nextPtr = s;
2176 return XML_ERROR_NONE;
2178 *eventEndPP = end;
2179 if (characterDataHandler) {
2180 XML_Char c = 0xA;
2181 characterDataHandler(handlerArg, &c, 1);
2183 else if (defaultHandler)
2184 reportDefault(parser, enc, s, end);
2185 /* We are at the end of the final buffer, should we check for
2186 XML_SUSPENDED, XML_FINISHED?
2188 if (startTagLevel == 0)
2189 return XML_ERROR_NO_ELEMENTS;
2190 if (tagLevel != startTagLevel)
2191 return XML_ERROR_ASYNC_ENTITY;
2192 *nextPtr = end;
2193 return XML_ERROR_NONE;
2194 case XML_TOK_NONE:
2195 if (haveMore) {
2196 *nextPtr = s;
2197 return XML_ERROR_NONE;
2199 if (startTagLevel > 0) {
2200 if (tagLevel != startTagLevel)
2201 return XML_ERROR_ASYNC_ENTITY;
2202 *nextPtr = s;
2203 return XML_ERROR_NONE;
2205 return XML_ERROR_NO_ELEMENTS;
2206 case XML_TOK_INVALID:
2207 *eventPP = next;
2208 return XML_ERROR_INVALID_TOKEN;
2209 case XML_TOK_PARTIAL:
2210 if (haveMore) {
2211 *nextPtr = s;
2212 return XML_ERROR_NONE;
2214 return XML_ERROR_UNCLOSED_TOKEN;
2215 case XML_TOK_PARTIAL_CHAR:
2216 if (haveMore) {
2217 *nextPtr = s;
2218 return XML_ERROR_NONE;
2220 return XML_ERROR_PARTIAL_CHAR;
2221 case XML_TOK_ENTITY_REF:
2223 const XML_Char *name;
2224 ENTITY *entity;
2225 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
2226 s + enc->minBytesPerChar,
2227 next - enc->minBytesPerChar);
2228 if (ch) {
2229 if (characterDataHandler)
2230 characterDataHandler(handlerArg, &ch, 1);
2231 else if (defaultHandler)
2232 reportDefault(parser, enc, s, next);
2233 break;
2235 name = poolStoreString(&dtd->pool, enc,
2236 s + enc->minBytesPerChar,
2237 next - enc->minBytesPerChar);
2238 if (!name)
2239 return XML_ERROR_NO_MEMORY;
2240 entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
2241 poolDiscard(&dtd->pool);
2242 /* First, determine if a check for an existing declaration is needed;
2243 if yes, check that the entity exists, and that it is internal,
2244 otherwise call the skipped entity or default handler.
2246 if (!dtd->hasParamEntityRefs || dtd->standalone) {
2247 if (!entity)
2248 return XML_ERROR_UNDEFINED_ENTITY;
2249 else if (!entity->is_internal)
2250 return XML_ERROR_ENTITY_DECLARED_IN_PE;
2252 else if (!entity) {
2253 if (skippedEntityHandler)
2254 skippedEntityHandler(handlerArg, name, 0);
2255 else if (defaultHandler)
2256 reportDefault(parser, enc, s, next);
2257 break;
2259 if (entity->open)
2260 return XML_ERROR_RECURSIVE_ENTITY_REF;
2261 if (entity->notation)
2262 return XML_ERROR_BINARY_ENTITY_REF;
2263 if (entity->textPtr) {
2264 enum XML_Error result;
2265 if (!defaultExpandInternalEntities) {
2266 if (skippedEntityHandler)
2267 skippedEntityHandler(handlerArg, entity->name, 0);
2268 else if (defaultHandler)
2269 reportDefault(parser, enc, s, next);
2270 break;
2272 result = processInternalEntity(parser, entity, XML_FALSE);
2273 if (result != XML_ERROR_NONE)
2274 return result;
2276 else if (externalEntityRefHandler) {
2277 const XML_Char *context;
2278 entity->open = XML_TRUE;
2279 context = getContext(parser);
2280 entity->open = XML_FALSE;
2281 if (!context)
2282 return XML_ERROR_NO_MEMORY;
2283 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
2284 context,
2285 entity->base,
2286 entity->systemId,
2287 entity->publicId))
2288 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2289 poolDiscard(&tempPool);
2291 else if (defaultHandler)
2292 reportDefault(parser, enc, s, next);
2293 break;
2295 case XML_TOK_START_TAG_NO_ATTS:
2296 /* fall through */
2297 case XML_TOK_START_TAG_WITH_ATTS:
2299 TAG *tag;
2300 enum XML_Error result;
2301 XML_Char *toPtr;
2302 if (freeTagList) {
2303 tag = freeTagList;
2304 freeTagList = freeTagList->parent;
2306 else {
2307 tag = (TAG *)MALLOC(sizeof(TAG));
2308 if (!tag)
2309 return XML_ERROR_NO_MEMORY;
2310 tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
2311 if (!tag->buf) {
2312 FREE(tag);
2313 return XML_ERROR_NO_MEMORY;
2315 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2317 tag->bindings = NULL;
2318 tag->parent = tagStack;
2319 tagStack = tag;
2320 tag->name.localPart = NULL;
2321 tag->name.prefix = NULL;
2322 tag->rawName = s + enc->minBytesPerChar;
2323 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
2324 ++tagLevel;
2326 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2327 const char *fromPtr = tag->rawName;
2328 toPtr = (XML_Char *)tag->buf;
2329 for (;;) {
2330 int bufSize;
2331 int convLen;
2332 XmlConvert(enc,
2333 &fromPtr, rawNameEnd,
2334 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
2335 convLen = (int)(toPtr - (XML_Char *)tag->buf);
2336 if (fromPtr == rawNameEnd) {
2337 tag->name.strLen = convLen;
2338 break;
2340 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2342 char *temp = (char *)REALLOC(tag->buf, bufSize);
2343 if (temp == NULL)
2344 return XML_ERROR_NO_MEMORY;
2345 tag->buf = temp;
2346 tag->bufEnd = temp + bufSize;
2347 toPtr = (XML_Char *)temp + convLen;
2351 tag->name.str = (XML_Char *)tag->buf;
2352 *toPtr = XML_T('\0');
2353 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2354 if (result)
2355 return result;
2356 if (startElementHandler)
2357 startElementHandler(handlerArg, tag->name.str,
2358 (const XML_Char **)atts);
2359 else if (defaultHandler)
2360 reportDefault(parser, enc, s, next);
2361 poolClear(&tempPool);
2362 break;
2364 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2365 /* fall through */
2366 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
2368 const char *rawName = s + enc->minBytesPerChar;
2369 enum XML_Error result;
2370 BINDING *bindings = NULL;
2371 XML_Bool noElmHandlers = XML_TRUE;
2372 TAG_NAME name;
2373 name.str = poolStoreString(&tempPool, enc, rawName,
2374 rawName + XmlNameLength(enc, rawName));
2375 if (!name.str)
2376 return XML_ERROR_NO_MEMORY;
2377 poolFinish(&tempPool);
2378 result = storeAtts(parser, enc, s, &name, &bindings);
2379 if (result)
2380 return result;
2381 poolFinish(&tempPool);
2382 if (startElementHandler) {
2383 startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
2384 noElmHandlers = XML_FALSE;
2386 if (endElementHandler) {
2387 if (startElementHandler)
2388 *eventPP = *eventEndPP;
2389 endElementHandler(handlerArg, name.str);
2390 noElmHandlers = XML_FALSE;
2392 if (noElmHandlers && defaultHandler)
2393 reportDefault(parser, enc, s, next);
2394 poolClear(&tempPool);
2395 while (bindings) {
2396 BINDING *b = bindings;
2397 if (endNamespaceDeclHandler)
2398 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2399 bindings = bindings->nextTagBinding;
2400 b->nextTagBinding = freeBindingList;
2401 freeBindingList = b;
2402 b->prefix->binding = b->prevPrefixBinding;
2405 if (tagLevel == 0)
2406 return epilogProcessor(parser, next, end, nextPtr);
2407 break;
2408 case XML_TOK_END_TAG:
2409 if (tagLevel == startTagLevel)
2410 return XML_ERROR_ASYNC_ENTITY;
2411 else {
2412 int len;
2413 const char *rawName;
2414 TAG *tag = tagStack;
2415 tagStack = tag->parent;
2416 tag->parent = freeTagList;
2417 freeTagList = tag;
2418 rawName = s + enc->minBytesPerChar*2;
2419 len = XmlNameLength(enc, rawName);
2420 if (len != tag->rawNameLength
2421 || memcmp(tag->rawName, rawName, len) != 0) {
2422 *eventPP = rawName;
2423 return XML_ERROR_TAG_MISMATCH;
2425 --tagLevel;
2426 if (endElementHandler) {
2427 const XML_Char *localPart;
2428 const XML_Char *prefix;
2429 XML_Char *uri;
2430 localPart = tag->name.localPart;
2431 if (ns && localPart) {
2432 /* localPart and prefix may have been overwritten in
2433 tag->name.str, since this points to the binding->uri
2434 buffer which gets re-used; so we have to add them again
2436 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2437 /* don't need to check for space - already done in storeAtts() */
2438 while (*localPart) *uri++ = *localPart++;
2439 prefix = (XML_Char *)tag->name.prefix;
2440 if (ns_triplets && prefix) {
2441 *uri++ = namespaceSeparator;
2442 while (*prefix) *uri++ = *prefix++;
2444 *uri = XML_T('\0');
2446 endElementHandler(handlerArg, tag->name.str);
2448 else if (defaultHandler)
2449 reportDefault(parser, enc, s, next);
2450 while (tag->bindings) {
2451 BINDING *b = tag->bindings;
2452 if (endNamespaceDeclHandler)
2453 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2454 tag->bindings = tag->bindings->nextTagBinding;
2455 b->nextTagBinding = freeBindingList;
2456 freeBindingList = b;
2457 b->prefix->binding = b->prevPrefixBinding;
2459 if (tagLevel == 0)
2460 return epilogProcessor(parser, next, end, nextPtr);
2462 break;
2463 case XML_TOK_CHAR_REF:
2465 int n = XmlCharRefNumber(enc, s);
2466 if (n < 0)
2467 return XML_ERROR_BAD_CHAR_REF;
2468 if (characterDataHandler) {
2469 XML_Char buf[XML_ENCODE_MAX];
2470 characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
2472 else if (defaultHandler)
2473 reportDefault(parser, enc, s, next);
2475 break;
2476 case XML_TOK_XML_DECL:
2477 return XML_ERROR_MISPLACED_XML_PI;
2478 case XML_TOK_DATA_NEWLINE:
2479 if (characterDataHandler) {
2480 XML_Char c = 0xA;
2481 characterDataHandler(handlerArg, &c, 1);
2483 else if (defaultHandler)
2484 reportDefault(parser, enc, s, next);
2485 break;
2486 case XML_TOK_CDATA_SECT_OPEN:
2488 enum XML_Error result;
2489 if (startCdataSectionHandler)
2490 startCdataSectionHandler(handlerArg);
2491 #if 0
2492 /* Suppose you doing a transformation on a document that involves
2493 changing only the character data. You set up a defaultHandler
2494 and a characterDataHandler. The defaultHandler simply copies
2495 characters through. The characterDataHandler does the
2496 transformation and writes the characters out escaping them as
2497 necessary. This case will fail to work if we leave out the
2498 following two lines (because & and < inside CDATA sections will
2499 be incorrectly escaped).
2501 However, now we have a start/endCdataSectionHandler, so it seems
2502 easier to let the user deal with this.
2504 else if (characterDataHandler)
2505 characterDataHandler(handlerArg, dataBuf, 0);
2506 #endif
2507 else if (defaultHandler)
2508 reportDefault(parser, enc, s, next);
2509 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
2510 if (result != XML_ERROR_NONE)
2511 return result;
2512 else if (!next) {
2513 processor = cdataSectionProcessor;
2514 return result;
2517 break;
2518 case XML_TOK_TRAILING_RSQB:
2519 if (haveMore) {
2520 *nextPtr = s;
2521 return XML_ERROR_NONE;
2523 if (characterDataHandler) {
2524 if (MUST_CONVERT(enc, s)) {
2525 ICHAR *dataPtr = (ICHAR *)dataBuf;
2526 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
2527 characterDataHandler(handlerArg, dataBuf,
2528 (int)(dataPtr - (ICHAR *)dataBuf));
2530 else
2531 characterDataHandler(handlerArg,
2532 (XML_Char *)s,
2533 (int)((XML_Char *)end - (XML_Char *)s));
2535 else if (defaultHandler)
2536 reportDefault(parser, enc, s, end);
2537 /* We are at the end of the final buffer, should we check for
2538 XML_SUSPENDED, XML_FINISHED?
2540 if (startTagLevel == 0) {
2541 *eventPP = end;
2542 return XML_ERROR_NO_ELEMENTS;
2544 if (tagLevel != startTagLevel) {
2545 *eventPP = end;
2546 return XML_ERROR_ASYNC_ENTITY;
2548 *nextPtr = end;
2549 return XML_ERROR_NONE;
2550 case XML_TOK_DATA_CHARS:
2552 XML_CharacterDataHandler charDataHandler = characterDataHandler;
2553 if (charDataHandler) {
2554 if (MUST_CONVERT(enc, s)) {
2555 for (;;) {
2556 ICHAR *dataPtr = (ICHAR *)dataBuf;
2557 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
2558 *eventEndPP = s;
2559 charDataHandler(handlerArg, dataBuf,
2560 (int)(dataPtr - (ICHAR *)dataBuf));
2561 if (s == next)
2562 break;
2563 *eventPP = s;
2566 else
2567 charDataHandler(handlerArg,
2568 (XML_Char *)s,
2569 (int)((XML_Char *)next - (XML_Char *)s));
2571 else if (defaultHandler)
2572 reportDefault(parser, enc, s, next);
2574 break;
2575 case XML_TOK_PI:
2576 if (!reportProcessingInstruction(parser, enc, s, next))
2577 return XML_ERROR_NO_MEMORY;
2578 break;
2579 case XML_TOK_COMMENT:
2580 if (!reportComment(parser, enc, s, next))
2581 return XML_ERROR_NO_MEMORY;
2582 break;
2583 default:
2584 if (defaultHandler)
2585 reportDefault(parser, enc, s, next);
2586 break;
2588 *eventPP = s = next;
2589 switch (ps_parsing) {
2590 case XML_SUSPENDED:
2591 *nextPtr = next;
2592 return XML_ERROR_NONE;
2593 case XML_FINISHED:
2594 return XML_ERROR_ABORTED;
2595 default: ;
2598 /* not reached */
2601 /* Precondition: all arguments must be non-NULL;
2602 Purpose:
2603 - normalize attributes
2604 - check attributes for well-formedness
2605 - generate namespace aware attribute names (URI, prefix)
2606 - build list of attributes for startElementHandler
2607 - default attributes
2608 - process namespace declarations (check and report them)
2609 - generate namespace aware element name (URI, prefix)
2611 static enum XML_Error
2612 storeAtts(XML_Parser parser, const ENCODING *enc,
2613 const char *attStr, TAG_NAME *tagNamePtr,
2614 BINDING **bindingsPtr)
2616 DTD * const dtd = _dtd; /* save one level of indirection */
2617 ELEMENT_TYPE *elementType;
2618 int nDefaultAtts;
2619 const XML_Char **appAtts; /* the attribute list for the application */
2620 int attIndex = 0;
2621 int prefixLen;
2622 int i;
2623 int n;
2624 XML_Char *uri;
2625 int nPrefixes = 0;
2626 BINDING *binding;
2627 const XML_Char *localPart;
2629 /* lookup the element type name */
2630 elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0);
2631 if (!elementType) {
2632 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
2633 if (!name)
2634 return XML_ERROR_NO_MEMORY;
2635 elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name,
2636 sizeof(ELEMENT_TYPE));
2637 if (!elementType)
2638 return XML_ERROR_NO_MEMORY;
2639 if (ns && !setElementTypePrefix(parser, elementType))
2640 return XML_ERROR_NO_MEMORY;
2642 nDefaultAtts = elementType->nDefaultAtts;
2644 /* get the attributes from the tokenizer */
2645 n = XmlGetAttributes(enc, attStr, attsSize, atts);
2646 if (n + nDefaultAtts > attsSize) {
2647 int oldAttsSize = attsSize;
2648 ATTRIBUTE *temp;
2649 attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
2650 temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
2651 if (temp == NULL)
2652 return XML_ERROR_NO_MEMORY;
2653 atts = temp;
2654 if (n > oldAttsSize)
2655 XmlGetAttributes(enc, attStr, n, atts);
2658 appAtts = (const XML_Char **)atts;
2659 for (i = 0; i < n; i++) {
2660 /* add the name and value to the attribute list */
2661 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
2662 atts[i].name
2663 + XmlNameLength(enc, atts[i].name));
2664 if (!attId)
2665 return XML_ERROR_NO_MEMORY;
2666 /* Detect duplicate attributes by their QNames. This does not work when
2667 namespace processing is turned on and different prefixes for the same
2668 namespace are used. For this case we have a check further down.
2670 if ((attId->name)[-1]) {
2671 if (enc == encoding)
2672 eventPtr = atts[i].name;
2673 return XML_ERROR_DUPLICATE_ATTRIBUTE;
2675 (attId->name)[-1] = 1;
2676 appAtts[attIndex++] = attId->name;
2677 if (!atts[i].normalized) {
2678 enum XML_Error result;
2679 XML_Bool isCdata = XML_TRUE;
2681 /* figure out whether declared as other than CDATA */
2682 if (attId->maybeTokenized) {
2683 int j;
2684 for (j = 0; j < nDefaultAtts; j++) {
2685 if (attId == elementType->defaultAtts[j].id) {
2686 isCdata = elementType->defaultAtts[j].isCdata;
2687 break;
2692 /* normalize the attribute value */
2693 result = storeAttributeValue(parser, enc, isCdata,
2694 atts[i].valuePtr, atts[i].valueEnd,
2695 &tempPool);
2696 if (result)
2697 return result;
2698 appAtts[attIndex] = poolStart(&tempPool);
2699 poolFinish(&tempPool);
2701 else {
2702 /* the value did not need normalizing */
2703 appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
2704 atts[i].valueEnd);
2705 if (appAtts[attIndex] == 0)
2706 return XML_ERROR_NO_MEMORY;
2707 poolFinish(&tempPool);
2709 /* handle prefixed attribute names */
2710 if (attId->prefix) {
2711 if (attId->xmlns) {
2712 /* deal with namespace declarations here */
2713 enum XML_Error result = addBinding(parser, attId->prefix, attId,
2714 appAtts[attIndex], bindingsPtr);
2715 if (result)
2716 return result;
2717 --attIndex;
2719 else {
2720 /* deal with other prefixed names later */
2721 attIndex++;
2722 nPrefixes++;
2723 (attId->name)[-1] = 2;
2726 else
2727 attIndex++;
2730 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
2731 nSpecifiedAtts = attIndex;
2732 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
2733 for (i = 0; i < attIndex; i += 2)
2734 if (appAtts[i] == elementType->idAtt->name) {
2735 idAttIndex = i;
2736 break;
2739 else
2740 idAttIndex = -1;
2742 /* do attribute defaulting */
2743 for (i = 0; i < nDefaultAtts; i++) {
2744 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
2745 if (!(da->id->name)[-1] && da->value) {
2746 if (da->id->prefix) {
2747 if (da->id->xmlns) {
2748 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
2749 da->value, bindingsPtr);
2750 if (result)
2751 return result;
2753 else {
2754 (da->id->name)[-1] = 2;
2755 nPrefixes++;
2756 appAtts[attIndex++] = da->id->name;
2757 appAtts[attIndex++] = da->value;
2760 else {
2761 (da->id->name)[-1] = 1;
2762 appAtts[attIndex++] = da->id->name;
2763 appAtts[attIndex++] = da->value;
2767 appAtts[attIndex] = 0;
2769 /* expand prefixed attribute names, check for duplicates,
2770 and clear flags that say whether attributes were specified */
2771 i = 0;
2772 if (nPrefixes) {
2773 int j; /* hash table index */
2774 unsigned long version = nsAttsVersion;
2775 int nsAttsSize = (int)1 << nsAttsPower;
2776 /* size of hash table must be at least 2 * (# of prefixed attributes) */
2777 if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */
2778 NS_ATT *temp;
2779 /* hash table size must also be a power of 2 and >= 8 */
2780 while (nPrefixes >> nsAttsPower++);
2781 if (nsAttsPower < 3)
2782 nsAttsPower = 3;
2783 nsAttsSize = (int)1 << nsAttsPower;
2784 temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
2785 if (!temp)
2786 return XML_ERROR_NO_MEMORY;
2787 nsAtts = temp;
2788 version = 0; /* force re-initialization of nsAtts hash table */
2790 /* using a version flag saves us from initializing nsAtts every time */
2791 if (!version) { /* initialize version flags when version wraps around */
2792 version = INIT_ATTS_VERSION;
2793 for (j = nsAttsSize; j != 0; )
2794 nsAtts[--j].version = version;
2796 nsAttsVersion = --version;
2798 /* expand prefixed names and check for duplicates */
2799 for (; i < attIndex; i += 2) {
2800 const XML_Char *s = appAtts[i];
2801 if (s[-1] == 2) { /* prefixed */
2802 ATTRIBUTE_ID *id;
2803 const BINDING *b;
2804 unsigned long uriHash = 0;
2805 ((XML_Char *)s)[-1] = 0; /* clear flag */
2806 id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);
2807 b = id->prefix->binding;
2808 if (!b)
2809 return XML_ERROR_UNBOUND_PREFIX;
2811 /* as we expand the name we also calculate its hash value */
2812 for (j = 0; j < b->uriLen; j++) {
2813 const XML_Char c = b->uri[j];
2814 if (!poolAppendChar(&tempPool, c))
2815 return XML_ERROR_NO_MEMORY;
2816 uriHash = CHAR_HASH(uriHash, c);
2818 while (*s++ != XML_T(':'))
2820 do { /* copies null terminator */
2821 const XML_Char c = *s;
2822 if (!poolAppendChar(&tempPool, *s))
2823 return XML_ERROR_NO_MEMORY;
2824 uriHash = CHAR_HASH(uriHash, c);
2825 } while (*s++);
2827 { /* Check hash table for duplicate of expanded name (uriName).
2828 Derived from code in lookup(HASH_TABLE *table, ...).
2830 unsigned char step = 0;
2831 unsigned long mask = nsAttsSize - 1;
2832 j = uriHash & mask; /* index into hash table */
2833 while (nsAtts[j].version == version) {
2834 /* for speed we compare stored hash values first */
2835 if (uriHash == nsAtts[j].hash) {
2836 const XML_Char *s1 = poolStart(&tempPool);
2837 const XML_Char *s2 = nsAtts[j].uriName;
2838 /* s1 is null terminated, but not s2 */
2839 for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
2840 if (*s1 == 0)
2841 return XML_ERROR_DUPLICATE_ATTRIBUTE;
2843 if (!step)
2844 step = PROBE_STEP(uriHash, mask, nsAttsPower);
2845 j < step ? (j += nsAttsSize - step) : (j -= step);
2849 if (ns_triplets) { /* append namespace separator and prefix */
2850 tempPool.ptr[-1] = namespaceSeparator;
2851 s = b->prefix->name;
2852 do {
2853 if (!poolAppendChar(&tempPool, *s))
2854 return XML_ERROR_NO_MEMORY;
2855 } while (*s++);
2858 /* store expanded name in attribute list */
2859 s = poolStart(&tempPool);
2860 poolFinish(&tempPool);
2861 appAtts[i] = s;
2863 /* fill empty slot with new version, uriName and hash value */
2864 nsAtts[j].version = version;
2865 nsAtts[j].hash = uriHash;
2866 nsAtts[j].uriName = s;
2868 if (!--nPrefixes) {
2869 i += 2;
2870 break;
2873 else /* not prefixed */
2874 ((XML_Char *)s)[-1] = 0; /* clear flag */
2877 /* clear flags for the remaining attributes */
2878 for (; i < attIndex; i += 2)
2879 ((XML_Char *)(appAtts[i]))[-1] = 0;
2880 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
2881 binding->attId->name[-1] = 0;
2883 if (!ns)
2884 return XML_ERROR_NONE;
2886 /* expand the element type name */
2887 if (elementType->prefix) {
2888 binding = elementType->prefix->binding;
2889 if (!binding)
2890 return XML_ERROR_UNBOUND_PREFIX;
2891 localPart = tagNamePtr->str;
2892 while (*localPart++ != XML_T(':'))
2895 else if (dtd->defaultPrefix.binding) {
2896 binding = dtd->defaultPrefix.binding;
2897 localPart = tagNamePtr->str;
2899 else
2900 return XML_ERROR_NONE;
2901 prefixLen = 0;
2902 if (ns_triplets && binding->prefix->name) {
2903 for (; binding->prefix->name[prefixLen++];)
2904 ; /* prefixLen includes null terminator */
2906 tagNamePtr->localPart = localPart;
2907 tagNamePtr->uriLen = binding->uriLen;
2908 tagNamePtr->prefix = binding->prefix->name;
2909 tagNamePtr->prefixLen = prefixLen;
2910 for (i = 0; localPart[i++];)
2911 ; /* i includes null terminator */
2912 n = i + binding->uriLen + prefixLen;
2913 if (n > binding->uriAlloc) {
2914 TAG *p;
2915 uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
2916 if (!uri)
2917 return XML_ERROR_NO_MEMORY;
2918 binding->uriAlloc = n + EXPAND_SPARE;
2919 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
2920 for (p = tagStack; p; p = p->parent)
2921 if (p->name.str == binding->uri)
2922 p->name.str = uri;
2923 FREE(binding->uri);
2924 binding->uri = uri;
2926 /* if namespaceSeparator != '\0' then uri includes it already */
2927 uri = binding->uri + binding->uriLen;
2928 memcpy(uri, localPart, i * sizeof(XML_Char));
2929 /* we always have a namespace separator between localPart and prefix */
2930 if (prefixLen) {
2931 uri += i - 1;
2932 *uri = namespaceSeparator; /* replace null terminator */
2933 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
2935 tagNamePtr->str = binding->uri;
2936 return XML_ERROR_NONE;
2939 /* addBinding() overwrites the value of prefix->binding without checking.
2940 Therefore one must keep track of the old value outside of addBinding().
2942 static enum XML_Error
2943 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
2944 const XML_Char *uri, BINDING **bindingsPtr)
2946 static const XML_Char xmlNamespace[] = {
2947 'h', 't', 't', 'p', ':', '/', '/',
2948 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
2949 'X', 'M', 'L', '/', '1', '9', '9', '8', '/',
2950 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0'
2952 static const int xmlLen =
2953 (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
2954 static const XML_Char xmlnsNamespace[] = {
2955 'h', 't', 't', 'p', ':', '/', '/',
2956 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
2957 '2', '0', '0', '0', '/', 'x', 'm', 'l', 'n', 's', '/', '\0'
2959 static const int xmlnsLen =
2960 (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
2962 XML_Bool mustBeXML = XML_FALSE;
2963 XML_Bool isXML = XML_TRUE;
2964 XML_Bool isXMLNS = XML_TRUE;
2966 BINDING *b;
2967 int len;
2969 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
2970 if (*uri == XML_T('\0') && prefix->name)
2971 return XML_ERROR_UNDECLARING_PREFIX;
2973 if (prefix->name
2974 && prefix->name[0] == XML_T('x')
2975 && prefix->name[1] == XML_T('m')
2976 && prefix->name[2] == XML_T('l')) {
2978 /* Not allowed to bind xmlns */
2979 if (prefix->name[3] == XML_T('n')
2980 && prefix->name[4] == XML_T('s')
2981 && prefix->name[5] == XML_T('\0'))
2982 return XML_ERROR_RESERVED_PREFIX_XMLNS;
2984 if (prefix->name[3] == XML_T('\0'))
2985 mustBeXML = XML_TRUE;
2988 for (len = 0; uri[len]; len++) {
2989 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
2990 isXML = XML_FALSE;
2992 if (!mustBeXML && isXMLNS
2993 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
2994 isXMLNS = XML_FALSE;
2996 isXML = isXML && len == xmlLen;
2997 isXMLNS = isXMLNS && len == xmlnsLen;
2999 if (mustBeXML != isXML)
3000 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3001 : XML_ERROR_RESERVED_NAMESPACE_URI;
3003 if (isXMLNS)
3004 return XML_ERROR_RESERVED_NAMESPACE_URI;
3006 if (namespaceSeparator)
3007 len++;
3008 if (freeBindingList) {
3009 b = freeBindingList;
3010 if (len > b->uriAlloc) {
3011 XML_Char *temp = (XML_Char *)REALLOC(b->uri,
3012 sizeof(XML_Char) * (len + EXPAND_SPARE));
3013 if (temp == NULL)
3014 return XML_ERROR_NO_MEMORY;
3015 b->uri = temp;
3016 b->uriAlloc = len + EXPAND_SPARE;
3018 freeBindingList = b->nextTagBinding;
3020 else {
3021 b = (BINDING *)MALLOC(sizeof(BINDING));
3022 if (!b)
3023 return XML_ERROR_NO_MEMORY;
3024 b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
3025 if (!b->uri) {
3026 FREE(b);
3027 return XML_ERROR_NO_MEMORY;
3029 b->uriAlloc = len + EXPAND_SPARE;
3031 b->uriLen = len;
3032 memcpy(b->uri, uri, len * sizeof(XML_Char));
3033 if (namespaceSeparator)
3034 b->uri[len - 1] = namespaceSeparator;
3035 b->prefix = prefix;
3036 b->attId = attId;
3037 b->prevPrefixBinding = prefix->binding;
3038 /* NULL binding when default namespace undeclared */
3039 if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
3040 prefix->binding = NULL;
3041 else
3042 prefix->binding = b;
3043 b->nextTagBinding = *bindingsPtr;
3044 *bindingsPtr = b;
3045 /* if attId == NULL then we are not starting a namespace scope */
3046 if (attId && startNamespaceDeclHandler)
3047 startNamespaceDeclHandler(handlerArg, prefix->name,
3048 prefix->binding ? uri : 0);
3049 return XML_ERROR_NONE;
3052 /* The idea here is to avoid using stack for each CDATA section when
3053 the whole file is parsed with one call.
3055 static enum XML_Error PTRCALL
3056 cdataSectionProcessor(XML_Parser parser,
3057 const char *start,
3058 const char *end,
3059 const char **endPtr)
3061 enum XML_Error result = doCdataSection(parser, encoding, &start, end,
3062 endPtr, (XML_Bool)!ps_finalBuffer);
3063 if (result != XML_ERROR_NONE)
3064 return result;
3065 if (start) {
3066 if (parentParser) { /* we are parsing an external entity */
3067 processor = externalEntityContentProcessor;
3068 return externalEntityContentProcessor(parser, start, end, endPtr);
3070 else {
3071 processor = contentProcessor;
3072 return contentProcessor(parser, start, end, endPtr);
3075 return result;
3078 /* startPtr gets set to non-null if the section is closed, and to null if
3079 the section is not yet closed.
3081 static enum XML_Error
3082 doCdataSection(XML_Parser parser,
3083 const ENCODING *enc,
3084 const char **startPtr,
3085 const char *end,
3086 const char **nextPtr,
3087 XML_Bool haveMore)
3089 const char *s = *startPtr;
3090 const char **eventPP;
3091 const char **eventEndPP;
3092 if (enc == encoding) {
3093 eventPP = &eventPtr;
3094 *eventPP = s;
3095 eventEndPP = &eventEndPtr;
3097 else {
3098 eventPP = &(openInternalEntities->internalEventPtr);
3099 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3101 *eventPP = s;
3102 *startPtr = NULL;
3104 for (;;) {
3105 const char *next;
3106 int tok = XmlCdataSectionTok(enc, s, end, &next);
3107 *eventEndPP = next;
3108 switch (tok) {
3109 case XML_TOK_CDATA_SECT_CLOSE:
3110 if (endCdataSectionHandler)
3111 endCdataSectionHandler(handlerArg);
3112 #if 0
3113 /* see comment under XML_TOK_CDATA_SECT_OPEN */
3114 else if (characterDataHandler)
3115 characterDataHandler(handlerArg, dataBuf, 0);
3116 #endif
3117 else if (defaultHandler)
3118 reportDefault(parser, enc, s, next);
3119 *startPtr = next;
3120 *nextPtr = next;
3121 if (ps_parsing == XML_FINISHED)
3122 return XML_ERROR_ABORTED;
3123 else
3124 return XML_ERROR_NONE;
3125 case XML_TOK_DATA_NEWLINE:
3126 if (characterDataHandler) {
3127 XML_Char c = 0xA;
3128 characterDataHandler(handlerArg, &c, 1);
3130 else if (defaultHandler)
3131 reportDefault(parser, enc, s, next);
3132 break;
3133 case XML_TOK_DATA_CHARS:
3135 XML_CharacterDataHandler charDataHandler = characterDataHandler;
3136 if (charDataHandler) {
3137 if (MUST_CONVERT(enc, s)) {
3138 for (;;) {
3139 ICHAR *dataPtr = (ICHAR *)dataBuf;
3140 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
3141 *eventEndPP = next;
3142 charDataHandler(handlerArg, dataBuf,
3143 (int)(dataPtr - (ICHAR *)dataBuf));
3144 if (s == next)
3145 break;
3146 *eventPP = s;
3149 else
3150 charDataHandler(handlerArg,
3151 (XML_Char *)s,
3152 (int)((XML_Char *)next - (XML_Char *)s));
3154 else if (defaultHandler)
3155 reportDefault(parser, enc, s, next);
3157 break;
3158 case XML_TOK_INVALID:
3159 *eventPP = next;
3160 return XML_ERROR_INVALID_TOKEN;
3161 case XML_TOK_PARTIAL_CHAR:
3162 if (haveMore) {
3163 *nextPtr = s;
3164 return XML_ERROR_NONE;
3166 return XML_ERROR_PARTIAL_CHAR;
3167 case XML_TOK_PARTIAL:
3168 case XML_TOK_NONE:
3169 if (haveMore) {
3170 *nextPtr = s;
3171 return XML_ERROR_NONE;
3173 return XML_ERROR_UNCLOSED_CDATA_SECTION;
3174 default:
3175 *eventPP = next;
3176 return XML_ERROR_UNEXPECTED_STATE;
3179 *eventPP = s = next;
3180 switch (ps_parsing) {
3181 case XML_SUSPENDED:
3182 *nextPtr = next;
3183 return XML_ERROR_NONE;
3184 case XML_FINISHED:
3185 return XML_ERROR_ABORTED;
3186 default: ;
3189 /* not reached */
3192 #ifdef XML_DTD
3194 /* The idea here is to avoid using stack for each IGNORE section when
3195 the whole file is parsed with one call.
3197 static enum XML_Error PTRCALL
3198 ignoreSectionProcessor(XML_Parser parser,
3199 const char *start,
3200 const char *end,
3201 const char **endPtr)
3203 enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
3204 endPtr, (XML_Bool)!ps_finalBuffer);
3205 if (result != XML_ERROR_NONE)
3206 return result;
3207 if (start) {
3208 processor = prologProcessor;
3209 return prologProcessor(parser, start, end, endPtr);
3211 return result;
3214 /* startPtr gets set to non-null is the section is closed, and to null
3215 if the section is not yet closed.
3217 static enum XML_Error
3218 doIgnoreSection(XML_Parser parser,
3219 const ENCODING *enc,
3220 const char **startPtr,
3221 const char *end,
3222 const char **nextPtr,
3223 XML_Bool haveMore)
3225 const char *next;
3226 int tok;
3227 const char *s = *startPtr;
3228 const char **eventPP;
3229 const char **eventEndPP;
3230 if (enc == encoding) {
3231 eventPP = &eventPtr;
3232 *eventPP = s;
3233 eventEndPP = &eventEndPtr;
3235 else {
3236 eventPP = &(openInternalEntities->internalEventPtr);
3237 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3239 *eventPP = s;
3240 *startPtr = NULL;
3241 tok = XmlIgnoreSectionTok(enc, s, end, &next);
3242 *eventEndPP = next;
3243 switch (tok) {
3244 case XML_TOK_IGNORE_SECT:
3245 if (defaultHandler)
3246 reportDefault(parser, enc, s, next);
3247 *startPtr = next;
3248 *nextPtr = next;
3249 if (ps_parsing == XML_FINISHED)
3250 return XML_ERROR_ABORTED;
3251 else
3252 return XML_ERROR_NONE;
3253 case XML_TOK_INVALID:
3254 *eventPP = next;
3255 return XML_ERROR_INVALID_TOKEN;
3256 case XML_TOK_PARTIAL_CHAR:
3257 if (haveMore) {
3258 *nextPtr = s;
3259 return XML_ERROR_NONE;
3261 return XML_ERROR_PARTIAL_CHAR;
3262 case XML_TOK_PARTIAL:
3263 case XML_TOK_NONE:
3264 if (haveMore) {
3265 *nextPtr = s;
3266 return XML_ERROR_NONE;
3268 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3269 default:
3270 *eventPP = next;
3271 return XML_ERROR_UNEXPECTED_STATE;
3273 /* not reached */
3276 #endif /* XML_DTD */
3278 static enum XML_Error
3279 initializeEncoding(XML_Parser parser)
3281 const char *s;
3282 #ifdef XML_UNICODE
3283 char encodingBuf[128];
3284 if (!protocolEncodingName)
3285 s = NULL;
3286 else {
3287 int i;
3288 for (i = 0; protocolEncodingName[i]; i++) {
3289 if (i == sizeof(encodingBuf) - 1
3290 || (protocolEncodingName[i] & ~0x7f) != 0) {
3291 encodingBuf[0] = '\0';
3292 break;
3294 encodingBuf[i] = (char)protocolEncodingName[i];
3296 encodingBuf[i] = '\0';
3297 s = encodingBuf;
3299 #else
3300 s = protocolEncodingName;
3301 #endif
3302 if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
3303 return XML_ERROR_NONE;
3304 return handleUnknownEncoding(parser, protocolEncodingName);
3307 static enum XML_Error
3308 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
3309 const char *s, const char *next)
3311 const char *encodingName = NULL;
3312 const XML_Char *storedEncName = NULL;
3313 const ENCODING *newEncoding = NULL;
3314 const char *version = NULL;
3315 const char *versionend;
3316 const XML_Char *storedversion = NULL;
3317 int standalone = -1;
3318 if (!(ns
3319 ? XmlParseXmlDeclNS
3320 : XmlParseXmlDecl)(isGeneralTextEntity,
3321 encoding,
3323 next,
3324 &eventPtr,
3325 &version,
3326 &versionend,
3327 &encodingName,
3328 &newEncoding,
3329 &standalone)) {
3330 if (isGeneralTextEntity)
3331 return XML_ERROR_TEXT_DECL;
3332 else
3333 return XML_ERROR_XML_DECL;
3335 if (!isGeneralTextEntity && standalone == 1) {
3336 _dtd->standalone = XML_TRUE;
3337 #ifdef XML_DTD
3338 if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
3339 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
3340 #endif /* XML_DTD */
3342 if (xmlDeclHandler) {
3343 if (encodingName != NULL) {
3344 storedEncName = poolStoreString(&temp2Pool,
3345 encoding,
3346 encodingName,
3347 encodingName
3348 + XmlNameLength(encoding, encodingName));
3349 if (!storedEncName)
3350 return XML_ERROR_NO_MEMORY;
3351 poolFinish(&temp2Pool);
3353 if (version) {
3354 storedversion = poolStoreString(&temp2Pool,
3355 encoding,
3356 version,
3357 versionend - encoding->minBytesPerChar);
3358 if (!storedversion)
3359 return XML_ERROR_NO_MEMORY;
3361 xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
3363 else if (defaultHandler)
3364 reportDefault(parser, encoding, s, next);
3365 if (protocolEncodingName == NULL) {
3366 if (newEncoding) {
3367 if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
3368 eventPtr = encodingName;
3369 return XML_ERROR_INCORRECT_ENCODING;
3371 encoding = newEncoding;
3373 else if (encodingName) {
3374 enum XML_Error result;
3375 if (!storedEncName) {
3376 storedEncName = poolStoreString(
3377 &temp2Pool, encoding, encodingName,
3378 encodingName + XmlNameLength(encoding, encodingName));
3379 if (!storedEncName)
3380 return XML_ERROR_NO_MEMORY;
3382 result = handleUnknownEncoding(parser, storedEncName);
3383 poolClear(&temp2Pool);
3384 if (result == XML_ERROR_UNKNOWN_ENCODING)
3385 eventPtr = encodingName;
3386 return result;
3390 if (storedEncName || storedversion)
3391 poolClear(&temp2Pool);
3393 return XML_ERROR_NONE;
3396 static enum XML_Error
3397 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
3399 if (unknownEncodingHandler) {
3400 XML_Encoding info;
3401 int i;
3402 for (i = 0; i < 256; i++)
3403 info.map[i] = -1;
3404 info.convert = NULL;
3405 info.data = NULL;
3406 info.release = NULL;
3407 if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
3408 &info)) {
3409 ENCODING *enc;
3410 unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
3411 if (!unknownEncodingMem) {
3412 if (info.release)
3413 info.release(info.data);
3414 return XML_ERROR_NO_MEMORY;
3416 enc = (ns
3417 ? XmlInitUnknownEncodingNS
3418 : XmlInitUnknownEncoding)(unknownEncodingMem,
3419 info.map,
3420 info.convert,
3421 info.data);
3422 if (enc) {
3423 unknownEncodingData = info.data;
3424 unknownEncodingRelease = info.release;
3425 encoding = enc;
3426 return XML_ERROR_NONE;
3429 if (info.release != NULL)
3430 info.release(info.data);
3432 return XML_ERROR_UNKNOWN_ENCODING;
3435 static enum XML_Error PTRCALL
3436 prologInitProcessor(XML_Parser parser,
3437 const char *s,
3438 const char *end,
3439 const char **nextPtr)
3441 enum XML_Error result = initializeEncoding(parser);
3442 if (result != XML_ERROR_NONE)
3443 return result;
3444 processor = prologProcessor;
3445 return prologProcessor(parser, s, end, nextPtr);
3448 #ifdef XML_DTD
3450 static enum XML_Error PTRCALL
3451 externalParEntInitProcessor(XML_Parser parser,
3452 const char *s,
3453 const char *end,
3454 const char **nextPtr)
3456 enum XML_Error result = initializeEncoding(parser);
3457 if (result != XML_ERROR_NONE)
3458 return result;
3460 /* we know now that XML_Parse(Buffer) has been called,
3461 so we consider the external parameter entity read */
3462 _dtd->paramEntityRead = XML_TRUE;
3464 if (prologState.inEntityValue) {
3465 processor = entityValueInitProcessor;
3466 return entityValueInitProcessor(parser, s, end, nextPtr);
3468 else {
3469 processor = externalParEntProcessor;
3470 return externalParEntProcessor(parser, s, end, nextPtr);
3474 static enum XML_Error PTRCALL
3475 entityValueInitProcessor(XML_Parser parser,
3476 const char *s,
3477 const char *end,
3478 const char **nextPtr)
3480 int tok;
3481 const char *start = s;
3482 const char *next = start;
3483 eventPtr = start;
3485 for (;;) {
3486 tok = XmlPrologTok(encoding, start, end, &next);
3487 eventEndPtr = next;
3488 if (tok <= 0) {
3489 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3490 *nextPtr = s;
3491 return XML_ERROR_NONE;
3493 switch (tok) {
3494 case XML_TOK_INVALID:
3495 return XML_ERROR_INVALID_TOKEN;
3496 case XML_TOK_PARTIAL:
3497 return XML_ERROR_UNCLOSED_TOKEN;
3498 case XML_TOK_PARTIAL_CHAR:
3499 return XML_ERROR_PARTIAL_CHAR;
3500 case XML_TOK_NONE: /* start == end */
3501 default:
3502 break;
3504 /* found end of entity value - can store it now */
3505 return storeEntityValue(parser, encoding, s, end);
3507 else if (tok == XML_TOK_XML_DECL) {
3508 enum XML_Error result;
3509 result = processXmlDecl(parser, 0, start, next);
3510 if (result != XML_ERROR_NONE)
3511 return result;
3512 switch (ps_parsing) {
3513 case XML_SUSPENDED:
3514 *nextPtr = next;
3515 return XML_ERROR_NONE;
3516 case XML_FINISHED:
3517 return XML_ERROR_ABORTED;
3518 default:
3519 *nextPtr = next;
3521 /* stop scanning for text declaration - we found one */
3522 processor = entityValueProcessor;
3523 return entityValueProcessor(parser, next, end, nextPtr);
3525 /* If we are at the end of the buffer, this would cause XmlPrologTok to
3526 return XML_TOK_NONE on the next call, which would then cause the
3527 function to exit with *nextPtr set to s - that is what we want for other
3528 tokens, but not for the BOM - we would rather like to skip it;
3529 then, when this routine is entered the next time, XmlPrologTok will
3530 return XML_TOK_INVALID, since the BOM is still in the buffer
3532 else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
3533 *nextPtr = next;
3534 return XML_ERROR_NONE;
3536 start = next;
3537 eventPtr = start;
3541 static enum XML_Error PTRCALL
3542 externalParEntProcessor(XML_Parser parser,
3543 const char *s,
3544 const char *end,
3545 const char **nextPtr)
3547 const char *next = s;
3548 int tok;
3550 tok = XmlPrologTok(encoding, s, end, &next);
3551 if (tok <= 0) {
3552 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3553 *nextPtr = s;
3554 return XML_ERROR_NONE;
3556 switch (tok) {
3557 case XML_TOK_INVALID:
3558 return XML_ERROR_INVALID_TOKEN;
3559 case XML_TOK_PARTIAL:
3560 return XML_ERROR_UNCLOSED_TOKEN;
3561 case XML_TOK_PARTIAL_CHAR:
3562 return XML_ERROR_PARTIAL_CHAR;
3563 case XML_TOK_NONE: /* start == end */
3564 default:
3565 break;
3568 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
3569 However, when parsing an external subset, doProlog will not accept a BOM
3570 as valid, and report a syntax error, so we have to skip the BOM
3572 else if (tok == XML_TOK_BOM) {
3573 s = next;
3574 tok = XmlPrologTok(encoding, s, end, &next);
3577 processor = prologProcessor;
3578 return doProlog(parser, encoding, s, end, tok, next,
3579 nextPtr, (XML_Bool)!ps_finalBuffer);
3582 static enum XML_Error PTRCALL
3583 entityValueProcessor(XML_Parser parser,
3584 const char *s,
3585 const char *end,
3586 const char **nextPtr)
3588 const char *start = s;
3589 const char *next = s;
3590 const ENCODING *enc = encoding;
3591 int tok;
3593 for (;;) {
3594 tok = XmlPrologTok(enc, start, end, &next);
3595 if (tok <= 0) {
3596 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
3597 *nextPtr = s;
3598 return XML_ERROR_NONE;
3600 switch (tok) {
3601 case XML_TOK_INVALID:
3602 return XML_ERROR_INVALID_TOKEN;
3603 case XML_TOK_PARTIAL:
3604 return XML_ERROR_UNCLOSED_TOKEN;
3605 case XML_TOK_PARTIAL_CHAR:
3606 return XML_ERROR_PARTIAL_CHAR;
3607 case XML_TOK_NONE: /* start == end */
3608 default:
3609 break;
3611 /* found end of entity value - can store it now */
3612 return storeEntityValue(parser, enc, s, end);
3614 start = next;
3618 #endif /* XML_DTD */
3620 static enum XML_Error PTRCALL
3621 prologProcessor(XML_Parser parser,
3622 const char *s,
3623 const char *end,
3624 const char **nextPtr)
3626 const char *next = s;
3627 int tok = XmlPrologTok(encoding, s, end, &next);
3628 return doProlog(parser, encoding, s, end, tok, next,
3629 nextPtr, (XML_Bool)!ps_finalBuffer);
3632 static enum XML_Error
3633 doProlog(XML_Parser parser,
3634 const ENCODING *enc,
3635 const char *s,
3636 const char *end,
3637 int tok,
3638 const char *next,
3639 const char **nextPtr,
3640 XML_Bool haveMore)
3642 #ifdef XML_DTD
3643 static const XML_Char externalSubsetName[] = { '#' , '\0' };
3644 #endif /* XML_DTD */
3645 static const XML_Char atypeCDATA[] = { 'C', 'D', 'A', 'T', 'A', '\0' };
3646 static const XML_Char atypeID[] = { 'I', 'D', '\0' };
3647 static const XML_Char atypeIDREF[] = { 'I', 'D', 'R', 'E', 'F', '\0' };
3648 static const XML_Char atypeIDREFS[] = { 'I', 'D', 'R', 'E', 'F', 'S', '\0' };
3649 static const XML_Char atypeENTITY[] = { 'E', 'N', 'T', 'I', 'T', 'Y', '\0' };
3650 static const XML_Char atypeENTITIES[] =
3651 { 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S', '\0' };
3652 static const XML_Char atypeNMTOKEN[] = {
3653 'N', 'M', 'T', 'O', 'K', 'E', 'N', '\0' };
3654 static const XML_Char atypeNMTOKENS[] = {
3655 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S', '\0' };
3656 static const XML_Char notationPrefix[] = {
3657 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', '(', '\0' };
3658 static const XML_Char enumValueSep[] = { '|', '\0' };
3659 static const XML_Char enumValueStart[] = { '(', '\0' };
3661 /* save one level of indirection */
3662 DTD * const dtd = _dtd;
3664 const char **eventPP;
3665 const char **eventEndPP;
3666 enum XML_Content_Quant quant;
3668 if (enc == encoding) {
3669 eventPP = &eventPtr;
3670 eventEndPP = &eventEndPtr;
3672 else {
3673 eventPP = &(openInternalEntities->internalEventPtr);
3674 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3677 for (;;) {
3678 int role;
3679 XML_Bool handleDefault = XML_TRUE;
3680 *eventPP = s;
3681 *eventEndPP = next;
3682 if (tok <= 0) {
3683 if (haveMore && tok != XML_TOK_INVALID) {
3684 *nextPtr = s;
3685 return XML_ERROR_NONE;
3687 switch (tok) {
3688 case XML_TOK_INVALID:
3689 *eventPP = next;
3690 return XML_ERROR_INVALID_TOKEN;
3691 case XML_TOK_PARTIAL:
3692 return XML_ERROR_UNCLOSED_TOKEN;
3693 case XML_TOK_PARTIAL_CHAR:
3694 return XML_ERROR_PARTIAL_CHAR;
3695 case XML_TOK_NONE:
3696 #ifdef XML_DTD
3697 /* for internal PE NOT referenced between declarations */
3698 if (enc != encoding && !openInternalEntities->betweenDecl) {
3699 *nextPtr = s;
3700 return XML_ERROR_NONE;
3702 /* WFC: PE Between Declarations - must check that PE contains
3703 complete markup, not only for external PEs, but also for
3704 internal PEs if the reference occurs between declarations.
3706 if (isParamEntity || enc != encoding) {
3707 if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
3708 == XML_ROLE_ERROR)
3709 return XML_ERROR_INCOMPLETE_PE;
3710 *nextPtr = s;
3711 return XML_ERROR_NONE;
3713 #endif /* XML_DTD */
3714 return XML_ERROR_NO_ELEMENTS;
3715 default:
3716 tok = -tok;
3717 next = end;
3718 break;
3721 role = XmlTokenRole(&prologState, tok, s, next, enc);
3722 switch (role) {
3723 case XML_ROLE_XML_DECL:
3725 enum XML_Error result = processXmlDecl(parser, 0, s, next);
3726 if (result != XML_ERROR_NONE)
3727 return result;
3728 enc = encoding;
3729 handleDefault = XML_FALSE;
3731 break;
3732 case XML_ROLE_DOCTYPE_NAME:
3733 if (startDoctypeDeclHandler) {
3734 doctypeName = poolStoreString(&tempPool, enc, s, next);
3735 if (!doctypeName)
3736 return XML_ERROR_NO_MEMORY;
3737 poolFinish(&tempPool);
3738 doctypePubid = NULL;
3739 handleDefault = XML_FALSE;
3741 doctypeSysid = NULL; /* always initialize to NULL */
3742 break;
3743 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
3744 if (startDoctypeDeclHandler) {
3745 startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
3746 doctypePubid, 1);
3747 doctypeName = NULL;
3748 poolClear(&tempPool);
3749 handleDefault = XML_FALSE;
3751 break;
3752 #ifdef XML_DTD
3753 case XML_ROLE_TEXT_DECL:
3755 enum XML_Error result = processXmlDecl(parser, 1, s, next);
3756 if (result != XML_ERROR_NONE)
3757 return result;
3758 enc = encoding;
3759 handleDefault = XML_FALSE;
3761 break;
3762 #endif /* XML_DTD */
3763 case XML_ROLE_DOCTYPE_PUBLIC_ID:
3764 #ifdef XML_DTD
3765 useForeignDTD = XML_FALSE;
3766 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
3767 externalSubsetName,
3768 sizeof(ENTITY));
3769 if (!declEntity)
3770 return XML_ERROR_NO_MEMORY;
3771 #endif /* XML_DTD */
3772 dtd->hasParamEntityRefs = XML_TRUE;
3773 if (startDoctypeDeclHandler) {
3774 if (!XmlIsPublicId(enc, s, next, eventPP))
3775 return XML_ERROR_PUBLICID;
3776 doctypePubid = poolStoreString(&tempPool, enc,
3777 s + enc->minBytesPerChar,
3778 next - enc->minBytesPerChar);
3779 if (!doctypePubid)
3780 return XML_ERROR_NO_MEMORY;
3781 normalizePublicId((XML_Char *)doctypePubid);
3782 poolFinish(&tempPool);
3783 handleDefault = XML_FALSE;
3784 goto alreadyChecked;
3786 /* fall through */
3787 case XML_ROLE_ENTITY_PUBLIC_ID:
3788 if (!XmlIsPublicId(enc, s, next, eventPP))
3789 return XML_ERROR_PUBLICID;
3790 alreadyChecked:
3791 if (dtd->keepProcessing && declEntity) {
3792 XML_Char *tem = poolStoreString(&dtd->pool,
3793 enc,
3794 s + enc->minBytesPerChar,
3795 next - enc->minBytesPerChar);
3796 if (!tem)
3797 return XML_ERROR_NO_MEMORY;
3798 normalizePublicId(tem);
3799 declEntity->publicId = tem;
3800 poolFinish(&dtd->pool);
3801 if (entityDeclHandler)
3802 handleDefault = XML_FALSE;
3804 break;
3805 case XML_ROLE_DOCTYPE_CLOSE:
3806 if (doctypeName) {
3807 startDoctypeDeclHandler(handlerArg, doctypeName,
3808 doctypeSysid, doctypePubid, 0);
3809 poolClear(&tempPool);
3810 handleDefault = XML_FALSE;
3812 /* doctypeSysid will be non-NULL in the case of a previous
3813 XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
3814 was not set, indicating an external subset
3816 #ifdef XML_DTD
3817 if (doctypeSysid || useForeignDTD) {
3818 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3819 dtd->hasParamEntityRefs = XML_TRUE;
3820 if (paramEntityParsing && externalEntityRefHandler) {
3821 ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
3822 externalSubsetName,
3823 sizeof(ENTITY));
3824 if (!entity)
3825 return XML_ERROR_NO_MEMORY;
3826 if (useForeignDTD)
3827 entity->base = curBase;
3828 dtd->paramEntityRead = XML_FALSE;
3829 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3831 entity->base,
3832 entity->systemId,
3833 entity->publicId))
3834 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3835 if (dtd->paramEntityRead) {
3836 if (!dtd->standalone &&
3837 notStandaloneHandler &&
3838 !notStandaloneHandler(handlerArg))
3839 return XML_ERROR_NOT_STANDALONE;
3841 /* if we didn't read the foreign DTD then this means that there
3842 is no external subset and we must reset dtd->hasParamEntityRefs
3844 else if (!doctypeSysid)
3845 dtd->hasParamEntityRefs = hadParamEntityRefs;
3846 /* end of DTD - no need to update dtd->keepProcessing */
3848 useForeignDTD = XML_FALSE;
3850 #endif /* XML_DTD */
3851 if (endDoctypeDeclHandler) {
3852 endDoctypeDeclHandler(handlerArg);
3853 handleDefault = XML_FALSE;
3855 break;
3856 case XML_ROLE_INSTANCE_START:
3857 #ifdef XML_DTD
3858 /* if there is no DOCTYPE declaration then now is the
3859 last chance to read the foreign DTD
3861 if (useForeignDTD) {
3862 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
3863 dtd->hasParamEntityRefs = XML_TRUE;
3864 if (paramEntityParsing && externalEntityRefHandler) {
3865 ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
3866 externalSubsetName,
3867 sizeof(ENTITY));
3868 if (!entity)
3869 return XML_ERROR_NO_MEMORY;
3870 entity->base = curBase;
3871 dtd->paramEntityRead = XML_FALSE;
3872 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3874 entity->base,
3875 entity->systemId,
3876 entity->publicId))
3877 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3878 if (dtd->paramEntityRead) {
3879 if (!dtd->standalone &&
3880 notStandaloneHandler &&
3881 !notStandaloneHandler(handlerArg))
3882 return XML_ERROR_NOT_STANDALONE;
3884 /* if we didn't read the foreign DTD then this means that there
3885 is no external subset and we must reset dtd->hasParamEntityRefs
3887 else
3888 dtd->hasParamEntityRefs = hadParamEntityRefs;
3889 /* end of DTD - no need to update dtd->keepProcessing */
3892 #endif /* XML_DTD */
3893 processor = contentProcessor;
3894 return contentProcessor(parser, s, end, nextPtr);
3895 case XML_ROLE_ATTLIST_ELEMENT_NAME:
3896 declElementType = getElementType(parser, enc, s, next);
3897 if (!declElementType)
3898 return XML_ERROR_NO_MEMORY;
3899 goto checkAttListDeclHandler;
3900 case XML_ROLE_ATTRIBUTE_NAME:
3901 declAttributeId = getAttributeId(parser, enc, s, next);
3902 if (!declAttributeId)
3903 return XML_ERROR_NO_MEMORY;
3904 declAttributeIsCdata = XML_FALSE;
3905 declAttributeType = NULL;
3906 declAttributeIsId = XML_FALSE;
3907 goto checkAttListDeclHandler;
3908 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
3909 declAttributeIsCdata = XML_TRUE;
3910 declAttributeType = atypeCDATA;
3911 goto checkAttListDeclHandler;
3912 case XML_ROLE_ATTRIBUTE_TYPE_ID:
3913 declAttributeIsId = XML_TRUE;
3914 declAttributeType = atypeID;
3915 goto checkAttListDeclHandler;
3916 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
3917 declAttributeType = atypeIDREF;
3918 goto checkAttListDeclHandler;
3919 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
3920 declAttributeType = atypeIDREFS;
3921 goto checkAttListDeclHandler;
3922 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
3923 declAttributeType = atypeENTITY;
3924 goto checkAttListDeclHandler;
3925 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
3926 declAttributeType = atypeENTITIES;
3927 goto checkAttListDeclHandler;
3928 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
3929 declAttributeType = atypeNMTOKEN;
3930 goto checkAttListDeclHandler;
3931 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
3932 declAttributeType = atypeNMTOKENS;
3933 checkAttListDeclHandler:
3934 if (dtd->keepProcessing && attlistDeclHandler)
3935 handleDefault = XML_FALSE;
3936 break;
3937 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
3938 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
3939 if (dtd->keepProcessing && attlistDeclHandler) {
3940 const XML_Char *prefix;
3941 if (declAttributeType) {
3942 prefix = enumValueSep;
3944 else {
3945 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
3946 ? notationPrefix
3947 : enumValueStart);
3949 if (!poolAppendString(&tempPool, prefix))
3950 return XML_ERROR_NO_MEMORY;
3951 if (!poolAppend(&tempPool, enc, s, next))
3952 return XML_ERROR_NO_MEMORY;
3953 declAttributeType = tempPool.start;
3954 handleDefault = XML_FALSE;
3956 break;
3957 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
3958 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
3959 if (dtd->keepProcessing) {
3960 if (!defineAttribute(declElementType, declAttributeId,
3961 declAttributeIsCdata, declAttributeIsId,
3962 0, parser))
3963 return XML_ERROR_NO_MEMORY;
3964 if (attlistDeclHandler && declAttributeType) {
3965 if (*declAttributeType == XML_T('(')
3966 || (*declAttributeType == XML_T('N')
3967 && declAttributeType[1] == XML_T('O'))) {
3968 /* Enumerated or Notation type */
3969 if (!poolAppendChar(&tempPool, XML_T(')'))
3970 || !poolAppendChar(&tempPool, XML_T('\0')))
3971 return XML_ERROR_NO_MEMORY;
3972 declAttributeType = tempPool.start;
3973 poolFinish(&tempPool);
3975 *eventEndPP = s;
3976 attlistDeclHandler(handlerArg, declElementType->name,
3977 declAttributeId->name, declAttributeType,
3978 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
3979 poolClear(&tempPool);
3980 handleDefault = XML_FALSE;
3983 break;
3984 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
3985 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
3986 if (dtd->keepProcessing) {
3987 const XML_Char *attVal;
3988 enum XML_Error result =
3989 storeAttributeValue(parser, enc, declAttributeIsCdata,
3990 s + enc->minBytesPerChar,
3991 next - enc->minBytesPerChar,
3992 &dtd->pool);
3993 if (result)
3994 return result;
3995 attVal = poolStart(&dtd->pool);
3996 poolFinish(&dtd->pool);
3997 /* ID attributes aren't allowed to have a default */
3998 if (!defineAttribute(declElementType, declAttributeId,
3999 declAttributeIsCdata, XML_FALSE, attVal, parser))
4000 return XML_ERROR_NO_MEMORY;
4001 if (attlistDeclHandler && declAttributeType) {
4002 if (*declAttributeType == XML_T('(')
4003 || (*declAttributeType == XML_T('N')
4004 && declAttributeType[1] == XML_T('O'))) {
4005 /* Enumerated or Notation type */
4006 if (!poolAppendChar(&tempPool, XML_T(')'))
4007 || !poolAppendChar(&tempPool, XML_T('\0')))
4008 return XML_ERROR_NO_MEMORY;
4009 declAttributeType = tempPool.start;
4010 poolFinish(&tempPool);
4012 *eventEndPP = s;
4013 attlistDeclHandler(handlerArg, declElementType->name,
4014 declAttributeId->name, declAttributeType,
4015 attVal,
4016 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
4017 poolClear(&tempPool);
4018 handleDefault = XML_FALSE;
4021 break;
4022 case XML_ROLE_ENTITY_VALUE:
4023 if (dtd->keepProcessing) {
4024 enum XML_Error result = storeEntityValue(parser, enc,
4025 s + enc->minBytesPerChar,
4026 next - enc->minBytesPerChar);
4027 if (declEntity) {
4028 declEntity->textPtr = poolStart(&dtd->entityValuePool);
4029 declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
4030 poolFinish(&dtd->entityValuePool);
4031 if (entityDeclHandler) {
4032 *eventEndPP = s;
4033 entityDeclHandler(handlerArg,
4034 declEntity->name,
4035 declEntity->is_param,
4036 declEntity->textPtr,
4037 declEntity->textLen,
4038 curBase, 0, 0, 0);
4039 handleDefault = XML_FALSE;
4042 else
4043 poolDiscard(&dtd->entityValuePool);
4044 if (result != XML_ERROR_NONE)
4045 return result;
4047 break;
4048 case XML_ROLE_DOCTYPE_SYSTEM_ID:
4049 #ifdef XML_DTD
4050 useForeignDTD = XML_FALSE;
4051 #endif /* XML_DTD */
4052 dtd->hasParamEntityRefs = XML_TRUE;
4053 if (startDoctypeDeclHandler) {
4054 doctypeSysid = poolStoreString(&tempPool, enc,
4055 s + enc->minBytesPerChar,
4056 next - enc->minBytesPerChar);
4057 if (doctypeSysid == NULL)
4058 return XML_ERROR_NO_MEMORY;
4059 poolFinish(&tempPool);
4060 handleDefault = XML_FALSE;
4062 #ifdef XML_DTD
4063 else
4064 /* use externalSubsetName to make doctypeSysid non-NULL
4065 for the case where no startDoctypeDeclHandler is set */
4066 doctypeSysid = externalSubsetName;
4067 #endif /* XML_DTD */
4068 if (!dtd->standalone
4069 #ifdef XML_DTD
4070 && !paramEntityParsing
4071 #endif /* XML_DTD */
4072 && notStandaloneHandler
4073 && !notStandaloneHandler(handlerArg))
4074 return XML_ERROR_NOT_STANDALONE;
4075 #ifndef XML_DTD
4076 break;
4077 #else /* XML_DTD */
4078 if (!declEntity) {
4079 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
4080 externalSubsetName,
4081 sizeof(ENTITY));
4082 if (!declEntity)
4083 return XML_ERROR_NO_MEMORY;
4084 declEntity->publicId = NULL;
4086 /* fall through */
4087 #endif /* XML_DTD */
4088 case XML_ROLE_ENTITY_SYSTEM_ID:
4089 if (dtd->keepProcessing && declEntity) {
4090 declEntity->systemId = poolStoreString(&dtd->pool, enc,
4091 s + enc->minBytesPerChar,
4092 next - enc->minBytesPerChar);
4093 if (!declEntity->systemId)
4094 return XML_ERROR_NO_MEMORY;
4095 declEntity->base = curBase;
4096 poolFinish(&dtd->pool);
4097 if (entityDeclHandler)
4098 handleDefault = XML_FALSE;
4100 break;
4101 case XML_ROLE_ENTITY_COMPLETE:
4102 if (dtd->keepProcessing && declEntity && entityDeclHandler) {
4103 *eventEndPP = s;
4104 entityDeclHandler(handlerArg,
4105 declEntity->name,
4106 declEntity->is_param,
4107 0,0,
4108 declEntity->base,
4109 declEntity->systemId,
4110 declEntity->publicId,
4112 handleDefault = XML_FALSE;
4114 break;
4115 case XML_ROLE_ENTITY_NOTATION_NAME:
4116 if (dtd->keepProcessing && declEntity) {
4117 declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
4118 if (!declEntity->notation)
4119 return XML_ERROR_NO_MEMORY;
4120 poolFinish(&dtd->pool);
4121 if (unparsedEntityDeclHandler) {
4122 *eventEndPP = s;
4123 unparsedEntityDeclHandler(handlerArg,
4124 declEntity->name,
4125 declEntity->base,
4126 declEntity->systemId,
4127 declEntity->publicId,
4128 declEntity->notation);
4129 handleDefault = XML_FALSE;
4131 else if (entityDeclHandler) {
4132 *eventEndPP = s;
4133 entityDeclHandler(handlerArg,
4134 declEntity->name,
4135 0,0,0,
4136 declEntity->base,
4137 declEntity->systemId,
4138 declEntity->publicId,
4139 declEntity->notation);
4140 handleDefault = XML_FALSE;
4143 break;
4144 case XML_ROLE_GENERAL_ENTITY_NAME:
4146 if (XmlPredefinedEntityName(enc, s, next)) {
4147 declEntity = NULL;
4148 break;
4150 if (dtd->keepProcessing) {
4151 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4152 if (!name)
4153 return XML_ERROR_NO_MEMORY;
4154 declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
4155 sizeof(ENTITY));
4156 if (!declEntity)
4157 return XML_ERROR_NO_MEMORY;
4158 if (declEntity->name != name) {
4159 poolDiscard(&dtd->pool);
4160 declEntity = NULL;
4162 else {
4163 poolFinish(&dtd->pool);
4164 declEntity->publicId = NULL;
4165 declEntity->is_param = XML_FALSE;
4166 /* if we have a parent parser or are reading an internal parameter
4167 entity, then the entity declaration is not considered "internal"
4169 declEntity->is_internal = !(parentParser || openInternalEntities);
4170 if (entityDeclHandler)
4171 handleDefault = XML_FALSE;
4174 else {
4175 poolDiscard(&dtd->pool);
4176 declEntity = NULL;
4179 break;
4180 case XML_ROLE_PARAM_ENTITY_NAME:
4181 #ifdef XML_DTD
4182 if (dtd->keepProcessing) {
4183 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4184 if (!name)
4185 return XML_ERROR_NO_MEMORY;
4186 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
4187 name, sizeof(ENTITY));
4188 if (!declEntity)
4189 return XML_ERROR_NO_MEMORY;
4190 if (declEntity->name != name) {
4191 poolDiscard(&dtd->pool);
4192 declEntity = NULL;
4194 else {
4195 poolFinish(&dtd->pool);
4196 declEntity->publicId = NULL;
4197 declEntity->is_param = XML_TRUE;
4198 /* if we have a parent parser or are reading an internal parameter
4199 entity, then the entity declaration is not considered "internal"
4201 declEntity->is_internal = !(parentParser || openInternalEntities);
4202 if (entityDeclHandler)
4203 handleDefault = XML_FALSE;
4206 else {
4207 poolDiscard(&dtd->pool);
4208 declEntity = NULL;
4210 #else /* not XML_DTD */
4211 declEntity = NULL;
4212 #endif /* XML_DTD */
4213 break;
4214 case XML_ROLE_NOTATION_NAME:
4215 declNotationPublicId = NULL;
4216 declNotationName = NULL;
4217 if (notationDeclHandler) {
4218 declNotationName = poolStoreString(&tempPool, enc, s, next);
4219 if (!declNotationName)
4220 return XML_ERROR_NO_MEMORY;
4221 poolFinish(&tempPool);
4222 handleDefault = XML_FALSE;
4224 break;
4225 case XML_ROLE_NOTATION_PUBLIC_ID:
4226 if (!XmlIsPublicId(enc, s, next, eventPP))
4227 return XML_ERROR_PUBLICID;
4228 if (declNotationName) { /* means notationDeclHandler != NULL */
4229 XML_Char *tem = poolStoreString(&tempPool,
4230 enc,
4231 s + enc->minBytesPerChar,
4232 next - enc->minBytesPerChar);
4233 if (!tem)
4234 return XML_ERROR_NO_MEMORY;
4235 normalizePublicId(tem);
4236 declNotationPublicId = tem;
4237 poolFinish(&tempPool);
4238 handleDefault = XML_FALSE;
4240 break;
4241 case XML_ROLE_NOTATION_SYSTEM_ID:
4242 if (declNotationName && notationDeclHandler) {
4243 const XML_Char *systemId
4244 = poolStoreString(&tempPool, enc,
4245 s + enc->minBytesPerChar,
4246 next - enc->minBytesPerChar);
4247 if (!systemId)
4248 return XML_ERROR_NO_MEMORY;
4249 *eventEndPP = s;
4250 notationDeclHandler(handlerArg,
4251 declNotationName,
4252 curBase,
4253 systemId,
4254 declNotationPublicId);
4255 handleDefault = XML_FALSE;
4257 poolClear(&tempPool);
4258 break;
4259 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
4260 if (declNotationPublicId && notationDeclHandler) {
4261 *eventEndPP = s;
4262 notationDeclHandler(handlerArg,
4263 declNotationName,
4264 curBase,
4266 declNotationPublicId);
4267 handleDefault = XML_FALSE;
4269 poolClear(&tempPool);
4270 break;
4271 case XML_ROLE_ERROR:
4272 switch (tok) {
4273 case XML_TOK_PARAM_ENTITY_REF:
4274 /* PE references in internal subset are
4275 not allowed within declarations. */
4276 return XML_ERROR_PARAM_ENTITY_REF;
4277 case XML_TOK_XML_DECL:
4278 return XML_ERROR_MISPLACED_XML_PI;
4279 default:
4280 return XML_ERROR_SYNTAX;
4282 #ifdef XML_DTD
4283 case XML_ROLE_IGNORE_SECT:
4285 enum XML_Error result;
4286 if (defaultHandler)
4287 reportDefault(parser, enc, s, next);
4288 handleDefault = XML_FALSE;
4289 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
4290 if (result != XML_ERROR_NONE)
4291 return result;
4292 else if (!next) {
4293 processor = ignoreSectionProcessor;
4294 return result;
4297 break;
4298 #endif /* XML_DTD */
4299 case XML_ROLE_GROUP_OPEN:
4300 if (prologState.level >= groupSize) {
4301 if (groupSize) {
4302 char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
4303 if (temp == NULL)
4304 return XML_ERROR_NO_MEMORY;
4305 groupConnector = temp;
4306 if (dtd->scaffIndex) {
4307 int *temp = (int *)REALLOC(dtd->scaffIndex,
4308 groupSize * sizeof(int));
4309 if (temp == NULL)
4310 return XML_ERROR_NO_MEMORY;
4311 dtd->scaffIndex = temp;
4314 else {
4315 groupConnector = (char *)MALLOC(groupSize = 32);
4316 if (!groupConnector)
4317 return XML_ERROR_NO_MEMORY;
4320 groupConnector[prologState.level] = 0;
4321 if (dtd->in_eldecl) {
4322 int myindex = nextScaffoldPart(parser);
4323 if (myindex < 0)
4324 return XML_ERROR_NO_MEMORY;
4325 dtd->scaffIndex[dtd->scaffLevel] = myindex;
4326 dtd->scaffLevel++;
4327 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
4328 if (elementDeclHandler)
4329 handleDefault = XML_FALSE;
4331 break;
4332 case XML_ROLE_GROUP_SEQUENCE:
4333 if (groupConnector[prologState.level] == '|')
4334 return XML_ERROR_SYNTAX;
4335 groupConnector[prologState.level] = ',';
4336 if (dtd->in_eldecl && elementDeclHandler)
4337 handleDefault = XML_FALSE;
4338 break;
4339 case XML_ROLE_GROUP_CHOICE:
4340 if (groupConnector[prologState.level] == ',')
4341 return XML_ERROR_SYNTAX;
4342 if (dtd->in_eldecl
4343 && !groupConnector[prologState.level]
4344 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4345 != XML_CTYPE_MIXED)
4347 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4348 = XML_CTYPE_CHOICE;
4349 if (elementDeclHandler)
4350 handleDefault = XML_FALSE;
4352 groupConnector[prologState.level] = '|';
4353 break;
4354 case XML_ROLE_PARAM_ENTITY_REF:
4355 #ifdef XML_DTD
4356 case XML_ROLE_INNER_PARAM_ENTITY_REF:
4357 dtd->hasParamEntityRefs = XML_TRUE;
4358 if (!paramEntityParsing)
4359 dtd->keepProcessing = dtd->standalone;
4360 else {
4361 const XML_Char *name;
4362 ENTITY *entity;
4363 name = poolStoreString(&dtd->pool, enc,
4364 s + enc->minBytesPerChar,
4365 next - enc->minBytesPerChar);
4366 if (!name)
4367 return XML_ERROR_NO_MEMORY;
4368 entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
4369 poolDiscard(&dtd->pool);
4370 /* first, determine if a check for an existing declaration is needed;
4371 if yes, check that the entity exists, and that it is internal,
4372 otherwise call the skipped entity handler
4374 if (prologState.documentEntity &&
4375 (dtd->standalone
4376 ? !openInternalEntities
4377 : !dtd->hasParamEntityRefs)) {
4378 if (!entity)
4379 return XML_ERROR_UNDEFINED_ENTITY;
4380 else if (!entity->is_internal)
4381 return XML_ERROR_ENTITY_DECLARED_IN_PE;
4383 else if (!entity) {
4384 dtd->keepProcessing = dtd->standalone;
4385 /* cannot report skipped entities in declarations */
4386 if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
4387 skippedEntityHandler(handlerArg, name, 1);
4388 handleDefault = XML_FALSE;
4390 break;
4392 if (entity->open)
4393 return XML_ERROR_RECURSIVE_ENTITY_REF;
4394 if (entity->textPtr) {
4395 enum XML_Error result;
4396 XML_Bool betweenDecl =
4397 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
4398 result = processInternalEntity(parser, entity, betweenDecl);
4399 if (result != XML_ERROR_NONE)
4400 return result;
4401 handleDefault = XML_FALSE;
4402 break;
4404 if (externalEntityRefHandler) {
4405 dtd->paramEntityRead = XML_FALSE;
4406 entity->open = XML_TRUE;
4407 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4409 entity->base,
4410 entity->systemId,
4411 entity->publicId)) {
4412 entity->open = XML_FALSE;
4413 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4415 entity->open = XML_FALSE;
4416 handleDefault = XML_FALSE;
4417 if (!dtd->paramEntityRead) {
4418 dtd->keepProcessing = dtd->standalone;
4419 break;
4422 else {
4423 dtd->keepProcessing = dtd->standalone;
4424 break;
4427 #endif /* XML_DTD */
4428 if (!dtd->standalone &&
4429 notStandaloneHandler &&
4430 !notStandaloneHandler(handlerArg))
4431 return XML_ERROR_NOT_STANDALONE;
4432 break;
4434 /* Element declaration stuff */
4436 case XML_ROLE_ELEMENT_NAME:
4437 if (elementDeclHandler) {
4438 declElementType = getElementType(parser, enc, s, next);
4439 if (!declElementType)
4440 return XML_ERROR_NO_MEMORY;
4441 dtd->scaffLevel = 0;
4442 dtd->scaffCount = 0;
4443 dtd->in_eldecl = XML_TRUE;
4444 handleDefault = XML_FALSE;
4446 break;
4448 case XML_ROLE_CONTENT_ANY:
4449 case XML_ROLE_CONTENT_EMPTY:
4450 if (dtd->in_eldecl) {
4451 if (elementDeclHandler) {
4452 XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
4453 if (!content)
4454 return XML_ERROR_NO_MEMORY;
4455 content->quant = XML_CQUANT_NONE;
4456 content->name = NULL;
4457 content->numchildren = 0;
4458 content->children = NULL;
4459 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
4460 XML_CTYPE_ANY :
4461 XML_CTYPE_EMPTY);
4462 *eventEndPP = s;
4463 elementDeclHandler(handlerArg, declElementType->name, content);
4464 handleDefault = XML_FALSE;
4466 dtd->in_eldecl = XML_FALSE;
4468 break;
4470 case XML_ROLE_CONTENT_PCDATA:
4471 if (dtd->in_eldecl) {
4472 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4473 = XML_CTYPE_MIXED;
4474 if (elementDeclHandler)
4475 handleDefault = XML_FALSE;
4477 break;
4479 case XML_ROLE_CONTENT_ELEMENT:
4480 quant = XML_CQUANT_NONE;
4481 goto elementContent;
4482 case XML_ROLE_CONTENT_ELEMENT_OPT:
4483 quant = XML_CQUANT_OPT;
4484 goto elementContent;
4485 case XML_ROLE_CONTENT_ELEMENT_REP:
4486 quant = XML_CQUANT_REP;
4487 goto elementContent;
4488 case XML_ROLE_CONTENT_ELEMENT_PLUS:
4489 quant = XML_CQUANT_PLUS;
4490 elementContent:
4491 if (dtd->in_eldecl) {
4492 ELEMENT_TYPE *el;
4493 const XML_Char *name;
4494 int nameLen;
4495 const char *nxt = (quant == XML_CQUANT_NONE
4496 ? next
4497 : next - enc->minBytesPerChar);
4498 int myindex = nextScaffoldPart(parser);
4499 if (myindex < 0)
4500 return XML_ERROR_NO_MEMORY;
4501 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
4502 dtd->scaffold[myindex].quant = quant;
4503 el = getElementType(parser, enc, s, nxt);
4504 if (!el)
4505 return XML_ERROR_NO_MEMORY;
4506 name = el->name;
4507 dtd->scaffold[myindex].name = name;
4508 nameLen = 0;
4509 for (; name[nameLen++]; );
4510 dtd->contentStringLen += nameLen;
4511 if (elementDeclHandler)
4512 handleDefault = XML_FALSE;
4514 break;
4516 case XML_ROLE_GROUP_CLOSE:
4517 quant = XML_CQUANT_NONE;
4518 goto closeGroup;
4519 case XML_ROLE_GROUP_CLOSE_OPT:
4520 quant = XML_CQUANT_OPT;
4521 goto closeGroup;
4522 case XML_ROLE_GROUP_CLOSE_REP:
4523 quant = XML_CQUANT_REP;
4524 goto closeGroup;
4525 case XML_ROLE_GROUP_CLOSE_PLUS:
4526 quant = XML_CQUANT_PLUS;
4527 closeGroup:
4528 if (dtd->in_eldecl) {
4529 if (elementDeclHandler)
4530 handleDefault = XML_FALSE;
4531 dtd->scaffLevel--;
4532 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
4533 if (dtd->scaffLevel == 0) {
4534 if (!handleDefault) {
4535 XML_Content *model = build_model(parser);
4536 if (!model)
4537 return XML_ERROR_NO_MEMORY;
4538 *eventEndPP = s;
4539 elementDeclHandler(handlerArg, declElementType->name, model);
4541 dtd->in_eldecl = XML_FALSE;
4542 dtd->contentStringLen = 0;
4545 break;
4546 /* End element declaration stuff */
4548 case XML_ROLE_PI:
4549 if (!reportProcessingInstruction(parser, enc, s, next))
4550 return XML_ERROR_NO_MEMORY;
4551 handleDefault = XML_FALSE;
4552 break;
4553 case XML_ROLE_COMMENT:
4554 if (!reportComment(parser, enc, s, next))
4555 return XML_ERROR_NO_MEMORY;
4556 handleDefault = XML_FALSE;
4557 break;
4558 case XML_ROLE_NONE:
4559 switch (tok) {
4560 case XML_TOK_BOM:
4561 handleDefault = XML_FALSE;
4562 break;
4564 break;
4565 case XML_ROLE_DOCTYPE_NONE:
4566 if (startDoctypeDeclHandler)
4567 handleDefault = XML_FALSE;
4568 break;
4569 case XML_ROLE_ENTITY_NONE:
4570 if (dtd->keepProcessing && entityDeclHandler)
4571 handleDefault = XML_FALSE;
4572 break;
4573 case XML_ROLE_NOTATION_NONE:
4574 if (notationDeclHandler)
4575 handleDefault = XML_FALSE;
4576 break;
4577 case XML_ROLE_ATTLIST_NONE:
4578 if (dtd->keepProcessing && attlistDeclHandler)
4579 handleDefault = XML_FALSE;
4580 break;
4581 case XML_ROLE_ELEMENT_NONE:
4582 if (elementDeclHandler)
4583 handleDefault = XML_FALSE;
4584 break;
4585 } /* end of big switch */
4587 if (handleDefault && defaultHandler)
4588 reportDefault(parser, enc, s, next);
4590 switch (ps_parsing) {
4591 case XML_SUSPENDED:
4592 *nextPtr = next;
4593 return XML_ERROR_NONE;
4594 case XML_FINISHED:
4595 return XML_ERROR_ABORTED;
4596 default:
4597 s = next;
4598 tok = XmlPrologTok(enc, s, end, &next);
4601 /* not reached */
4604 static enum XML_Error PTRCALL
4605 epilogProcessor(XML_Parser parser,
4606 const char *s,
4607 const char *end,
4608 const char **nextPtr)
4610 processor = epilogProcessor;
4611 eventPtr = s;
4612 for (;;) {
4613 const char *next = NULL;
4614 int tok = XmlPrologTok(encoding, s, end, &next);
4615 eventEndPtr = next;
4616 switch (tok) {
4617 /* report partial linebreak - it might be the last token */
4618 case -XML_TOK_PROLOG_S:
4619 if (defaultHandler) {
4620 reportDefault(parser, encoding, s, next);
4621 if (ps_parsing == XML_FINISHED)
4622 return XML_ERROR_ABORTED;
4624 *nextPtr = next;
4625 return XML_ERROR_NONE;
4626 case XML_TOK_NONE:
4627 *nextPtr = s;
4628 return XML_ERROR_NONE;
4629 case XML_TOK_PROLOG_S:
4630 if (defaultHandler)
4631 reportDefault(parser, encoding, s, next);
4632 break;
4633 case XML_TOK_PI:
4634 if (!reportProcessingInstruction(parser, encoding, s, next))
4635 return XML_ERROR_NO_MEMORY;
4636 break;
4637 case XML_TOK_COMMENT:
4638 if (!reportComment(parser, encoding, s, next))
4639 return XML_ERROR_NO_MEMORY;
4640 break;
4641 case XML_TOK_INVALID:
4642 eventPtr = next;
4643 return XML_ERROR_INVALID_TOKEN;
4644 case XML_TOK_PARTIAL:
4645 if (!ps_finalBuffer) {
4646 *nextPtr = s;
4647 return XML_ERROR_NONE;
4649 return XML_ERROR_UNCLOSED_TOKEN;
4650 case XML_TOK_PARTIAL_CHAR:
4651 if (!ps_finalBuffer) {
4652 *nextPtr = s;
4653 return XML_ERROR_NONE;
4655 return XML_ERROR_PARTIAL_CHAR;
4656 default:
4657 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
4659 eventPtr = s = next;
4660 switch (ps_parsing) {
4661 case XML_SUSPENDED:
4662 *nextPtr = next;
4663 return XML_ERROR_NONE;
4664 case XML_FINISHED:
4665 return XML_ERROR_ABORTED;
4666 default: ;
4671 static enum XML_Error
4672 processInternalEntity(XML_Parser parser, ENTITY *entity,
4673 XML_Bool betweenDecl)
4675 const char *textStart, *textEnd;
4676 const char *next;
4677 enum XML_Error result;
4678 OPEN_INTERNAL_ENTITY *openEntity;
4680 if (freeInternalEntities) {
4681 openEntity = freeInternalEntities;
4682 freeInternalEntities = openEntity->next;
4684 else {
4685 openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
4686 if (!openEntity)
4687 return XML_ERROR_NO_MEMORY;
4689 entity->open = XML_TRUE;
4690 entity->processed = 0;
4691 openEntity->next = openInternalEntities;
4692 openInternalEntities = openEntity;
4693 openEntity->entity = entity;
4694 openEntity->startTagLevel = tagLevel;
4695 openEntity->betweenDecl = betweenDecl;
4696 openEntity->internalEventPtr = NULL;
4697 openEntity->internalEventEndPtr = NULL;
4698 textStart = (char *)entity->textPtr;
4699 textEnd = (char *)(entity->textPtr + entity->textLen);
4701 #ifdef XML_DTD
4702 if (entity->is_param) {
4703 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4704 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4705 next, &next, XML_FALSE);
4707 else
4708 #endif /* XML_DTD */
4709 result = doContent(parser, tagLevel, internalEncoding, textStart,
4710 textEnd, &next, XML_FALSE);
4712 if (result == XML_ERROR_NONE) {
4713 if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4714 entity->processed = (int)(next - textStart);
4715 processor = internalEntityProcessor;
4717 else {
4718 entity->open = XML_FALSE;
4719 openInternalEntities = openEntity->next;
4720 /* put openEntity back in list of free instances */
4721 openEntity->next = freeInternalEntities;
4722 freeInternalEntities = openEntity;
4725 return result;
4728 static enum XML_Error PTRCALL
4729 internalEntityProcessor(XML_Parser parser,
4730 const char *s,
4731 const char *end,
4732 const char **nextPtr)
4734 ENTITY *entity;
4735 const char *textStart, *textEnd;
4736 const char *next;
4737 enum XML_Error result;
4738 OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
4739 if (!openEntity)
4740 return XML_ERROR_UNEXPECTED_STATE;
4742 entity = openEntity->entity;
4743 textStart = ((char *)entity->textPtr) + entity->processed;
4744 textEnd = (char *)(entity->textPtr + entity->textLen);
4746 #ifdef XML_DTD
4747 if (entity->is_param) {
4748 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
4749 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
4750 next, &next, XML_FALSE);
4752 else
4753 #endif /* XML_DTD */
4754 result = doContent(parser, openEntity->startTagLevel, internalEncoding,
4755 textStart, textEnd, &next, XML_FALSE);
4757 if (result != XML_ERROR_NONE)
4758 return result;
4759 else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
4760 entity->processed = (int)(next - (char *)entity->textPtr);
4761 return result;
4763 else {
4764 entity->open = XML_FALSE;
4765 openInternalEntities = openEntity->next;
4766 /* put openEntity back in list of free instances */
4767 openEntity->next = freeInternalEntities;
4768 freeInternalEntities = openEntity;
4771 #ifdef XML_DTD
4772 if (entity->is_param) {
4773 int tok;
4774 processor = prologProcessor;
4775 tok = XmlPrologTok(encoding, s, end, &next);
4776 return doProlog(parser, encoding, s, end, tok, next, nextPtr,
4777 (XML_Bool)!ps_finalBuffer);
4779 else
4780 #endif /* XML_DTD */
4782 processor = contentProcessor;
4783 /* see externalEntityContentProcessor vs contentProcessor */
4784 return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
4785 nextPtr, (XML_Bool)!ps_finalBuffer);
4789 static enum XML_Error PTRCALL
4790 errorProcessor(XML_Parser parser,
4791 const char *s,
4792 const char *end,
4793 const char **nextPtr)
4795 return errorCode;
4798 static enum XML_Error
4799 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4800 const char *ptr, const char *end,
4801 STRING_POOL *pool)
4803 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
4804 end, pool);
4805 if (result)
4806 return result;
4807 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
4808 poolChop(pool);
4809 if (!poolAppendChar(pool, XML_T('\0')))
4810 return XML_ERROR_NO_MEMORY;
4811 return XML_ERROR_NONE;
4814 static enum XML_Error
4815 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4816 const char *ptr, const char *end,
4817 STRING_POOL *pool)
4819 DTD * const dtd = _dtd; /* save one level of indirection */
4820 for (;;) {
4821 const char *next;
4822 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
4823 switch (tok) {
4824 case XML_TOK_NONE:
4825 return XML_ERROR_NONE;
4826 case XML_TOK_INVALID:
4827 if (enc == encoding)
4828 eventPtr = next;
4829 return XML_ERROR_INVALID_TOKEN;
4830 case XML_TOK_PARTIAL:
4831 if (enc == encoding)
4832 eventPtr = ptr;
4833 return XML_ERROR_INVALID_TOKEN;
4834 case XML_TOK_CHAR_REF:
4836 XML_Char buf[XML_ENCODE_MAX];
4837 int i;
4838 int n = XmlCharRefNumber(enc, ptr);
4839 if (n < 0) {
4840 if (enc == encoding)
4841 eventPtr = ptr;
4842 return XML_ERROR_BAD_CHAR_REF;
4844 if (!isCdata
4845 && n == 0x20 /* space */
4846 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4847 break;
4848 n = XmlEncode(n, (ICHAR *)buf);
4849 if (!n) {
4850 if (enc == encoding)
4851 eventPtr = ptr;
4852 return XML_ERROR_BAD_CHAR_REF;
4854 for (i = 0; i < n; i++) {
4855 if (!poolAppendChar(pool, buf[i]))
4856 return XML_ERROR_NO_MEMORY;
4859 break;
4860 case XML_TOK_DATA_CHARS:
4861 if (!poolAppend(pool, enc, ptr, next))
4862 return XML_ERROR_NO_MEMORY;
4863 break;
4864 case XML_TOK_TRAILING_CR:
4865 next = ptr + enc->minBytesPerChar;
4866 /* fall through */
4867 case XML_TOK_ATTRIBUTE_VALUE_S:
4868 case XML_TOK_DATA_NEWLINE:
4869 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4870 break;
4871 if (!poolAppendChar(pool, 0x20))
4872 return XML_ERROR_NO_MEMORY;
4873 break;
4874 case XML_TOK_ENTITY_REF:
4876 const XML_Char *name;
4877 ENTITY *entity;
4878 char checkEntityDecl;
4879 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
4880 ptr + enc->minBytesPerChar,
4881 next - enc->minBytesPerChar);
4882 if (ch) {
4883 if (!poolAppendChar(pool, ch))
4884 return XML_ERROR_NO_MEMORY;
4885 break;
4887 name = poolStoreString(&temp2Pool, enc,
4888 ptr + enc->minBytesPerChar,
4889 next - enc->minBytesPerChar);
4890 if (!name)
4891 return XML_ERROR_NO_MEMORY;
4892 entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
4893 poolDiscard(&temp2Pool);
4894 /* First, determine if a check for an existing declaration is needed;
4895 if yes, check that the entity exists, and that it is internal.
4897 if (pool == &dtd->pool) /* are we called from prolog? */
4898 checkEntityDecl =
4899 #ifdef XML_DTD
4900 prologState.documentEntity &&
4901 #endif /* XML_DTD */
4902 (dtd->standalone
4903 ? !openInternalEntities
4904 : !dtd->hasParamEntityRefs);
4905 else /* if (pool == &tempPool): we are called from content */
4906 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
4907 if (checkEntityDecl) {
4908 if (!entity)
4909 return XML_ERROR_UNDEFINED_ENTITY;
4910 else if (!entity->is_internal)
4911 return XML_ERROR_ENTITY_DECLARED_IN_PE;
4913 else if (!entity) {
4914 /* Cannot report skipped entity here - see comments on
4915 skippedEntityHandler.
4916 if (skippedEntityHandler)
4917 skippedEntityHandler(handlerArg, name, 0);
4919 /* Cannot call the default handler because this would be
4920 out of sync with the call to the startElementHandler.
4921 if ((pool == &tempPool) && defaultHandler)
4922 reportDefault(parser, enc, ptr, next);
4924 break;
4926 if (entity->open) {
4927 if (enc == encoding)
4928 eventPtr = ptr;
4929 return XML_ERROR_RECURSIVE_ENTITY_REF;
4931 if (entity->notation) {
4932 if (enc == encoding)
4933 eventPtr = ptr;
4934 return XML_ERROR_BINARY_ENTITY_REF;
4936 if (!entity->textPtr) {
4937 if (enc == encoding)
4938 eventPtr = ptr;
4939 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
4941 else {
4942 enum XML_Error result;
4943 const XML_Char *textEnd = entity->textPtr + entity->textLen;
4944 entity->open = XML_TRUE;
4945 result = appendAttributeValue(parser, internalEncoding, isCdata,
4946 (char *)entity->textPtr,
4947 (char *)textEnd, pool);
4948 entity->open = XML_FALSE;
4949 if (result)
4950 return result;
4953 break;
4954 default:
4955 if (enc == encoding)
4956 eventPtr = ptr;
4957 return XML_ERROR_UNEXPECTED_STATE;
4959 ptr = next;
4961 /* not reached */
4964 static enum XML_Error
4965 storeEntityValue(XML_Parser parser,
4966 const ENCODING *enc,
4967 const char *entityTextPtr,
4968 const char *entityTextEnd)
4970 DTD * const dtd = _dtd; /* save one level of indirection */
4971 STRING_POOL *pool = &(dtd->entityValuePool);
4972 enum XML_Error result = XML_ERROR_NONE;
4973 #ifdef XML_DTD
4974 int oldInEntityValue = prologState.inEntityValue;
4975 prologState.inEntityValue = 1;
4976 #endif /* XML_DTD */
4977 /* never return Null for the value argument in EntityDeclHandler,
4978 since this would indicate an external entity; therefore we
4979 have to make sure that entityValuePool.start is not null */
4980 if (!pool->blocks) {
4981 if (!poolGrow(pool))
4982 return XML_ERROR_NO_MEMORY;
4985 for (;;) {
4986 const char *next;
4987 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
4988 switch (tok) {
4989 case XML_TOK_PARAM_ENTITY_REF:
4990 #ifdef XML_DTD
4991 if (isParamEntity || enc != encoding) {
4992 const XML_Char *name;
4993 ENTITY *entity;
4994 name = poolStoreString(&tempPool, enc,
4995 entityTextPtr + enc->minBytesPerChar,
4996 next - enc->minBytesPerChar);
4997 if (!name) {
4998 result = XML_ERROR_NO_MEMORY;
4999 goto endEntityValue;
5001 entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
5002 poolDiscard(&tempPool);
5003 if (!entity) {
5004 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5005 /* cannot report skipped entity here - see comments on
5006 skippedEntityHandler
5007 if (skippedEntityHandler)
5008 skippedEntityHandler(handlerArg, name, 0);
5010 dtd->keepProcessing = dtd->standalone;
5011 goto endEntityValue;
5013 if (entity->open) {
5014 if (enc == encoding)
5015 eventPtr = entityTextPtr;
5016 result = XML_ERROR_RECURSIVE_ENTITY_REF;
5017 goto endEntityValue;
5019 if (entity->systemId) {
5020 if (externalEntityRefHandler) {
5021 dtd->paramEntityRead = XML_FALSE;
5022 entity->open = XML_TRUE;
5023 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
5025 entity->base,
5026 entity->systemId,
5027 entity->publicId)) {
5028 entity->open = XML_FALSE;
5029 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5030 goto endEntityValue;
5032 entity->open = XML_FALSE;
5033 if (!dtd->paramEntityRead)
5034 dtd->keepProcessing = dtd->standalone;
5036 else
5037 dtd->keepProcessing = dtd->standalone;
5039 else {
5040 entity->open = XML_TRUE;
5041 result = storeEntityValue(parser,
5042 internalEncoding,
5043 (char *)entity->textPtr,
5044 (char *)(entity->textPtr
5045 + entity->textLen));
5046 entity->open = XML_FALSE;
5047 if (result)
5048 goto endEntityValue;
5050 break;
5052 #endif /* XML_DTD */
5053 /* In the internal subset, PE references are not legal
5054 within markup declarations, e.g entity values in this case. */
5055 eventPtr = entityTextPtr;
5056 result = XML_ERROR_PARAM_ENTITY_REF;
5057 goto endEntityValue;
5058 case XML_TOK_NONE:
5059 result = XML_ERROR_NONE;
5060 goto endEntityValue;
5061 case XML_TOK_ENTITY_REF:
5062 case XML_TOK_DATA_CHARS:
5063 if (!poolAppend(pool, enc, entityTextPtr, next)) {
5064 result = XML_ERROR_NO_MEMORY;
5065 goto endEntityValue;
5067 break;
5068 case XML_TOK_TRAILING_CR:
5069 next = entityTextPtr + enc->minBytesPerChar;
5070 /* fall through */
5071 case XML_TOK_DATA_NEWLINE:
5072 if (pool->end == pool->ptr && !poolGrow(pool)) {
5073 result = XML_ERROR_NO_MEMORY;
5074 goto endEntityValue;
5076 *(pool->ptr)++ = 0xA;
5077 break;
5078 case XML_TOK_CHAR_REF:
5080 XML_Char buf[XML_ENCODE_MAX];
5081 int i;
5082 int n = XmlCharRefNumber(enc, entityTextPtr);
5083 if (n < 0) {
5084 if (enc == encoding)
5085 eventPtr = entityTextPtr;
5086 result = XML_ERROR_BAD_CHAR_REF;
5087 goto endEntityValue;
5089 n = XmlEncode(n, (ICHAR *)buf);
5090 if (!n) {
5091 if (enc == encoding)
5092 eventPtr = entityTextPtr;
5093 result = XML_ERROR_BAD_CHAR_REF;
5094 goto endEntityValue;
5096 for (i = 0; i < n; i++) {
5097 if (pool->end == pool->ptr && !poolGrow(pool)) {
5098 result = XML_ERROR_NO_MEMORY;
5099 goto endEntityValue;
5101 *(pool->ptr)++ = buf[i];
5104 break;
5105 case XML_TOK_PARTIAL:
5106 if (enc == encoding)
5107 eventPtr = entityTextPtr;
5108 result = XML_ERROR_INVALID_TOKEN;
5109 goto endEntityValue;
5110 case XML_TOK_INVALID:
5111 if (enc == encoding)
5112 eventPtr = next;
5113 result = XML_ERROR_INVALID_TOKEN;
5114 goto endEntityValue;
5115 default:
5116 if (enc == encoding)
5117 eventPtr = entityTextPtr;
5118 result = XML_ERROR_UNEXPECTED_STATE;
5119 goto endEntityValue;
5121 entityTextPtr = next;
5123 endEntityValue:
5124 #ifdef XML_DTD
5125 prologState.inEntityValue = oldInEntityValue;
5126 #endif /* XML_DTD */
5127 return result;
5130 static void FASTCALL
5131 normalizeLines(XML_Char *s)
5133 XML_Char *p;
5134 for (;; s++) {
5135 if (*s == XML_T('\0'))
5136 return;
5137 if (*s == 0xD)
5138 break;
5140 p = s;
5141 do {
5142 if (*s == 0xD) {
5143 *p++ = 0xA;
5144 if (*++s == 0xA)
5145 s++;
5147 else
5148 *p++ = *s++;
5149 } while (*s);
5150 *p = XML_T('\0');
5153 static int
5154 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5155 const char *start, const char *end)
5157 const XML_Char *target;
5158 XML_Char *data;
5159 const char *tem;
5160 if (!processingInstructionHandler) {
5161 if (defaultHandler)
5162 reportDefault(parser, enc, start, end);
5163 return 1;
5165 start += enc->minBytesPerChar * 2;
5166 tem = start + XmlNameLength(enc, start);
5167 target = poolStoreString(&tempPool, enc, start, tem);
5168 if (!target)
5169 return 0;
5170 poolFinish(&tempPool);
5171 data = poolStoreString(&tempPool, enc,
5172 XmlSkipS(enc, tem),
5173 end - enc->minBytesPerChar*2);
5174 if (!data)
5175 return 0;
5176 normalizeLines(data);
5177 processingInstructionHandler(handlerArg, target, data);
5178 poolClear(&tempPool);
5179 return 1;
5182 static int
5183 reportComment(XML_Parser parser, const ENCODING *enc,
5184 const char *start, const char *end)
5186 XML_Char *data;
5187 if (!commentHandler) {
5188 if (defaultHandler)
5189 reportDefault(parser, enc, start, end);
5190 return 1;
5192 data = poolStoreString(&tempPool,
5193 enc,
5194 start + enc->minBytesPerChar * 4,
5195 end - enc->minBytesPerChar * 3);
5196 if (!data)
5197 return 0;
5198 normalizeLines(data);
5199 commentHandler(handlerArg, data);
5200 poolClear(&tempPool);
5201 return 1;
5204 static void
5205 reportDefault(XML_Parser parser, const ENCODING *enc,
5206 const char *s, const char *end)
5208 if (MUST_CONVERT(enc, s)) {
5209 const char **eventPP;
5210 const char **eventEndPP;
5211 if (enc == encoding) {
5212 eventPP = &eventPtr;
5213 eventEndPP = &eventEndPtr;
5215 else {
5216 eventPP = &(openInternalEntities->internalEventPtr);
5217 eventEndPP = &(openInternalEntities->internalEventEndPtr);
5219 do {
5220 ICHAR *dataPtr = (ICHAR *)dataBuf;
5221 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
5222 *eventEndPP = s;
5223 defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
5224 *eventPP = s;
5225 } while (s != end);
5227 else
5228 defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
5232 static int
5233 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
5234 XML_Bool isId, const XML_Char *value, XML_Parser parser)
5236 DEFAULT_ATTRIBUTE *att;
5237 if (value || isId) {
5238 /* The handling of default attributes gets messed up if we have
5239 a default which duplicates a non-default. */
5240 int i;
5241 for (i = 0; i < type->nDefaultAtts; i++)
5242 if (attId == type->defaultAtts[i].id)
5243 return 1;
5244 if (isId && !type->idAtt && !attId->xmlns)
5245 type->idAtt = attId;
5247 if (type->nDefaultAtts == type->allocDefaultAtts) {
5248 if (type->allocDefaultAtts == 0) {
5249 type->allocDefaultAtts = 8;
5250 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
5251 * sizeof(DEFAULT_ATTRIBUTE));
5252 if (!type->defaultAtts)
5253 return 0;
5255 else {
5256 DEFAULT_ATTRIBUTE *temp;
5257 int count = type->allocDefaultAtts * 2;
5258 temp = (DEFAULT_ATTRIBUTE *)
5259 REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
5260 if (temp == NULL)
5261 return 0;
5262 type->allocDefaultAtts = count;
5263 type->defaultAtts = temp;
5266 att = type->defaultAtts + type->nDefaultAtts;
5267 att->id = attId;
5268 att->value = value;
5269 att->isCdata = isCdata;
5270 if (!isCdata)
5271 attId->maybeTokenized = XML_TRUE;
5272 type->nDefaultAtts += 1;
5273 return 1;
5276 static int
5277 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
5279 DTD * const dtd = _dtd; /* save one level of indirection */
5280 const XML_Char *name;
5281 for (name = elementType->name; *name; name++) {
5282 if (*name == XML_T(':')) {
5283 PREFIX *prefix;
5284 const XML_Char *s;
5285 for (s = elementType->name; s != name; s++) {
5286 if (!poolAppendChar(&dtd->pool, *s))
5287 return 0;
5289 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5290 return 0;
5291 prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
5292 sizeof(PREFIX));
5293 if (!prefix)
5294 return 0;
5295 if (prefix->name == poolStart(&dtd->pool))
5296 poolFinish(&dtd->pool);
5297 else
5298 poolDiscard(&dtd->pool);
5299 elementType->prefix = prefix;
5303 return 1;
5306 static ATTRIBUTE_ID *
5307 getAttributeId(XML_Parser parser, const ENCODING *enc,
5308 const char *start, const char *end)
5310 DTD * const dtd = _dtd; /* save one level of indirection */
5311 ATTRIBUTE_ID *id;
5312 const XML_Char *name;
5313 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5314 return NULL;
5315 name = poolStoreString(&dtd->pool, enc, start, end);
5316 if (!name)
5317 return NULL;
5318 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
5319 ++name;
5320 id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
5321 if (!id)
5322 return NULL;
5323 if (id->name != name)
5324 poolDiscard(&dtd->pool);
5325 else {
5326 poolFinish(&dtd->pool);
5327 if (!ns)
5329 else if (name[0] == XML_T('x')
5330 && name[1] == XML_T('m')
5331 && name[2] == XML_T('l')
5332 && name[3] == XML_T('n')
5333 && name[4] == XML_T('s')
5334 && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
5335 if (name[5] == XML_T('\0'))
5336 id->prefix = &dtd->defaultPrefix;
5337 else
5338 id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
5339 id->xmlns = XML_TRUE;
5341 else {
5342 int i;
5343 for (i = 0; name[i]; i++) {
5344 /* attributes without prefix are *not* in the default namespace */
5345 if (name[i] == XML_T(':')) {
5346 int j;
5347 for (j = 0; j < i; j++) {
5348 if (!poolAppendChar(&dtd->pool, name[j]))
5349 return NULL;
5351 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
5352 return NULL;
5353 id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
5354 sizeof(PREFIX));
5355 if (id->prefix->name == poolStart(&dtd->pool))
5356 poolFinish(&dtd->pool);
5357 else
5358 poolDiscard(&dtd->pool);
5359 break;
5364 return id;
5367 #define CONTEXT_SEP XML_T('\f')
5369 static const XML_Char *
5370 getContext(XML_Parser parser)
5372 DTD * const dtd = _dtd; /* save one level of indirection */
5373 HASH_TABLE_ITER iter;
5374 XML_Bool needSep = XML_FALSE;
5376 if (dtd->defaultPrefix.binding) {
5377 int i;
5378 int len;
5379 if (!poolAppendChar(&tempPool, XML_T('=')))
5380 return NULL;
5381 len = dtd->defaultPrefix.binding->uriLen;
5382 if (namespaceSeparator)
5383 len--;
5384 for (i = 0; i < len; i++)
5385 if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
5386 return NULL;
5387 needSep = XML_TRUE;
5390 hashTableIterInit(&iter, &(dtd->prefixes));
5391 for (;;) {
5392 int i;
5393 int len;
5394 const XML_Char *s;
5395 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
5396 if (!prefix)
5397 break;
5398 if (!prefix->binding)
5399 continue;
5400 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5401 return NULL;
5402 for (s = prefix->name; *s; s++)
5403 if (!poolAppendChar(&tempPool, *s))
5404 return NULL;
5405 if (!poolAppendChar(&tempPool, XML_T('=')))
5406 return NULL;
5407 len = prefix->binding->uriLen;
5408 if (namespaceSeparator)
5409 len--;
5410 for (i = 0; i < len; i++)
5411 if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
5412 return NULL;
5413 needSep = XML_TRUE;
5417 hashTableIterInit(&iter, &(dtd->generalEntities));
5418 for (;;) {
5419 const XML_Char *s;
5420 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
5421 if (!e)
5422 break;
5423 if (!e->open)
5424 continue;
5425 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
5426 return NULL;
5427 for (s = e->name; *s; s++)
5428 if (!poolAppendChar(&tempPool, *s))
5429 return 0;
5430 needSep = XML_TRUE;
5433 if (!poolAppendChar(&tempPool, XML_T('\0')))
5434 return NULL;
5435 return tempPool.start;
5438 static XML_Bool
5439 setContext(XML_Parser parser, const XML_Char *context)
5441 DTD * const dtd = _dtd; /* save one level of indirection */
5442 const XML_Char *s = context;
5444 while (*context != XML_T('\0')) {
5445 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
5446 ENTITY *e;
5447 if (!poolAppendChar(&tempPool, XML_T('\0')))
5448 return XML_FALSE;
5449 e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
5450 if (e)
5451 e->open = XML_TRUE;
5452 if (*s != XML_T('\0'))
5453 s++;
5454 context = s;
5455 poolDiscard(&tempPool);
5457 else if (*s == XML_T('=')) {
5458 PREFIX *prefix;
5459 if (poolLength(&tempPool) == 0)
5460 prefix = &dtd->defaultPrefix;
5461 else {
5462 if (!poolAppendChar(&tempPool, XML_T('\0')))
5463 return XML_FALSE;
5464 prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
5465 sizeof(PREFIX));
5466 if (!prefix)
5467 return XML_FALSE;
5468 if (prefix->name == poolStart(&tempPool)) {
5469 prefix->name = poolCopyString(&dtd->pool, prefix->name);
5470 if (!prefix->name)
5471 return XML_FALSE;
5473 poolDiscard(&tempPool);
5475 for (context = s + 1;
5476 *context != CONTEXT_SEP && *context != XML_T('\0');
5477 context++)
5478 if (!poolAppendChar(&tempPool, *context))
5479 return XML_FALSE;
5480 if (!poolAppendChar(&tempPool, XML_T('\0')))
5481 return XML_FALSE;
5482 if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
5483 &inheritedBindings) != XML_ERROR_NONE)
5484 return XML_FALSE;
5485 poolDiscard(&tempPool);
5486 if (*context != XML_T('\0'))
5487 ++context;
5488 s = context;
5490 else {
5491 if (!poolAppendChar(&tempPool, *s))
5492 return XML_FALSE;
5493 s++;
5496 return XML_TRUE;
5499 static void FASTCALL
5500 normalizePublicId(XML_Char *publicId)
5502 XML_Char *p = publicId;
5503 XML_Char *s;
5504 for (s = publicId; *s; s++) {
5505 switch (*s) {
5506 case 0x20:
5507 case 0xD:
5508 case 0xA:
5509 if (p != publicId && p[-1] != 0x20)
5510 *p++ = 0x20;
5511 break;
5512 default:
5513 *p++ = *s;
5516 if (p != publicId && p[-1] == 0x20)
5517 --p;
5518 *p = XML_T('\0');
5521 static DTD *
5522 dtdCreate(const XML_Memory_Handling_Suite *ms)
5524 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
5525 if (p == NULL)
5526 return p;
5527 poolInit(&(p->pool), ms);
5528 poolInit(&(p->entityValuePool), ms);
5529 hashTableInit(&(p->generalEntities), ms);
5530 hashTableInit(&(p->elementTypes), ms);
5531 hashTableInit(&(p->attributeIds), ms);
5532 hashTableInit(&(p->prefixes), ms);
5533 #ifdef XML_DTD
5534 p->paramEntityRead = XML_FALSE;
5535 hashTableInit(&(p->paramEntities), ms);
5536 #endif /* XML_DTD */
5537 p->defaultPrefix.name = NULL;
5538 p->defaultPrefix.binding = NULL;
5540 p->in_eldecl = XML_FALSE;
5541 p->scaffIndex = NULL;
5542 p->scaffold = NULL;
5543 p->scaffLevel = 0;
5544 p->scaffSize = 0;
5545 p->scaffCount = 0;
5546 p->contentStringLen = 0;
5548 p->keepProcessing = XML_TRUE;
5549 p->hasParamEntityRefs = XML_FALSE;
5550 p->standalone = XML_FALSE;
5551 return p;
5554 static void
5555 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
5557 HASH_TABLE_ITER iter;
5558 hashTableIterInit(&iter, &(p->elementTypes));
5559 for (;;) {
5560 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5561 if (!e)
5562 break;
5563 if (e->allocDefaultAtts != 0)
5564 ms->free_fcn(e->defaultAtts);
5566 hashTableClear(&(p->generalEntities));
5567 #ifdef XML_DTD
5568 p->paramEntityRead = XML_FALSE;
5569 hashTableClear(&(p->paramEntities));
5570 #endif /* XML_DTD */
5571 hashTableClear(&(p->elementTypes));
5572 hashTableClear(&(p->attributeIds));
5573 hashTableClear(&(p->prefixes));
5574 poolClear(&(p->pool));
5575 poolClear(&(p->entityValuePool));
5576 p->defaultPrefix.name = NULL;
5577 p->defaultPrefix.binding = NULL;
5579 p->in_eldecl = XML_FALSE;
5581 ms->free_fcn(p->scaffIndex);
5582 p->scaffIndex = NULL;
5583 ms->free_fcn(p->scaffold);
5584 p->scaffold = NULL;
5586 p->scaffLevel = 0;
5587 p->scaffSize = 0;
5588 p->scaffCount = 0;
5589 p->contentStringLen = 0;
5591 p->keepProcessing = XML_TRUE;
5592 p->hasParamEntityRefs = XML_FALSE;
5593 p->standalone = XML_FALSE;
5596 static void
5597 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
5599 HASH_TABLE_ITER iter;
5600 hashTableIterInit(&iter, &(p->elementTypes));
5601 for (;;) {
5602 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5603 if (!e)
5604 break;
5605 if (e->allocDefaultAtts != 0)
5606 ms->free_fcn(e->defaultAtts);
5608 hashTableDestroy(&(p->generalEntities));
5609 #ifdef XML_DTD
5610 hashTableDestroy(&(p->paramEntities));
5611 #endif /* XML_DTD */
5612 hashTableDestroy(&(p->elementTypes));
5613 hashTableDestroy(&(p->attributeIds));
5614 hashTableDestroy(&(p->prefixes));
5615 poolDestroy(&(p->pool));
5616 poolDestroy(&(p->entityValuePool));
5617 if (isDocEntity) {
5618 ms->free_fcn(p->scaffIndex);
5619 ms->free_fcn(p->scaffold);
5621 ms->free_fcn(p);
5624 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
5625 The new DTD has already been initialized.
5627 static int
5628 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
5630 HASH_TABLE_ITER iter;
5632 /* Copy the prefix table. */
5634 hashTableIterInit(&iter, &(oldDtd->prefixes));
5635 for (;;) {
5636 const XML_Char *name;
5637 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
5638 if (!oldP)
5639 break;
5640 name = poolCopyString(&(newDtd->pool), oldP->name);
5641 if (!name)
5642 return 0;
5643 if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
5644 return 0;
5647 hashTableIterInit(&iter, &(oldDtd->attributeIds));
5649 /* Copy the attribute id table. */
5651 for (;;) {
5652 ATTRIBUTE_ID *newA;
5653 const XML_Char *name;
5654 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
5656 if (!oldA)
5657 break;
5658 /* Remember to allocate the scratch byte before the name. */
5659 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
5660 return 0;
5661 name = poolCopyString(&(newDtd->pool), oldA->name);
5662 if (!name)
5663 return 0;
5664 ++name;
5665 newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
5666 sizeof(ATTRIBUTE_ID));
5667 if (!newA)
5668 return 0;
5669 newA->maybeTokenized = oldA->maybeTokenized;
5670 if (oldA->prefix) {
5671 newA->xmlns = oldA->xmlns;
5672 if (oldA->prefix == &oldDtd->defaultPrefix)
5673 newA->prefix = &newDtd->defaultPrefix;
5674 else
5675 newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
5676 oldA->prefix->name, 0);
5680 /* Copy the element type table. */
5682 hashTableIterInit(&iter, &(oldDtd->elementTypes));
5684 for (;;) {
5685 int i;
5686 ELEMENT_TYPE *newE;
5687 const XML_Char *name;
5688 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5689 if (!oldE)
5690 break;
5691 name = poolCopyString(&(newDtd->pool), oldE->name);
5692 if (!name)
5693 return 0;
5694 newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
5695 sizeof(ELEMENT_TYPE));
5696 if (!newE)
5697 return 0;
5698 if (oldE->nDefaultAtts) {
5699 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
5700 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
5701 if (!newE->defaultAtts) {
5702 ms->free_fcn(newE);
5703 return 0;
5706 if (oldE->idAtt)
5707 newE->idAtt = (ATTRIBUTE_ID *)
5708 lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
5709 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
5710 if (oldE->prefix)
5711 newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
5712 oldE->prefix->name, 0);
5713 for (i = 0; i < newE->nDefaultAtts; i++) {
5714 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
5715 lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
5716 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
5717 if (oldE->defaultAtts[i].value) {
5718 newE->defaultAtts[i].value
5719 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
5720 if (!newE->defaultAtts[i].value)
5721 return 0;
5723 else
5724 newE->defaultAtts[i].value = NULL;
5728 /* Copy the entity tables. */
5729 if (!copyEntityTable(&(newDtd->generalEntities),
5730 &(newDtd->pool),
5731 &(oldDtd->generalEntities)))
5732 return 0;
5734 #ifdef XML_DTD
5735 if (!copyEntityTable(&(newDtd->paramEntities),
5736 &(newDtd->pool),
5737 &(oldDtd->paramEntities)))
5738 return 0;
5739 newDtd->paramEntityRead = oldDtd->paramEntityRead;
5740 #endif /* XML_DTD */
5742 newDtd->keepProcessing = oldDtd->keepProcessing;
5743 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
5744 newDtd->standalone = oldDtd->standalone;
5746 /* Don't want deep copying for scaffolding */
5747 newDtd->in_eldecl = oldDtd->in_eldecl;
5748 newDtd->scaffold = oldDtd->scaffold;
5749 newDtd->contentStringLen = oldDtd->contentStringLen;
5750 newDtd->scaffSize = oldDtd->scaffSize;
5751 newDtd->scaffLevel = oldDtd->scaffLevel;
5752 newDtd->scaffIndex = oldDtd->scaffIndex;
5754 return 1;
5755 } /* End dtdCopy */
5757 static int
5758 copyEntityTable(HASH_TABLE *newTable,
5759 STRING_POOL *newPool,
5760 const HASH_TABLE *oldTable)
5762 HASH_TABLE_ITER iter;
5763 const XML_Char *cachedOldBase = NULL;
5764 const XML_Char *cachedNewBase = NULL;
5766 hashTableIterInit(&iter, oldTable);
5768 for (;;) {
5769 ENTITY *newE;
5770 const XML_Char *name;
5771 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
5772 if (!oldE)
5773 break;
5774 name = poolCopyString(newPool, oldE->name);
5775 if (!name)
5776 return 0;
5777 newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
5778 if (!newE)
5779 return 0;
5780 if (oldE->systemId) {
5781 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
5782 if (!tem)
5783 return 0;
5784 newE->systemId = tem;
5785 if (oldE->base) {
5786 if (oldE->base == cachedOldBase)
5787 newE->base = cachedNewBase;
5788 else {
5789 cachedOldBase = oldE->base;
5790 tem = poolCopyString(newPool, cachedOldBase);
5791 if (!tem)
5792 return 0;
5793 cachedNewBase = newE->base = tem;
5796 if (oldE->publicId) {
5797 tem = poolCopyString(newPool, oldE->publicId);
5798 if (!tem)
5799 return 0;
5800 newE->publicId = tem;
5803 else {
5804 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
5805 oldE->textLen);
5806 if (!tem)
5807 return 0;
5808 newE->textPtr = tem;
5809 newE->textLen = oldE->textLen;
5811 if (oldE->notation) {
5812 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
5813 if (!tem)
5814 return 0;
5815 newE->notation = tem;
5817 newE->is_param = oldE->is_param;
5818 newE->is_internal = oldE->is_internal;
5820 return 1;
5823 #define INIT_POWER 6
5825 static XML_Bool FASTCALL
5826 keyeq(KEY s1, KEY s2)
5828 for (; *s1 == *s2; s1++, s2++)
5829 if (*s1 == 0)
5830 return XML_TRUE;
5831 return XML_FALSE;
5834 static unsigned long FASTCALL
5835 hash(KEY s)
5837 unsigned long h = 0;
5838 while (*s)
5839 h = CHAR_HASH(h, *s++);
5840 return h;
5843 static NAMED *
5844 lookup(HASH_TABLE *table, KEY name, size_t createSize)
5846 size_t i;
5847 if (table->size == 0) {
5848 size_t tsize;
5849 if (!createSize)
5850 return NULL;
5851 table->power = INIT_POWER;
5852 /* table->size is a power of 2 */
5853 table->size = (size_t)1 << INIT_POWER;
5854 tsize = table->size * sizeof(NAMED *);
5855 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
5856 if (!table->v) {
5857 table->size = 0;
5858 return NULL;
5860 memset(table->v, 0, tsize);
5861 i = hash(name) & ((unsigned long)table->size - 1);
5863 else {
5864 unsigned long h = hash(name);
5865 unsigned long mask = (unsigned long)table->size - 1;
5866 unsigned char step = 0;
5867 i = h & mask;
5868 while (table->v[i]) {
5869 if (keyeq(name, table->v[i]->name))
5870 return table->v[i];
5871 if (!step)
5872 step = PROBE_STEP(h, mask, table->power);
5873 i < step ? (i += table->size - step) : (i -= step);
5875 if (!createSize)
5876 return NULL;
5878 /* check for overflow (table is half full) */
5879 if (table->used >> (table->power - 1)) {
5880 unsigned char newPower = table->power + 1;
5881 size_t newSize = (size_t)1 << newPower;
5882 unsigned long newMask = (unsigned long)newSize - 1;
5883 size_t tsize = newSize * sizeof(NAMED *);
5884 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
5885 if (!newV)
5886 return NULL;
5887 memset(newV, 0, tsize);
5888 for (i = 0; i < table->size; i++)
5889 if (table->v[i]) {
5890 unsigned long newHash = hash(table->v[i]->name);
5891 size_t j = newHash & newMask;
5892 step = 0;
5893 while (newV[j]) {
5894 if (!step)
5895 step = PROBE_STEP(newHash, newMask, newPower);
5896 j < step ? (j += newSize - step) : (j -= step);
5898 newV[j] = table->v[i];
5900 table->mem->free_fcn(table->v);
5901 table->v = newV;
5902 table->power = newPower;
5903 table->size = newSize;
5904 i = h & newMask;
5905 step = 0;
5906 while (table->v[i]) {
5907 if (!step)
5908 step = PROBE_STEP(h, newMask, newPower);
5909 i < step ? (i += newSize - step) : (i -= step);
5913 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
5914 if (!table->v[i])
5915 return NULL;
5916 memset(table->v[i], 0, createSize);
5917 table->v[i]->name = name;
5918 (table->used)++;
5919 return table->v[i];
5922 static void FASTCALL
5923 hashTableClear(HASH_TABLE *table)
5925 size_t i;
5926 for (i = 0; i < table->size; i++) {
5927 table->mem->free_fcn(table->v[i]);
5928 table->v[i] = NULL;
5930 table->used = 0;
5933 static void FASTCALL
5934 hashTableDestroy(HASH_TABLE *table)
5936 size_t i;
5937 for (i = 0; i < table->size; i++)
5938 table->mem->free_fcn(table->v[i]);
5939 table->mem->free_fcn(table->v);
5942 static void FASTCALL
5943 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
5945 p->power = 0;
5946 p->size = 0;
5947 p->used = 0;
5948 p->v = NULL;
5949 p->mem = ms;
5952 static void FASTCALL
5953 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
5955 iter->p = table->v;
5956 iter->end = iter->p + table->size;
5959 static NAMED * FASTCALL
5960 hashTableIterNext(HASH_TABLE_ITER *iter)
5962 while (iter->p != iter->end) {
5963 NAMED *tem = *(iter->p)++;
5964 if (tem)
5965 return tem;
5967 return NULL;
5970 static void FASTCALL
5971 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
5973 pool->blocks = NULL;
5974 pool->freeBlocks = NULL;
5975 pool->start = NULL;
5976 pool->ptr = NULL;
5977 pool->end = NULL;
5978 pool->mem = ms;
5981 static void FASTCALL
5982 poolClear(STRING_POOL *pool)
5984 if (!pool->freeBlocks)
5985 pool->freeBlocks = pool->blocks;
5986 else {
5987 BLOCK *p = pool->blocks;
5988 while (p) {
5989 BLOCK *tem = p->next;
5990 p->next = pool->freeBlocks;
5991 pool->freeBlocks = p;
5992 p = tem;
5995 pool->blocks = NULL;
5996 pool->start = NULL;
5997 pool->ptr = NULL;
5998 pool->end = NULL;
6001 static void FASTCALL
6002 poolDestroy(STRING_POOL *pool)
6004 BLOCK *p = pool->blocks;
6005 while (p) {
6006 BLOCK *tem = p->next;
6007 pool->mem->free_fcn(p);
6008 p = tem;
6010 p = pool->freeBlocks;
6011 while (p) {
6012 BLOCK *tem = p->next;
6013 pool->mem->free_fcn(p);
6014 p = tem;
6018 static XML_Char *
6019 poolAppend(STRING_POOL *pool, const ENCODING *enc,
6020 const char *ptr, const char *end)
6022 if (!pool->ptr && !poolGrow(pool))
6023 return NULL;
6024 for (;;) {
6025 XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6026 if (ptr == end)
6027 break;
6028 if (!poolGrow(pool))
6029 return NULL;
6031 return pool->start;
6034 static const XML_Char * FASTCALL
6035 poolCopyString(STRING_POOL *pool, const XML_Char *s)
6037 do {
6038 if (!poolAppendChar(pool, *s))
6039 return NULL;
6040 } while (*s++);
6041 s = pool->start;
6042 poolFinish(pool);
6043 return s;
6046 static const XML_Char *
6047 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
6049 if (!pool->ptr && !poolGrow(pool))
6050 return NULL;
6051 for (; n > 0; --n, s++) {
6052 if (!poolAppendChar(pool, *s))
6053 return NULL;
6055 s = pool->start;
6056 poolFinish(pool);
6057 return s;
6060 static const XML_Char * FASTCALL
6061 poolAppendString(STRING_POOL *pool, const XML_Char *s)
6063 while (*s) {
6064 if (!poolAppendChar(pool, *s))
6065 return NULL;
6066 s++;
6068 return pool->start;
6071 static XML_Char *
6072 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
6073 const char *ptr, const char *end)
6075 if (!poolAppend(pool, enc, ptr, end))
6076 return NULL;
6077 if (pool->ptr == pool->end && !poolGrow(pool))
6078 return NULL;
6079 *(pool->ptr)++ = 0;
6080 return pool->start;
6083 static XML_Bool FASTCALL
6084 poolGrow(STRING_POOL *pool)
6086 if (pool->freeBlocks) {
6087 if (pool->start == 0) {
6088 pool->blocks = pool->freeBlocks;
6089 pool->freeBlocks = pool->freeBlocks->next;
6090 pool->blocks->next = NULL;
6091 pool->start = pool->blocks->s;
6092 pool->end = pool->start + pool->blocks->size;
6093 pool->ptr = pool->start;
6094 return XML_TRUE;
6096 if (pool->end - pool->start < pool->freeBlocks->size) {
6097 BLOCK *tem = pool->freeBlocks->next;
6098 pool->freeBlocks->next = pool->blocks;
6099 pool->blocks = pool->freeBlocks;
6100 pool->freeBlocks = tem;
6101 memcpy(pool->blocks->s, pool->start,
6102 (pool->end - pool->start) * sizeof(XML_Char));
6103 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6104 pool->start = pool->blocks->s;
6105 pool->end = pool->start + pool->blocks->size;
6106 return XML_TRUE;
6109 if (pool->blocks && pool->start == pool->blocks->s) {
6110 int blockSize = (int)(pool->end - pool->start)*2;
6111 pool->blocks = (BLOCK *)
6112 pool->mem->realloc_fcn(pool->blocks,
6113 (offsetof(BLOCK, s)
6114 + blockSize * sizeof(XML_Char)));
6115 if (pool->blocks == NULL)
6116 return XML_FALSE;
6117 pool->blocks->size = blockSize;
6118 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6119 pool->start = pool->blocks->s;
6120 pool->end = pool->start + blockSize;
6122 else {
6123 BLOCK *tem;
6124 int blockSize = (int)(pool->end - pool->start);
6125 if (blockSize < INIT_BLOCK_SIZE)
6126 blockSize = INIT_BLOCK_SIZE;
6127 else
6128 blockSize *= 2;
6129 tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
6130 + blockSize * sizeof(XML_Char));
6131 if (!tem)
6132 return XML_FALSE;
6133 tem->size = blockSize;
6134 tem->next = pool->blocks;
6135 pool->blocks = tem;
6136 if (pool->ptr != pool->start)
6137 memcpy(tem->s, pool->start,
6138 (pool->ptr - pool->start) * sizeof(XML_Char));
6139 pool->ptr = tem->s + (pool->ptr - pool->start);
6140 pool->start = tem->s;
6141 pool->end = tem->s + blockSize;
6143 return XML_TRUE;
6146 static int FASTCALL
6147 nextScaffoldPart(XML_Parser parser)
6149 DTD * const dtd = _dtd; /* save one level of indirection */
6150 CONTENT_SCAFFOLD * me;
6151 int next;
6153 if (!dtd->scaffIndex) {
6154 dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
6155 if (!dtd->scaffIndex)
6156 return -1;
6157 dtd->scaffIndex[0] = 0;
6160 if (dtd->scaffCount >= dtd->scaffSize) {
6161 CONTENT_SCAFFOLD *temp;
6162 if (dtd->scaffold) {
6163 temp = (CONTENT_SCAFFOLD *)
6164 REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
6165 if (temp == NULL)
6166 return -1;
6167 dtd->scaffSize *= 2;
6169 else {
6170 temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
6171 * sizeof(CONTENT_SCAFFOLD));
6172 if (temp == NULL)
6173 return -1;
6174 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
6176 dtd->scaffold = temp;
6178 next = dtd->scaffCount++;
6179 me = &dtd->scaffold[next];
6180 if (dtd->scaffLevel) {
6181 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
6182 if (parent->lastchild) {
6183 dtd->scaffold[parent->lastchild].nextsib = next;
6185 if (!parent->childcnt)
6186 parent->firstchild = next;
6187 parent->lastchild = next;
6188 parent->childcnt++;
6190 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
6191 return next;
6194 static void
6195 build_node(XML_Parser parser,
6196 int src_node,
6197 XML_Content *dest,
6198 XML_Content **contpos,
6199 XML_Char **strpos)
6201 DTD * const dtd = _dtd; /* save one level of indirection */
6202 dest->type = dtd->scaffold[src_node].type;
6203 dest->quant = dtd->scaffold[src_node].quant;
6204 if (dest->type == XML_CTYPE_NAME) {
6205 const XML_Char *src;
6206 dest->name = *strpos;
6207 src = dtd->scaffold[src_node].name;
6208 for (;;) {
6209 *(*strpos)++ = *src;
6210 if (!*src)
6211 break;
6212 src++;
6214 dest->numchildren = 0;
6215 dest->children = NULL;
6217 else {
6218 unsigned int i;
6219 int cn;
6220 dest->numchildren = dtd->scaffold[src_node].childcnt;
6221 dest->children = *contpos;
6222 *contpos += dest->numchildren;
6223 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
6224 i < dest->numchildren;
6225 i++, cn = dtd->scaffold[cn].nextsib) {
6226 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
6228 dest->name = NULL;
6232 static XML_Content *
6233 build_model (XML_Parser parser)
6235 DTD * const dtd = _dtd; /* save one level of indirection */
6236 XML_Content *ret;
6237 XML_Content *cpos;
6238 XML_Char * str;
6239 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
6240 + (dtd->contentStringLen * sizeof(XML_Char)));
6242 ret = (XML_Content *)MALLOC(allocsize);
6243 if (!ret)
6244 return NULL;
6246 str = (XML_Char *) (&ret[dtd->scaffCount]);
6247 cpos = &ret[1];
6249 build_node(parser, 0, ret, &cpos, &str);
6250 return ret;
6253 static ELEMENT_TYPE *
6254 getElementType(XML_Parser parser,
6255 const ENCODING *enc,
6256 const char *ptr,
6257 const char *end)
6259 DTD * const dtd = _dtd; /* save one level of indirection */
6260 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
6261 ELEMENT_TYPE *ret;
6263 if (!name)
6264 return NULL;
6265 ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
6266 if (!ret)
6267 return NULL;
6268 if (ret->name != name)
6269 poolDiscard(&dtd->pool);
6270 else {
6271 poolFinish(&dtd->pool);
6272 if (!setElementTypePrefix(parser, ret))
6273 return NULL;
6275 return ret;