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