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