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

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