source: trunk/src/helpers/xmlparse.c@ 142

Last change on this file since 142 was 142, checked in by umoeller, 24 years ago

misc. updates

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