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