source: branches/branch-1-0/src/helpers/xmlparse.c@ 302

Last change on this file since 302 was 222, checked in by umoeller, 23 years ago

Minor adjustments for new static handling.

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