fix to work on python <= 2.1
[python/dscho.git] / Modules / expat / xmlparse.c
blobeae9374ff5a22917bbdf1b8ce9d741faa6603bc6
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() */
8 #ifdef COMPILED_FROM_DSP
10 #include "winconfig.h"
11 #define XMLPARSEAPI(type) type __cdecl
12 #include "expat.h"
13 #undef XMLPARSEAPI
15 #elif defined(MACOS_CLASSIC)
17 #include "macconfig.h"
18 #include "expat.h"
20 #else
22 /* Unused - MvL
23 #include <expat_config.h>
26 #ifdef __declspec
27 #define XMLPARSEAPI(type) type __cdecl
28 #endif
30 #include "expat.h"
32 #ifdef __declspec
33 #undef XMLPARSEAPI
34 #endif
35 #endif /* ndef COMPILED_FROM_DSP */
37 #ifdef XML_UNICODE
38 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
39 #define XmlConvert XmlUtf16Convert
40 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
41 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
42 #define XmlEncode XmlUtf16Encode
43 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
44 typedef unsigned short ICHAR;
45 #else
46 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
47 #define XmlConvert XmlUtf8Convert
48 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
49 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
50 #define XmlEncode XmlUtf8Encode
51 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
52 typedef char ICHAR;
53 #endif
56 #ifndef XML_NS
58 #define XmlInitEncodingNS XmlInitEncoding
59 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
60 #undef XmlGetInternalEncodingNS
61 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
62 #define XmlParseXmlDeclNS XmlParseXmlDecl
64 #endif
66 #ifdef XML_UNICODE
68 #ifdef XML_UNICODE_WCHAR_T
69 #define XML_T(x) (const wchar_t)x
70 #define XML_L(x) L ## x
71 #else
72 #define XML_T(x) (const unsigned short)x
73 #define XML_L(x) x
74 #endif
76 #else
78 #define XML_T(x) x
79 #define XML_L(x) x
81 #endif
83 /* Round up n to be a multiple of sz, where sz is a power of 2. */
84 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
86 #include "internal.h"
87 #include "xmltok.h"
88 #include "xmlrole.h"
90 typedef const XML_Char *KEY;
92 typedef struct {
93 KEY name;
94 } NAMED;
96 typedef struct {
97 NAMED **v;
98 size_t size;
99 size_t used;
100 size_t usedLim;
101 const XML_Memory_Handling_Suite *mem;
102 } HASH_TABLE;
104 typedef struct {
105 NAMED **p;
106 NAMED **end;
107 } HASH_TABLE_ITER;
109 #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
110 #define INIT_DATA_BUF_SIZE 1024
111 #define INIT_ATTS_SIZE 16
112 #define INIT_BLOCK_SIZE 1024
113 #define INIT_BUFFER_SIZE 1024
115 #define EXPAND_SPARE 24
117 typedef struct binding {
118 struct prefix *prefix;
119 struct binding *nextTagBinding;
120 struct binding *prevPrefixBinding;
121 const struct attribute_id *attId;
122 XML_Char *uri;
123 int uriLen;
124 int uriAlloc;
125 } BINDING;
127 typedef struct prefix {
128 const XML_Char *name;
129 BINDING *binding;
130 } PREFIX;
132 typedef struct {
133 const XML_Char *str;
134 const XML_Char *localPart;
135 const XML_Char *prefix;
136 int strLen;
137 int uriLen;
138 int prefixLen;
139 } TAG_NAME;
141 /* TAG represents an open element.
142 The name of the element is stored in both the document and API
143 encodings. The memory buffer 'buf' is a separately-allocated
144 memory area which stores the name. During the XML_Parse()/
145 XMLParseBuffer() when the element is open, the memory for the 'raw'
146 version of the name (in the document encoding) is shared with the
147 document buffer. If the element is open across calls to
148 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
149 contain the 'raw' name as well.
151 A parser re-uses these structures, maintaining a list of allocated
152 TAG objects in a free list.
154 typedef struct tag {
155 struct tag *parent; /* parent of this element */
156 const char *rawName; /* tagName in the original encoding */
157 int rawNameLength;
158 TAG_NAME name; /* tagName in the API encoding */
159 char *buf; /* buffer for name components */
160 char *bufEnd; /* end of the buffer */
161 BINDING *bindings;
162 } TAG;
164 typedef struct {
165 const XML_Char *name;
166 const XML_Char *textPtr;
167 int textLen;
168 const XML_Char *systemId;
169 const XML_Char *base;
170 const XML_Char *publicId;
171 const XML_Char *notation;
172 XML_Bool open;
173 XML_Bool is_param;
174 XML_Bool is_internal; /* true if declared in internal subset outside PE */
175 } ENTITY;
177 typedef struct {
178 enum XML_Content_Type type;
179 enum XML_Content_Quant quant;
180 const XML_Char * name;
181 int firstchild;
182 int lastchild;
183 int childcnt;
184 int nextsib;
185 } CONTENT_SCAFFOLD;
187 #define INIT_SCAFFOLD_ELEMENTS 32
189 typedef struct block {
190 struct block *next;
191 int size;
192 XML_Char s[1];
193 } BLOCK;
195 typedef struct {
196 BLOCK *blocks;
197 BLOCK *freeBlocks;
198 const XML_Char *end;
199 XML_Char *ptr;
200 XML_Char *start;
201 const XML_Memory_Handling_Suite *mem;
202 } STRING_POOL;
204 /* The XML_Char before the name is used to determine whether
205 an attribute has been specified. */
206 typedef struct attribute_id {
207 XML_Char *name;
208 PREFIX *prefix;
209 XML_Bool maybeTokenized;
210 XML_Bool xmlns;
211 } ATTRIBUTE_ID;
213 typedef struct {
214 const ATTRIBUTE_ID *id;
215 XML_Bool isCdata;
216 const XML_Char *value;
217 } DEFAULT_ATTRIBUTE;
219 typedef struct {
220 const XML_Char *name;
221 PREFIX *prefix;
222 const ATTRIBUTE_ID *idAtt;
223 int nDefaultAtts;
224 int allocDefaultAtts;
225 DEFAULT_ATTRIBUTE *defaultAtts;
226 } ELEMENT_TYPE;
228 typedef struct {
229 HASH_TABLE generalEntities;
230 HASH_TABLE elementTypes;
231 HASH_TABLE attributeIds;
232 HASH_TABLE prefixes;
233 STRING_POOL pool;
234 STRING_POOL entityValuePool;
235 /* false once a parameter entity reference has been skipped */
236 XML_Bool keepProcessing;
237 /* true once an internal or external PE reference has been encountered;
238 this includes the reference to an external subset */
239 XML_Bool hasParamEntityRefs;
240 XML_Bool standalone;
241 #ifdef XML_DTD
242 /* indicates if external PE has been read */
243 XML_Bool paramEntityRead;
244 HASH_TABLE paramEntities;
245 #endif /* XML_DTD */
246 PREFIX defaultPrefix;
247 /* === scaffolding for building content model === */
248 XML_Bool in_eldecl;
249 CONTENT_SCAFFOLD *scaffold;
250 unsigned contentStringLen;
251 unsigned scaffSize;
252 unsigned scaffCount;
253 int scaffLevel;
254 int *scaffIndex;
255 } DTD;
257 typedef struct open_internal_entity {
258 const char *internalEventPtr;
259 const char *internalEventEndPtr;
260 struct open_internal_entity *next;
261 ENTITY *entity;
262 } OPEN_INTERNAL_ENTITY;
264 typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
265 const char *start,
266 const char *end,
267 const char **endPtr);
269 static Processor prologProcessor;
270 static Processor prologInitProcessor;
271 static Processor contentProcessor;
272 static Processor cdataSectionProcessor;
273 #ifdef XML_DTD
274 static Processor ignoreSectionProcessor;
275 static Processor externalParEntProcessor;
276 static Processor externalParEntInitProcessor;
277 static Processor entityValueProcessor;
278 static Processor entityValueInitProcessor;
279 #endif /* XML_DTD */
280 static Processor epilogProcessor;
281 static Processor errorProcessor;
282 static Processor externalEntityInitProcessor;
283 static Processor externalEntityInitProcessor2;
284 static Processor externalEntityInitProcessor3;
285 static Processor externalEntityContentProcessor;
287 static enum XML_Error
288 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
289 static enum XML_Error
290 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
291 const char *, const char *);
292 static enum XML_Error
293 initializeEncoding(XML_Parser parser);
294 static enum XML_Error
295 doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
296 const char *end, int tok, const char *next, const char **nextPtr);
297 static enum XML_Error
298 processInternalParamEntity(XML_Parser parser, ENTITY *entity);
299 static enum XML_Error
300 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
301 const char *start, const char *end, const char **endPtr);
302 static enum XML_Error
303 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
304 const char *end, const char **nextPtr);
305 #ifdef XML_DTD
306 static enum XML_Error
307 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
308 const char *end, const char **nextPtr);
309 #endif /* XML_DTD */
311 static enum XML_Error
312 storeAtts(XML_Parser parser, const ENCODING *, const char *s,
313 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
314 static enum XML_Error
315 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
316 const XML_Char *uri, BINDING **bindingsPtr);
317 static int
318 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *,
319 XML_Bool isCdata, XML_Bool isId, const XML_Char *dfltValue,
320 XML_Parser parser);
321 static enum XML_Error
322 storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
323 const char *, const char *, STRING_POOL *);
324 static enum XML_Error
325 appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
326 const char *, const char *, STRING_POOL *);
327 static ATTRIBUTE_ID *
328 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
329 const char *end);
330 static int
331 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
332 static enum XML_Error
333 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
334 const char *end);
335 static int
336 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
337 const char *start, const char *end);
338 static int
339 reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
340 const char *end);
341 static void
342 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
343 const char *end);
345 static const XML_Char * getContext(XML_Parser parser);
346 static XML_Bool
347 setContext(XML_Parser parser, const XML_Char *context);
349 static void FASTCALL normalizePublicId(XML_Char *s);
351 static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
352 /* do not call if parentParser != NULL */
353 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
354 static void
355 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
356 static int
357 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
358 static int
359 copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
361 static NAMED *
362 lookup(HASH_TABLE *table, KEY name, size_t createSize);
363 static void FASTCALL
364 hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
365 static void FASTCALL hashTableClear(HASH_TABLE *);
366 static void FASTCALL hashTableDestroy(HASH_TABLE *);
367 static void FASTCALL
368 hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
369 static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
371 static void FASTCALL
372 poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
373 static void FASTCALL poolClear(STRING_POOL *);
374 static void FASTCALL poolDestroy(STRING_POOL *);
375 static XML_Char *
376 poolAppend(STRING_POOL *pool, const ENCODING *enc,
377 const char *ptr, const char *end);
378 static XML_Char *
379 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
380 const char *ptr, const char *end);
381 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
382 static const XML_Char * FASTCALL
383 poolCopyString(STRING_POOL *pool, const XML_Char *s);
384 static const XML_Char *
385 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
386 static const XML_Char * FASTCALL
387 poolAppendString(STRING_POOL *pool, const XML_Char *s);
389 static int FASTCALL nextScaffoldPart(XML_Parser parser);
390 static XML_Content * build_model(XML_Parser parser);
391 static ELEMENT_TYPE *
392 getElementType(XML_Parser parser, const ENCODING *enc,
393 const char *ptr, const char *end);
395 static XML_Parser
396 parserCreate(const XML_Char *encodingName,
397 const XML_Memory_Handling_Suite *memsuite,
398 const XML_Char *nameSep,
399 DTD *dtd);
400 static void
401 parserInit(XML_Parser parser, const XML_Char *encodingName);
403 #define poolStart(pool) ((pool)->start)
404 #define poolEnd(pool) ((pool)->ptr)
405 #define poolLength(pool) ((pool)->ptr - (pool)->start)
406 #define poolChop(pool) ((void)--(pool->ptr))
407 #define poolLastChar(pool) (((pool)->ptr)[-1])
408 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
409 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
410 #define poolAppendChar(pool, c) \
411 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
412 ? 0 \
413 : ((*((pool)->ptr)++ = c), 1))
415 struct XML_ParserStruct {
416 /* The first member must be userData so that the XML_GetUserData
417 macro works. */
418 void *m_userData;
419 void *m_handlerArg;
420 char *m_buffer;
421 const XML_Memory_Handling_Suite m_mem;
422 /* first character to be parsed */
423 const char *m_bufferPtr;
424 /* past last character to be parsed */
425 char *m_bufferEnd;
426 /* allocated end of buffer */
427 const char *m_bufferLim;
428 long m_parseEndByteIndex;
429 const char *m_parseEndPtr;
430 XML_Char *m_dataBuf;
431 XML_Char *m_dataBufEnd;
432 XML_StartElementHandler m_startElementHandler;
433 XML_EndElementHandler m_endElementHandler;
434 XML_CharacterDataHandler m_characterDataHandler;
435 XML_ProcessingInstructionHandler m_processingInstructionHandler;
436 XML_CommentHandler m_commentHandler;
437 XML_StartCdataSectionHandler m_startCdataSectionHandler;
438 XML_EndCdataSectionHandler m_endCdataSectionHandler;
439 XML_DefaultHandler m_defaultHandler;
440 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
441 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
442 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
443 XML_NotationDeclHandler m_notationDeclHandler;
444 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
445 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
446 XML_NotStandaloneHandler m_notStandaloneHandler;
447 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
448 XML_Parser m_externalEntityRefHandlerArg;
449 XML_SkippedEntityHandler m_skippedEntityHandler;
450 XML_UnknownEncodingHandler m_unknownEncodingHandler;
451 XML_ElementDeclHandler m_elementDeclHandler;
452 XML_AttlistDeclHandler m_attlistDeclHandler;
453 XML_EntityDeclHandler m_entityDeclHandler;
454 XML_XmlDeclHandler m_xmlDeclHandler;
455 const ENCODING *m_encoding;
456 INIT_ENCODING m_initEncoding;
457 const ENCODING *m_internalEncoding;
458 const XML_Char *m_protocolEncodingName;
459 XML_Bool m_ns;
460 XML_Bool m_ns_triplets;
461 void *m_unknownEncodingMem;
462 void *m_unknownEncodingData;
463 void *m_unknownEncodingHandlerData;
464 void (*m_unknownEncodingRelease)(void *);
465 PROLOG_STATE m_prologState;
466 Processor *m_processor;
467 enum XML_Error m_errorCode;
468 const char *m_eventPtr;
469 const char *m_eventEndPtr;
470 const char *m_positionPtr;
471 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
472 XML_Bool m_defaultExpandInternalEntities;
473 int m_tagLevel;
474 ENTITY *m_declEntity;
475 const XML_Char *m_doctypeName;
476 const XML_Char *m_doctypeSysid;
477 const XML_Char *m_doctypePubid;
478 const XML_Char *m_declAttributeType;
479 const XML_Char *m_declNotationName;
480 const XML_Char *m_declNotationPublicId;
481 ELEMENT_TYPE *m_declElementType;
482 ATTRIBUTE_ID *m_declAttributeId;
483 XML_Bool m_declAttributeIsCdata;
484 XML_Bool m_declAttributeIsId;
485 DTD *m_dtd;
486 const XML_Char *m_curBase;
487 TAG *m_tagStack;
488 TAG *m_freeTagList;
489 BINDING *m_inheritedBindings;
490 BINDING *m_freeBindingList;
491 int m_attsSize;
492 int m_nSpecifiedAtts;
493 int m_idAttIndex;
494 ATTRIBUTE *m_atts;
495 POSITION m_position;
496 STRING_POOL m_tempPool;
497 STRING_POOL m_temp2Pool;
498 char *m_groupConnector;
499 unsigned m_groupSize;
500 XML_Char m_namespaceSeparator;
501 XML_Parser m_parentParser;
502 #ifdef XML_DTD
503 XML_Bool m_isParamEntity;
504 XML_Bool m_useForeignDTD;
505 enum XML_ParamEntityParsing m_paramEntityParsing;
506 #endif
509 #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
510 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
511 #define FREE(p) (parser->m_mem.free_fcn((p)))
513 #define userData (parser->m_userData)
514 #define handlerArg (parser->m_handlerArg)
515 #define startElementHandler (parser->m_startElementHandler)
516 #define endElementHandler (parser->m_endElementHandler)
517 #define characterDataHandler (parser->m_characterDataHandler)
518 #define processingInstructionHandler \
519 (parser->m_processingInstructionHandler)
520 #define commentHandler (parser->m_commentHandler)
521 #define startCdataSectionHandler \
522 (parser->m_startCdataSectionHandler)
523 #define endCdataSectionHandler (parser->m_endCdataSectionHandler)
524 #define defaultHandler (parser->m_defaultHandler)
525 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
526 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
527 #define unparsedEntityDeclHandler \
528 (parser->m_unparsedEntityDeclHandler)
529 #define notationDeclHandler (parser->m_notationDeclHandler)
530 #define startNamespaceDeclHandler \
531 (parser->m_startNamespaceDeclHandler)
532 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
533 #define notStandaloneHandler (parser->m_notStandaloneHandler)
534 #define externalEntityRefHandler \
535 (parser->m_externalEntityRefHandler)
536 #define externalEntityRefHandlerArg \
537 (parser->m_externalEntityRefHandlerArg)
538 #define internalEntityRefHandler \
539 (parser->m_internalEntityRefHandler)
540 #define skippedEntityHandler (parser->m_skippedEntityHandler)
541 #define unknownEncodingHandler (parser->m_unknownEncodingHandler)
542 #define elementDeclHandler (parser->m_elementDeclHandler)
543 #define attlistDeclHandler (parser->m_attlistDeclHandler)
544 #define entityDeclHandler (parser->m_entityDeclHandler)
545 #define xmlDeclHandler (parser->m_xmlDeclHandler)
546 #define encoding (parser->m_encoding)
547 #define initEncoding (parser->m_initEncoding)
548 #define internalEncoding (parser->m_internalEncoding)
549 #define unknownEncodingMem (parser->m_unknownEncodingMem)
550 #define unknownEncodingData (parser->m_unknownEncodingData)
551 #define unknownEncodingHandlerData \
552 (parser->m_unknownEncodingHandlerData)
553 #define unknownEncodingRelease (parser->m_unknownEncodingRelease)
554 #define protocolEncodingName (parser->m_protocolEncodingName)
555 #define ns (parser->m_ns)
556 #define ns_triplets (parser->m_ns_triplets)
557 #define prologState (parser->m_prologState)
558 #define processor (parser->m_processor)
559 #define errorCode (parser->m_errorCode)
560 #define eventPtr (parser->m_eventPtr)
561 #define eventEndPtr (parser->m_eventEndPtr)
562 #define positionPtr (parser->m_positionPtr)
563 #define position (parser->m_position)
564 #define openInternalEntities (parser->m_openInternalEntities)
565 #define defaultExpandInternalEntities \
566 (parser->m_defaultExpandInternalEntities)
567 #define tagLevel (parser->m_tagLevel)
568 #define buffer (parser->m_buffer)
569 #define bufferPtr (parser->m_bufferPtr)
570 #define bufferEnd (parser->m_bufferEnd)
571 #define parseEndByteIndex (parser->m_parseEndByteIndex)
572 #define parseEndPtr (parser->m_parseEndPtr)
573 #define bufferLim (parser->m_bufferLim)
574 #define dataBuf (parser->m_dataBuf)
575 #define dataBufEnd (parser->m_dataBufEnd)
576 #define _dtd (parser->m_dtd)
577 #define curBase (parser->m_curBase)
578 #define declEntity (parser->m_declEntity)
579 #define doctypeName (parser->m_doctypeName)
580 #define doctypeSysid (parser->m_doctypeSysid)
581 #define doctypePubid (parser->m_doctypePubid)
582 #define declAttributeType (parser->m_declAttributeType)
583 #define declNotationName (parser->m_declNotationName)
584 #define declNotationPublicId (parser->m_declNotationPublicId)
585 #define declElementType (parser->m_declElementType)
586 #define declAttributeId (parser->m_declAttributeId)
587 #define declAttributeIsCdata (parser->m_declAttributeIsCdata)
588 #define declAttributeIsId (parser->m_declAttributeIsId)
589 #define freeTagList (parser->m_freeTagList)
590 #define freeBindingList (parser->m_freeBindingList)
591 #define inheritedBindings (parser->m_inheritedBindings)
592 #define tagStack (parser->m_tagStack)
593 #define atts (parser->m_atts)
594 #define attsSize (parser->m_attsSize)
595 #define nSpecifiedAtts (parser->m_nSpecifiedAtts)
596 #define idAttIndex (parser->m_idAttIndex)
597 #define tempPool (parser->m_tempPool)
598 #define temp2Pool (parser->m_temp2Pool)
599 #define groupConnector (parser->m_groupConnector)
600 #define groupSize (parser->m_groupSize)
601 #define namespaceSeparator (parser->m_namespaceSeparator)
602 #define parentParser (parser->m_parentParser)
603 #ifdef XML_DTD
604 #define isParamEntity (parser->m_isParamEntity)
605 #define useForeignDTD (parser->m_useForeignDTD)
606 #define paramEntityParsing (parser->m_paramEntityParsing)
607 #endif /* XML_DTD */
609 #define parsing \
610 (parentParser \
612 (isParamEntity \
614 (processor != externalParEntInitProcessor) \
616 (processor != externalEntityInitProcessor)) \
618 (processor != prologInitProcessor))
620 XML_Parser
621 XML_ParserCreate(const XML_Char *encodingName)
623 return XML_ParserCreate_MM(encodingName, NULL, NULL);
626 XML_Parser
627 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
629 XML_Char tmp[2];
630 *tmp = nsSep;
631 return XML_ParserCreate_MM(encodingName, NULL, tmp);
634 static const XML_Char implicitContext[] = {
635 'x', 'm', 'l', '=', 'h', 't', 't', 'p', ':', '/', '/',
636 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/',
637 'X', 'M', 'L', '/', '1', '9', '9', '8', '/',
638 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0'
641 XML_Parser
642 XML_ParserCreate_MM(const XML_Char *encodingName,
643 const XML_Memory_Handling_Suite *memsuite,
644 const XML_Char *nameSep)
646 XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL);
647 if (parser != NULL && ns) {
648 /* implicit context only set for root parser, since child
649 parsers (i.e. external entity parsers) will inherit it
651 if (!setContext(parser, implicitContext)) {
652 XML_ParserFree(parser);
653 return NULL;
656 return parser;
659 static XML_Parser
660 parserCreate(const XML_Char *encodingName,
661 const XML_Memory_Handling_Suite *memsuite,
662 const XML_Char *nameSep,
663 DTD *dtd)
665 XML_Parser parser;
667 if (memsuite) {
668 XML_Memory_Handling_Suite *mtemp;
669 parser = (XML_Parser)
670 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
671 if (parser != NULL) {
672 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
673 mtemp->malloc_fcn = memsuite->malloc_fcn;
674 mtemp->realloc_fcn = memsuite->realloc_fcn;
675 mtemp->free_fcn = memsuite->free_fcn;
678 else {
679 XML_Memory_Handling_Suite *mtemp;
680 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
681 if (parser != NULL) {
682 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
683 mtemp->malloc_fcn = malloc;
684 mtemp->realloc_fcn = realloc;
685 mtemp->free_fcn = free;
689 if (!parser)
690 return parser;
692 buffer = NULL;
693 bufferLim = NULL;
695 attsSize = INIT_ATTS_SIZE;
696 atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
697 if (atts == NULL) {
698 FREE(parser);
699 return NULL;
701 dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
702 if (dataBuf == NULL) {
703 FREE(atts);
704 FREE(parser);
705 return NULL;
707 dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
709 if (dtd)
710 _dtd = dtd;
711 else {
712 _dtd = dtdCreate(&parser->m_mem);
713 if (_dtd == NULL) {
714 FREE(dataBuf);
715 FREE(atts);
716 FREE(parser);
717 return NULL;
721 freeBindingList = NULL;
722 freeTagList = NULL;
724 groupSize = 0;
725 groupConnector = NULL;
727 unknownEncodingHandler = NULL;
728 unknownEncodingHandlerData = NULL;
730 namespaceSeparator = '!';
731 ns = XML_FALSE;
732 ns_triplets = XML_FALSE;
734 poolInit(&tempPool, &(parser->m_mem));
735 poolInit(&temp2Pool, &(parser->m_mem));
736 parserInit(parser, encodingName);
738 if (encodingName && !protocolEncodingName) {
739 XML_ParserFree(parser);
740 return NULL;
743 if (nameSep) {
744 ns = XML_TRUE;
745 internalEncoding = XmlGetInternalEncodingNS();
746 namespaceSeparator = *nameSep;
748 else {
749 internalEncoding = XmlGetInternalEncoding();
752 return parser;
755 static void
756 parserInit(XML_Parser parser, const XML_Char *encodingName)
758 processor = prologInitProcessor;
759 XmlPrologStateInit(&prologState);
760 protocolEncodingName = (encodingName != NULL
761 ? poolCopyString(&tempPool, encodingName)
762 : NULL);
763 curBase = NULL;
764 XmlInitEncoding(&initEncoding, &encoding, 0);
765 userData = NULL;
766 handlerArg = NULL;
767 startElementHandler = NULL;
768 endElementHandler = NULL;
769 characterDataHandler = NULL;
770 processingInstructionHandler = NULL;
771 commentHandler = NULL;
772 startCdataSectionHandler = NULL;
773 endCdataSectionHandler = NULL;
774 defaultHandler = NULL;
775 startDoctypeDeclHandler = NULL;
776 endDoctypeDeclHandler = NULL;
777 unparsedEntityDeclHandler = NULL;
778 notationDeclHandler = NULL;
779 startNamespaceDeclHandler = NULL;
780 endNamespaceDeclHandler = NULL;
781 notStandaloneHandler = NULL;
782 externalEntityRefHandler = NULL;
783 externalEntityRefHandlerArg = parser;
784 skippedEntityHandler = NULL;
785 elementDeclHandler = NULL;
786 attlistDeclHandler = NULL;
787 entityDeclHandler = NULL;
788 xmlDeclHandler = NULL;
789 bufferPtr = buffer;
790 bufferEnd = buffer;
791 parseEndByteIndex = 0;
792 parseEndPtr = NULL;
793 declElementType = NULL;
794 declAttributeId = NULL;
795 declEntity = NULL;
796 doctypeName = NULL;
797 doctypeSysid = NULL;
798 doctypePubid = NULL;
799 declAttributeType = NULL;
800 declNotationName = NULL;
801 declNotationPublicId = NULL;
802 declAttributeIsCdata = XML_FALSE;
803 declAttributeIsId = XML_FALSE;
804 memset(&position, 0, sizeof(POSITION));
805 errorCode = XML_ERROR_NONE;
806 eventPtr = NULL;
807 eventEndPtr = NULL;
808 positionPtr = NULL;
809 openInternalEntities = 0;
810 defaultExpandInternalEntities = XML_TRUE;
811 tagLevel = 0;
812 tagStack = NULL;
813 inheritedBindings = NULL;
814 nSpecifiedAtts = 0;
815 unknownEncodingMem = NULL;
816 unknownEncodingRelease = NULL;
817 unknownEncodingData = NULL;
818 parentParser = NULL;
819 #ifdef XML_DTD
820 isParamEntity = XML_FALSE;
821 useForeignDTD = XML_FALSE;
822 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
823 #endif
826 /* moves list of bindings to freeBindingList */
827 static void FASTCALL
828 moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
830 while (bindings) {
831 BINDING *b = bindings;
832 bindings = bindings->nextTagBinding;
833 b->nextTagBinding = freeBindingList;
834 freeBindingList = b;
838 XML_Bool
839 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
841 TAG *tStk;
842 if (parentParser)
843 return XML_FALSE;
844 /* move tagStack to freeTagList */
845 tStk = tagStack;
846 while (tStk) {
847 TAG *tag = tStk;
848 tStk = tStk->parent;
849 tag->parent = freeTagList;
850 moveToFreeBindingList(parser, tag->bindings);
851 tag->bindings = NULL;
852 freeTagList = tag;
854 moveToFreeBindingList(parser, inheritedBindings);
855 if (unknownEncodingMem)
856 FREE(unknownEncodingMem);
857 if (unknownEncodingRelease)
858 unknownEncodingRelease(unknownEncodingData);
859 poolClear(&tempPool);
860 poolClear(&temp2Pool);
861 parserInit(parser, encodingName);
862 dtdReset(_dtd, &parser->m_mem);
863 return setContext(parser, implicitContext);
866 enum XML_Status
867 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
869 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
870 XXX There's no way for the caller to determine which of the
871 XXX possible error cases caused the XML_STATUS_ERROR return.
873 if (parsing)
874 return XML_STATUS_ERROR;
875 if (encodingName == NULL)
876 protocolEncodingName = NULL;
877 else {
878 protocolEncodingName = poolCopyString(&tempPool, encodingName);
879 if (!protocolEncodingName)
880 return XML_STATUS_ERROR;
882 return XML_STATUS_OK;
885 XML_Parser
886 XML_ExternalEntityParserCreate(XML_Parser oldParser,
887 const XML_Char *context,
888 const XML_Char *encodingName)
890 XML_Parser parser = oldParser;
891 DTD *newDtd = NULL;
892 DTD *oldDtd = _dtd;
893 XML_StartElementHandler oldStartElementHandler = startElementHandler;
894 XML_EndElementHandler oldEndElementHandler = endElementHandler;
895 XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
896 XML_ProcessingInstructionHandler oldProcessingInstructionHandler
897 = processingInstructionHandler;
898 XML_CommentHandler oldCommentHandler = commentHandler;
899 XML_StartCdataSectionHandler oldStartCdataSectionHandler
900 = startCdataSectionHandler;
901 XML_EndCdataSectionHandler oldEndCdataSectionHandler
902 = endCdataSectionHandler;
903 XML_DefaultHandler oldDefaultHandler = defaultHandler;
904 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
905 = unparsedEntityDeclHandler;
906 XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
907 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
908 = startNamespaceDeclHandler;
909 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
910 = endNamespaceDeclHandler;
911 XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
912 XML_ExternalEntityRefHandler oldExternalEntityRefHandler
913 = externalEntityRefHandler;
914 XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
915 XML_UnknownEncodingHandler oldUnknownEncodingHandler
916 = unknownEncodingHandler;
917 XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
918 XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
919 XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
920 XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
921 ELEMENT_TYPE * oldDeclElementType = declElementType;
923 void *oldUserData = userData;
924 void *oldHandlerArg = handlerArg;
925 XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
926 XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
927 #ifdef XML_DTD
928 enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
929 int oldInEntityValue = prologState.inEntityValue;
930 #endif
931 XML_Bool oldns_triplets = ns_triplets;
933 #ifdef XML_DTD
934 if (!context)
935 newDtd = oldDtd;
936 #endif /* XML_DTD */
938 /* Note that the magical uses of the pre-processor to make field
939 access look more like C++ require that `parser' be overwritten
940 here. This makes this function more painful to follow than it
941 would be otherwise.
943 if (ns) {
944 XML_Char tmp[2];
945 *tmp = namespaceSeparator;
946 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
948 else {
949 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
952 if (!parser)
953 return NULL;
955 startElementHandler = oldStartElementHandler;
956 endElementHandler = oldEndElementHandler;
957 characterDataHandler = oldCharacterDataHandler;
958 processingInstructionHandler = oldProcessingInstructionHandler;
959 commentHandler = oldCommentHandler;
960 startCdataSectionHandler = oldStartCdataSectionHandler;
961 endCdataSectionHandler = oldEndCdataSectionHandler;
962 defaultHandler = oldDefaultHandler;
963 unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
964 notationDeclHandler = oldNotationDeclHandler;
965 startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
966 endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
967 notStandaloneHandler = oldNotStandaloneHandler;
968 externalEntityRefHandler = oldExternalEntityRefHandler;
969 skippedEntityHandler = oldSkippedEntityHandler;
970 unknownEncodingHandler = oldUnknownEncodingHandler;
971 elementDeclHandler = oldElementDeclHandler;
972 attlistDeclHandler = oldAttlistDeclHandler;
973 entityDeclHandler = oldEntityDeclHandler;
974 xmlDeclHandler = oldXmlDeclHandler;
975 declElementType = oldDeclElementType;
976 userData = oldUserData;
977 if (oldUserData == oldHandlerArg)
978 handlerArg = userData;
979 else
980 handlerArg = parser;
981 if (oldExternalEntityRefHandlerArg != oldParser)
982 externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
983 defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
984 ns_triplets = oldns_triplets;
985 parentParser = oldParser;
986 #ifdef XML_DTD
987 paramEntityParsing = oldParamEntityParsing;
988 prologState.inEntityValue = oldInEntityValue;
989 if (context) {
990 #endif /* XML_DTD */
991 if (!dtdCopy(_dtd, oldDtd, &parser->m_mem)
992 || !setContext(parser, context)) {
993 XML_ParserFree(parser);
994 return NULL;
996 processor = externalEntityInitProcessor;
997 #ifdef XML_DTD
999 else {
1000 /* The DTD instance referenced by _dtd is shared between the document's
1001 root parser and external PE parsers, therefore one does not need to
1002 call setContext. In addition, one also *must* not call setContext,
1003 because this would overwrite existing prefix->binding pointers in
1004 _dtd with ones that get destroyed with the external PE parser.
1005 This would leave those prefixes with dangling pointers.
1007 isParamEntity = XML_TRUE;
1008 XmlPrologStateInitExternalEntity(&prologState);
1009 processor = externalParEntInitProcessor;
1011 #endif /* XML_DTD */
1012 return parser;
1015 static void FASTCALL
1016 destroyBindings(BINDING *bindings, XML_Parser parser)
1018 for (;;) {
1019 BINDING *b = bindings;
1020 if (!b)
1021 break;
1022 bindings = b->nextTagBinding;
1023 FREE(b->uri);
1024 FREE(b);
1028 void
1029 XML_ParserFree(XML_Parser parser)
1031 for (;;) {
1032 TAG *p;
1033 if (tagStack == NULL) {
1034 if (freeTagList == NULL)
1035 break;
1036 tagStack = freeTagList;
1037 freeTagList = NULL;
1039 p = tagStack;
1040 tagStack = tagStack->parent;
1041 FREE(p->buf);
1042 destroyBindings(p->bindings, parser);
1043 FREE(p);
1045 destroyBindings(freeBindingList, parser);
1046 destroyBindings(inheritedBindings, parser);
1047 poolDestroy(&tempPool);
1048 poolDestroy(&temp2Pool);
1049 #ifdef XML_DTD
1050 /* external parameter entity parsers share the DTD structure
1051 parser->m_dtd with the root parser, so we must not destroy it
1053 if (!isParamEntity && _dtd)
1054 #else
1055 if (_dtd)
1056 #endif /* XML_DTD */
1057 dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
1058 FREE((void *)atts);
1059 if (groupConnector)
1060 FREE(groupConnector);
1061 if (buffer)
1062 FREE(buffer);
1063 FREE(dataBuf);
1064 if (unknownEncodingMem)
1065 FREE(unknownEncodingMem);
1066 if (unknownEncodingRelease)
1067 unknownEncodingRelease(unknownEncodingData);
1068 FREE(parser);
1071 void
1072 XML_UseParserAsHandlerArg(XML_Parser parser)
1074 handlerArg = parser;
1077 enum XML_Error
1078 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
1080 #ifdef XML_DTD
1081 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1082 if (parsing)
1083 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
1084 useForeignDTD = useDTD;
1085 return XML_ERROR_NONE;
1086 #else
1087 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1088 #endif
1091 void
1092 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
1094 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1095 if (parsing)
1096 return;
1097 ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
1100 void
1101 XML_SetUserData(XML_Parser parser, void *p)
1103 if (handlerArg == userData)
1104 handlerArg = userData = p;
1105 else
1106 userData = p;
1109 enum XML_Status
1110 XML_SetBase(XML_Parser parser, const XML_Char *p)
1112 if (p) {
1113 p = poolCopyString(&_dtd->pool, p);
1114 if (!p)
1115 return XML_STATUS_ERROR;
1116 curBase = p;
1118 else
1119 curBase = NULL;
1120 return XML_STATUS_OK;
1123 const XML_Char *
1124 XML_GetBase(XML_Parser parser)
1126 return curBase;
1130 XML_GetSpecifiedAttributeCount(XML_Parser parser)
1132 return nSpecifiedAtts;
1136 XML_GetIdAttributeIndex(XML_Parser parser)
1138 return idAttIndex;
1141 void
1142 XML_SetElementHandler(XML_Parser parser,
1143 XML_StartElementHandler start,
1144 XML_EndElementHandler end)
1146 startElementHandler = start;
1147 endElementHandler = end;
1150 void
1151 XML_SetStartElementHandler(XML_Parser parser,
1152 XML_StartElementHandler start) {
1153 startElementHandler = start;
1156 void
1157 XML_SetEndElementHandler(XML_Parser parser,
1158 XML_EndElementHandler end) {
1159 endElementHandler = end;
1162 void
1163 XML_SetCharacterDataHandler(XML_Parser parser,
1164 XML_CharacterDataHandler handler)
1166 characterDataHandler = handler;
1169 void
1170 XML_SetProcessingInstructionHandler(XML_Parser parser,
1171 XML_ProcessingInstructionHandler handler)
1173 processingInstructionHandler = handler;
1176 void
1177 XML_SetCommentHandler(XML_Parser parser,
1178 XML_CommentHandler handler)
1180 commentHandler = handler;
1183 void
1184 XML_SetCdataSectionHandler(XML_Parser parser,
1185 XML_StartCdataSectionHandler start,
1186 XML_EndCdataSectionHandler end)
1188 startCdataSectionHandler = start;
1189 endCdataSectionHandler = end;
1192 void
1193 XML_SetStartCdataSectionHandler(XML_Parser parser,
1194 XML_StartCdataSectionHandler start) {
1195 startCdataSectionHandler = start;
1198 void
1199 XML_SetEndCdataSectionHandler(XML_Parser parser,
1200 XML_EndCdataSectionHandler end) {
1201 endCdataSectionHandler = end;
1204 void
1205 XML_SetDefaultHandler(XML_Parser parser,
1206 XML_DefaultHandler handler)
1208 defaultHandler = handler;
1209 defaultExpandInternalEntities = XML_FALSE;
1212 void
1213 XML_SetDefaultHandlerExpand(XML_Parser parser,
1214 XML_DefaultHandler handler)
1216 defaultHandler = handler;
1217 defaultExpandInternalEntities = XML_TRUE;
1220 void
1221 XML_SetDoctypeDeclHandler(XML_Parser parser,
1222 XML_StartDoctypeDeclHandler start,
1223 XML_EndDoctypeDeclHandler end)
1225 startDoctypeDeclHandler = start;
1226 endDoctypeDeclHandler = end;
1229 void
1230 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1231 XML_StartDoctypeDeclHandler start) {
1232 startDoctypeDeclHandler = start;
1235 void
1236 XML_SetEndDoctypeDeclHandler(XML_Parser parser,
1237 XML_EndDoctypeDeclHandler end) {
1238 endDoctypeDeclHandler = end;
1241 void
1242 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1243 XML_UnparsedEntityDeclHandler handler)
1245 unparsedEntityDeclHandler = handler;
1248 void
1249 XML_SetNotationDeclHandler(XML_Parser parser,
1250 XML_NotationDeclHandler handler)
1252 notationDeclHandler = handler;
1255 void
1256 XML_SetNamespaceDeclHandler(XML_Parser parser,
1257 XML_StartNamespaceDeclHandler start,
1258 XML_EndNamespaceDeclHandler end)
1260 startNamespaceDeclHandler = start;
1261 endNamespaceDeclHandler = end;
1264 void
1265 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1266 XML_StartNamespaceDeclHandler start) {
1267 startNamespaceDeclHandler = start;
1270 void
1271 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1272 XML_EndNamespaceDeclHandler end) {
1273 endNamespaceDeclHandler = end;
1276 void
1277 XML_SetNotStandaloneHandler(XML_Parser parser,
1278 XML_NotStandaloneHandler handler)
1280 notStandaloneHandler = handler;
1283 void
1284 XML_SetExternalEntityRefHandler(XML_Parser parser,
1285 XML_ExternalEntityRefHandler handler)
1287 externalEntityRefHandler = handler;
1290 void
1291 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
1293 if (arg)
1294 externalEntityRefHandlerArg = (XML_Parser)arg;
1295 else
1296 externalEntityRefHandlerArg = parser;
1299 void
1300 XML_SetSkippedEntityHandler(XML_Parser parser,
1301 XML_SkippedEntityHandler handler)
1303 skippedEntityHandler = handler;
1306 void
1307 XML_SetUnknownEncodingHandler(XML_Parser parser,
1308 XML_UnknownEncodingHandler handler,
1309 void *data)
1311 unknownEncodingHandler = handler;
1312 unknownEncodingHandlerData = data;
1315 void
1316 XML_SetElementDeclHandler(XML_Parser parser,
1317 XML_ElementDeclHandler eldecl)
1319 elementDeclHandler = eldecl;
1322 void
1323 XML_SetAttlistDeclHandler(XML_Parser parser,
1324 XML_AttlistDeclHandler attdecl)
1326 attlistDeclHandler = attdecl;
1329 void
1330 XML_SetEntityDeclHandler(XML_Parser parser,
1331 XML_EntityDeclHandler handler)
1333 entityDeclHandler = handler;
1336 void
1337 XML_SetXmlDeclHandler(XML_Parser parser,
1338 XML_XmlDeclHandler handler) {
1339 xmlDeclHandler = handler;
1343 XML_SetParamEntityParsing(XML_Parser parser,
1344 enum XML_ParamEntityParsing peParsing)
1346 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1347 if (parsing)
1348 return 0;
1349 #ifdef XML_DTD
1350 paramEntityParsing = peParsing;
1351 return 1;
1352 #else
1353 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1354 #endif
1357 enum XML_Status
1358 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
1360 if (len == 0) {
1361 if (!isFinal)
1362 return XML_STATUS_OK;
1363 positionPtr = bufferPtr;
1364 errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0);
1365 if (errorCode == XML_ERROR_NONE)
1366 return XML_STATUS_OK;
1367 eventEndPtr = eventPtr;
1368 processor = errorProcessor;
1369 return XML_STATUS_ERROR;
1371 #ifndef XML_CONTEXT_BYTES
1372 else if (bufferPtr == bufferEnd) {
1373 const char *end;
1374 int nLeftOver;
1375 parseEndByteIndex += len;
1376 positionPtr = s;
1377 if (isFinal) {
1378 errorCode = processor(parser, s, parseEndPtr = s + len, 0);
1379 if (errorCode == XML_ERROR_NONE)
1380 return XML_STATUS_OK;
1381 eventEndPtr = eventPtr;
1382 processor = errorProcessor;
1383 return XML_STATUS_ERROR;
1385 errorCode = processor(parser, s, parseEndPtr = s + len, &end);
1386 if (errorCode != XML_ERROR_NONE) {
1387 eventEndPtr = eventPtr;
1388 processor = errorProcessor;
1389 return XML_STATUS_ERROR;
1391 XmlUpdatePosition(encoding, positionPtr, end, &position);
1392 positionPtr = end;
1393 nLeftOver = s + len - end;
1394 if (nLeftOver) {
1395 if (buffer == NULL || nLeftOver > bufferLim - buffer) {
1396 /* FIXME avoid integer overflow */
1397 char *temp;
1398 temp = (buffer == NULL
1399 ? (char *)MALLOC(len * 2)
1400 : (char *)REALLOC(buffer, len * 2));
1401 if (temp == NULL) {
1402 errorCode = XML_ERROR_NO_MEMORY;
1403 return XML_STATUS_ERROR;
1405 buffer = temp;
1406 if (!buffer) {
1407 errorCode = XML_ERROR_NO_MEMORY;
1408 eventPtr = eventEndPtr = NULL;
1409 processor = errorProcessor;
1410 return XML_STATUS_ERROR;
1412 bufferLim = buffer + len * 2;
1414 memcpy(buffer, end, nLeftOver);
1415 bufferPtr = buffer;
1416 bufferEnd = buffer + nLeftOver;
1418 return XML_STATUS_OK;
1420 #endif /* not defined XML_CONTEXT_BYTES */
1421 else {
1422 void *buff = XML_GetBuffer(parser, len);
1423 if (buff == NULL)
1424 return XML_STATUS_ERROR;
1425 else {
1426 memcpy(buff, s, len);
1427 return XML_ParseBuffer(parser, len, isFinal);
1432 enum XML_Status
1433 XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
1435 const char *start = bufferPtr;
1436 positionPtr = start;
1437 bufferEnd += len;
1438 parseEndByteIndex += len;
1439 errorCode = processor(parser, start, parseEndPtr = bufferEnd,
1440 isFinal ? (const char **)NULL : &bufferPtr);
1441 if (errorCode == XML_ERROR_NONE) {
1442 if (!isFinal) {
1443 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1444 positionPtr = bufferPtr;
1446 return XML_STATUS_OK;
1448 else {
1449 eventEndPtr = eventPtr;
1450 processor = errorProcessor;
1451 return XML_STATUS_ERROR;
1455 void *
1456 XML_GetBuffer(XML_Parser parser, int len)
1458 if (len > bufferLim - bufferEnd) {
1459 /* FIXME avoid integer overflow */
1460 int neededSize = len + (bufferEnd - bufferPtr);
1461 #ifdef XML_CONTEXT_BYTES
1462 int keep = bufferPtr - buffer;
1464 if (keep > XML_CONTEXT_BYTES)
1465 keep = XML_CONTEXT_BYTES;
1466 neededSize += keep;
1467 #endif /* defined XML_CONTEXT_BYTES */
1468 if (neededSize <= bufferLim - buffer) {
1469 #ifdef XML_CONTEXT_BYTES
1470 if (keep < bufferPtr - buffer) {
1471 int offset = (bufferPtr - buffer) - keep;
1472 memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
1473 bufferEnd -= offset;
1474 bufferPtr -= offset;
1476 #else
1477 memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
1478 bufferEnd = buffer + (bufferEnd - bufferPtr);
1479 bufferPtr = buffer;
1480 #endif /* not defined XML_CONTEXT_BYTES */
1482 else {
1483 char *newBuf;
1484 int bufferSize = bufferLim - bufferPtr;
1485 if (bufferSize == 0)
1486 bufferSize = INIT_BUFFER_SIZE;
1487 do {
1488 bufferSize *= 2;
1489 } while (bufferSize < neededSize);
1490 newBuf = (char *)MALLOC(bufferSize);
1491 if (newBuf == 0) {
1492 errorCode = XML_ERROR_NO_MEMORY;
1493 return NULL;
1495 bufferLim = newBuf + bufferSize;
1496 #ifdef XML_CONTEXT_BYTES
1497 if (bufferPtr) {
1498 int keep = bufferPtr - buffer;
1499 if (keep > XML_CONTEXT_BYTES)
1500 keep = XML_CONTEXT_BYTES;
1501 memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
1502 FREE(buffer);
1503 buffer = newBuf;
1504 bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
1505 bufferPtr = buffer + keep;
1507 else {
1508 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1509 bufferPtr = buffer = newBuf;
1511 #else
1512 if (bufferPtr) {
1513 memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
1514 FREE(buffer);
1516 bufferEnd = newBuf + (bufferEnd - bufferPtr);
1517 bufferPtr = buffer = newBuf;
1518 #endif /* not defined XML_CONTEXT_BYTES */
1521 return bufferEnd;
1524 enum XML_Error
1525 XML_GetErrorCode(XML_Parser parser)
1527 return errorCode;
1530 long
1531 XML_GetCurrentByteIndex(XML_Parser parser)
1533 if (eventPtr)
1534 return parseEndByteIndex - (parseEndPtr - eventPtr);
1535 return -1;
1539 XML_GetCurrentByteCount(XML_Parser parser)
1541 if (eventEndPtr && eventPtr)
1542 return eventEndPtr - eventPtr;
1543 return 0;
1546 const char *
1547 XML_GetInputContext(XML_Parser parser, int *offset, int *size)
1549 #ifdef XML_CONTEXT_BYTES
1550 if (eventPtr && buffer) {
1551 *offset = eventPtr - buffer;
1552 *size = bufferEnd - buffer;
1553 return buffer;
1555 #endif /* defined XML_CONTEXT_BYTES */
1556 return (char *) 0;
1560 XML_GetCurrentLineNumber(XML_Parser parser)
1562 if (eventPtr) {
1563 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1564 positionPtr = eventPtr;
1566 return position.lineNumber + 1;
1570 XML_GetCurrentColumnNumber(XML_Parser parser)
1572 if (eventPtr) {
1573 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1574 positionPtr = eventPtr;
1576 return position.columnNumber;
1579 void
1580 XML_FreeContentModel(XML_Parser parser, XML_Content *model)
1582 FREE(model);
1585 void *
1586 XML_MemMalloc(XML_Parser parser, size_t size)
1588 return MALLOC(size);
1591 void *
1592 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
1594 return REALLOC(ptr, size);
1597 void
1598 XML_MemFree(XML_Parser parser, void *ptr)
1600 FREE(ptr);
1603 void
1604 XML_DefaultCurrent(XML_Parser parser)
1606 if (defaultHandler) {
1607 if (openInternalEntities)
1608 reportDefault(parser,
1609 internalEncoding,
1610 openInternalEntities->internalEventPtr,
1611 openInternalEntities->internalEventEndPtr);
1612 else
1613 reportDefault(parser, encoding, eventPtr, eventEndPtr);
1617 const XML_LChar *
1618 XML_ErrorString(enum XML_Error code)
1620 static const XML_LChar *message[] = {
1622 XML_L("out of memory"),
1623 XML_L("syntax error"),
1624 XML_L("no element found"),
1625 XML_L("not well-formed (invalid token)"),
1626 XML_L("unclosed token"),
1627 XML_L("partial character"),
1628 XML_L("mismatched tag"),
1629 XML_L("duplicate attribute"),
1630 XML_L("junk after document element"),
1631 XML_L("illegal parameter entity reference"),
1632 XML_L("undefined entity"),
1633 XML_L("recursive entity reference"),
1634 XML_L("asynchronous entity"),
1635 XML_L("reference to invalid character number"),
1636 XML_L("reference to binary entity"),
1637 XML_L("reference to external entity in attribute"),
1638 XML_L("xml declaration not at start of external entity"),
1639 XML_L("unknown encoding"),
1640 XML_L("encoding specified in XML declaration is incorrect"),
1641 XML_L("unclosed CDATA section"),
1642 XML_L("error in processing external entity reference"),
1643 XML_L("document is not standalone"),
1644 XML_L("unexpected parser state - please send a bug report"),
1645 XML_L("entity declared in parameter entity"),
1646 XML_L("requested feature requires XML_DTD support in Expat"),
1647 XML_L("cannot change setting once parsing has begun")
1649 if (code > 0 && code < sizeof(message)/sizeof(message[0]))
1650 return message[code];
1651 return NULL;
1654 const XML_LChar *
1655 XML_ExpatVersion(void) {
1657 /* V1 is used to string-ize the version number. However, it would
1658 string-ize the actual version macro *names* unless we get them
1659 substituted before being passed to V1. CPP is defined to expand
1660 a macro, then rescan for more expansions. Thus, we use V2 to expand
1661 the version macros, then CPP will expand the resulting V1() macro
1662 with the correct numerals. */
1663 /* ### I'm assuming cpp is portable in this respect... */
1665 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
1666 #define V2(a,b,c) XML_L("expat_")V1(a,b,c)
1668 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
1670 #undef V1
1671 #undef V2
1674 XML_Expat_Version
1675 XML_ExpatVersionInfo(void)
1677 XML_Expat_Version version;
1679 version.major = XML_MAJOR_VERSION;
1680 version.minor = XML_MINOR_VERSION;
1681 version.micro = XML_MICRO_VERSION;
1683 return version;
1686 const XML_Feature *
1687 XML_GetFeatureList(void)
1689 static XML_Feature features[] = {
1690 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)")},
1691 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)")},
1692 #ifdef XML_UNICODE
1693 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE")},
1694 #endif
1695 #ifdef XML_UNICODE_WCHAR_T
1696 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T")},
1697 #endif
1698 #ifdef XML_DTD
1699 {XML_FEATURE_DTD, XML_L("XML_DTD")},
1700 #endif
1701 #ifdef XML_CONTEXT_BYTES
1702 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
1703 XML_CONTEXT_BYTES},
1704 #endif
1705 #ifdef XML_MIN_SIZE
1706 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE")},
1707 #endif
1708 {XML_FEATURE_END, NULL}
1711 features[0].value = sizeof(XML_Char);
1712 features[1].value = sizeof(XML_LChar);
1713 return features;
1716 /* Initially tag->rawName always points into the parse buffer;
1717 for those TAG instances opened while the current parse buffer was
1718 processed, and not yet closed, we need to store tag->rawName in a more
1719 permanent location, since the parse buffer is about to be discarded.
1721 static XML_Bool
1722 storeRawNames(XML_Parser parser)
1724 TAG *tag = tagStack;
1725 while (tag) {
1726 int bufSize;
1727 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
1728 char *rawNameBuf = tag->buf + nameLen;
1729 /* Stop if already stored. Since tagStack is a stack, we can stop
1730 at the first entry that has already been copied; everything
1731 below it in the stack is already been accounted for in a
1732 previous call to this function.
1734 if (tag->rawName == rawNameBuf)
1735 break;
1736 /* For re-use purposes we need to ensure that the
1737 size of tag->buf is a multiple of sizeof(XML_Char).
1739 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
1740 if (bufSize > tag->bufEnd - tag->buf) {
1741 char *temp = (char *)REALLOC(tag->buf, bufSize);
1742 if (temp == NULL)
1743 return XML_FALSE;
1744 /* if tag->name.str points to tag->buf (only when namespace
1745 processing is off) then we have to update it
1747 if (tag->name.str == (XML_Char *)tag->buf)
1748 tag->name.str = (XML_Char *)temp;
1749 /* if tag->name.localPart is set (when namespace processing is on)
1750 then update it as well, since it will always point into tag->buf
1752 if (tag->name.localPart)
1753 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
1754 (XML_Char *)tag->buf);
1755 tag->buf = temp;
1756 tag->bufEnd = temp + bufSize;
1757 rawNameBuf = temp + nameLen;
1759 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
1760 tag->rawName = rawNameBuf;
1761 tag = tag->parent;
1763 return XML_TRUE;
1766 static enum XML_Error PTRCALL
1767 contentProcessor(XML_Parser parser,
1768 const char *start,
1769 const char *end,
1770 const char **endPtr)
1772 enum XML_Error result =
1773 doContent(parser, 0, encoding, start, end, endPtr);
1774 if (result != XML_ERROR_NONE)
1775 return result;
1776 if (!storeRawNames(parser))
1777 return XML_ERROR_NO_MEMORY;
1778 return result;
1781 static enum XML_Error PTRCALL
1782 externalEntityInitProcessor(XML_Parser parser,
1783 const char *start,
1784 const char *end,
1785 const char **endPtr)
1787 enum XML_Error result = initializeEncoding(parser);
1788 if (result != XML_ERROR_NONE)
1789 return result;
1790 processor = externalEntityInitProcessor2;
1791 return externalEntityInitProcessor2(parser, start, end, endPtr);
1794 static enum XML_Error PTRCALL
1795 externalEntityInitProcessor2(XML_Parser parser,
1796 const char *start,
1797 const char *end,
1798 const char **endPtr)
1800 const char *next = start; /* XmlContentTok doesn't always set the last arg */
1801 int tok = XmlContentTok(encoding, start, end, &next);
1802 switch (tok) {
1803 case XML_TOK_BOM:
1804 /* If we are at the end of the buffer, this would cause the next stage,
1805 i.e. externalEntityInitProcessor3, to pass control directly to
1806 doContent (by detecting XML_TOK_NONE) without processing any xml text
1807 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
1809 if (next == end && endPtr) {
1810 *endPtr = next;
1811 return XML_ERROR_NONE;
1813 start = next;
1814 break;
1815 case XML_TOK_PARTIAL:
1816 if (endPtr) {
1817 *endPtr = start;
1818 return XML_ERROR_NONE;
1820 eventPtr = start;
1821 return XML_ERROR_UNCLOSED_TOKEN;
1822 case XML_TOK_PARTIAL_CHAR:
1823 if (endPtr) {
1824 *endPtr = start;
1825 return XML_ERROR_NONE;
1827 eventPtr = start;
1828 return XML_ERROR_PARTIAL_CHAR;
1830 processor = externalEntityInitProcessor3;
1831 return externalEntityInitProcessor3(parser, start, end, endPtr);
1834 static enum XML_Error PTRCALL
1835 externalEntityInitProcessor3(XML_Parser parser,
1836 const char *start,
1837 const char *end,
1838 const char **endPtr)
1840 const char *next = start; /* XmlContentTok doesn't always set the last arg */
1841 int tok = XmlContentTok(encoding, start, end, &next);
1842 switch (tok) {
1843 case XML_TOK_XML_DECL:
1845 enum XML_Error result = processXmlDecl(parser, 1, start, next);
1846 if (result != XML_ERROR_NONE)
1847 return result;
1848 start = next;
1850 break;
1851 case XML_TOK_PARTIAL:
1852 if (endPtr) {
1853 *endPtr = start;
1854 return XML_ERROR_NONE;
1856 eventPtr = start;
1857 return XML_ERROR_UNCLOSED_TOKEN;
1858 case XML_TOK_PARTIAL_CHAR:
1859 if (endPtr) {
1860 *endPtr = start;
1861 return XML_ERROR_NONE;
1863 eventPtr = start;
1864 return XML_ERROR_PARTIAL_CHAR;
1866 processor = externalEntityContentProcessor;
1867 tagLevel = 1;
1868 return externalEntityContentProcessor(parser, start, end, endPtr);
1871 static enum XML_Error PTRCALL
1872 externalEntityContentProcessor(XML_Parser parser,
1873 const char *start,
1874 const char *end,
1875 const char **endPtr)
1877 enum XML_Error result =
1878 doContent(parser, 1, encoding, start, end, endPtr);
1879 if (result != XML_ERROR_NONE)
1880 return result;
1881 if (!storeRawNames(parser))
1882 return XML_ERROR_NO_MEMORY;
1883 return result;
1886 static enum XML_Error
1887 doContent(XML_Parser parser,
1888 int startTagLevel,
1889 const ENCODING *enc,
1890 const char *s,
1891 const char *end,
1892 const char **nextPtr)
1894 DTD * const dtd = _dtd; /* save one level of indirection */
1895 const char **eventPP;
1896 const char **eventEndPP;
1897 if (enc == encoding) {
1898 eventPP = &eventPtr;
1899 eventEndPP = &eventEndPtr;
1901 else {
1902 eventPP = &(openInternalEntities->internalEventPtr);
1903 eventEndPP = &(openInternalEntities->internalEventEndPtr);
1905 *eventPP = s;
1906 for (;;) {
1907 const char *next = s; /* XmlContentTok doesn't always set the last arg */
1908 int tok = XmlContentTok(enc, s, end, &next);
1909 *eventEndPP = next;
1910 switch (tok) {
1911 case XML_TOK_TRAILING_CR:
1912 if (nextPtr) {
1913 *nextPtr = s;
1914 return XML_ERROR_NONE;
1916 *eventEndPP = end;
1917 if (characterDataHandler) {
1918 XML_Char c = 0xA;
1919 characterDataHandler(handlerArg, &c, 1);
1921 else if (defaultHandler)
1922 reportDefault(parser, enc, s, end);
1923 if (startTagLevel == 0)
1924 return XML_ERROR_NO_ELEMENTS;
1925 if (tagLevel != startTagLevel)
1926 return XML_ERROR_ASYNC_ENTITY;
1927 return XML_ERROR_NONE;
1928 case XML_TOK_NONE:
1929 if (nextPtr) {
1930 *nextPtr = s;
1931 return XML_ERROR_NONE;
1933 if (startTagLevel > 0) {
1934 if (tagLevel != startTagLevel)
1935 return XML_ERROR_ASYNC_ENTITY;
1936 return XML_ERROR_NONE;
1938 return XML_ERROR_NO_ELEMENTS;
1939 case XML_TOK_INVALID:
1940 *eventPP = next;
1941 return XML_ERROR_INVALID_TOKEN;
1942 case XML_TOK_PARTIAL:
1943 if (nextPtr) {
1944 *nextPtr = s;
1945 return XML_ERROR_NONE;
1947 return XML_ERROR_UNCLOSED_TOKEN;
1948 case XML_TOK_PARTIAL_CHAR:
1949 if (nextPtr) {
1950 *nextPtr = s;
1951 return XML_ERROR_NONE;
1953 return XML_ERROR_PARTIAL_CHAR;
1954 case XML_TOK_ENTITY_REF:
1956 const XML_Char *name;
1957 ENTITY *entity;
1958 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
1959 s + enc->minBytesPerChar,
1960 next - enc->minBytesPerChar);
1961 if (ch) {
1962 if (characterDataHandler)
1963 characterDataHandler(handlerArg, &ch, 1);
1964 else if (defaultHandler)
1965 reportDefault(parser, enc, s, next);
1966 break;
1968 name = poolStoreString(&dtd->pool, enc,
1969 s + enc->minBytesPerChar,
1970 next - enc->minBytesPerChar);
1971 if (!name)
1972 return XML_ERROR_NO_MEMORY;
1973 entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
1974 poolDiscard(&dtd->pool);
1975 /* First, determine if a check for an existing declaration is needed;
1976 if yes, check that the entity exists, and that it is internal,
1977 otherwise call the skipped entity or default handler.
1979 if (!dtd->hasParamEntityRefs || dtd->standalone) {
1980 if (!entity)
1981 return XML_ERROR_UNDEFINED_ENTITY;
1982 else if (!entity->is_internal)
1983 return XML_ERROR_ENTITY_DECLARED_IN_PE;
1985 else if (!entity) {
1986 if (skippedEntityHandler)
1987 skippedEntityHandler(handlerArg, name, 0);
1988 else if (defaultHandler)
1989 reportDefault(parser, enc, s, next);
1990 break;
1992 if (entity->open)
1993 return XML_ERROR_RECURSIVE_ENTITY_REF;
1994 if (entity->notation)
1995 return XML_ERROR_BINARY_ENTITY_REF;
1996 if (entity->textPtr) {
1997 enum XML_Error result;
1998 OPEN_INTERNAL_ENTITY openEntity;
1999 if (!defaultExpandInternalEntities) {
2000 if (skippedEntityHandler)
2001 skippedEntityHandler(handlerArg, entity->name, 0);
2002 else if (defaultHandler)
2003 reportDefault(parser, enc, s, next);
2004 break;
2006 entity->open = XML_TRUE;
2007 openEntity.next = openInternalEntities;
2008 openInternalEntities = &openEntity;
2009 openEntity.entity = entity;
2010 openEntity.internalEventPtr = NULL;
2011 openEntity.internalEventEndPtr = NULL;
2012 result = doContent(parser,
2013 tagLevel,
2014 internalEncoding,
2015 (char *)entity->textPtr,
2016 (char *)(entity->textPtr + entity->textLen),
2018 entity->open = XML_FALSE;
2019 openInternalEntities = openEntity.next;
2020 if (result)
2021 return result;
2023 else if (externalEntityRefHandler) {
2024 const XML_Char *context;
2025 entity->open = XML_TRUE;
2026 context = getContext(parser);
2027 entity->open = XML_FALSE;
2028 if (!context)
2029 return XML_ERROR_NO_MEMORY;
2030 if (!externalEntityRefHandler((XML_Parser)externalEntityRefHandlerArg,
2031 context,
2032 entity->base,
2033 entity->systemId,
2034 entity->publicId))
2035 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2036 poolDiscard(&tempPool);
2038 else if (defaultHandler)
2039 reportDefault(parser, enc, s, next);
2040 break;
2042 case XML_TOK_START_TAG_NO_ATTS:
2043 /* fall through */
2044 case XML_TOK_START_TAG_WITH_ATTS:
2046 TAG *tag;
2047 enum XML_Error result;
2048 XML_Char *toPtr;
2049 if (freeTagList) {
2050 tag = freeTagList;
2051 freeTagList = freeTagList->parent;
2053 else {
2054 tag = (TAG *)MALLOC(sizeof(TAG));
2055 if (!tag)
2056 return XML_ERROR_NO_MEMORY;
2057 tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
2058 if (!tag->buf) {
2059 FREE(tag);
2060 return XML_ERROR_NO_MEMORY;
2062 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2064 tag->bindings = NULL;
2065 tag->parent = tagStack;
2066 tagStack = tag;
2067 tag->name.localPart = NULL;
2068 tag->name.prefix = NULL;
2069 tag->rawName = s + enc->minBytesPerChar;
2070 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
2071 ++tagLevel;
2073 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2074 const char *fromPtr = tag->rawName;
2075 toPtr = (XML_Char *)tag->buf;
2076 for (;;) {
2077 int bufSize;
2078 int convLen;
2079 XmlConvert(enc,
2080 &fromPtr, rawNameEnd,
2081 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
2082 convLen = toPtr - (XML_Char *)tag->buf;
2083 if (fromPtr == rawNameEnd) {
2084 tag->name.strLen = convLen;
2085 break;
2087 bufSize = (tag->bufEnd - tag->buf) << 1;
2089 char *temp = (char *)REALLOC(tag->buf, bufSize);
2090 if (temp == NULL)
2091 return XML_ERROR_NO_MEMORY;
2092 tag->buf = temp;
2093 tag->bufEnd = temp + bufSize;
2094 toPtr = (XML_Char *)temp + convLen;
2098 tag->name.str = (XML_Char *)tag->buf;
2099 *toPtr = XML_T('\0');
2100 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2101 if (result)
2102 return result;
2103 if (startElementHandler)
2104 startElementHandler(handlerArg, tag->name.str,
2105 (const XML_Char **)atts);
2106 else if (defaultHandler)
2107 reportDefault(parser, enc, s, next);
2108 poolClear(&tempPool);
2109 break;
2111 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2112 /* fall through */
2113 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
2115 const char *rawName = s + enc->minBytesPerChar;
2116 enum XML_Error result;
2117 BINDING *bindings = NULL;
2118 XML_Bool noElmHandlers = XML_TRUE;
2119 TAG_NAME name;
2120 name.str = poolStoreString(&tempPool, enc, rawName,
2121 rawName + XmlNameLength(enc, rawName));
2122 if (!name.str)
2123 return XML_ERROR_NO_MEMORY;
2124 poolFinish(&tempPool);
2125 result = storeAtts(parser, enc, s, &name, &bindings);
2126 if (result)
2127 return result;
2128 poolFinish(&tempPool);
2129 if (startElementHandler) {
2130 startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
2131 noElmHandlers = XML_FALSE;
2133 if (endElementHandler) {
2134 if (startElementHandler)
2135 *eventPP = *eventEndPP;
2136 endElementHandler(handlerArg, name.str);
2137 noElmHandlers = XML_FALSE;
2139 if (noElmHandlers && defaultHandler)
2140 reportDefault(parser, enc, s, next);
2141 poolClear(&tempPool);
2142 while (bindings) {
2143 BINDING *b = bindings;
2144 if (endNamespaceDeclHandler)
2145 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2146 bindings = bindings->nextTagBinding;
2147 b->nextTagBinding = freeBindingList;
2148 freeBindingList = b;
2149 b->prefix->binding = b->prevPrefixBinding;
2152 if (tagLevel == 0)
2153 return epilogProcessor(parser, next, end, nextPtr);
2154 break;
2155 case XML_TOK_END_TAG:
2156 if (tagLevel == startTagLevel)
2157 return XML_ERROR_ASYNC_ENTITY;
2158 else {
2159 int len;
2160 const char *rawName;
2161 TAG *tag = tagStack;
2162 tagStack = tag->parent;
2163 tag->parent = freeTagList;
2164 freeTagList = tag;
2165 rawName = s + enc->minBytesPerChar*2;
2166 len = XmlNameLength(enc, rawName);
2167 if (len != tag->rawNameLength
2168 || memcmp(tag->rawName, rawName, len) != 0) {
2169 *eventPP = rawName;
2170 return XML_ERROR_TAG_MISMATCH;
2172 --tagLevel;
2173 if (endElementHandler) {
2174 const XML_Char *localPart;
2175 const XML_Char *prefix;
2176 XML_Char *uri;
2177 localPart = tag->name.localPart;
2178 if (ns && localPart) {
2179 /* localPart and prefix may have been overwritten in
2180 tag->name.str, since this points to the binding->uri
2181 buffer which gets re-used; so we have to add them again
2183 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2184 /* don't need to check for space - already done in storeAtts() */
2185 while (*localPart) *uri++ = *localPart++;
2186 prefix = (XML_Char *)tag->name.prefix;
2187 if (ns_triplets && prefix) {
2188 *uri++ = namespaceSeparator;
2189 while (*prefix) *uri++ = *prefix++;
2191 *uri = XML_T('\0');
2193 endElementHandler(handlerArg, tag->name.str);
2195 else if (defaultHandler)
2196 reportDefault(parser, enc, s, next);
2197 while (tag->bindings) {
2198 BINDING *b = tag->bindings;
2199 if (endNamespaceDeclHandler)
2200 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2201 tag->bindings = tag->bindings->nextTagBinding;
2202 b->nextTagBinding = freeBindingList;
2203 freeBindingList = b;
2204 b->prefix->binding = b->prevPrefixBinding;
2206 if (tagLevel == 0)
2207 return epilogProcessor(parser, next, end, nextPtr);
2209 break;
2210 case XML_TOK_CHAR_REF:
2212 int n = XmlCharRefNumber(enc, s);
2213 if (n < 0)
2214 return XML_ERROR_BAD_CHAR_REF;
2215 if (characterDataHandler) {
2216 XML_Char buf[XML_ENCODE_MAX];
2217 characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
2219 else if (defaultHandler)
2220 reportDefault(parser, enc, s, next);
2222 break;
2223 case XML_TOK_XML_DECL:
2224 return XML_ERROR_MISPLACED_XML_PI;
2225 case XML_TOK_DATA_NEWLINE:
2226 if (characterDataHandler) {
2227 XML_Char c = 0xA;
2228 characterDataHandler(handlerArg, &c, 1);
2230 else if (defaultHandler)
2231 reportDefault(parser, enc, s, next);
2232 break;
2233 case XML_TOK_CDATA_SECT_OPEN:
2235 enum XML_Error result;
2236 if (startCdataSectionHandler)
2237 startCdataSectionHandler(handlerArg);
2238 #if 0
2239 /* Suppose you doing a transformation on a document that involves
2240 changing only the character data. You set up a defaultHandler
2241 and a characterDataHandler. The defaultHandler simply copies
2242 characters through. The characterDataHandler does the
2243 transformation and writes the characters out escaping them as
2244 necessary. This case will fail to work if we leave out the
2245 following two lines (because & and < inside CDATA sections will
2246 be incorrectly escaped).
2248 However, now we have a start/endCdataSectionHandler, so it seems
2249 easier to let the user deal with this.
2251 else if (characterDataHandler)
2252 characterDataHandler(handlerArg, dataBuf, 0);
2253 #endif
2254 else if (defaultHandler)
2255 reportDefault(parser, enc, s, next);
2256 result = doCdataSection(parser, enc, &next, end, nextPtr);
2257 if (!next) {
2258 processor = cdataSectionProcessor;
2259 return result;
2262 break;
2263 case XML_TOK_TRAILING_RSQB:
2264 if (nextPtr) {
2265 *nextPtr = s;
2266 return XML_ERROR_NONE;
2268 if (characterDataHandler) {
2269 if (MUST_CONVERT(enc, s)) {
2270 ICHAR *dataPtr = (ICHAR *)dataBuf;
2271 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
2272 characterDataHandler(handlerArg, dataBuf,
2273 dataPtr - (ICHAR *)dataBuf);
2275 else
2276 characterDataHandler(handlerArg,
2277 (XML_Char *)s,
2278 (XML_Char *)end - (XML_Char *)s);
2280 else if (defaultHandler)
2281 reportDefault(parser, enc, s, end);
2282 if (startTagLevel == 0) {
2283 *eventPP = end;
2284 return XML_ERROR_NO_ELEMENTS;
2286 if (tagLevel != startTagLevel) {
2287 *eventPP = end;
2288 return XML_ERROR_ASYNC_ENTITY;
2290 return XML_ERROR_NONE;
2291 case XML_TOK_DATA_CHARS:
2292 if (characterDataHandler) {
2293 if (MUST_CONVERT(enc, s)) {
2294 for (;;) {
2295 ICHAR *dataPtr = (ICHAR *)dataBuf;
2296 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
2297 *eventEndPP = s;
2298 characterDataHandler(handlerArg, dataBuf,
2299 dataPtr - (ICHAR *)dataBuf);
2300 if (s == next)
2301 break;
2302 *eventPP = s;
2305 else
2306 characterDataHandler(handlerArg,
2307 (XML_Char *)s,
2308 (XML_Char *)next - (XML_Char *)s);
2310 else if (defaultHandler)
2311 reportDefault(parser, enc, s, next);
2312 break;
2313 case XML_TOK_PI:
2314 if (!reportProcessingInstruction(parser, enc, s, next))
2315 return XML_ERROR_NO_MEMORY;
2316 break;
2317 case XML_TOK_COMMENT:
2318 if (!reportComment(parser, enc, s, next))
2319 return XML_ERROR_NO_MEMORY;
2320 break;
2321 default:
2322 if (defaultHandler)
2323 reportDefault(parser, enc, s, next);
2324 break;
2326 *eventPP = s = next;
2328 /* not reached */
2331 /* Precondition: all arguments must be non-NULL;
2332 Purpose:
2333 - normalize attributes
2334 - check attributes for well-formedness
2335 - generate namespace aware attribute names (URI, prefix)
2336 - build list of attributes for startElementHandler
2337 - default attributes
2338 - process namespace declarations (check and report them)
2339 - generate namespace aware element name (URI, prefix)
2341 static enum XML_Error
2342 storeAtts(XML_Parser parser, const ENCODING *enc,
2343 const char *attStr, TAG_NAME *tagNamePtr,
2344 BINDING **bindingsPtr)
2346 DTD * const dtd = _dtd; /* save one level of indirection */
2347 ELEMENT_TYPE *elementType = NULL;
2348 int nDefaultAtts = 0;
2349 const XML_Char **appAtts; /* the attribute list for the application */
2350 int attIndex = 0;
2351 int prefixLen;
2352 int i;
2353 int n;
2354 XML_Char *uri;
2355 int nPrefixes = 0;
2356 BINDING *binding;
2357 const XML_Char *localPart;
2359 /* lookup the element type name */
2360 elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0);
2361 if (!elementType) {
2362 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
2363 if (!name)
2364 return XML_ERROR_NO_MEMORY;
2365 elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name,
2366 sizeof(ELEMENT_TYPE));
2367 if (!elementType)
2368 return XML_ERROR_NO_MEMORY;
2369 if (ns && !setElementTypePrefix(parser, elementType))
2370 return XML_ERROR_NO_MEMORY;
2372 nDefaultAtts = elementType->nDefaultAtts;
2374 /* get the attributes from the tokenizer */
2375 n = XmlGetAttributes(enc, attStr, attsSize, atts);
2376 if (n + nDefaultAtts > attsSize) {
2377 int oldAttsSize = attsSize;
2378 ATTRIBUTE *temp;
2379 attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
2380 temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
2381 if (temp == NULL)
2382 return XML_ERROR_NO_MEMORY;
2383 atts = temp;
2384 if (n > oldAttsSize)
2385 XmlGetAttributes(enc, attStr, n, atts);
2388 appAtts = (const XML_Char **)atts;
2389 for (i = 0; i < n; i++) {
2390 /* add the name and value to the attribute list */
2391 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
2392 atts[i].name
2393 + XmlNameLength(enc, atts[i].name));
2394 if (!attId)
2395 return XML_ERROR_NO_MEMORY;
2396 /* detect duplicate attributes */
2397 if ((attId->name)[-1]) {
2398 if (enc == encoding)
2399 eventPtr = atts[i].name;
2400 return XML_ERROR_DUPLICATE_ATTRIBUTE;
2402 (attId->name)[-1] = 1;
2403 appAtts[attIndex++] = attId->name;
2404 if (!atts[i].normalized) {
2405 enum XML_Error result;
2406 XML_Bool isCdata = XML_TRUE;
2408 /* figure out whether declared as other than CDATA */
2409 if (attId->maybeTokenized) {
2410 int j;
2411 for (j = 0; j < nDefaultAtts; j++) {
2412 if (attId == elementType->defaultAtts[j].id) {
2413 isCdata = elementType->defaultAtts[j].isCdata;
2414 break;
2419 /* normalize the attribute value */
2420 result = storeAttributeValue(parser, enc, isCdata,
2421 atts[i].valuePtr, atts[i].valueEnd,
2422 &tempPool);
2423 if (result)
2424 return result;
2425 appAtts[attIndex] = poolStart(&tempPool);
2426 poolFinish(&tempPool);
2428 else {
2429 /* the value did not need normalizing */
2430 appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
2431 atts[i].valueEnd);
2432 if (appAtts[attIndex] == 0)
2433 return XML_ERROR_NO_MEMORY;
2434 poolFinish(&tempPool);
2436 /* handle prefixed attribute names */
2437 if (attId->prefix) {
2438 if (attId->xmlns) {
2439 /* deal with namespace declarations here */
2440 enum XML_Error result = addBinding(parser, attId->prefix, attId,
2441 appAtts[attIndex], bindingsPtr);
2442 if (result)
2443 return result;
2444 --attIndex;
2446 else {
2447 /* deal with other prefixed names later */
2448 attIndex++;
2449 nPrefixes++;
2450 (attId->name)[-1] = 2;
2453 else
2454 attIndex++;
2457 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
2458 nSpecifiedAtts = attIndex;
2459 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
2460 for (i = 0; i < attIndex; i += 2)
2461 if (appAtts[i] == elementType->idAtt->name) {
2462 idAttIndex = i;
2463 break;
2466 else
2467 idAttIndex = -1;
2469 /* do attribute defaulting */
2470 for (i = 0; i < nDefaultAtts; i++) {
2471 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
2472 if (!(da->id->name)[-1] && da->value) {
2473 if (da->id->prefix) {
2474 if (da->id->xmlns) {
2475 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
2476 da->value, bindingsPtr);
2477 if (result)
2478 return result;
2480 else {
2481 (da->id->name)[-1] = 2;
2482 nPrefixes++;
2483 appAtts[attIndex++] = da->id->name;
2484 appAtts[attIndex++] = da->value;
2487 else {
2488 (da->id->name)[-1] = 1;
2489 appAtts[attIndex++] = da->id->name;
2490 appAtts[attIndex++] = da->value;
2494 appAtts[attIndex] = 0;
2496 i = 0;
2497 if (nPrefixes) {
2498 /* expand prefixed attribute names */
2499 for (; i < attIndex; i += 2) {
2500 if (appAtts[i][-1] == 2) {
2501 ATTRIBUTE_ID *id;
2502 ((XML_Char *)(appAtts[i]))[-1] = 0;
2503 id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, appAtts[i], 0);
2504 if (id->prefix->binding) {
2505 int j;
2506 const BINDING *b = id->prefix->binding;
2507 const XML_Char *s = appAtts[i];
2508 for (j = 0; j < b->uriLen; j++) {
2509 if (!poolAppendChar(&tempPool, b->uri[j]))
2510 return XML_ERROR_NO_MEMORY;
2512 while (*s++ != XML_T(':'))
2514 do {
2515 if (!poolAppendChar(&tempPool, *s))
2516 return XML_ERROR_NO_MEMORY;
2517 } while (*s++);
2518 if (ns_triplets) {
2519 tempPool.ptr[-1] = namespaceSeparator;
2520 s = b->prefix->name;
2521 do {
2522 if (!poolAppendChar(&tempPool, *s))
2523 return XML_ERROR_NO_MEMORY;
2524 } while (*s++);
2527 appAtts[i] = poolStart(&tempPool);
2528 poolFinish(&tempPool);
2530 if (!--nPrefixes)
2531 break;
2533 else
2534 ((XML_Char *)(appAtts[i]))[-1] = 0;
2537 /* clear the flags that say whether attributes were specified */
2538 for (; i < attIndex; i += 2)
2539 ((XML_Char *)(appAtts[i]))[-1] = 0;
2540 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
2541 binding->attId->name[-1] = 0;
2543 /* expand the element type name */
2544 if (elementType->prefix) {
2545 binding = elementType->prefix->binding;
2546 if (!binding)
2547 return XML_ERROR_NONE;
2548 localPart = tagNamePtr->str;
2549 while (*localPart++ != XML_T(':'))
2552 else if (dtd->defaultPrefix.binding) {
2553 binding = dtd->defaultPrefix.binding;
2554 localPart = tagNamePtr->str;
2556 else
2557 return XML_ERROR_NONE;
2558 prefixLen = 0;
2559 if (ns && ns_triplets && binding->prefix->name) {
2560 for (; binding->prefix->name[prefixLen++];)
2563 tagNamePtr->localPart = localPart;
2564 tagNamePtr->uriLen = binding->uriLen;
2565 tagNamePtr->prefix = binding->prefix->name;
2566 tagNamePtr->prefixLen = prefixLen;
2567 for (i = 0; localPart[i++];)
2569 n = i + binding->uriLen + prefixLen;
2570 if (n > binding->uriAlloc) {
2571 TAG *p;
2572 uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
2573 if (!uri)
2574 return XML_ERROR_NO_MEMORY;
2575 binding->uriAlloc = n + EXPAND_SPARE;
2576 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
2577 for (p = tagStack; p; p = p->parent)
2578 if (p->name.str == binding->uri)
2579 p->name.str = uri;
2580 FREE(binding->uri);
2581 binding->uri = uri;
2583 uri = binding->uri + binding->uriLen;
2584 memcpy(uri, localPart, i * sizeof(XML_Char));
2585 if (prefixLen) {
2586 uri = uri + (i - 1);
2587 if (namespaceSeparator) { *(uri) = namespaceSeparator; }
2588 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
2590 tagNamePtr->str = binding->uri;
2591 return XML_ERROR_NONE;
2594 /* addBinding() overwrites the value of prefix->binding without checking.
2595 Therefore one must keep track of the old value outside of addBinding().
2597 static enum XML_Error
2598 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
2599 const XML_Char *uri, BINDING **bindingsPtr)
2601 BINDING *b;
2602 int len;
2604 /* empty string is only valid when there is no prefix per XML NS 1.0 */
2605 if (*uri == XML_T('\0') && prefix->name)
2606 return XML_ERROR_SYNTAX;
2608 for (len = 0; uri[len]; len++)
2610 if (namespaceSeparator)
2611 len++;
2612 if (freeBindingList) {
2613 b = freeBindingList;
2614 if (len > b->uriAlloc) {
2615 XML_Char *temp = (XML_Char *)REALLOC(b->uri,
2616 sizeof(XML_Char) * (len + EXPAND_SPARE));
2617 if (temp == NULL)
2618 return XML_ERROR_NO_MEMORY;
2619 b->uri = temp;
2620 b->uriAlloc = len + EXPAND_SPARE;
2622 freeBindingList = b->nextTagBinding;
2624 else {
2625 b = (BINDING *)MALLOC(sizeof(BINDING));
2626 if (!b)
2627 return XML_ERROR_NO_MEMORY;
2628 b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
2629 if (!b->uri) {
2630 FREE(b);
2631 return XML_ERROR_NO_MEMORY;
2633 b->uriAlloc = len + EXPAND_SPARE;
2635 b->uriLen = len;
2636 memcpy(b->uri, uri, len * sizeof(XML_Char));
2637 if (namespaceSeparator)
2638 b->uri[len - 1] = namespaceSeparator;
2639 b->prefix = prefix;
2640 b->attId = attId;
2641 b->prevPrefixBinding = prefix->binding;
2642 if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
2643 prefix->binding = NULL;
2644 else
2645 prefix->binding = b;
2646 b->nextTagBinding = *bindingsPtr;
2647 *bindingsPtr = b;
2648 if (startNamespaceDeclHandler)
2649 startNamespaceDeclHandler(handlerArg, prefix->name,
2650 prefix->binding ? uri : 0);
2651 return XML_ERROR_NONE;
2654 /* The idea here is to avoid using stack for each CDATA section when
2655 the whole file is parsed with one call.
2657 static enum XML_Error PTRCALL
2658 cdataSectionProcessor(XML_Parser parser,
2659 const char *start,
2660 const char *end,
2661 const char **endPtr)
2663 enum XML_Error result = doCdataSection(parser, encoding, &start,
2664 end, endPtr);
2665 if (start) {
2666 if (parentParser) { /* we are parsing an external entity */
2667 processor = externalEntityContentProcessor;
2668 return externalEntityContentProcessor(parser, start, end, endPtr);
2670 else {
2671 processor = contentProcessor;
2672 return contentProcessor(parser, start, end, endPtr);
2675 return result;
2678 /* startPtr gets set to non-null is the section is closed, and to null if
2679 the section is not yet closed.
2681 static enum XML_Error
2682 doCdataSection(XML_Parser parser,
2683 const ENCODING *enc,
2684 const char **startPtr,
2685 const char *end,
2686 const char **nextPtr)
2688 const char *s = *startPtr;
2689 const char **eventPP;
2690 const char **eventEndPP;
2691 if (enc == encoding) {
2692 eventPP = &eventPtr;
2693 *eventPP = s;
2694 eventEndPP = &eventEndPtr;
2696 else {
2697 eventPP = &(openInternalEntities->internalEventPtr);
2698 eventEndPP = &(openInternalEntities->internalEventEndPtr);
2700 *eventPP = s;
2701 *startPtr = NULL;
2702 for (;;) {
2703 const char *next;
2704 int tok = XmlCdataSectionTok(enc, s, end, &next);
2705 *eventEndPP = next;
2706 switch (tok) {
2707 case XML_TOK_CDATA_SECT_CLOSE:
2708 if (endCdataSectionHandler)
2709 endCdataSectionHandler(handlerArg);
2710 #if 0
2711 /* see comment under XML_TOK_CDATA_SECT_OPEN */
2712 else if (characterDataHandler)
2713 characterDataHandler(handlerArg, dataBuf, 0);
2714 #endif
2715 else if (defaultHandler)
2716 reportDefault(parser, enc, s, next);
2717 *startPtr = next;
2718 return XML_ERROR_NONE;
2719 case XML_TOK_DATA_NEWLINE:
2720 if (characterDataHandler) {
2721 XML_Char c = 0xA;
2722 characterDataHandler(handlerArg, &c, 1);
2724 else if (defaultHandler)
2725 reportDefault(parser, enc, s, next);
2726 break;
2727 case XML_TOK_DATA_CHARS:
2728 if (characterDataHandler) {
2729 if (MUST_CONVERT(enc, s)) {
2730 for (;;) {
2731 ICHAR *dataPtr = (ICHAR *)dataBuf;
2732 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
2733 *eventEndPP = next;
2734 characterDataHandler(handlerArg, dataBuf,
2735 dataPtr - (ICHAR *)dataBuf);
2736 if (s == next)
2737 break;
2738 *eventPP = s;
2741 else
2742 characterDataHandler(handlerArg,
2743 (XML_Char *)s,
2744 (XML_Char *)next - (XML_Char *)s);
2746 else if (defaultHandler)
2747 reportDefault(parser, enc, s, next);
2748 break;
2749 case XML_TOK_INVALID:
2750 *eventPP = next;
2751 return XML_ERROR_INVALID_TOKEN;
2752 case XML_TOK_PARTIAL_CHAR:
2753 if (nextPtr) {
2754 *nextPtr = s;
2755 return XML_ERROR_NONE;
2757 return XML_ERROR_PARTIAL_CHAR;
2758 case XML_TOK_PARTIAL:
2759 case XML_TOK_NONE:
2760 if (nextPtr) {
2761 *nextPtr = s;
2762 return XML_ERROR_NONE;
2764 return XML_ERROR_UNCLOSED_CDATA_SECTION;
2765 default:
2766 *eventPP = next;
2767 return XML_ERROR_UNEXPECTED_STATE;
2769 *eventPP = s = next;
2771 /* not reached */
2774 #ifdef XML_DTD
2776 /* The idea here is to avoid using stack for each IGNORE section when
2777 the whole file is parsed with one call.
2779 static enum XML_Error PTRCALL
2780 ignoreSectionProcessor(XML_Parser parser,
2781 const char *start,
2782 const char *end,
2783 const char **endPtr)
2785 enum XML_Error result = doIgnoreSection(parser, encoding, &start,
2786 end, endPtr);
2787 if (start) {
2788 processor = prologProcessor;
2789 return prologProcessor(parser, start, end, endPtr);
2791 return result;
2794 /* startPtr gets set to non-null is the section is closed, and to null
2795 if the section is not yet closed.
2797 static enum XML_Error
2798 doIgnoreSection(XML_Parser parser,
2799 const ENCODING *enc,
2800 const char **startPtr,
2801 const char *end,
2802 const char **nextPtr)
2804 const char *next;
2805 int tok;
2806 const char *s = *startPtr;
2807 const char **eventPP;
2808 const char **eventEndPP;
2809 if (enc == encoding) {
2810 eventPP = &eventPtr;
2811 *eventPP = s;
2812 eventEndPP = &eventEndPtr;
2814 else {
2815 eventPP = &(openInternalEntities->internalEventPtr);
2816 eventEndPP = &(openInternalEntities->internalEventEndPtr);
2818 *eventPP = s;
2819 *startPtr = NULL;
2820 tok = XmlIgnoreSectionTok(enc, s, end, &next);
2821 *eventEndPP = next;
2822 switch (tok) {
2823 case XML_TOK_IGNORE_SECT:
2824 if (defaultHandler)
2825 reportDefault(parser, enc, s, next);
2826 *startPtr = next;
2827 return XML_ERROR_NONE;
2828 case XML_TOK_INVALID:
2829 *eventPP = next;
2830 return XML_ERROR_INVALID_TOKEN;
2831 case XML_TOK_PARTIAL_CHAR:
2832 if (nextPtr) {
2833 *nextPtr = s;
2834 return XML_ERROR_NONE;
2836 return XML_ERROR_PARTIAL_CHAR;
2837 case XML_TOK_PARTIAL:
2838 case XML_TOK_NONE:
2839 if (nextPtr) {
2840 *nextPtr = s;
2841 return XML_ERROR_NONE;
2843 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
2844 default:
2845 *eventPP = next;
2846 return XML_ERROR_UNEXPECTED_STATE;
2848 /* not reached */
2851 #endif /* XML_DTD */
2853 static enum XML_Error
2854 initializeEncoding(XML_Parser parser)
2856 const char *s;
2857 #ifdef XML_UNICODE
2858 char encodingBuf[128];
2859 if (!protocolEncodingName)
2860 s = NULL;
2861 else {
2862 int i;
2863 for (i = 0; protocolEncodingName[i]; i++) {
2864 if (i == sizeof(encodingBuf) - 1
2865 || (protocolEncodingName[i] & ~0x7f) != 0) {
2866 encodingBuf[0] = '\0';
2867 break;
2869 encodingBuf[i] = (char)protocolEncodingName[i];
2871 encodingBuf[i] = '\0';
2872 s = encodingBuf;
2874 #else
2875 s = protocolEncodingName;
2876 #endif
2877 if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
2878 return XML_ERROR_NONE;
2879 return handleUnknownEncoding(parser, protocolEncodingName);
2882 static enum XML_Error
2883 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
2884 const char *s, const char *next)
2886 const char *encodingName = NULL;
2887 const XML_Char *storedEncName = NULL;
2888 const ENCODING *newEncoding = NULL;
2889 const char *version = NULL;
2890 const char *versionend;
2891 const XML_Char *storedversion = NULL;
2892 int standalone = -1;
2893 if (!(ns
2894 ? XmlParseXmlDeclNS
2895 : XmlParseXmlDecl)(isGeneralTextEntity,
2896 encoding,
2898 next,
2899 &eventPtr,
2900 &version,
2901 &versionend,
2902 &encodingName,
2903 &newEncoding,
2904 &standalone))
2905 return XML_ERROR_SYNTAX;
2906 if (!isGeneralTextEntity && standalone == 1) {
2907 _dtd->standalone = XML_TRUE;
2908 #ifdef XML_DTD
2909 if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
2910 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
2911 #endif /* XML_DTD */
2913 if (xmlDeclHandler) {
2914 if (encodingName != NULL) {
2915 storedEncName = poolStoreString(&temp2Pool,
2916 encoding,
2917 encodingName,
2918 encodingName
2919 + XmlNameLength(encoding, encodingName));
2920 if (!storedEncName)
2921 return XML_ERROR_NO_MEMORY;
2922 poolFinish(&temp2Pool);
2924 if (version) {
2925 storedversion = poolStoreString(&temp2Pool,
2926 encoding,
2927 version,
2928 versionend - encoding->minBytesPerChar);
2929 if (!storedversion)
2930 return XML_ERROR_NO_MEMORY;
2932 xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
2934 else if (defaultHandler)
2935 reportDefault(parser, encoding, s, next);
2936 if (protocolEncodingName == NULL) {
2937 if (newEncoding) {
2938 if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
2939 eventPtr = encodingName;
2940 return XML_ERROR_INCORRECT_ENCODING;
2942 encoding = newEncoding;
2944 else if (encodingName) {
2945 enum XML_Error result;
2946 if (!storedEncName) {
2947 storedEncName = poolStoreString(
2948 &temp2Pool, encoding, encodingName,
2949 encodingName + XmlNameLength(encoding, encodingName));
2950 if (!storedEncName)
2951 return XML_ERROR_NO_MEMORY;
2953 result = handleUnknownEncoding(parser, storedEncName);
2954 poolClear(&temp2Pool);
2955 if (result == XML_ERROR_UNKNOWN_ENCODING)
2956 eventPtr = encodingName;
2957 return result;
2961 if (storedEncName || storedversion)
2962 poolClear(&temp2Pool);
2964 return XML_ERROR_NONE;
2967 static enum XML_Error
2968 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
2970 if (unknownEncodingHandler) {
2971 XML_Encoding info;
2972 int i;
2973 for (i = 0; i < 256; i++)
2974 info.map[i] = -1;
2975 info.convert = NULL;
2976 info.data = NULL;
2977 info.release = NULL;
2978 if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
2979 &info)) {
2980 ENCODING *enc;
2981 unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
2982 if (!unknownEncodingMem) {
2983 if (info.release)
2984 info.release(info.data);
2985 return XML_ERROR_NO_MEMORY;
2987 enc = (ns
2988 ? XmlInitUnknownEncodingNS
2989 : XmlInitUnknownEncoding)(unknownEncodingMem,
2990 info.map,
2991 info.convert,
2992 info.data);
2993 if (enc) {
2994 unknownEncodingData = info.data;
2995 unknownEncodingRelease = info.release;
2996 encoding = enc;
2997 return XML_ERROR_NONE;
3000 if (info.release != NULL)
3001 info.release(info.data);
3003 return XML_ERROR_UNKNOWN_ENCODING;
3006 static enum XML_Error PTRCALL
3007 prologInitProcessor(XML_Parser parser,
3008 const char *s,
3009 const char *end,
3010 const char **nextPtr)
3012 enum XML_Error result = initializeEncoding(parser);
3013 if (result != XML_ERROR_NONE)
3014 return result;
3015 processor = prologProcessor;
3016 return prologProcessor(parser, s, end, nextPtr);
3019 #ifdef XML_DTD
3021 static enum XML_Error PTRCALL
3022 externalParEntInitProcessor(XML_Parser parser,
3023 const char *s,
3024 const char *end,
3025 const char **nextPtr)
3027 enum XML_Error result = initializeEncoding(parser);
3028 if (result != XML_ERROR_NONE)
3029 return result;
3031 /* we know now that XML_Parse(Buffer) has been called,
3032 so we consider the external parameter entity read */
3033 _dtd->paramEntityRead = XML_TRUE;
3035 if (prologState.inEntityValue) {
3036 processor = entityValueInitProcessor;
3037 return entityValueInitProcessor(parser, s, end, nextPtr);
3039 else {
3040 processor = externalParEntProcessor;
3041 return externalParEntProcessor(parser, s, end, nextPtr);
3045 static enum XML_Error PTRCALL
3046 entityValueInitProcessor(XML_Parser parser,
3047 const char *s,
3048 const char *end,
3049 const char **nextPtr)
3051 const char *start = s;
3052 const char *next = s;
3053 int tok;
3055 for (;;) {
3056 tok = XmlPrologTok(encoding, start, end, &next);
3057 if (tok <= 0) {
3058 if (nextPtr != 0 && tok != XML_TOK_INVALID) {
3059 *nextPtr = s;
3060 return XML_ERROR_NONE;
3062 switch (tok) {
3063 case XML_TOK_INVALID:
3064 return XML_ERROR_INVALID_TOKEN;
3065 case XML_TOK_PARTIAL:
3066 return XML_ERROR_UNCLOSED_TOKEN;
3067 case XML_TOK_PARTIAL_CHAR:
3068 return XML_ERROR_PARTIAL_CHAR;
3069 case XML_TOK_NONE: /* start == end */
3070 default:
3071 break;
3073 return storeEntityValue(parser, encoding, s, end);
3075 else if (tok == XML_TOK_XML_DECL) {
3076 enum XML_Error result = processXmlDecl(parser, 0, start, next);
3077 if (result != XML_ERROR_NONE)
3078 return result;
3079 if (nextPtr) *nextPtr = next;
3080 /* stop scanning for text declaration - we found one */
3081 processor = entityValueProcessor;
3082 return entityValueProcessor(parser, next, end, nextPtr);
3084 /* If we are at the end of the buffer, this would cause XmlPrologTok to
3085 return XML_TOK_NONE on the next call, which would then cause the
3086 function to exit with *nextPtr set to s - that is what we want for other
3087 tokens, but not for the BOM - we would rather like to skip it;
3088 then, when this routine is entered the next time, XmlPrologTok will
3089 return XML_TOK_INVALID, since the BOM is still in the buffer
3091 else if (tok == XML_TOK_BOM && next == end && nextPtr) {
3092 *nextPtr = next;
3093 return XML_ERROR_NONE;
3095 start = next;
3099 static enum XML_Error PTRCALL
3100 externalParEntProcessor(XML_Parser parser,
3101 const char *s,
3102 const char *end,
3103 const char **nextPtr)
3105 const char *start = s;
3106 const char *next = s;
3107 int tok;
3109 tok = XmlPrologTok(encoding, start, end, &next);
3110 if (tok <= 0) {
3111 if (nextPtr != 0 && tok != XML_TOK_INVALID) {
3112 *nextPtr = s;
3113 return XML_ERROR_NONE;
3115 switch (tok) {
3116 case XML_TOK_INVALID:
3117 return XML_ERROR_INVALID_TOKEN;
3118 case XML_TOK_PARTIAL:
3119 return XML_ERROR_UNCLOSED_TOKEN;
3120 case XML_TOK_PARTIAL_CHAR:
3121 return XML_ERROR_PARTIAL_CHAR;
3122 case XML_TOK_NONE: /* start == end */
3123 default:
3124 break;
3127 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
3128 However, when parsing an external subset, doProlog will not accept a BOM
3129 as valid, and report a syntax error, so we have to skip the BOM
3131 else if (tok == XML_TOK_BOM) {
3132 s = next;
3133 tok = XmlPrologTok(encoding, s, end, &next);
3136 processor = prologProcessor;
3137 return doProlog(parser, encoding, s, end, tok, next, nextPtr);
3140 static enum XML_Error PTRCALL
3141 entityValueProcessor(XML_Parser parser,
3142 const char *s,
3143 const char *end,
3144 const char **nextPtr)
3146 const char *start = s;
3147 const char *next = s;
3148 const ENCODING *enc = encoding;
3149 int tok;
3151 for (;;) {
3152 tok = XmlPrologTok(enc, start, end, &next);
3153 if (tok <= 0) {
3154 if (nextPtr != 0 && tok != XML_TOK_INVALID) {
3155 *nextPtr = s;
3156 return XML_ERROR_NONE;
3158 switch (tok) {
3159 case XML_TOK_INVALID:
3160 return XML_ERROR_INVALID_TOKEN;
3161 case XML_TOK_PARTIAL:
3162 return XML_ERROR_UNCLOSED_TOKEN;
3163 case XML_TOK_PARTIAL_CHAR:
3164 return XML_ERROR_PARTIAL_CHAR;
3165 case XML_TOK_NONE: /* start == end */
3166 default:
3167 break;
3169 return storeEntityValue(parser, enc, s, end);
3171 start = next;
3175 #endif /* XML_DTD */
3177 static enum XML_Error PTRCALL
3178 prologProcessor(XML_Parser parser,
3179 const char *s,
3180 const char *end,
3181 const char **nextPtr)
3183 const char *next = s;
3184 int tok = XmlPrologTok(encoding, s, end, &next);
3185 return doProlog(parser, encoding, s, end, tok, next, nextPtr);
3188 static enum XML_Error
3189 doProlog(XML_Parser parser,
3190 const ENCODING *enc,
3191 const char *s,
3192 const char *end,
3193 int tok,
3194 const char *next,
3195 const char **nextPtr)
3197 #ifdef XML_DTD
3198 static const XML_Char externalSubsetName[] = { '#' , '\0' };
3199 #endif /* XML_DTD */
3200 static const XML_Char atypeCDATA[] = { 'C', 'D', 'A', 'T', 'A', '\0' };
3201 static const XML_Char atypeID[] = { 'I', 'D', '\0' };
3202 static const XML_Char atypeIDREF[] = { 'I', 'D', 'R', 'E', 'F', '\0' };
3203 static const XML_Char atypeIDREFS[] = { 'I', 'D', 'R', 'E', 'F', 'S', '\0' };
3204 static const XML_Char atypeENTITY[] = { 'E', 'N', 'T', 'I', 'T', 'Y', '\0' };
3205 static const XML_Char atypeENTITIES[] =
3206 { 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S', '\0' };
3207 static const XML_Char atypeNMTOKEN[] = {
3208 'N', 'M', 'T', 'O', 'K', 'E', 'N', '\0' };
3209 static const XML_Char atypeNMTOKENS[] = {
3210 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S', '\0' };
3211 static const XML_Char notationPrefix[] = {
3212 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', '(', '\0' };
3213 static const XML_Char enumValueSep[] = { '|', '\0' };
3214 static const XML_Char enumValueStart[] = { '(', '\0' };
3216 DTD * const dtd = _dtd; /* save one level of indirection */
3218 const char **eventPP;
3219 const char **eventEndPP;
3220 enum XML_Content_Quant quant;
3222 if (enc == encoding) {
3223 eventPP = &eventPtr;
3224 eventEndPP = &eventEndPtr;
3226 else {
3227 eventPP = &(openInternalEntities->internalEventPtr);
3228 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3230 for (;;) {
3231 int role;
3232 XML_Bool handleDefault = XML_TRUE;
3233 *eventPP = s;
3234 *eventEndPP = next;
3235 if (tok <= 0) {
3236 if (nextPtr != 0 && tok != XML_TOK_INVALID) {
3237 *nextPtr = s;
3238 return XML_ERROR_NONE;
3240 switch (tok) {
3241 case XML_TOK_INVALID:
3242 *eventPP = next;
3243 return XML_ERROR_INVALID_TOKEN;
3244 case XML_TOK_PARTIAL:
3245 return XML_ERROR_UNCLOSED_TOKEN;
3246 case XML_TOK_PARTIAL_CHAR:
3247 return XML_ERROR_PARTIAL_CHAR;
3248 case XML_TOK_NONE:
3249 #ifdef XML_DTD
3250 if (enc != encoding)
3251 return XML_ERROR_NONE;
3252 if (isParamEntity) {
3253 if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
3254 == XML_ROLE_ERROR)
3255 return XML_ERROR_SYNTAX;
3256 return XML_ERROR_NONE;
3258 #endif /* XML_DTD */
3259 return XML_ERROR_NO_ELEMENTS;
3260 default:
3261 tok = -tok;
3262 next = end;
3263 break;
3266 role = XmlTokenRole(&prologState, tok, s, next, enc);
3267 switch (role) {
3268 case XML_ROLE_XML_DECL:
3270 enum XML_Error result = processXmlDecl(parser, 0, s, next);
3271 if (result != XML_ERROR_NONE)
3272 return result;
3273 enc = encoding;
3274 handleDefault = XML_FALSE;
3276 break;
3277 case XML_ROLE_DOCTYPE_NAME:
3278 if (startDoctypeDeclHandler) {
3279 doctypeName = poolStoreString(&tempPool, enc, s, next);
3280 if (!doctypeName)
3281 return XML_ERROR_NO_MEMORY;
3282 poolFinish(&tempPool);
3283 doctypePubid = NULL;
3284 handleDefault = XML_FALSE;
3286 doctypeSysid = NULL; /* always initialize to NULL */
3287 break;
3288 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
3289 if (startDoctypeDeclHandler) {
3290 startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
3291 doctypePubid, 1);
3292 doctypeName = NULL;
3293 poolClear(&tempPool);
3294 handleDefault = XML_FALSE;
3296 break;
3297 #ifdef XML_DTD
3298 case XML_ROLE_TEXT_DECL:
3300 enum XML_Error result = processXmlDecl(parser, 1, s, next);
3301 if (result != XML_ERROR_NONE)
3302 return result;
3303 enc = encoding;
3304 handleDefault = XML_FALSE;
3306 break;
3307 #endif /* XML_DTD */
3308 case XML_ROLE_DOCTYPE_PUBLIC_ID:
3309 #ifdef XML_DTD
3310 useForeignDTD = XML_FALSE;
3311 #endif /* XML_DTD */
3312 dtd->hasParamEntityRefs = XML_TRUE;
3313 if (startDoctypeDeclHandler) {
3314 doctypePubid = poolStoreString(&tempPool, enc,
3315 s + enc->minBytesPerChar,
3316 next - enc->minBytesPerChar);
3317 if (!doctypePubid)
3318 return XML_ERROR_NO_MEMORY;
3319 poolFinish(&tempPool);
3320 handleDefault = XML_FALSE;
3322 #ifdef XML_DTD
3323 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
3324 externalSubsetName,
3325 sizeof(ENTITY));
3326 if (!declEntity)
3327 return XML_ERROR_NO_MEMORY;
3328 #endif /* XML_DTD */
3329 /* fall through */
3330 case XML_ROLE_ENTITY_PUBLIC_ID:
3331 if (!XmlIsPublicId(enc, s, next, eventPP))
3332 return XML_ERROR_SYNTAX;
3333 if (dtd->keepProcessing && declEntity) {
3334 XML_Char *tem = poolStoreString(&dtd->pool,
3335 enc,
3336 s + enc->minBytesPerChar,
3337 next - enc->minBytesPerChar);
3338 if (!tem)
3339 return XML_ERROR_NO_MEMORY;
3340 normalizePublicId(tem);
3341 declEntity->publicId = tem;
3342 poolFinish(&dtd->pool);
3343 if (entityDeclHandler)
3344 handleDefault = XML_FALSE;
3346 break;
3347 case XML_ROLE_DOCTYPE_CLOSE:
3348 if (doctypeName) {
3349 startDoctypeDeclHandler(handlerArg, doctypeName,
3350 doctypeSysid, doctypePubid, 0);
3351 poolClear(&tempPool);
3352 handleDefault = XML_FALSE;
3354 /* doctypeSysid will be non-NULL in the case of a previous
3355 XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
3356 was not set, indicating an external subset
3358 #ifdef XML_DTD
3359 if (doctypeSysid || useForeignDTD) {
3360 dtd->hasParamEntityRefs = XML_TRUE; /* when docTypeSysid == NULL */
3361 if (paramEntityParsing && externalEntityRefHandler) {
3362 ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
3363 externalSubsetName,
3364 sizeof(ENTITY));
3365 if (!entity)
3366 return XML_ERROR_NO_MEMORY;
3367 if (useForeignDTD)
3368 entity->base = curBase;
3369 dtd->paramEntityRead = XML_FALSE;
3370 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3372 entity->base,
3373 entity->systemId,
3374 entity->publicId))
3375 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3376 if (dtd->paramEntityRead &&
3377 !dtd->standalone &&
3378 notStandaloneHandler &&
3379 !notStandaloneHandler(handlerArg))
3380 return XML_ERROR_NOT_STANDALONE;
3381 /* end of DTD - no need to update dtd->keepProcessing */
3383 useForeignDTD = XML_FALSE;
3385 #endif /* XML_DTD */
3386 if (endDoctypeDeclHandler) {
3387 endDoctypeDeclHandler(handlerArg);
3388 handleDefault = XML_FALSE;
3390 break;
3391 case XML_ROLE_INSTANCE_START:
3392 #ifdef XML_DTD
3393 /* if there is no DOCTYPE declaration then now is the
3394 last chance to read the foreign DTD
3396 if (useForeignDTD) {
3397 dtd->hasParamEntityRefs = XML_TRUE;
3398 if (paramEntityParsing && externalEntityRefHandler) {
3399 ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
3400 externalSubsetName,
3401 sizeof(ENTITY));
3402 if (!entity)
3403 return XML_ERROR_NO_MEMORY;
3404 entity->base = curBase;
3405 dtd->paramEntityRead = XML_FALSE;
3406 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3408 entity->base,
3409 entity->systemId,
3410 entity->publicId))
3411 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3412 if (dtd->paramEntityRead &&
3413 !dtd->standalone &&
3414 notStandaloneHandler &&
3415 !notStandaloneHandler(handlerArg))
3416 return XML_ERROR_NOT_STANDALONE;
3417 /* end of DTD - no need to update dtd->keepProcessing */
3420 #endif /* XML_DTD */
3421 processor = contentProcessor;
3422 return contentProcessor(parser, s, end, nextPtr);
3423 case XML_ROLE_ATTLIST_ELEMENT_NAME:
3424 declElementType = getElementType(parser, enc, s, next);
3425 if (!declElementType)
3426 return XML_ERROR_NO_MEMORY;
3427 goto checkAttListDeclHandler;
3428 case XML_ROLE_ATTRIBUTE_NAME:
3429 declAttributeId = getAttributeId(parser, enc, s, next);
3430 if (!declAttributeId)
3431 return XML_ERROR_NO_MEMORY;
3432 declAttributeIsCdata = XML_FALSE;
3433 declAttributeType = NULL;
3434 declAttributeIsId = XML_FALSE;
3435 goto checkAttListDeclHandler;
3436 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
3437 declAttributeIsCdata = XML_TRUE;
3438 declAttributeType = atypeCDATA;
3439 goto checkAttListDeclHandler;
3440 case XML_ROLE_ATTRIBUTE_TYPE_ID:
3441 declAttributeIsId = XML_TRUE;
3442 declAttributeType = atypeID;
3443 goto checkAttListDeclHandler;
3444 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
3445 declAttributeType = atypeIDREF;
3446 goto checkAttListDeclHandler;
3447 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
3448 declAttributeType = atypeIDREFS;
3449 goto checkAttListDeclHandler;
3450 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
3451 declAttributeType = atypeENTITY;
3452 goto checkAttListDeclHandler;
3453 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
3454 declAttributeType = atypeENTITIES;
3455 goto checkAttListDeclHandler;
3456 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
3457 declAttributeType = atypeNMTOKEN;
3458 goto checkAttListDeclHandler;
3459 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
3460 declAttributeType = atypeNMTOKENS;
3461 checkAttListDeclHandler:
3462 if (dtd->keepProcessing && attlistDeclHandler)
3463 handleDefault = XML_FALSE;
3464 break;
3465 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
3466 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
3467 if (dtd->keepProcessing && attlistDeclHandler) {
3468 const XML_Char *prefix;
3469 if (declAttributeType) {
3470 prefix = enumValueSep;
3472 else {
3473 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
3474 ? notationPrefix
3475 : enumValueStart);
3477 if (!poolAppendString(&tempPool, prefix))
3478 return XML_ERROR_NO_MEMORY;
3479 if (!poolAppend(&tempPool, enc, s, next))
3480 return XML_ERROR_NO_MEMORY;
3481 declAttributeType = tempPool.start;
3482 handleDefault = XML_FALSE;
3484 break;
3485 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
3486 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
3487 if (dtd->keepProcessing) {
3488 if (!defineAttribute(declElementType, declAttributeId,
3489 declAttributeIsCdata, declAttributeIsId, 0,
3490 parser))
3491 return XML_ERROR_NO_MEMORY;
3492 if (attlistDeclHandler && declAttributeType) {
3493 if (*declAttributeType == XML_T('(')
3494 || (*declAttributeType == XML_T('N')
3495 && declAttributeType[1] == XML_T('O'))) {
3496 /* Enumerated or Notation type */
3497 if (!poolAppendChar(&tempPool, XML_T(')'))
3498 || !poolAppendChar(&tempPool, XML_T('\0')))
3499 return XML_ERROR_NO_MEMORY;
3500 declAttributeType = tempPool.start;
3501 poolFinish(&tempPool);
3503 *eventEndPP = s;
3504 attlistDeclHandler(handlerArg, declElementType->name,
3505 declAttributeId->name, declAttributeType,
3506 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
3507 poolClear(&tempPool);
3508 handleDefault = XML_FALSE;
3511 break;
3512 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
3513 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
3514 if (dtd->keepProcessing) {
3515 const XML_Char *attVal;
3516 enum XML_Error result
3517 = storeAttributeValue(parser, enc, declAttributeIsCdata,
3518 s + enc->minBytesPerChar,
3519 next - enc->minBytesPerChar,
3520 &dtd->pool);
3521 if (result)
3522 return result;
3523 attVal = poolStart(&dtd->pool);
3524 poolFinish(&dtd->pool);
3525 /* ID attributes aren't allowed to have a default */
3526 if (!defineAttribute(declElementType, declAttributeId,
3527 declAttributeIsCdata, XML_FALSE, attVal, parser))
3528 return XML_ERROR_NO_MEMORY;
3529 if (attlistDeclHandler && declAttributeType) {
3530 if (*declAttributeType == XML_T('(')
3531 || (*declAttributeType == XML_T('N')
3532 && declAttributeType[1] == XML_T('O'))) {
3533 /* Enumerated or Notation type */
3534 if (!poolAppendChar(&tempPool, XML_T(')'))
3535 || !poolAppendChar(&tempPool, XML_T('\0')))
3536 return XML_ERROR_NO_MEMORY;
3537 declAttributeType = tempPool.start;
3538 poolFinish(&tempPool);
3540 *eventEndPP = s;
3541 attlistDeclHandler(handlerArg, declElementType->name,
3542 declAttributeId->name, declAttributeType,
3543 attVal,
3544 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
3545 poolClear(&tempPool);
3546 handleDefault = XML_FALSE;
3549 break;
3550 case XML_ROLE_ENTITY_VALUE:
3551 if (dtd->keepProcessing) {
3552 enum XML_Error result = storeEntityValue(parser, enc,
3553 s + enc->minBytesPerChar,
3554 next - enc->minBytesPerChar);
3555 if (declEntity) {
3556 declEntity->textPtr = poolStart(&dtd->entityValuePool);
3557 declEntity->textLen = poolLength(&dtd->entityValuePool);
3558 poolFinish(&dtd->entityValuePool);
3559 if (entityDeclHandler) {
3560 *eventEndPP = s;
3561 entityDeclHandler(handlerArg,
3562 declEntity->name,
3563 declEntity->is_param,
3564 declEntity->textPtr,
3565 declEntity->textLen,
3566 curBase, 0, 0, 0);
3567 handleDefault = XML_FALSE;
3570 else
3571 poolDiscard(&dtd->entityValuePool);
3572 if (result != XML_ERROR_NONE)
3573 return result;
3575 break;
3576 case XML_ROLE_DOCTYPE_SYSTEM_ID:
3577 #ifdef XML_DTD
3578 useForeignDTD = XML_FALSE;
3579 #endif /* XML_DTD */
3580 dtd->hasParamEntityRefs = XML_TRUE;
3581 if (startDoctypeDeclHandler) {
3582 doctypeSysid = poolStoreString(&tempPool, enc,
3583 s + enc->minBytesPerChar,
3584 next - enc->minBytesPerChar);
3585 if (doctypeSysid == NULL)
3586 return XML_ERROR_NO_MEMORY;
3587 poolFinish(&tempPool);
3588 handleDefault = XML_FALSE;
3590 #ifdef XML_DTD
3591 else
3592 /* use externalSubsetName to make doctypeSysid non-NULL
3593 for the case where no startDoctypeDeclHandler is set */
3594 doctypeSysid = externalSubsetName;
3595 #endif /* XML_DTD */
3596 if (!dtd->standalone
3597 #ifdef XML_DTD
3598 && !paramEntityParsing
3599 #endif /* XML_DTD */
3600 && notStandaloneHandler
3601 && !notStandaloneHandler(handlerArg))
3602 return XML_ERROR_NOT_STANDALONE;
3603 #ifndef XML_DTD
3604 break;
3605 #else /* XML_DTD */
3606 if (!declEntity) {
3607 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
3608 externalSubsetName,
3609 sizeof(ENTITY));
3610 if (!declEntity)
3611 return XML_ERROR_NO_MEMORY;
3612 declEntity->publicId = NULL;
3614 /* fall through */
3615 #endif /* XML_DTD */
3616 case XML_ROLE_ENTITY_SYSTEM_ID:
3617 if (dtd->keepProcessing && declEntity) {
3618 declEntity->systemId = poolStoreString(&dtd->pool, enc,
3619 s + enc->minBytesPerChar,
3620 next - enc->minBytesPerChar);
3621 if (!declEntity->systemId)
3622 return XML_ERROR_NO_MEMORY;
3623 declEntity->base = curBase;
3624 poolFinish(&dtd->pool);
3625 if (entityDeclHandler)
3626 handleDefault = XML_FALSE;
3628 break;
3629 case XML_ROLE_ENTITY_COMPLETE:
3630 if (dtd->keepProcessing && declEntity && entityDeclHandler) {
3631 *eventEndPP = s;
3632 entityDeclHandler(handlerArg,
3633 declEntity->name,
3634 declEntity->is_param,
3635 0,0,
3636 declEntity->base,
3637 declEntity->systemId,
3638 declEntity->publicId,
3640 handleDefault = XML_FALSE;
3642 break;
3643 case XML_ROLE_ENTITY_NOTATION_NAME:
3644 if (dtd->keepProcessing && declEntity) {
3645 declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
3646 if (!declEntity->notation)
3647 return XML_ERROR_NO_MEMORY;
3648 poolFinish(&dtd->pool);
3649 if (unparsedEntityDeclHandler) {
3650 *eventEndPP = s;
3651 unparsedEntityDeclHandler(handlerArg,
3652 declEntity->name,
3653 declEntity->base,
3654 declEntity->systemId,
3655 declEntity->publicId,
3656 declEntity->notation);
3657 handleDefault = XML_FALSE;
3659 else if (entityDeclHandler) {
3660 *eventEndPP = s;
3661 entityDeclHandler(handlerArg,
3662 declEntity->name,
3663 0,0,0,
3664 declEntity->base,
3665 declEntity->systemId,
3666 declEntity->publicId,
3667 declEntity->notation);
3668 handleDefault = XML_FALSE;
3671 break;
3672 case XML_ROLE_GENERAL_ENTITY_NAME:
3674 if (XmlPredefinedEntityName(enc, s, next)) {
3675 declEntity = NULL;
3676 break;
3678 if (dtd->keepProcessing) {
3679 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
3680 if (!name)
3681 return XML_ERROR_NO_MEMORY;
3682 declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
3683 sizeof(ENTITY));
3684 if (!declEntity)
3685 return XML_ERROR_NO_MEMORY;
3686 if (declEntity->name != name) {
3687 poolDiscard(&dtd->pool);
3688 declEntity = NULL;
3690 else {
3691 poolFinish(&dtd->pool);
3692 declEntity->publicId = NULL;
3693 declEntity->is_param = XML_FALSE;
3694 /* if we have a parent parser or are reading an internal parameter
3695 entity, then the entity declaration is not considered "internal"
3697 declEntity->is_internal = !(parentParser || openInternalEntities);
3698 if (entityDeclHandler)
3699 handleDefault = XML_FALSE;
3702 else {
3703 poolDiscard(&dtd->pool);
3704 declEntity = NULL;
3707 break;
3708 case XML_ROLE_PARAM_ENTITY_NAME:
3709 #ifdef XML_DTD
3710 if (dtd->keepProcessing) {
3711 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
3712 if (!name)
3713 return XML_ERROR_NO_MEMORY;
3714 declEntity = (ENTITY *)lookup(&dtd->paramEntities,
3715 name, sizeof(ENTITY));
3716 if (!declEntity)
3717 return XML_ERROR_NO_MEMORY;
3718 if (declEntity->name != name) {
3719 poolDiscard(&dtd->pool);
3720 declEntity = NULL;
3722 else {
3723 poolFinish(&dtd->pool);
3724 declEntity->publicId = NULL;
3725 declEntity->is_param = XML_TRUE;
3726 /* if we have a parent parser or are reading an internal parameter
3727 entity, then the entity declaration is not considered "internal"
3729 declEntity->is_internal = !(parentParser || openInternalEntities);
3730 if (entityDeclHandler)
3731 handleDefault = XML_FALSE;
3734 else {
3735 poolDiscard(&dtd->pool);
3736 declEntity = NULL;
3738 #else /* not XML_DTD */
3739 declEntity = NULL;
3740 #endif /* XML_DTD */
3741 break;
3742 case XML_ROLE_NOTATION_NAME:
3743 declNotationPublicId = NULL;
3744 declNotationName = NULL;
3745 if (notationDeclHandler) {
3746 declNotationName = poolStoreString(&tempPool, enc, s, next);
3747 if (!declNotationName)
3748 return XML_ERROR_NO_MEMORY;
3749 poolFinish(&tempPool);
3750 handleDefault = XML_FALSE;
3752 break;
3753 case XML_ROLE_NOTATION_PUBLIC_ID:
3754 if (!XmlIsPublicId(enc, s, next, eventPP))
3755 return XML_ERROR_SYNTAX;
3756 if (declNotationName) { /* means notationDeclHandler != NULL */
3757 XML_Char *tem = poolStoreString(&tempPool,
3758 enc,
3759 s + enc->minBytesPerChar,
3760 next - enc->minBytesPerChar);
3761 if (!tem)
3762 return XML_ERROR_NO_MEMORY;
3763 normalizePublicId(tem);
3764 declNotationPublicId = tem;
3765 poolFinish(&tempPool);
3766 handleDefault = XML_FALSE;
3768 break;
3769 case XML_ROLE_NOTATION_SYSTEM_ID:
3770 if (declNotationName && notationDeclHandler) {
3771 const XML_Char *systemId
3772 = poolStoreString(&tempPool, enc,
3773 s + enc->minBytesPerChar,
3774 next - enc->minBytesPerChar);
3775 if (!systemId)
3776 return XML_ERROR_NO_MEMORY;
3777 *eventEndPP = s;
3778 notationDeclHandler(handlerArg,
3779 declNotationName,
3780 curBase,
3781 systemId,
3782 declNotationPublicId);
3783 handleDefault = XML_FALSE;
3785 poolClear(&tempPool);
3786 break;
3787 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
3788 if (declNotationPublicId && notationDeclHandler) {
3789 *eventEndPP = s;
3790 notationDeclHandler(handlerArg,
3791 declNotationName,
3792 curBase,
3794 declNotationPublicId);
3795 handleDefault = XML_FALSE;
3797 poolClear(&tempPool);
3798 break;
3799 case XML_ROLE_ERROR:
3800 switch (tok) {
3801 case XML_TOK_PARAM_ENTITY_REF:
3802 return XML_ERROR_PARAM_ENTITY_REF;
3803 case XML_TOK_XML_DECL:
3804 return XML_ERROR_MISPLACED_XML_PI;
3805 default:
3806 return XML_ERROR_SYNTAX;
3808 #ifdef XML_DTD
3809 case XML_ROLE_IGNORE_SECT:
3811 enum XML_Error result;
3812 if (defaultHandler)
3813 reportDefault(parser, enc, s, next);
3814 handleDefault = XML_FALSE;
3815 result = doIgnoreSection(parser, enc, &next, end, nextPtr);
3816 if (!next) {
3817 processor = ignoreSectionProcessor;
3818 return result;
3821 break;
3822 #endif /* XML_DTD */
3823 case XML_ROLE_GROUP_OPEN:
3824 if (prologState.level >= groupSize) {
3825 if (groupSize) {
3826 char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
3827 if (temp == NULL)
3828 return XML_ERROR_NO_MEMORY;
3829 groupConnector = temp;
3830 if (dtd->scaffIndex) {
3831 int *temp = (int *)REALLOC(dtd->scaffIndex,
3832 groupSize * sizeof(int));
3833 if (temp == NULL)
3834 return XML_ERROR_NO_MEMORY;
3835 dtd->scaffIndex = temp;
3838 else {
3839 groupConnector = (char *)MALLOC(groupSize = 32);
3840 if (!groupConnector)
3841 return XML_ERROR_NO_MEMORY;
3844 groupConnector[prologState.level] = 0;
3845 if (dtd->in_eldecl) {
3846 int myindex = nextScaffoldPart(parser);
3847 if (myindex < 0)
3848 return XML_ERROR_NO_MEMORY;
3849 dtd->scaffIndex[dtd->scaffLevel] = myindex;
3850 dtd->scaffLevel++;
3851 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
3852 if (elementDeclHandler)
3853 handleDefault = XML_FALSE;
3855 break;
3856 case XML_ROLE_GROUP_SEQUENCE:
3857 if (groupConnector[prologState.level] == '|')
3858 return XML_ERROR_SYNTAX;
3859 groupConnector[prologState.level] = ',';
3860 if (dtd->in_eldecl && elementDeclHandler)
3861 handleDefault = XML_FALSE;
3862 break;
3863 case XML_ROLE_GROUP_CHOICE:
3864 if (groupConnector[prologState.level] == ',')
3865 return XML_ERROR_SYNTAX;
3866 if (dtd->in_eldecl
3867 && !groupConnector[prologState.level]
3868 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
3869 != XML_CTYPE_MIXED)
3871 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
3872 = XML_CTYPE_CHOICE;
3873 if (elementDeclHandler)
3874 handleDefault = XML_FALSE;
3876 groupConnector[prologState.level] = '|';
3877 break;
3878 case XML_ROLE_PARAM_ENTITY_REF:
3879 #ifdef XML_DTD
3880 case XML_ROLE_INNER_PARAM_ENTITY_REF:
3881 /* PE references in internal subset are
3882 not allowed within declarations */
3883 if (prologState.documentEntity &&
3884 role == XML_ROLE_INNER_PARAM_ENTITY_REF)
3885 return XML_ERROR_PARAM_ENTITY_REF;
3886 dtd->hasParamEntityRefs = XML_TRUE;
3887 if (!paramEntityParsing)
3888 dtd->keepProcessing = dtd->standalone;
3889 else {
3890 const XML_Char *name;
3891 ENTITY *entity;
3892 name = poolStoreString(&dtd->pool, enc,
3893 s + enc->minBytesPerChar,
3894 next - enc->minBytesPerChar);
3895 if (!name)
3896 return XML_ERROR_NO_MEMORY;
3897 entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
3898 poolDiscard(&dtd->pool);
3899 /* first, determine if a check for an existing declaration is needed;
3900 if yes, check that the entity exists, and that it is internal,
3901 otherwise call the skipped entity handler
3903 if (prologState.documentEntity &&
3904 (dtd->standalone
3905 ? !openInternalEntities
3906 : !dtd->hasParamEntityRefs)) {
3907 if (!entity)
3908 return XML_ERROR_UNDEFINED_ENTITY;
3909 else if (!entity->is_internal)
3910 return XML_ERROR_ENTITY_DECLARED_IN_PE;
3912 else if (!entity) {
3913 dtd->keepProcessing = dtd->standalone;
3914 /* cannot report skipped entities in declarations */
3915 if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
3916 skippedEntityHandler(handlerArg, name, 1);
3917 handleDefault = XML_FALSE;
3919 break;
3921 if (entity->open)
3922 return XML_ERROR_RECURSIVE_ENTITY_REF;
3923 if (entity->textPtr) {
3924 enum XML_Error result;
3925 result = processInternalParamEntity(parser, entity);
3926 if (result != XML_ERROR_NONE)
3927 return result;
3928 handleDefault = XML_FALSE;
3929 break;
3931 if (externalEntityRefHandler) {
3932 dtd->paramEntityRead = XML_FALSE;
3933 entity->open = XML_TRUE;
3934 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
3936 entity->base,
3937 entity->systemId,
3938 entity->publicId)) {
3939 entity->open = XML_FALSE;
3940 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
3942 entity->open = XML_FALSE;
3943 handleDefault = XML_FALSE;
3944 if (!dtd->paramEntityRead) {
3945 dtd->keepProcessing = dtd->standalone;
3946 break;
3949 else {
3950 dtd->keepProcessing = dtd->standalone;
3951 break;
3954 #endif /* XML_DTD */
3955 if (!dtd->standalone &&
3956 notStandaloneHandler &&
3957 !notStandaloneHandler(handlerArg))
3958 return XML_ERROR_NOT_STANDALONE;
3959 break;
3961 /* Element declaration stuff */
3963 case XML_ROLE_ELEMENT_NAME:
3964 if (elementDeclHandler) {
3965 declElementType = getElementType(parser, enc, s, next);
3966 if (!declElementType)
3967 return XML_ERROR_NO_MEMORY;
3968 dtd->scaffLevel = 0;
3969 dtd->scaffCount = 0;
3970 dtd->in_eldecl = XML_TRUE;
3971 handleDefault = XML_FALSE;
3973 break;
3975 case XML_ROLE_CONTENT_ANY:
3976 case XML_ROLE_CONTENT_EMPTY:
3977 if (dtd->in_eldecl) {
3978 if (elementDeclHandler) {
3979 XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
3980 if (!content)
3981 return XML_ERROR_NO_MEMORY;
3982 content->quant = XML_CQUANT_NONE;
3983 content->name = NULL;
3984 content->numchildren = 0;
3985 content->children = NULL;
3986 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
3987 XML_CTYPE_ANY :
3988 XML_CTYPE_EMPTY);
3989 *eventEndPP = s;
3990 elementDeclHandler(handlerArg, declElementType->name, content);
3991 handleDefault = XML_FALSE;
3993 dtd->in_eldecl = XML_FALSE;
3995 break;
3997 case XML_ROLE_CONTENT_PCDATA:
3998 if (dtd->in_eldecl) {
3999 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4000 = XML_CTYPE_MIXED;
4001 if (elementDeclHandler)
4002 handleDefault = XML_FALSE;
4004 break;
4006 case XML_ROLE_CONTENT_ELEMENT:
4007 quant = XML_CQUANT_NONE;
4008 goto elementContent;
4009 case XML_ROLE_CONTENT_ELEMENT_OPT:
4010 quant = XML_CQUANT_OPT;
4011 goto elementContent;
4012 case XML_ROLE_CONTENT_ELEMENT_REP:
4013 quant = XML_CQUANT_REP;
4014 goto elementContent;
4015 case XML_ROLE_CONTENT_ELEMENT_PLUS:
4016 quant = XML_CQUANT_PLUS;
4017 elementContent:
4018 if (dtd->in_eldecl) {
4019 ELEMENT_TYPE *el;
4020 const XML_Char *name;
4021 int nameLen;
4022 const char *nxt = (quant == XML_CQUANT_NONE
4023 ? next
4024 : next - enc->minBytesPerChar);
4025 int myindex = nextScaffoldPart(parser);
4026 if (myindex < 0)
4027 return XML_ERROR_NO_MEMORY;
4028 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
4029 dtd->scaffold[myindex].quant = quant;
4030 el = getElementType(parser, enc, s, nxt);
4031 if (!el)
4032 return XML_ERROR_NO_MEMORY;
4033 name = el->name;
4034 dtd->scaffold[myindex].name = name;
4035 nameLen = 0;
4036 for (; name[nameLen++]; );
4037 dtd->contentStringLen += nameLen;
4038 if (elementDeclHandler)
4039 handleDefault = XML_FALSE;
4041 break;
4043 case XML_ROLE_GROUP_CLOSE:
4044 quant = XML_CQUANT_NONE;
4045 goto closeGroup;
4046 case XML_ROLE_GROUP_CLOSE_OPT:
4047 quant = XML_CQUANT_OPT;
4048 goto closeGroup;
4049 case XML_ROLE_GROUP_CLOSE_REP:
4050 quant = XML_CQUANT_REP;
4051 goto closeGroup;
4052 case XML_ROLE_GROUP_CLOSE_PLUS:
4053 quant = XML_CQUANT_PLUS;
4054 closeGroup:
4055 if (dtd->in_eldecl) {
4056 if (elementDeclHandler)
4057 handleDefault = XML_FALSE;
4058 dtd->scaffLevel--;
4059 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
4060 if (dtd->scaffLevel == 0) {
4061 if (!handleDefault) {
4062 XML_Content *model = build_model(parser);
4063 if (!model)
4064 return XML_ERROR_NO_MEMORY;
4065 *eventEndPP = s;
4066 elementDeclHandler(handlerArg, declElementType->name, model);
4068 dtd->in_eldecl = XML_FALSE;
4069 dtd->contentStringLen = 0;
4072 break;
4073 /* End element declaration stuff */
4075 case XML_ROLE_PI:
4076 if (!reportProcessingInstruction(parser, enc, s, next))
4077 return XML_ERROR_NO_MEMORY;
4078 handleDefault = XML_FALSE;
4079 break;
4080 case XML_ROLE_COMMENT:
4081 if (!reportComment(parser, enc, s, next))
4082 return XML_ERROR_NO_MEMORY;
4083 handleDefault = XML_FALSE;
4084 break;
4085 case XML_ROLE_NONE:
4086 switch (tok) {
4087 case XML_TOK_BOM:
4088 handleDefault = XML_FALSE;
4089 break;
4091 break;
4092 case XML_ROLE_DOCTYPE_NONE:
4093 if (startDoctypeDeclHandler)
4094 handleDefault = XML_FALSE;
4095 break;
4096 case XML_ROLE_ENTITY_NONE:
4097 if (dtd->keepProcessing && entityDeclHandler)
4098 handleDefault = XML_FALSE;
4099 break;
4100 case XML_ROLE_NOTATION_NONE:
4101 if (notationDeclHandler)
4102 handleDefault = XML_FALSE;
4103 break;
4104 case XML_ROLE_ATTLIST_NONE:
4105 if (dtd->keepProcessing && attlistDeclHandler)
4106 handleDefault = XML_FALSE;
4107 break;
4108 case XML_ROLE_ELEMENT_NONE:
4109 if (elementDeclHandler)
4110 handleDefault = XML_FALSE;
4111 break;
4112 } /* end of big switch */
4114 if (handleDefault && defaultHandler)
4115 reportDefault(parser, enc, s, next);
4117 s = next;
4118 tok = XmlPrologTok(enc, s, end, &next);
4120 /* not reached */
4123 static enum XML_Error PTRCALL
4124 epilogProcessor(XML_Parser parser,
4125 const char *s,
4126 const char *end,
4127 const char **nextPtr)
4129 processor = epilogProcessor;
4130 eventPtr = s;
4131 for (;;) {
4132 const char *next = NULL;
4133 int tok = XmlPrologTok(encoding, s, end, &next);
4134 eventEndPtr = next;
4135 switch (tok) {
4136 /* report partial linebreak - it might be the last token */
4137 case -XML_TOK_PROLOG_S:
4138 if (defaultHandler) {
4139 eventEndPtr = next;
4140 reportDefault(parser, encoding, s, next);
4142 if (nextPtr)
4143 *nextPtr = next;
4144 return XML_ERROR_NONE;
4145 case XML_TOK_NONE:
4146 if (nextPtr)
4147 *nextPtr = s;
4148 return XML_ERROR_NONE;
4149 case XML_TOK_PROLOG_S:
4150 if (defaultHandler)
4151 reportDefault(parser, encoding, s, next);
4152 break;
4153 case XML_TOK_PI:
4154 if (!reportProcessingInstruction(parser, encoding, s, next))
4155 return XML_ERROR_NO_MEMORY;
4156 break;
4157 case XML_TOK_COMMENT:
4158 if (!reportComment(parser, encoding, s, next))
4159 return XML_ERROR_NO_MEMORY;
4160 break;
4161 case XML_TOK_INVALID:
4162 eventPtr = next;
4163 return XML_ERROR_INVALID_TOKEN;
4164 case XML_TOK_PARTIAL:
4165 if (nextPtr) {
4166 *nextPtr = s;
4167 return XML_ERROR_NONE;
4169 return XML_ERROR_UNCLOSED_TOKEN;
4170 case XML_TOK_PARTIAL_CHAR:
4171 if (nextPtr) {
4172 *nextPtr = s;
4173 return XML_ERROR_NONE;
4175 return XML_ERROR_PARTIAL_CHAR;
4176 default:
4177 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
4179 eventPtr = s = next;
4183 #ifdef XML_DTD
4185 static enum XML_Error
4186 processInternalParamEntity(XML_Parser parser, ENTITY *entity)
4188 const char *s, *end, *next;
4189 int tok;
4190 enum XML_Error result;
4191 OPEN_INTERNAL_ENTITY openEntity;
4192 entity->open = XML_TRUE;
4193 openEntity.next = openInternalEntities;
4194 openInternalEntities = &openEntity;
4195 openEntity.entity = entity;
4196 openEntity.internalEventPtr = NULL;
4197 openEntity.internalEventEndPtr = NULL;
4198 s = (char *)entity->textPtr;
4199 end = (char *)(entity->textPtr + entity->textLen);
4200 tok = XmlPrologTok(internalEncoding, s, end, &next);
4201 result = doProlog(parser, internalEncoding, s, end, tok, next, 0);
4202 entity->open = XML_FALSE;
4203 openInternalEntities = openEntity.next;
4204 return result;
4207 #endif /* XML_DTD */
4209 static enum XML_Error PTRCALL
4210 errorProcessor(XML_Parser parser,
4211 const char *s,
4212 const char *end,
4213 const char **nextPtr)
4215 return errorCode;
4218 static enum XML_Error
4219 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4220 const char *ptr, const char *end,
4221 STRING_POOL *pool)
4223 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
4224 end, pool);
4225 if (result)
4226 return result;
4227 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
4228 poolChop(pool);
4229 if (!poolAppendChar(pool, XML_T('\0')))
4230 return XML_ERROR_NO_MEMORY;
4231 return XML_ERROR_NONE;
4234 static enum XML_Error
4235 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
4236 const char *ptr, const char *end,
4237 STRING_POOL *pool)
4239 DTD * const dtd = _dtd; /* save one level of indirection */
4240 for (;;) {
4241 const char *next;
4242 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
4243 switch (tok) {
4244 case XML_TOK_NONE:
4245 return XML_ERROR_NONE;
4246 case XML_TOK_INVALID:
4247 if (enc == encoding)
4248 eventPtr = next;
4249 return XML_ERROR_INVALID_TOKEN;
4250 case XML_TOK_PARTIAL:
4251 if (enc == encoding)
4252 eventPtr = ptr;
4253 return XML_ERROR_INVALID_TOKEN;
4254 case XML_TOK_CHAR_REF:
4256 XML_Char buf[XML_ENCODE_MAX];
4257 int i;
4258 int n = XmlCharRefNumber(enc, ptr);
4259 if (n < 0) {
4260 if (enc == encoding)
4261 eventPtr = ptr;
4262 return XML_ERROR_BAD_CHAR_REF;
4264 if (!isCdata
4265 && n == 0x20 /* space */
4266 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4267 break;
4268 n = XmlEncode(n, (ICHAR *)buf);
4269 if (!n) {
4270 if (enc == encoding)
4271 eventPtr = ptr;
4272 return XML_ERROR_BAD_CHAR_REF;
4274 for (i = 0; i < n; i++) {
4275 if (!poolAppendChar(pool, buf[i]))
4276 return XML_ERROR_NO_MEMORY;
4279 break;
4280 case XML_TOK_DATA_CHARS:
4281 if (!poolAppend(pool, enc, ptr, next))
4282 return XML_ERROR_NO_MEMORY;
4283 break;
4284 case XML_TOK_TRAILING_CR:
4285 next = ptr + enc->minBytesPerChar;
4286 /* fall through */
4287 case XML_TOK_ATTRIBUTE_VALUE_S:
4288 case XML_TOK_DATA_NEWLINE:
4289 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
4290 break;
4291 if (!poolAppendChar(pool, 0x20))
4292 return XML_ERROR_NO_MEMORY;
4293 break;
4294 case XML_TOK_ENTITY_REF:
4296 const XML_Char *name;
4297 ENTITY *entity;
4298 char checkEntityDecl;
4299 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
4300 ptr + enc->minBytesPerChar,
4301 next - enc->minBytesPerChar);
4302 if (ch) {
4303 if (!poolAppendChar(pool, ch))
4304 return XML_ERROR_NO_MEMORY;
4305 break;
4307 name = poolStoreString(&temp2Pool, enc,
4308 ptr + enc->minBytesPerChar,
4309 next - enc->minBytesPerChar);
4310 if (!name)
4311 return XML_ERROR_NO_MEMORY;
4312 entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
4313 poolDiscard(&temp2Pool);
4314 /* first, determine if a check for an existing declaration is needed;
4315 if yes, check that the entity exists, and that it is internal,
4316 otherwise call the default handler (if called from content)
4318 if (pool == &dtd->pool) /* are we called from prolog? */
4319 checkEntityDecl =
4320 #ifdef XML_DTD
4321 prologState.documentEntity &&
4322 #endif /* XML_DTD */
4323 (dtd->standalone
4324 ? !openInternalEntities
4325 : !dtd->hasParamEntityRefs);
4326 else /* if (pool == &tempPool): we are called from content */
4327 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
4328 if (checkEntityDecl) {
4329 if (!entity)
4330 return XML_ERROR_UNDEFINED_ENTITY;
4331 else if (!entity->is_internal)
4332 return XML_ERROR_ENTITY_DECLARED_IN_PE;
4334 else if (!entity) {
4335 /* cannot report skipped entity here - see comments on
4336 skippedEntityHandler
4337 if (skippedEntityHandler)
4338 skippedEntityHandler(handlerArg, name, 0);
4340 if ((pool == &tempPool) && defaultHandler)
4341 reportDefault(parser, enc, ptr, next);
4342 break;
4344 if (entity->open) {
4345 if (enc == encoding)
4346 eventPtr = ptr;
4347 return XML_ERROR_RECURSIVE_ENTITY_REF;
4349 if (entity->notation) {
4350 if (enc == encoding)
4351 eventPtr = ptr;
4352 return XML_ERROR_BINARY_ENTITY_REF;
4354 if (!entity->textPtr) {
4355 if (enc == encoding)
4356 eventPtr = ptr;
4357 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
4359 else {
4360 enum XML_Error result;
4361 const XML_Char *textEnd = entity->textPtr + entity->textLen;
4362 entity->open = XML_TRUE;
4363 result = appendAttributeValue(parser, internalEncoding, isCdata,
4364 (char *)entity->textPtr,
4365 (char *)textEnd, pool);
4366 entity->open = XML_FALSE;
4367 if (result)
4368 return result;
4371 break;
4372 default:
4373 if (enc == encoding)
4374 eventPtr = ptr;
4375 return XML_ERROR_UNEXPECTED_STATE;
4377 ptr = next;
4379 /* not reached */
4382 static enum XML_Error
4383 storeEntityValue(XML_Parser parser,
4384 const ENCODING *enc,
4385 const char *entityTextPtr,
4386 const char *entityTextEnd)
4388 DTD * const dtd = _dtd; /* save one level of indirection */
4389 STRING_POOL *pool = &(dtd->entityValuePool);
4390 enum XML_Error result = XML_ERROR_NONE;
4391 #ifdef XML_DTD
4392 int oldInEntityValue = prologState.inEntityValue;
4393 prologState.inEntityValue = 1;
4394 #endif /* XML_DTD */
4395 /* never return Null for the value argument in EntityDeclHandler,
4396 since this would indicate an external entity; therefore we
4397 have to make sure that entityValuePool.start is not null */
4398 if (!pool->blocks) {
4399 if (!poolGrow(pool))
4400 return XML_ERROR_NO_MEMORY;
4403 for (;;) {
4404 const char *next;
4405 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
4406 switch (tok) {
4407 case XML_TOK_PARAM_ENTITY_REF:
4408 #ifdef XML_DTD
4409 if (isParamEntity || enc != encoding) {
4410 const XML_Char *name;
4411 ENTITY *entity;
4412 name = poolStoreString(&tempPool, enc,
4413 entityTextPtr + enc->minBytesPerChar,
4414 next - enc->minBytesPerChar);
4415 if (!name) {
4416 result = XML_ERROR_NO_MEMORY;
4417 goto endEntityValue;
4419 entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
4420 poolDiscard(&tempPool);
4421 if (!entity) {
4422 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
4423 /* cannot report skipped entity here - see comments on
4424 skippedEntityHandler
4425 if (skippedEntityHandler)
4426 skippedEntityHandler(handlerArg, name, 0);
4428 dtd->keepProcessing = dtd->standalone;
4429 goto endEntityValue;
4431 if (entity->open) {
4432 if (enc == encoding)
4433 eventPtr = entityTextPtr;
4434 result = XML_ERROR_RECURSIVE_ENTITY_REF;
4435 goto endEntityValue;
4437 if (entity->systemId) {
4438 if (externalEntityRefHandler) {
4439 dtd->paramEntityRead = XML_FALSE;
4440 entity->open = XML_TRUE;
4441 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4443 entity->base,
4444 entity->systemId,
4445 entity->publicId)) {
4446 entity->open = XML_FALSE;
4447 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4448 goto endEntityValue;
4450 entity->open = XML_FALSE;
4451 if (!dtd->paramEntityRead)
4452 dtd->keepProcessing = dtd->standalone;
4454 else
4455 dtd->keepProcessing = dtd->standalone;
4457 else {
4458 entity->open = XML_TRUE;
4459 result = storeEntityValue(parser,
4460 internalEncoding,
4461 (char *)entity->textPtr,
4462 (char *)(entity->textPtr
4463 + entity->textLen));
4464 entity->open = XML_FALSE;
4465 if (result)
4466 goto endEntityValue;
4468 break;
4470 #endif /* XML_DTD */
4471 /* in the internal subset, PE references are not legal
4472 within markup declarations, e.g entity values in this case */
4473 eventPtr = entityTextPtr;
4474 result = XML_ERROR_PARAM_ENTITY_REF;
4475 goto endEntityValue;
4476 case XML_TOK_NONE:
4477 result = XML_ERROR_NONE;
4478 goto endEntityValue;
4479 case XML_TOK_ENTITY_REF:
4480 case XML_TOK_DATA_CHARS:
4481 if (!poolAppend(pool, enc, entityTextPtr, next)) {
4482 result = XML_ERROR_NO_MEMORY;
4483 goto endEntityValue;
4485 break;
4486 case XML_TOK_TRAILING_CR:
4487 next = entityTextPtr + enc->minBytesPerChar;
4488 /* fall through */
4489 case XML_TOK_DATA_NEWLINE:
4490 if (pool->end == pool->ptr && !poolGrow(pool)) {
4491 result = XML_ERROR_NO_MEMORY;
4492 goto endEntityValue;
4494 *(pool->ptr)++ = 0xA;
4495 break;
4496 case XML_TOK_CHAR_REF:
4498 XML_Char buf[XML_ENCODE_MAX];
4499 int i;
4500 int n = XmlCharRefNumber(enc, entityTextPtr);
4501 if (n < 0) {
4502 if (enc == encoding)
4503 eventPtr = entityTextPtr;
4504 result = XML_ERROR_BAD_CHAR_REF;
4505 goto endEntityValue;
4507 n = XmlEncode(n, (ICHAR *)buf);
4508 if (!n) {
4509 if (enc == encoding)
4510 eventPtr = entityTextPtr;
4511 result = XML_ERROR_BAD_CHAR_REF;
4512 goto endEntityValue;
4514 for (i = 0; i < n; i++) {
4515 if (pool->end == pool->ptr && !poolGrow(pool)) {
4516 result = XML_ERROR_NO_MEMORY;
4517 goto endEntityValue;
4519 *(pool->ptr)++ = buf[i];
4522 break;
4523 case XML_TOK_PARTIAL:
4524 if (enc == encoding)
4525 eventPtr = entityTextPtr;
4526 result = XML_ERROR_INVALID_TOKEN;
4527 goto endEntityValue;
4528 case XML_TOK_INVALID:
4529 if (enc == encoding)
4530 eventPtr = next;
4531 result = XML_ERROR_INVALID_TOKEN;
4532 goto endEntityValue;
4533 default:
4534 if (enc == encoding)
4535 eventPtr = entityTextPtr;
4536 result = XML_ERROR_UNEXPECTED_STATE;
4537 goto endEntityValue;
4539 entityTextPtr = next;
4541 endEntityValue:
4542 #ifdef XML_DTD
4543 prologState.inEntityValue = oldInEntityValue;
4544 #endif /* XML_DTD */
4545 return result;
4548 static void FASTCALL
4549 normalizeLines(XML_Char *s)
4551 XML_Char *p;
4552 for (;; s++) {
4553 if (*s == XML_T('\0'))
4554 return;
4555 if (*s == 0xD)
4556 break;
4558 p = s;
4559 do {
4560 if (*s == 0xD) {
4561 *p++ = 0xA;
4562 if (*++s == 0xA)
4563 s++;
4565 else
4566 *p++ = *s++;
4567 } while (*s);
4568 *p = XML_T('\0');
4571 static int
4572 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
4573 const char *start, const char *end)
4575 const XML_Char *target;
4576 XML_Char *data;
4577 const char *tem;
4578 if (!processingInstructionHandler) {
4579 if (defaultHandler)
4580 reportDefault(parser, enc, start, end);
4581 return 1;
4583 start += enc->minBytesPerChar * 2;
4584 tem = start + XmlNameLength(enc, start);
4585 target = poolStoreString(&tempPool, enc, start, tem);
4586 if (!target)
4587 return 0;
4588 poolFinish(&tempPool);
4589 data = poolStoreString(&tempPool, enc,
4590 XmlSkipS(enc, tem),
4591 end - enc->minBytesPerChar*2);
4592 if (!data)
4593 return 0;
4594 normalizeLines(data);
4595 processingInstructionHandler(handlerArg, target, data);
4596 poolClear(&tempPool);
4597 return 1;
4600 static int
4601 reportComment(XML_Parser parser, const ENCODING *enc,
4602 const char *start, const char *end)
4604 XML_Char *data;
4605 if (!commentHandler) {
4606 if (defaultHandler)
4607 reportDefault(parser, enc, start, end);
4608 return 1;
4610 data = poolStoreString(&tempPool,
4611 enc,
4612 start + enc->minBytesPerChar * 4,
4613 end - enc->minBytesPerChar * 3);
4614 if (!data)
4615 return 0;
4616 normalizeLines(data);
4617 commentHandler(handlerArg, data);
4618 poolClear(&tempPool);
4619 return 1;
4622 static void
4623 reportDefault(XML_Parser parser, const ENCODING *enc,
4624 const char *s, const char *end)
4626 if (MUST_CONVERT(enc, s)) {
4627 const char **eventPP;
4628 const char **eventEndPP;
4629 if (enc == encoding) {
4630 eventPP = &eventPtr;
4631 eventEndPP = &eventEndPtr;
4633 else {
4634 eventPP = &(openInternalEntities->internalEventPtr);
4635 eventEndPP = &(openInternalEntities->internalEventEndPtr);
4637 do {
4638 ICHAR *dataPtr = (ICHAR *)dataBuf;
4639 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
4640 *eventEndPP = s;
4641 defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
4642 *eventPP = s;
4643 } while (s != end);
4645 else
4646 defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
4650 static int
4651 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
4652 XML_Bool isId, const XML_Char *value, XML_Parser parser)
4654 DEFAULT_ATTRIBUTE *att;
4655 if (value || isId) {
4656 /* The handling of default attributes gets messed up if we have
4657 a default which duplicates a non-default. */
4658 int i;
4659 for (i = 0; i < type->nDefaultAtts; i++)
4660 if (attId == type->defaultAtts[i].id)
4661 return 1;
4662 if (isId && !type->idAtt && !attId->xmlns)
4663 type->idAtt = attId;
4665 if (type->nDefaultAtts == type->allocDefaultAtts) {
4666 if (type->allocDefaultAtts == 0) {
4667 type->allocDefaultAtts = 8;
4668 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
4669 * sizeof(DEFAULT_ATTRIBUTE));
4670 if (!type->defaultAtts)
4671 return 0;
4673 else {
4674 DEFAULT_ATTRIBUTE *temp;
4675 int count = type->allocDefaultAtts * 2;
4676 temp = (DEFAULT_ATTRIBUTE *)
4677 REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
4678 if (temp == NULL)
4679 return 0;
4680 type->allocDefaultAtts = count;
4681 type->defaultAtts = temp;
4684 att = type->defaultAtts + type->nDefaultAtts;
4685 att->id = attId;
4686 att->value = value;
4687 att->isCdata = isCdata;
4688 if (!isCdata)
4689 attId->maybeTokenized = XML_TRUE;
4690 type->nDefaultAtts += 1;
4691 return 1;
4694 static int
4695 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
4697 DTD * const dtd = _dtd; /* save one level of indirection */
4698 const XML_Char *name;
4699 for (name = elementType->name; *name; name++) {
4700 if (*name == XML_T(':')) {
4701 PREFIX *prefix;
4702 const XML_Char *s;
4703 for (s = elementType->name; s != name; s++) {
4704 if (!poolAppendChar(&dtd->pool, *s))
4705 return 0;
4707 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
4708 return 0;
4709 prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
4710 sizeof(PREFIX));
4711 if (!prefix)
4712 return 0;
4713 if (prefix->name == poolStart(&dtd->pool))
4714 poolFinish(&dtd->pool);
4715 else
4716 poolDiscard(&dtd->pool);
4717 elementType->prefix = prefix;
4721 return 1;
4724 static ATTRIBUTE_ID *
4725 getAttributeId(XML_Parser parser, const ENCODING *enc,
4726 const char *start, const char *end)
4728 DTD * const dtd = _dtd; /* save one level of indirection */
4729 ATTRIBUTE_ID *id;
4730 const XML_Char *name;
4731 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
4732 return NULL;
4733 name = poolStoreString(&dtd->pool, enc, start, end);
4734 if (!name)
4735 return NULL;
4736 ++name;
4737 id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
4738 if (!id)
4739 return NULL;
4740 if (id->name != name)
4741 poolDiscard(&dtd->pool);
4742 else {
4743 poolFinish(&dtd->pool);
4744 if (!ns)
4746 else if (name[0] == XML_T('x')
4747 && name[1] == XML_T('m')
4748 && name[2] == XML_T('l')
4749 && name[3] == XML_T('n')
4750 && name[4] == XML_T('s')
4751 && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
4752 if (name[5] == XML_T('\0'))
4753 id->prefix = &dtd->defaultPrefix;
4754 else
4755 id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
4756 id->xmlns = XML_TRUE;
4758 else {
4759 int i;
4760 for (i = 0; name[i]; i++) {
4761 if (name[i] == XML_T(':')) {
4762 int j;
4763 for (j = 0; j < i; j++) {
4764 if (!poolAppendChar(&dtd->pool, name[j]))
4765 return NULL;
4767 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
4768 return NULL;
4769 id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
4770 sizeof(PREFIX));
4771 if (id->prefix->name == poolStart(&dtd->pool))
4772 poolFinish(&dtd->pool);
4773 else
4774 poolDiscard(&dtd->pool);
4775 break;
4780 return id;
4783 #define CONTEXT_SEP XML_T('\f')
4785 static const XML_Char *
4786 getContext(XML_Parser parser)
4788 DTD * const dtd = _dtd; /* save one level of indirection */
4789 HASH_TABLE_ITER iter;
4790 XML_Bool needSep = XML_FALSE;
4792 if (dtd->defaultPrefix.binding) {
4793 int i;
4794 int len;
4795 if (!poolAppendChar(&tempPool, XML_T('=')))
4796 return NULL;
4797 len = dtd->defaultPrefix.binding->uriLen;
4798 if (namespaceSeparator != XML_T('\0'))
4799 len--;
4800 for (i = 0; i < len; i++)
4801 if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
4802 return NULL;
4803 needSep = XML_TRUE;
4806 hashTableIterInit(&iter, &(dtd->prefixes));
4807 for (;;) {
4808 int i;
4809 int len;
4810 const XML_Char *s;
4811 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
4812 if (!prefix)
4813 break;
4814 if (!prefix->binding)
4815 continue;
4816 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
4817 return NULL;
4818 for (s = prefix->name; *s; s++)
4819 if (!poolAppendChar(&tempPool, *s))
4820 return NULL;
4821 if (!poolAppendChar(&tempPool, XML_T('=')))
4822 return NULL;
4823 len = prefix->binding->uriLen;
4824 if (namespaceSeparator != XML_T('\0'))
4825 len--;
4826 for (i = 0; i < len; i++)
4827 if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
4828 return NULL;
4829 needSep = XML_TRUE;
4833 hashTableIterInit(&iter, &(dtd->generalEntities));
4834 for (;;) {
4835 const XML_Char *s;
4836 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
4837 if (!e)
4838 break;
4839 if (!e->open)
4840 continue;
4841 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
4842 return NULL;
4843 for (s = e->name; *s; s++)
4844 if (!poolAppendChar(&tempPool, *s))
4845 return 0;
4846 needSep = XML_TRUE;
4849 if (!poolAppendChar(&tempPool, XML_T('\0')))
4850 return NULL;
4851 return tempPool.start;
4854 static XML_Bool
4855 setContext(XML_Parser parser, const XML_Char *context)
4857 DTD * const dtd = _dtd; /* save one level of indirection */
4858 const XML_Char *s = context;
4860 while (*context != XML_T('\0')) {
4861 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
4862 ENTITY *e;
4863 if (!poolAppendChar(&tempPool, XML_T('\0')))
4864 return XML_FALSE;
4865 e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
4866 if (e)
4867 e->open = XML_TRUE;
4868 if (*s != XML_T('\0'))
4869 s++;
4870 context = s;
4871 poolDiscard(&tempPool);
4873 else if (*s == XML_T('=')) {
4874 PREFIX *prefix;
4875 if (poolLength(&tempPool) == 0)
4876 prefix = &dtd->defaultPrefix;
4877 else {
4878 if (!poolAppendChar(&tempPool, XML_T('\0')))
4879 return XML_FALSE;
4880 prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
4881 sizeof(PREFIX));
4882 if (!prefix)
4883 return XML_FALSE;
4884 if (prefix->name == poolStart(&tempPool)) {
4885 prefix->name = poolCopyString(&dtd->pool, prefix->name);
4886 if (!prefix->name)
4887 return XML_FALSE;
4889 poolDiscard(&tempPool);
4891 for (context = s + 1;
4892 *context != CONTEXT_SEP && *context != XML_T('\0');
4893 context++)
4894 if (!poolAppendChar(&tempPool, *context))
4895 return XML_FALSE;
4896 if (!poolAppendChar(&tempPool, XML_T('\0')))
4897 return XML_FALSE;
4898 if (addBinding(parser, prefix, 0, poolStart(&tempPool),
4899 &inheritedBindings) != XML_ERROR_NONE)
4900 return XML_FALSE;
4901 poolDiscard(&tempPool);
4902 if (*context != XML_T('\0'))
4903 ++context;
4904 s = context;
4906 else {
4907 if (!poolAppendChar(&tempPool, *s))
4908 return XML_FALSE;
4909 s++;
4912 return XML_TRUE;
4915 static void FASTCALL
4916 normalizePublicId(XML_Char *publicId)
4918 XML_Char *p = publicId;
4919 XML_Char *s;
4920 for (s = publicId; *s; s++) {
4921 switch (*s) {
4922 case 0x20:
4923 case 0xD:
4924 case 0xA:
4925 if (p != publicId && p[-1] != 0x20)
4926 *p++ = 0x20;
4927 break;
4928 default:
4929 *p++ = *s;
4932 if (p != publicId && p[-1] == 0x20)
4933 --p;
4934 *p = XML_T('\0');
4937 static DTD *
4938 dtdCreate(const XML_Memory_Handling_Suite *ms)
4940 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
4941 if (p == NULL)
4942 return p;
4943 poolInit(&(p->pool), ms);
4944 #ifdef XML_DTD
4945 poolInit(&(p->entityValuePool), ms);
4946 #endif /* XML_DTD */
4947 hashTableInit(&(p->generalEntities), ms);
4948 hashTableInit(&(p->elementTypes), ms);
4949 hashTableInit(&(p->attributeIds), ms);
4950 hashTableInit(&(p->prefixes), ms);
4951 #ifdef XML_DTD
4952 p->paramEntityRead = XML_FALSE;
4953 hashTableInit(&(p->paramEntities), ms);
4954 #endif /* XML_DTD */
4955 p->defaultPrefix.name = NULL;
4956 p->defaultPrefix.binding = NULL;
4958 p->in_eldecl = XML_FALSE;
4959 p->scaffIndex = NULL;
4960 p->scaffold = NULL;
4961 p->scaffLevel = 0;
4962 p->scaffSize = 0;
4963 p->scaffCount = 0;
4964 p->contentStringLen = 0;
4966 p->keepProcessing = XML_TRUE;
4967 p->hasParamEntityRefs = XML_FALSE;
4968 p->standalone = XML_FALSE;
4969 return p;
4972 static void
4973 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
4975 HASH_TABLE_ITER iter;
4976 hashTableIterInit(&iter, &(p->elementTypes));
4977 for (;;) {
4978 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
4979 if (!e)
4980 break;
4981 if (e->allocDefaultAtts != 0)
4982 ms->free_fcn(e->defaultAtts);
4984 hashTableClear(&(p->generalEntities));
4985 #ifdef XML_DTD
4986 p->paramEntityRead = XML_FALSE;
4987 hashTableClear(&(p->paramEntities));
4988 #endif /* XML_DTD */
4989 hashTableClear(&(p->elementTypes));
4990 hashTableClear(&(p->attributeIds));
4991 hashTableClear(&(p->prefixes));
4992 poolClear(&(p->pool));
4993 #ifdef XML_DTD
4994 poolClear(&(p->entityValuePool));
4995 #endif /* XML_DTD */
4996 p->defaultPrefix.name = NULL;
4997 p->defaultPrefix.binding = NULL;
4999 p->in_eldecl = XML_FALSE;
5000 if (p->scaffIndex) {
5001 ms->free_fcn(p->scaffIndex);
5002 p->scaffIndex = NULL;
5004 if (p->scaffold) {
5005 ms->free_fcn(p->scaffold);
5006 p->scaffold = NULL;
5008 p->scaffLevel = 0;
5009 p->scaffSize = 0;
5010 p->scaffCount = 0;
5011 p->contentStringLen = 0;
5013 p->keepProcessing = XML_TRUE;
5014 p->hasParamEntityRefs = XML_FALSE;
5015 p->standalone = XML_FALSE;
5018 static void
5019 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
5021 HASH_TABLE_ITER iter;
5022 hashTableIterInit(&iter, &(p->elementTypes));
5023 for (;;) {
5024 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5025 if (!e)
5026 break;
5027 if (e->allocDefaultAtts != 0)
5028 ms->free_fcn(e->defaultAtts);
5030 hashTableDestroy(&(p->generalEntities));
5031 #ifdef XML_DTD
5032 hashTableDestroy(&(p->paramEntities));
5033 #endif /* XML_DTD */
5034 hashTableDestroy(&(p->elementTypes));
5035 hashTableDestroy(&(p->attributeIds));
5036 hashTableDestroy(&(p->prefixes));
5037 poolDestroy(&(p->pool));
5038 #ifdef XML_DTD
5039 poolDestroy(&(p->entityValuePool));
5040 #endif /* XML_DTD */
5041 if (isDocEntity) {
5042 if (p->scaffIndex)
5043 ms->free_fcn(p->scaffIndex);
5044 if (p->scaffold)
5045 ms->free_fcn(p->scaffold);
5047 ms->free_fcn(p);
5050 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
5051 The new DTD has already been initialized.
5053 static int
5054 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
5056 HASH_TABLE_ITER iter;
5058 /* Copy the prefix table. */
5060 hashTableIterInit(&iter, &(oldDtd->prefixes));
5061 for (;;) {
5062 const XML_Char *name;
5063 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
5064 if (!oldP)
5065 break;
5066 name = poolCopyString(&(newDtd->pool), oldP->name);
5067 if (!name)
5068 return 0;
5069 if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
5070 return 0;
5073 hashTableIterInit(&iter, &(oldDtd->attributeIds));
5075 /* Copy the attribute id table. */
5077 for (;;) {
5078 ATTRIBUTE_ID *newA;
5079 const XML_Char *name;
5080 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
5082 if (!oldA)
5083 break;
5084 /* Remember to allocate the scratch byte before the name. */
5085 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
5086 return 0;
5087 name = poolCopyString(&(newDtd->pool), oldA->name);
5088 if (!name)
5089 return 0;
5090 ++name;
5091 newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
5092 sizeof(ATTRIBUTE_ID));
5093 if (!newA)
5094 return 0;
5095 newA->maybeTokenized = oldA->maybeTokenized;
5096 if (oldA->prefix) {
5097 newA->xmlns = oldA->xmlns;
5098 if (oldA->prefix == &oldDtd->defaultPrefix)
5099 newA->prefix = &newDtd->defaultPrefix;
5100 else
5101 newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
5102 oldA->prefix->name, 0);
5106 /* Copy the element type table. */
5108 hashTableIterInit(&iter, &(oldDtd->elementTypes));
5110 for (;;) {
5111 int i;
5112 ELEMENT_TYPE *newE;
5113 const XML_Char *name;
5114 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
5115 if (!oldE)
5116 break;
5117 name = poolCopyString(&(newDtd->pool), oldE->name);
5118 if (!name)
5119 return 0;
5120 newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
5121 sizeof(ELEMENT_TYPE));
5122 if (!newE)
5123 return 0;
5124 if (oldE->nDefaultAtts) {
5125 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
5126 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
5127 if (!newE->defaultAtts) {
5128 ms->free_fcn(newE);
5129 return 0;
5132 if (oldE->idAtt)
5133 newE->idAtt = (ATTRIBUTE_ID *)
5134 lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
5135 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
5136 if (oldE->prefix)
5137 newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
5138 oldE->prefix->name, 0);
5139 for (i = 0; i < newE->nDefaultAtts; i++) {
5140 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
5141 lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
5142 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
5143 if (oldE->defaultAtts[i].value) {
5144 newE->defaultAtts[i].value
5145 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
5146 if (!newE->defaultAtts[i].value)
5147 return 0;
5149 else
5150 newE->defaultAtts[i].value = NULL;
5154 /* Copy the entity tables. */
5155 if (!copyEntityTable(&(newDtd->generalEntities),
5156 &(newDtd->pool),
5157 &(oldDtd->generalEntities)))
5158 return 0;
5160 #ifdef XML_DTD
5161 if (!copyEntityTable(&(newDtd->paramEntities),
5162 &(newDtd->pool),
5163 &(oldDtd->paramEntities)))
5164 return 0;
5165 newDtd->paramEntityRead = oldDtd->paramEntityRead;
5166 #endif /* XML_DTD */
5168 newDtd->keepProcessing = oldDtd->keepProcessing;
5169 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
5170 newDtd->standalone = oldDtd->standalone;
5172 /* Don't want deep copying for scaffolding */
5173 newDtd->in_eldecl = oldDtd->in_eldecl;
5174 newDtd->scaffold = oldDtd->scaffold;
5175 newDtd->contentStringLen = oldDtd->contentStringLen;
5176 newDtd->scaffSize = oldDtd->scaffSize;
5177 newDtd->scaffLevel = oldDtd->scaffLevel;
5178 newDtd->scaffIndex = oldDtd->scaffIndex;
5180 return 1;
5181 } /* End dtdCopy */
5183 static int
5184 copyEntityTable(HASH_TABLE *newTable,
5185 STRING_POOL *newPool,
5186 const HASH_TABLE *oldTable)
5188 HASH_TABLE_ITER iter;
5189 const XML_Char *cachedOldBase = NULL;
5190 const XML_Char *cachedNewBase = NULL;
5192 hashTableIterInit(&iter, oldTable);
5194 for (;;) {
5195 ENTITY *newE;
5196 const XML_Char *name;
5197 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
5198 if (!oldE)
5199 break;
5200 name = poolCopyString(newPool, oldE->name);
5201 if (!name)
5202 return 0;
5203 newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
5204 if (!newE)
5205 return 0;
5206 if (oldE->systemId) {
5207 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
5208 if (!tem)
5209 return 0;
5210 newE->systemId = tem;
5211 if (oldE->base) {
5212 if (oldE->base == cachedOldBase)
5213 newE->base = cachedNewBase;
5214 else {
5215 cachedOldBase = oldE->base;
5216 tem = poolCopyString(newPool, cachedOldBase);
5217 if (!tem)
5218 return 0;
5219 cachedNewBase = newE->base = tem;
5222 if (oldE->publicId) {
5223 tem = poolCopyString(newPool, oldE->publicId);
5224 if (!tem)
5225 return 0;
5226 newE->publicId = tem;
5229 else {
5230 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
5231 oldE->textLen);
5232 if (!tem)
5233 return 0;
5234 newE->textPtr = tem;
5235 newE->textLen = oldE->textLen;
5237 if (oldE->notation) {
5238 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
5239 if (!tem)
5240 return 0;
5241 newE->notation = tem;
5243 newE->is_param = oldE->is_param;
5244 newE->is_internal = oldE->is_internal;
5246 return 1;
5249 #define INIT_SIZE 64
5251 static int FASTCALL
5252 keyeq(KEY s1, KEY s2)
5254 for (; *s1 == *s2; s1++, s2++)
5255 if (*s1 == 0)
5256 return 1;
5257 return 0;
5260 static unsigned long FASTCALL
5261 hash(KEY s)
5263 unsigned long h = 0;
5264 while (*s)
5265 h = (h << 5) + h + (unsigned char)*s++;
5266 return h;
5269 static NAMED *
5270 lookup(HASH_TABLE *table, KEY name, size_t createSize)
5272 size_t i;
5273 if (table->size == 0) {
5274 size_t tsize;
5276 if (!createSize)
5277 return NULL;
5278 tsize = INIT_SIZE * sizeof(NAMED *);
5279 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
5280 if (!table->v)
5281 return NULL;
5282 memset(table->v, 0, tsize);
5283 table->size = INIT_SIZE;
5284 table->usedLim = INIT_SIZE / 2;
5285 i = hash(name) & (table->size - 1);
5287 else {
5288 unsigned long h = hash(name);
5289 for (i = h & (table->size - 1);
5290 table->v[i];
5291 i == 0 ? i = table->size - 1 : --i) {
5292 if (keyeq(name, table->v[i]->name))
5293 return table->v[i];
5295 if (!createSize)
5296 return NULL;
5297 if (table->used == table->usedLim) {
5298 /* check for overflow */
5299 size_t newSize = table->size * 2;
5300 size_t tsize = newSize * sizeof(NAMED *);
5301 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
5302 if (!newV)
5303 return NULL;
5304 memset(newV, 0, tsize);
5305 for (i = 0; i < table->size; i++)
5306 if (table->v[i]) {
5307 size_t j;
5308 for (j = hash(table->v[i]->name) & (newSize - 1);
5309 newV[j];
5310 j == 0 ? j = newSize - 1 : --j)
5312 newV[j] = table->v[i];
5314 table->mem->free_fcn(table->v);
5315 table->v = newV;
5316 table->size = newSize;
5317 table->usedLim = newSize/2;
5318 for (i = h & (table->size - 1);
5319 table->v[i];
5320 i == 0 ? i = table->size - 1 : --i)
5324 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
5325 if (!table->v[i])
5326 return NULL;
5327 memset(table->v[i], 0, createSize);
5328 table->v[i]->name = name;
5329 (table->used)++;
5330 return table->v[i];
5333 static void FASTCALL
5334 hashTableClear(HASH_TABLE *table)
5336 size_t i;
5337 for (i = 0; i < table->size; i++) {
5338 NAMED *p = table->v[i];
5339 if (p) {
5340 table->mem->free_fcn(p);
5341 table->v[i] = NULL;
5344 table->usedLim = table->size / 2;
5345 table->used = 0;
5348 static void FASTCALL
5349 hashTableDestroy(HASH_TABLE *table)
5351 size_t i;
5352 for (i = 0; i < table->size; i++) {
5353 NAMED *p = table->v[i];
5354 if (p)
5355 table->mem->free_fcn(p);
5357 if (table->v)
5358 table->mem->free_fcn(table->v);
5361 static void FASTCALL
5362 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
5364 p->size = 0;
5365 p->usedLim = 0;
5366 p->used = 0;
5367 p->v = NULL;
5368 p->mem = ms;
5371 static void FASTCALL
5372 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
5374 iter->p = table->v;
5375 iter->end = iter->p + table->size;
5378 static NAMED * FASTCALL
5379 hashTableIterNext(HASH_TABLE_ITER *iter)
5381 while (iter->p != iter->end) {
5382 NAMED *tem = *(iter->p)++;
5383 if (tem)
5384 return tem;
5386 return NULL;
5389 static void FASTCALL
5390 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
5392 pool->blocks = NULL;
5393 pool->freeBlocks = NULL;
5394 pool->start = NULL;
5395 pool->ptr = NULL;
5396 pool->end = NULL;
5397 pool->mem = ms;
5400 static void FASTCALL
5401 poolClear(STRING_POOL *pool)
5403 if (!pool->freeBlocks)
5404 pool->freeBlocks = pool->blocks;
5405 else {
5406 BLOCK *p = pool->blocks;
5407 while (p) {
5408 BLOCK *tem = p->next;
5409 p->next = pool->freeBlocks;
5410 pool->freeBlocks = p;
5411 p = tem;
5414 pool->blocks = NULL;
5415 pool->start = NULL;
5416 pool->ptr = NULL;
5417 pool->end = NULL;
5420 static void FASTCALL
5421 poolDestroy(STRING_POOL *pool)
5423 BLOCK *p = pool->blocks;
5424 while (p) {
5425 BLOCK *tem = p->next;
5426 pool->mem->free_fcn(p);
5427 p = tem;
5429 p = pool->freeBlocks;
5430 while (p) {
5431 BLOCK *tem = p->next;
5432 pool->mem->free_fcn(p);
5433 p = tem;
5437 static XML_Char *
5438 poolAppend(STRING_POOL *pool, const ENCODING *enc,
5439 const char *ptr, const char *end)
5441 if (!pool->ptr && !poolGrow(pool))
5442 return NULL;
5443 for (;;) {
5444 XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
5445 if (ptr == end)
5446 break;
5447 if (!poolGrow(pool))
5448 return NULL;
5450 return pool->start;
5453 static const XML_Char * FASTCALL
5454 poolCopyString(STRING_POOL *pool, const XML_Char *s)
5456 do {
5457 if (!poolAppendChar(pool, *s))
5458 return NULL;
5459 } while (*s++);
5460 s = pool->start;
5461 poolFinish(pool);
5462 return s;
5465 static const XML_Char *
5466 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
5468 if (!pool->ptr && !poolGrow(pool))
5469 return NULL;
5470 for (; n > 0; --n, s++) {
5471 if (!poolAppendChar(pool, *s))
5472 return NULL;
5474 s = pool->start;
5475 poolFinish(pool);
5476 return s;
5479 static const XML_Char * FASTCALL
5480 poolAppendString(STRING_POOL *pool, const XML_Char *s)
5482 while (*s) {
5483 if (!poolAppendChar(pool, *s))
5484 return NULL;
5485 s++;
5487 return pool->start;
5490 static XML_Char *
5491 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
5492 const char *ptr, const char *end)
5494 if (!poolAppend(pool, enc, ptr, end))
5495 return NULL;
5496 if (pool->ptr == pool->end && !poolGrow(pool))
5497 return NULL;
5498 *(pool->ptr)++ = 0;
5499 return pool->start;
5502 static XML_Bool FASTCALL
5503 poolGrow(STRING_POOL *pool)
5505 if (pool->freeBlocks) {
5506 if (pool->start == 0) {
5507 pool->blocks = pool->freeBlocks;
5508 pool->freeBlocks = pool->freeBlocks->next;
5509 pool->blocks->next = NULL;
5510 pool->start = pool->blocks->s;
5511 pool->end = pool->start + pool->blocks->size;
5512 pool->ptr = pool->start;
5513 return XML_TRUE;
5515 if (pool->end - pool->start < pool->freeBlocks->size) {
5516 BLOCK *tem = pool->freeBlocks->next;
5517 pool->freeBlocks->next = pool->blocks;
5518 pool->blocks = pool->freeBlocks;
5519 pool->freeBlocks = tem;
5520 memcpy(pool->blocks->s, pool->start,
5521 (pool->end - pool->start) * sizeof(XML_Char));
5522 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
5523 pool->start = pool->blocks->s;
5524 pool->end = pool->start + pool->blocks->size;
5525 return XML_TRUE;
5528 if (pool->blocks && pool->start == pool->blocks->s) {
5529 int blockSize = (pool->end - pool->start)*2;
5530 pool->blocks = (BLOCK *)
5531 pool->mem->realloc_fcn(pool->blocks,
5532 (offsetof(BLOCK, s)
5533 + blockSize * sizeof(XML_Char)));
5534 if (pool->blocks == NULL)
5535 return XML_FALSE;
5536 pool->blocks->size = blockSize;
5537 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
5538 pool->start = pool->blocks->s;
5539 pool->end = pool->start + blockSize;
5541 else {
5542 BLOCK *tem;
5543 int blockSize = pool->end - pool->start;
5544 if (blockSize < INIT_BLOCK_SIZE)
5545 blockSize = INIT_BLOCK_SIZE;
5546 else
5547 blockSize *= 2;
5548 tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
5549 + blockSize * sizeof(XML_Char));
5550 if (!tem)
5551 return XML_FALSE;
5552 tem->size = blockSize;
5553 tem->next = pool->blocks;
5554 pool->blocks = tem;
5555 if (pool->ptr != pool->start)
5556 memcpy(tem->s, pool->start,
5557 (pool->ptr - pool->start) * sizeof(XML_Char));
5558 pool->ptr = tem->s + (pool->ptr - pool->start);
5559 pool->start = tem->s;
5560 pool->end = tem->s + blockSize;
5562 return XML_TRUE;
5565 static int FASTCALL
5566 nextScaffoldPart(XML_Parser parser)
5568 DTD * const dtd = _dtd; /* save one level of indirection */
5569 CONTENT_SCAFFOLD * me;
5570 int next;
5572 if (!dtd->scaffIndex) {
5573 dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
5574 if (!dtd->scaffIndex)
5575 return -1;
5576 dtd->scaffIndex[0] = 0;
5579 if (dtd->scaffCount >= dtd->scaffSize) {
5580 CONTENT_SCAFFOLD *temp;
5581 if (dtd->scaffold) {
5582 temp = (CONTENT_SCAFFOLD *)
5583 REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
5584 if (temp == NULL)
5585 return -1;
5586 dtd->scaffSize *= 2;
5588 else {
5589 temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
5590 * sizeof(CONTENT_SCAFFOLD));
5591 if (temp == NULL)
5592 return -1;
5593 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
5595 dtd->scaffold = temp;
5597 next = dtd->scaffCount++;
5598 me = &dtd->scaffold[next];
5599 if (dtd->scaffLevel) {
5600 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
5601 if (parent->lastchild) {
5602 dtd->scaffold[parent->lastchild].nextsib = next;
5604 if (!parent->childcnt)
5605 parent->firstchild = next;
5606 parent->lastchild = next;
5607 parent->childcnt++;
5609 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
5610 return next;
5613 static void
5614 build_node(XML_Parser parser,
5615 int src_node,
5616 XML_Content *dest,
5617 XML_Content **contpos,
5618 XML_Char **strpos)
5620 DTD * const dtd = _dtd; /* save one level of indirection */
5621 dest->type = dtd->scaffold[src_node].type;
5622 dest->quant = dtd->scaffold[src_node].quant;
5623 if (dest->type == XML_CTYPE_NAME) {
5624 const XML_Char *src;
5625 dest->name = *strpos;
5626 src = dtd->scaffold[src_node].name;
5627 for (;;) {
5628 *(*strpos)++ = *src;
5629 if (!*src)
5630 break;
5631 src++;
5633 dest->numchildren = 0;
5634 dest->children = NULL;
5636 else {
5637 unsigned int i;
5638 int cn;
5639 dest->numchildren = dtd->scaffold[src_node].childcnt;
5640 dest->children = *contpos;
5641 *contpos += dest->numchildren;
5642 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
5643 i < dest->numchildren;
5644 i++, cn = dtd->scaffold[cn].nextsib) {
5645 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
5647 dest->name = NULL;
5651 static XML_Content *
5652 build_model (XML_Parser parser)
5654 DTD * const dtd = _dtd; /* save one level of indirection */
5655 XML_Content *ret;
5656 XML_Content *cpos;
5657 XML_Char * str;
5658 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
5659 + (dtd->contentStringLen * sizeof(XML_Char)));
5661 ret = (XML_Content *)MALLOC(allocsize);
5662 if (!ret)
5663 return NULL;
5665 str = (XML_Char *) (&ret[dtd->scaffCount]);
5666 cpos = &ret[1];
5668 build_node(parser, 0, ret, &cpos, &str);
5669 return ret;
5672 static ELEMENT_TYPE *
5673 getElementType(XML_Parser parser,
5674 const ENCODING *enc,
5675 const char *ptr,
5676 const char *end)
5678 DTD * const dtd = _dtd; /* save one level of indirection */
5679 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
5680 ELEMENT_TYPE *ret;
5682 if (!name)
5683 return NULL;
5684 ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
5685 if (!ret)
5686 return NULL;
5687 if (ret->name != name)
5688 poolDiscard(&dtd->pool);
5689 else {
5690 poolFinish(&dtd->pool);
5691 if (!setElementTypePrefix(parser, ret))
5692 return NULL;
5694 return ret;