initial load of upstream version 1.06.32
[xmlrpc-c] / lib / expat / xmlparse / xmlparse.c
1 /*
2 Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
3 See the file copying.txt for copying permission.
4 */
5
6 /* In 2001, this was part of the Expat package.  We copied it into
7    Xmlrpc-c because it's easier on the user than making him get and
8    link Expat separately, and we don't expect to benefit from separate
9    maintenance of Expat.
10
11    But we changed all the external symbols that in Expat are named
12    "XML_xxxx" to "xmlrpc_XML_xxxx" because people do link Xmlrpc-c
13    libraries into programs that also link Expat (a good example is
14    where an Apache module uses Xmlrpc-c).  We don't want our names to
15    collide with Expat's.
16 */
17
18 #include <stddef.h>
19
20 #include "xmlrpc_config.h"
21 #include "c_util.h"
22 #include "xmldef.h"
23 #include "xmlparse.h"
24
25 #ifdef XML_UNICODE
26 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
27 #define XmlConvert XmlUtf16Convert
28 #define XmlGetInternalEncoding xmlrpc_XmlGetUtf16InternalEncoding
29 #define XmlGetInternalEncodingNS xmlrpc_XmlGetUtf16InternalEncodingNS
30 #define XmlEncode xmlrpc_XmlUtf16Encode
31 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
32 typedef unsigned short ICHAR;
33 #else
34 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
35 #define XmlConvert XmlUtf8Convert
36 #define XmlGetInternalEncoding xmlrpc_XmlGetUtf8InternalEncoding
37 #define XmlGetInternalEncodingNS xmlrpc_XmlGetUtf8InternalEncodingNS
38 #define XmlEncode xmlrpc_XmlUtf8Encode
39 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
40 typedef char ICHAR;
41 #endif
42
43
44 #ifndef XML_NS
45
46 #define XmlInitEncodingNS xmlrpc_XmlInitEncoding
47 #define XmlInitUnknownEncodingNS xmlrpc_XmlInitUnknownEncoding
48 #undef XmlGetInternalEncodingNS
49 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
50 #define XmlParseXmlDeclNS xmlrpc_XmlParseXmlDecl
51
52 #endif
53
54 #ifdef XML_UNICODE_WCHAR_T
55 #define XML_T(x) L ## x
56 #else
57 #define XML_T(x) x
58 #endif
59
60 /* Round up n to be a multiple of sz, where sz is a power of 2. */
61 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
62
63 #include "xmltok.h"
64 #include "xmlrole.h"
65
66 typedef const XML_Char *KEY;
67
68 typedef struct {
69   KEY name;
70 } NAMED;
71
72 typedef struct {
73   NAMED **v;
74   size_t size;
75   size_t used;
76   size_t usedLim;
77 } HASH_TABLE;
78
79 typedef struct {
80   NAMED **p;
81   NAMED **end;
82 } HASH_TABLE_ITER;
83
84 #define INIT_TAG_BUF_SIZE 32  /* must be a multiple of sizeof(XML_Char) */
85 #define INIT_DATA_BUF_SIZE 1024
86 #define INIT_ATTS_SIZE 16
87 #define INIT_BLOCK_SIZE 1024
88 #define INIT_BUFFER_SIZE 1024
89
90 #define EXPAND_SPARE 24
91
92 typedef struct binding {
93   struct prefix *prefix;
94   struct binding *nextTagBinding;
95   struct binding *prevPrefixBinding;
96   const struct attribute_id *attId;
97   XML_Char *uri;
98   int uriLen;
99   int uriAlloc;
100 } BINDING;
101
102 typedef struct prefix {
103   const XML_Char *name;
104   BINDING *binding;
105 } PREFIX;
106
107 typedef struct {
108   const XML_Char *str;
109   const XML_Char *localPart;
110   int uriLen;
111 } TAG_NAME;
112
113 typedef struct tag {
114   struct tag *parent;
115   const char *rawName;
116   int rawNameLength;
117   TAG_NAME name;
118   char *buf;
119   char *bufEnd;
120   BINDING *bindings;
121 } TAG;
122
123 typedef struct {
124   const XML_Char *name;
125   const XML_Char *textPtr;
126   int textLen;
127   const XML_Char *systemId;
128   const XML_Char *base;
129   const XML_Char *publicId;
130   const XML_Char *notation;
131   char open;
132 } ENTITY;
133
134 typedef struct block {
135   struct block *next;
136   int size;
137   XML_Char s[1];
138 } BLOCK;
139
140 typedef struct {
141   BLOCK *blocks;
142   BLOCK *freeBlocks;
143   const XML_Char *end;
144   XML_Char *ptr;
145   XML_Char *start;
146 } STRING_POOL;
147
148 /* The XML_Char before the name is used to determine whether
149 an attribute has been specified. */
150 typedef struct attribute_id {
151   XML_Char *name;
152   PREFIX *prefix;
153   char maybeTokenized;
154   char xmlns;
155 } ATTRIBUTE_ID;
156
157 typedef struct {
158   const ATTRIBUTE_ID *id;
159   char isCdata;
160   const XML_Char *value;
161 } DEFAULT_ATTRIBUTE;
162
163 typedef struct {
164   const XML_Char *name;
165   PREFIX *prefix;
166   const ATTRIBUTE_ID *idAtt;
167   int nDefaultAtts;
168   int allocDefaultAtts;
169   DEFAULT_ATTRIBUTE *defaultAtts;
170 } ELEMENT_TYPE;
171
172 typedef struct {
173   HASH_TABLE generalEntities;
174   HASH_TABLE elementTypes;
175   HASH_TABLE attributeIds;
176   HASH_TABLE prefixes;
177   STRING_POOL pool;
178   int complete;
179   int standalone;
180 #ifdef XML_DTD
181   HASH_TABLE paramEntities;
182 #endif /* XML_DTD */
183   PREFIX defaultPrefix;
184 } DTD;
185
186 typedef struct open_internal_entity {
187   const char *internalEventPtr;
188   const char *internalEventEndPtr;
189   struct open_internal_entity *next;
190   ENTITY *entity;
191 } OPEN_INTERNAL_ENTITY;
192
193 typedef enum XML_Error Processor(XML_Parser parser,
194                                  const char *start,
195                                  const char *end,
196                                  const char **endPtr);
197
198 static Processor prologProcessor;
199 static Processor prologInitProcessor;
200 static Processor contentProcessor;
201 static Processor cdataSectionProcessor;
202 #ifdef XML_DTD
203 static Processor ignoreSectionProcessor;
204 #endif /* XML_DTD */
205 static Processor epilogProcessor;
206 static Processor errorProcessor;
207 static Processor externalEntityInitProcessor;
208 static Processor externalEntityInitProcessor2;
209 static Processor externalEntityInitProcessor3;
210 static Processor externalEntityContentProcessor;
211
212 static enum XML_Error
213 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
214 static enum XML_Error
215 processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *);
216 static enum XML_Error
217 initializeEncoding(XML_Parser parser);
218 static enum XML_Error
219 doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
220          const char *end, int tok, const char *next, const char **nextPtr);
221 static enum XML_Error
222 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
223           const char *start, const char *end, const char **endPtr);
224 static enum XML_Error
225 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
226 #ifdef XML_DTD
227 static enum XML_Error
228 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
229 #endif /* XML_DTD */
230 static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s,
231                                 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
232 static
233 int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr);
234 static int
235 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, int isId, const XML_Char *dfltValue);
236 static enum XML_Error
237 storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
238                     STRING_POOL *);
239 static enum XML_Error
240 appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
241                     STRING_POOL *);
242 static ATTRIBUTE_ID *
243 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
244 static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
245 static enum XML_Error
246 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
247 static int
248 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
249 static int
250 reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
251 static void
252 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
253
254 static const XML_Char *getContext(XML_Parser parser);
255 static int setContext(XML_Parser parser, const XML_Char *context);
256 static void normalizePublicId(XML_Char *s);
257 static int dtdInit(DTD *);
258 static void dtdDestroy(DTD *);
259 static int dtdCopy(DTD *newDtd, const DTD *oldDtd);
260 static int copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
261 #ifdef XML_DTD
262 static void dtdSwap(DTD *, DTD *);
263 #endif /* XML_DTD */
264 static NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize);
265 static void hashTableInit(HASH_TABLE *);
266 static void hashTableDestroy(HASH_TABLE *);
267 static void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
268 static NAMED *hashTableIterNext(HASH_TABLE_ITER *);
269 static void poolInit(STRING_POOL *);
270 static void poolClear(STRING_POOL *);
271 static void poolDestroy(STRING_POOL *);
272 static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
273                             const char *ptr, const char *end);
274 static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
275                                   const char *ptr, const char *end);
276 static int poolGrow(STRING_POOL *pool);
277 static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s);
278 static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
279
280 #define poolStart(pool) ((pool)->start)
281 #define poolEnd(pool) ((pool)->ptr)
282 #define poolLength(pool) ((pool)->ptr - (pool)->start)
283 #define poolChop(pool) ((void)--(pool->ptr))
284 #define poolLastChar(pool) (((pool)->ptr)[-1])
285 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
286 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
287 #define poolAppendChar(pool, c) \
288   (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
289    ? 0 \
290    : ((*((pool)->ptr)++ = c), 1))
291
292 typedef struct {
293   /* The first member must be userData so that the XML_GetUserData macro works. */
294   void *m_userData;
295   void *m_handlerArg;
296   char *m_buffer;
297   /* first character to be parsed */
298   const char *m_bufferPtr;
299   /* past last character to be parsed */
300   char *m_bufferEnd;
301   /* allocated end of buffer */
302   const char *m_bufferLim;
303   long m_parseEndByteIndex;
304   const char *m_parseEndPtr;
305   XML_Char *m_dataBuf;
306   XML_Char *m_dataBufEnd;
307   XML_StartElementHandler m_startElementHandler;
308   XML_EndElementHandler m_endElementHandler;
309   XML_CharacterDataHandler m_characterDataHandler;
310   XML_ProcessingInstructionHandler m_processingInstructionHandler;
311   XML_CommentHandler m_commentHandler;
312   XML_StartCdataSectionHandler m_startCdataSectionHandler;
313   XML_EndCdataSectionHandler m_endCdataSectionHandler;
314   XML_DefaultHandler m_defaultHandler;
315   XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
316   XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
317   XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
318   XML_NotationDeclHandler m_notationDeclHandler;
319   XML_ExternalParsedEntityDeclHandler m_externalParsedEntityDeclHandler;
320   XML_InternalParsedEntityDeclHandler m_internalParsedEntityDeclHandler;
321   XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
322   XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
323   XML_NotStandaloneHandler m_notStandaloneHandler;
324   XML_ExternalEntityRefHandler m_externalEntityRefHandler;
325   void *m_externalEntityRefHandlerArg;
326   XML_UnknownEncodingHandler m_unknownEncodingHandler;
327   const ENCODING *m_encoding;
328   INIT_ENCODING m_initEncoding;
329   const ENCODING *m_internalEncoding;
330   const XML_Char *m_protocolEncodingName;
331   int m_ns;
332   void *m_unknownEncodingMem;
333   void *m_unknownEncodingData;
334   void *m_unknownEncodingHandlerData;
335   void (*m_unknownEncodingRelease)(void *);
336   PROLOG_STATE m_prologState;
337   Processor *m_processor;
338   enum XML_Error m_errorCode;
339   const char *m_eventPtr;
340   const char *m_eventEndPtr;
341   const char *m_positionPtr;
342   OPEN_INTERNAL_ENTITY *m_openInternalEntities;
343   int m_defaultExpandInternalEntities;
344   int m_tagLevel;
345   ENTITY *m_declEntity;
346   const XML_Char *m_declNotationName;
347   const XML_Char *m_declNotationPublicId;
348   ELEMENT_TYPE *m_declElementType;
349   ATTRIBUTE_ID *m_declAttributeId;
350   char m_declAttributeIsCdata;
351   char m_declAttributeIsId;
352   DTD m_dtd;
353   const XML_Char *m_curBase;
354   TAG *m_tagStack;
355   TAG *m_freeTagList;
356   BINDING *m_inheritedBindings;
357   BINDING *m_freeBindingList;
358   int m_attsSize;
359   int m_nSpecifiedAtts;
360   int m_idAttIndex;
361   ATTRIBUTE *m_atts;
362   POSITION m_position;
363   STRING_POOL m_tempPool;
364   STRING_POOL m_temp2Pool;
365   char *m_groupConnector;
366   unsigned m_groupSize;
367   int m_hadExternalDoctype;
368   XML_Char m_namespaceSeparator;
369 #ifdef XML_DTD
370   enum XML_ParamEntityParsing m_paramEntityParsing;
371   XML_Parser m_parentParser;
372 #endif
373 } Parser;
374
375 #define userData (((Parser *)parser)->m_userData)
376 #define handlerArg (((Parser *)parser)->m_handlerArg)
377 #define startElementHandler (((Parser *)parser)->m_startElementHandler)
378 #define endElementHandler (((Parser *)parser)->m_endElementHandler)
379 #define characterDataHandler (((Parser *)parser)->m_characterDataHandler)
380 #define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler)
381 #define commentHandler (((Parser *)parser)->m_commentHandler)
382 #define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler)
383 #define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler)
384 #define defaultHandler (((Parser *)parser)->m_defaultHandler)
385 #define startDoctypeDeclHandler (((Parser *)parser)->m_startDoctypeDeclHandler)
386 #define endDoctypeDeclHandler (((Parser *)parser)->m_endDoctypeDeclHandler)
387 #define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler)
388 #define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler)
389 #define externalParsedEntityDeclHandler (((Parser *)parser)->m_externalParsedEntityDeclHandler)
390 #define internalParsedEntityDeclHandler (((Parser *)parser)->m_internalParsedEntityDeclHandler)
391 #define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler)
392 #define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler)
393 #define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler)
394 #define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler)
395 #define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg)
396 #define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler)
397 #define encoding (((Parser *)parser)->m_encoding)
398 #define initEncoding (((Parser *)parser)->m_initEncoding)
399 #define internalEncoding (((Parser *)parser)->m_internalEncoding)
400 #define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem)
401 #define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData)
402 #define unknownEncodingHandlerData \
403   (((Parser *)parser)->m_unknownEncodingHandlerData)
404 #define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease)
405 #define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName)
406 #define ns (((Parser *)parser)->m_ns)
407 #define prologState (((Parser *)parser)->m_prologState)
408 #define processor (((Parser *)parser)->m_processor)
409 #define errorCode (((Parser *)parser)->m_errorCode)
410 #define eventPtr (((Parser *)parser)->m_eventPtr)
411 #define eventEndPtr (((Parser *)parser)->m_eventEndPtr)
412 #define positionPtr (((Parser *)parser)->m_positionPtr)
413 #define position (((Parser *)parser)->m_position)
414 #define openInternalEntities (((Parser *)parser)->m_openInternalEntities)
415 #define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities)
416 #define tagLevel (((Parser *)parser)->m_tagLevel)
417 #define buffer (((Parser *)parser)->m_buffer)
418 #define bufferPtr (((Parser *)parser)->m_bufferPtr)
419 #define bufferEnd (((Parser *)parser)->m_bufferEnd)
420 #define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex)
421 #define parseEndPtr (((Parser *)parser)->m_parseEndPtr)
422 #define bufferLim (((Parser *)parser)->m_bufferLim)
423 #define dataBuf (((Parser *)parser)->m_dataBuf)
424 #define dataBufEnd (((Parser *)parser)->m_dataBufEnd)
425 #define dtd (((Parser *)parser)->m_dtd)
426 #define curBase (((Parser *)parser)->m_curBase)
427 #define declEntity (((Parser *)parser)->m_declEntity)
428 #define declNotationName (((Parser *)parser)->m_declNotationName)
429 #define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId)
430 #define declElementType (((Parser *)parser)->m_declElementType)
431 #define declAttributeId (((Parser *)parser)->m_declAttributeId)
432 #define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata)
433 #define declAttributeIsId (((Parser *)parser)->m_declAttributeIsId)
434 #define freeTagList (((Parser *)parser)->m_freeTagList)
435 #define freeBindingList (((Parser *)parser)->m_freeBindingList)
436 #define inheritedBindings (((Parser *)parser)->m_inheritedBindings)
437 #define tagStack (((Parser *)parser)->m_tagStack)
438 #define atts (((Parser *)parser)->m_atts)
439 #define attsSize (((Parser *)parser)->m_attsSize)
440 #define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts)
441 #define idAttIndex (((Parser *)parser)->m_idAttIndex)
442 #define tempPool (((Parser *)parser)->m_tempPool)
443 #define temp2Pool (((Parser *)parser)->m_temp2Pool)
444 #define groupConnector (((Parser *)parser)->m_groupConnector)
445 #define groupSize (((Parser *)parser)->m_groupSize)
446 #define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype)
447 #define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator)
448 #ifdef XML_DTD
449 #define parentParser (((Parser *)parser)->m_parentParser)
450 #define paramEntityParsing (((Parser *)parser)->m_paramEntityParsing)
451 #endif /* XML_DTD */
452
453 #ifdef _MSC_VER
454 #ifdef _DEBUG
455 Parser *asParser(XML_Parser parser)
456 {
457   return parser;
458 }
459 #endif
460 #endif
461
462 XML_Parser
463 xmlrpc_XML_ParserCreate(const XML_Char *encodingName)
464 {
465   XML_Parser parser = malloc(sizeof(Parser));
466   if (!parser)
467     return parser;
468   processor = prologInitProcessor;
469   xmlrpc_XmlPrologStateInit(&prologState);
470   userData = 0;
471   handlerArg = 0;
472   startElementHandler = 0;
473   endElementHandler = 0;
474   characterDataHandler = 0;
475   processingInstructionHandler = 0;
476   commentHandler = 0;
477   startCdataSectionHandler = 0;
478   endCdataSectionHandler = 0;
479   defaultHandler = 0;
480   startDoctypeDeclHandler = 0;
481   endDoctypeDeclHandler = 0;
482   unparsedEntityDeclHandler = 0;
483   notationDeclHandler = 0;
484   externalParsedEntityDeclHandler = 0;
485   internalParsedEntityDeclHandler = 0;
486   startNamespaceDeclHandler = 0;
487   endNamespaceDeclHandler = 0;
488   notStandaloneHandler = 0;
489   externalEntityRefHandler = 0;
490   externalEntityRefHandlerArg = parser;
491   unknownEncodingHandler = 0;
492   buffer = 0;
493   bufferPtr = 0;
494   bufferEnd = 0;
495   parseEndByteIndex = 0;
496   parseEndPtr = 0;
497   bufferLim = 0;
498   declElementType = 0;
499   declAttributeId = 0;
500   declEntity = 0;
501   declNotationName = 0;
502   declNotationPublicId = 0;
503   memset(&position, 0, sizeof(POSITION));
504   errorCode = XML_ERROR_NONE;
505   eventPtr = 0;
506   eventEndPtr = 0;
507   positionPtr = 0;
508   openInternalEntities = 0;
509   tagLevel = 0;
510   tagStack = 0;
511   freeTagList = 0;
512   freeBindingList = 0;
513   inheritedBindings = 0;
514   attsSize = INIT_ATTS_SIZE;
515   atts = malloc(attsSize * sizeof(ATTRIBUTE));
516   nSpecifiedAtts = 0;
517   dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
518   groupSize = 0;
519   groupConnector = 0;
520   hadExternalDoctype = 0;
521   unknownEncodingMem = 0;
522   unknownEncodingRelease = 0;
523   unknownEncodingData = 0;
524   unknownEncodingHandlerData = 0;
525   namespaceSeparator = '!';
526 #ifdef XML_DTD
527   parentParser = 0;
528   paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
529 #endif
530   ns = 0;
531   poolInit(&tempPool);
532   poolInit(&temp2Pool);
533   protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0;
534   curBase = 0;
535   if (!dtdInit(&dtd) || !atts || !dataBuf
536       || (encodingName && !protocolEncodingName)) {
537     xmlrpc_XML_ParserFree(parser);
538     return 0;
539   }
540   dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
541   xmlrpc_XmlInitEncoding(&initEncoding, &encoding, 0);
542   internalEncoding = XmlGetInternalEncoding();
543   return parser;
544 }
545
546 XML_Parser
547 xmlrpc_XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
548 {
549   static
550   const XML_Char implicitContext[] = {
551     XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='),
552     XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'),
553     XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'),
554     XML_T('.'), XML_T('w'), XML_T('3'),
555     XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'),
556     XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'),
557     XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'),
558     XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'),
559     XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'),
560     XML_T('\0')
561   };
562
563   XML_Parser parser = xmlrpc_XML_ParserCreate(encodingName);
564   if (parser) {
565     XmlInitEncodingNS(&initEncoding, &encoding, 0);
566     ns = 1;
567     internalEncoding = XmlGetInternalEncodingNS();
568     namespaceSeparator = nsSep;
569   }
570   if (!setContext(parser, implicitContext)) {
571     xmlrpc_XML_ParserFree(parser);
572     return 0;
573   }
574   return parser;
575 }
576
577 int
578 xmlrpc_XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
579 {
580   if (!encodingName)
581     protocolEncodingName = 0;
582   else {
583     protocolEncodingName = poolCopyString(&tempPool, encodingName);
584     if (!protocolEncodingName)
585       return 0;
586   }
587   return 1;
588 }
589
590 XML_Parser
591 xmlrpc_XML_ExternalEntityParserCreate(XML_Parser oldParser,
592                                       const XML_Char *context,
593                                       const XML_Char *encodingName)
594 {
595   XML_Parser parser = oldParser;
596   DTD *oldDtd = &dtd;
597   XML_StartElementHandler oldStartElementHandler = startElementHandler;
598   XML_EndElementHandler oldEndElementHandler = endElementHandler;
599   XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
600   XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler;
601   XML_CommentHandler oldCommentHandler = commentHandler;
602   XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler;
603   XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler;
604   XML_DefaultHandler oldDefaultHandler = defaultHandler;
605   XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler;
606   XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
607   XML_ExternalParsedEntityDeclHandler oldExternalParsedEntityDeclHandler = externalParsedEntityDeclHandler;
608   XML_InternalParsedEntityDeclHandler oldInternalParsedEntityDeclHandler = internalParsedEntityDeclHandler;
609   XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
610   XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
611   XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
612   XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler;
613   XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler;
614   void *oldUserData = userData;
615   void *oldHandlerArg = handlerArg;
616   int oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
617   void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
618 #ifdef XML_DTD
619   int oldParamEntityParsing = paramEntityParsing;
620 #endif
621   parser = (ns
622             ? xmlrpc_XML_ParserCreateNS(encodingName, namespaceSeparator)
623             : xmlrpc_XML_ParserCreate(encodingName));
624   if (!parser)
625     return 0;
626   startElementHandler = oldStartElementHandler;
627   endElementHandler = oldEndElementHandler;
628   characterDataHandler = oldCharacterDataHandler;
629   processingInstructionHandler = oldProcessingInstructionHandler;
630   commentHandler = oldCommentHandler;
631   startCdataSectionHandler = oldStartCdataSectionHandler;
632   endCdataSectionHandler = oldEndCdataSectionHandler;
633   defaultHandler = oldDefaultHandler;
634   unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
635   notationDeclHandler = oldNotationDeclHandler;
636   externalParsedEntityDeclHandler = oldExternalParsedEntityDeclHandler;
637   internalParsedEntityDeclHandler = oldInternalParsedEntityDeclHandler;
638   startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
639   endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
640   notStandaloneHandler = oldNotStandaloneHandler;
641   externalEntityRefHandler = oldExternalEntityRefHandler;
642   unknownEncodingHandler = oldUnknownEncodingHandler;
643   userData = oldUserData;
644   if (oldUserData == oldHandlerArg)
645     handlerArg = userData;
646   else
647     handlerArg = parser;
648   if (oldExternalEntityRefHandlerArg != oldParser)
649     externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
650   defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
651 #ifdef XML_DTD
652   paramEntityParsing = oldParamEntityParsing;
653   if (context) {
654 #endif /* XML_DTD */
655     if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) {
656       xmlrpc_XML_ParserFree(parser);
657       return 0;
658     }
659     processor = externalEntityInitProcessor;
660 #ifdef XML_DTD
661   }
662   else {
663     dtdSwap(&dtd, oldDtd);
664     parentParser = oldParser;
665     XmlPrologStateInitExternalEntity(&prologState);
666     dtd.complete = 1;
667     hadExternalDoctype = 1;
668   }
669 #endif /* XML_DTD */
670   return parser;
671 }
672
673 static
674 void destroyBindings(BINDING *bindings)
675 {
676   for (;;) {
677     BINDING *b = bindings;
678     if (!b)
679       break;
680     bindings = b->nextTagBinding;
681     free(b->uri);
682     free(b);
683   }
684 }
685
686 void
687 xmlrpc_XML_ParserFree(XML_Parser parser)
688 {
689   for (;;) {
690     TAG *p;
691     if (tagStack == 0) {
692       if (freeTagList == 0)
693         break;
694       tagStack = freeTagList;
695       freeTagList = 0;
696     }
697     p = tagStack;
698     tagStack = tagStack->parent;
699     free(p->buf);
700     destroyBindings(p->bindings);
701     free(p);
702   }
703   destroyBindings(freeBindingList);
704   destroyBindings(inheritedBindings);
705   poolDestroy(&tempPool);
706   poolDestroy(&temp2Pool);
707 #ifdef XML_DTD
708   if (parentParser) {
709     if (hadExternalDoctype)
710       dtd.complete = 0;
711     dtdSwap(&dtd, &((Parser *)parentParser)->m_dtd);
712   }
713 #endif /* XML_DTD */
714   dtdDestroy(&dtd);
715   free((void *)atts);
716   free(groupConnector);
717   free(buffer);
718   free(dataBuf);
719   free(unknownEncodingMem);
720   if (unknownEncodingRelease)
721     unknownEncodingRelease(unknownEncodingData);
722   free(parser);
723 }
724
725 void
726 xmlrpc_XML_UseParserAsHandlerArg(XML_Parser parser)
727 {
728   handlerArg = parser;
729 }
730
731 void
732 xmlrpc_XML_SetUserData(XML_Parser parser, void *p)
733 {
734   if (handlerArg == userData)
735     handlerArg = userData = p;
736   else
737     userData = p;
738 }
739
740 int
741 xmlrpc_XML_SetBase(XML_Parser parser, const XML_Char *p)
742 {
743   if (p) {
744     p = poolCopyString(&dtd.pool, p);
745     if (!p)
746       return 0;
747     curBase = p;
748   }
749   else
750     curBase = 0;
751   return 1;
752 }
753
754 const XML_Char *
755 xmlrpc_XML_GetBase(XML_Parser parser)
756 {
757   return curBase;
758 }
759
760 int
761 xmlrpc_XML_GetSpecifiedAttributeCount(XML_Parser parser)
762 {
763   return nSpecifiedAtts;
764 }
765
766 int
767 xmlrpc_XML_GetIdAttributeIndex(XML_Parser parser)
768 {
769   return idAttIndex;
770 }
771
772 void
773 xmlrpc_XML_SetElementHandler(XML_Parser parser,
774                              XML_StartElementHandler start,
775                              XML_EndElementHandler end)
776 {
777   startElementHandler = start;
778   endElementHandler = end;
779 }
780
781 void
782 xmlrpc_XML_SetCharacterDataHandler(XML_Parser parser,
783                                    XML_CharacterDataHandler handler)
784 {
785   characterDataHandler = handler;
786 }
787
788 void
789 xmlrpc_XML_SetProcessingInstructionHandler(
790     XML_Parser parser,
791     XML_ProcessingInstructionHandler handler)
792 {
793   processingInstructionHandler = handler;
794 }
795
796 void
797 xmlrpc_XML_SetCommentHandler(XML_Parser parser,
798                              XML_CommentHandler handler)
799 {
800   commentHandler = handler;
801 }
802
803 void
804 xmlrpc_XML_SetCdataSectionHandler(XML_Parser parser,
805                                   XML_StartCdataSectionHandler start,
806                                   XML_EndCdataSectionHandler end)
807 {
808   startCdataSectionHandler = start;
809   endCdataSectionHandler = end;
810 }
811
812 void
813 xmlrpc_XML_SetDefaultHandler(XML_Parser parser,
814                              XML_DefaultHandler handler)
815 {
816   defaultHandler = handler;
817   defaultExpandInternalEntities = 0;
818 }
819
820 void
821 xmlrpc_XML_SetDefaultHandlerExpand(XML_Parser parser,
822                                    XML_DefaultHandler handler)
823 {
824   defaultHandler = handler;
825   defaultExpandInternalEntities = 1;
826 }
827
828 void
829 xmlrpc_XML_SetDoctypeDeclHandler(XML_Parser parser,
830                                  XML_StartDoctypeDeclHandler start,
831                                  XML_EndDoctypeDeclHandler end)
832 {
833   startDoctypeDeclHandler = start;
834   endDoctypeDeclHandler = end;
835 }
836
837 void
838 xmlrpc_XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
839                                         XML_UnparsedEntityDeclHandler handler)
840 {
841   unparsedEntityDeclHandler = handler;
842 }
843
844 void
845 xmlrpc_XML_SetExternalParsedEntityDeclHandler(
846     XML_Parser parser,
847     XML_ExternalParsedEntityDeclHandler handler)
848 {
849   externalParsedEntityDeclHandler = handler;
850 }
851
852 void
853 xmlrpc_XML_SetInternalParsedEntityDeclHandler(
854     XML_Parser parser,
855     XML_InternalParsedEntityDeclHandler handler)
856 {
857   internalParsedEntityDeclHandler = handler;
858 }
859
860 void
861 xmlrpc_XML_SetNotationDeclHandler(XML_Parser parser,
862                                   XML_NotationDeclHandler handler)
863 {
864   notationDeclHandler = handler;
865 }
866
867 void
868 xmlrpc_XML_SetNamespaceDeclHandler(XML_Parser parser,
869                                    XML_StartNamespaceDeclHandler start,
870                                    XML_EndNamespaceDeclHandler end)
871 {
872   startNamespaceDeclHandler = start;
873   endNamespaceDeclHandler = end;
874 }
875
876 void
877 xmlrpc_XML_SetNotStandaloneHandler(XML_Parser parser,
878                                    XML_NotStandaloneHandler handler)
879 {
880   notStandaloneHandler = handler;
881 }
882
883 void
884 xmlrpc_XML_SetExternalEntityRefHandler(XML_Parser parser,
885                                        XML_ExternalEntityRefHandler handler)
886 {
887   externalEntityRefHandler = handler;
888 }
889
890 void
891 xmlrpc_XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
892 {
893   if (arg)
894     externalEntityRefHandlerArg = arg;
895   else
896     externalEntityRefHandlerArg = parser;
897 }
898
899 void
900 xmlrpc_XML_SetUnknownEncodingHandler(XML_Parser parser,
901                                      XML_UnknownEncodingHandler handler,
902                                      void *data)
903 {
904   unknownEncodingHandler = handler;
905   unknownEncodingHandlerData = data;
906 }
907
908
909
910 int
911 xmlrpc_XML_SetParamEntityParsing(
912     XML_Parser                  const parser  ATTR_UNUSED,
913     enum XML_ParamEntityParsing const parsing) {
914     
915     int retval;
916
917 #ifdef XML_DTD
918     paramEntityParsing = parsing;
919     retval = 1;
920 #else
921     retval = parsing == XML_PARAM_ENTITY_PARSING_NEVER;
922 #endif
923
924     return retval;
925 }
926
927
928
929 int
930 xmlrpc_XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
931 {
932   if (len == 0) {
933     if (!isFinal)
934       return 1;
935     positionPtr = bufferPtr;
936     errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0);
937     if (errorCode == XML_ERROR_NONE)
938       return 1;
939     eventEndPtr = eventPtr;
940     processor = errorProcessor;
941     return 0;
942   }
943   else if (bufferPtr == bufferEnd) {
944     const char *end;
945     int nLeftOver;
946     parseEndByteIndex += len;
947     positionPtr = s;
948     if (isFinal) {
949       errorCode = processor(parser, s, parseEndPtr = s + len, 0);
950       if (errorCode == XML_ERROR_NONE)
951         return 1;
952       eventEndPtr = eventPtr;
953       processor = errorProcessor;
954       return 0;
955     }
956     errorCode = processor(parser, s, parseEndPtr = s + len, &end);
957     if (errorCode != XML_ERROR_NONE) {
958       eventEndPtr = eventPtr;
959       processor = errorProcessor;
960       return 0;
961     }
962     XmlUpdatePosition(encoding, positionPtr, end, &position);
963     nLeftOver = s + len - end;
964     if (nLeftOver) {
965       if (buffer == 0 || nLeftOver > bufferLim - buffer) {
966         /* FIXME avoid integer overflow */
967         buffer = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2);
968         /* FIXME storage leak if realloc fails */
969         if (!buffer) {
970           errorCode = XML_ERROR_NO_MEMORY;
971           eventPtr = eventEndPtr = 0;
972           processor = errorProcessor;
973           return 0;
974         }
975         bufferLim = buffer + len * 2;
976       }
977       memcpy(buffer, end, nLeftOver);
978       bufferPtr = buffer;
979       bufferEnd = buffer + nLeftOver;
980     }
981     return 1;
982   }
983   else {
984     memcpy(xmlrpc_XML_GetBuffer(parser, len), s, len);
985     return xmlrpc_XML_ParseBuffer(parser, len, isFinal);
986   }
987 }
988
989 int
990 xmlrpc_XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
991 {
992   const char *start = bufferPtr;
993   positionPtr = start;
994   bufferEnd += len;
995   parseEndByteIndex += len;
996   errorCode = processor(parser, start, parseEndPtr = bufferEnd,
997                         isFinal ? (const char **)0 : &bufferPtr);
998   if (errorCode == XML_ERROR_NONE) {
999     if (!isFinal)
1000       XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1001     return 1;
1002   }
1003   else {
1004     eventEndPtr = eventPtr;
1005     processor = errorProcessor;
1006     return 0;
1007   }
1008 }
1009
1010 void *
1011 xmlrpc_XML_GetBuffer(XML_Parser parser, int len)
1012 {
1013   if (len > bufferLim - bufferEnd) {
1014     /* FIXME avoid integer overflow */
1015     int neededSize = len + (bufferEnd - bufferPtr);
1016     if (neededSize  <= bufferLim - buffer) {
1017       memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
1018       bufferEnd = buffer + (bufferEnd - bufferPtr);
1019       bufferPtr = buffer;
1020     }
1021     else {
1022       char *newBuf;
1023       int bufferSize = bufferLim - bufferPtr;
1024       if (bufferSize == 0)
1025         bufferSize = INIT_BUFFER_SIZE;
1026       do {
1027         bufferSize *= 2;
1028       } while (bufferSize < neededSize);
1029       newBuf = malloc(bufferSize);
1030       if (newBuf == 0) {
1031         errorCode = XML_ERROR_NO_MEMORY;
1032         return 0;
1033       }
1034       bufferLim = newBuf + bufferSize;
1035       if (bufferPtr) {
1036         memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
1037         free(buffer);
1038       }
1039       bufferEnd = newBuf + (bufferEnd - bufferPtr);
1040       bufferPtr = buffer = newBuf;
1041     }
1042   }
1043   return bufferEnd;
1044 }
1045
1046 enum XML_Error
1047 xmlrpc_XML_GetErrorCode(XML_Parser parser)
1048 {
1049   return errorCode;
1050 }
1051
1052 long
1053 xmlrpc_XML_GetCurrentByteIndex(XML_Parser parser)
1054 {
1055   if (eventPtr)
1056     return parseEndByteIndex - (parseEndPtr - eventPtr);
1057   return -1;
1058 }
1059
1060 int
1061 xmlrpc_XML_GetCurrentByteCount(XML_Parser parser)
1062 {
1063   if (eventEndPtr && eventPtr)
1064     return eventEndPtr - eventPtr;
1065   return 0;
1066 }
1067
1068 int
1069 xmlrpc_XML_GetCurrentLineNumber(XML_Parser parser)
1070 {
1071   if (eventPtr) {
1072     XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1073     positionPtr = eventPtr;
1074   }
1075   return position.lineNumber + 1;
1076 }
1077
1078 int
1079 xmlrpc_XML_GetCurrentColumnNumber(XML_Parser parser)
1080 {
1081   if (eventPtr) {
1082     XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
1083     positionPtr = eventPtr;
1084   }
1085   return position.columnNumber;
1086 }
1087
1088 void
1089 xmlrpc_XML_DefaultCurrent(XML_Parser parser)
1090 {
1091   if (defaultHandler) {
1092     if (openInternalEntities)
1093       reportDefault(parser,
1094                     internalEncoding,
1095                     openInternalEntities->internalEventPtr,
1096                     openInternalEntities->internalEventEndPtr);
1097     else
1098       reportDefault(parser, encoding, eventPtr, eventEndPtr);
1099   }
1100 }
1101
1102 const XML_LChar *
1103 xmlrpc_XML_ErrorString(int const code) {
1104
1105     static const XML_LChar * const message[] = {
1106         NULL,
1107         XML_T("out of memory"),
1108         XML_T("syntax error"),
1109         XML_T("no element found"),
1110         XML_T("not well-formed"),
1111         XML_T("unclosed token"),
1112         XML_T("unclosed token"),
1113         XML_T("mismatched tag"),
1114         XML_T("duplicate attribute"),
1115         XML_T("junk after document element"),
1116         XML_T("illegal parameter entity reference"),
1117         XML_T("undefined entity"),
1118         XML_T("recursive entity reference"),
1119         XML_T("asynchronous entity"),
1120         XML_T("reference to invalid character number"),
1121         XML_T("reference to binary entity"),
1122         XML_T("reference to external entity in attribute"),
1123         XML_T("xml processing instruction not at start of external entity"),
1124         XML_T("unknown encoding"),
1125         XML_T("encoding specified in XML declaration is incorrect"),
1126         XML_T("unclosed CDATA section"),
1127         XML_T("error in processing external entity reference"),
1128         XML_T("document is not standalone")
1129     };
1130
1131     const XML_LChar * retval;
1132
1133     if (code > 0 && (unsigned)code < ARRAY_SIZE(message))
1134         retval = message[code];
1135     else
1136         retval = NULL;
1137     
1138     return retval;
1139 }
1140
1141 static
1142 enum XML_Error contentProcessor(XML_Parser parser,
1143                                 const char *start,
1144                                 const char *end,
1145                                 const char **endPtr)
1146 {
1147   return doContent(parser, 0, encoding, start, end, endPtr);
1148 }
1149
1150 static
1151 enum XML_Error externalEntityInitProcessor(XML_Parser parser,
1152                                            const char *start,
1153                                            const char *end,
1154                                            const char **endPtr)
1155 {
1156   enum XML_Error result = initializeEncoding(parser);
1157   if (result != XML_ERROR_NONE)
1158     return result;
1159   processor = externalEntityInitProcessor2;
1160   return externalEntityInitProcessor2(parser, start, end, endPtr);
1161 }
1162
1163 static
1164 enum XML_Error externalEntityInitProcessor2(XML_Parser parser,
1165                                             const char *start,
1166                                             const char *end,
1167                                             const char **endPtr)
1168 {
1169   const char *next;
1170   int tok = XmlContentTok(encoding, start, end, &next);
1171   switch (tok) {
1172   case XML_TOK_BOM:
1173     start = next;
1174     break;
1175   case XML_TOK_PARTIAL:
1176     if (endPtr) {
1177       *endPtr = start;
1178       return XML_ERROR_NONE;
1179     }
1180     eventPtr = start;
1181     return XML_ERROR_UNCLOSED_TOKEN;
1182   case XML_TOK_PARTIAL_CHAR:
1183     if (endPtr) {
1184       *endPtr = start;
1185       return XML_ERROR_NONE;
1186     }
1187     eventPtr = start;
1188     return XML_ERROR_PARTIAL_CHAR;
1189   }
1190   processor = externalEntityInitProcessor3;
1191   return externalEntityInitProcessor3(parser, start, end, endPtr);
1192 }
1193
1194 static
1195 enum XML_Error externalEntityInitProcessor3(XML_Parser parser,
1196                                             const char *start,
1197                                             const char *end,
1198                                             const char **endPtr)
1199 {
1200   const char *next;
1201   int tok = XmlContentTok(encoding, start, end, &next);
1202   switch (tok) {
1203   case XML_TOK_XML_DECL:
1204     {
1205       enum XML_Error result = processXmlDecl(parser, 1, start, next);
1206       if (result != XML_ERROR_NONE)
1207         return result;
1208       start = next;
1209     }
1210     break;
1211   case XML_TOK_PARTIAL:
1212     if (endPtr) {
1213       *endPtr = start;
1214       return XML_ERROR_NONE;
1215     }
1216     eventPtr = start;
1217     return XML_ERROR_UNCLOSED_TOKEN;
1218   case XML_TOK_PARTIAL_CHAR:
1219     if (endPtr) {
1220       *endPtr = start;
1221       return XML_ERROR_NONE;
1222     }
1223     eventPtr = start;
1224     return XML_ERROR_PARTIAL_CHAR;
1225   }
1226   processor = externalEntityContentProcessor;
1227   tagLevel = 1;
1228   return doContent(parser, 1, encoding, start, end, endPtr);
1229 }
1230
1231 static
1232 enum XML_Error externalEntityContentProcessor(XML_Parser parser,
1233                                               const char *start,
1234                                               const char *end,
1235                                               const char **endPtr)
1236 {
1237   return doContent(parser, 1, encoding, start, end, endPtr);
1238 }
1239
1240 static enum XML_Error
1241 doContent(XML_Parser parser,
1242           int startTagLevel,
1243           const ENCODING *enc,
1244           const char *s,
1245           const char *end,
1246           const char **nextPtr)
1247 {
1248   const char **eventPP;
1249   const char **eventEndPP;
1250   if (enc == encoding) {
1251     eventPP = &eventPtr;
1252     eventEndPP = &eventEndPtr;
1253   }
1254   else {
1255     eventPP = &(openInternalEntities->internalEventPtr);
1256     eventEndPP = &(openInternalEntities->internalEventEndPtr);
1257   }
1258   *eventPP = s;
1259   for (;;) {
1260     const char *next = s; /* XmlContentTok doesn't always set the last arg */
1261     int tok = XmlContentTok(enc, s, end, &next);
1262     *eventEndPP = next;
1263     switch (tok) {
1264     case XML_TOK_TRAILING_CR:
1265       if (nextPtr) {
1266         *nextPtr = s;
1267         return XML_ERROR_NONE;
1268       }
1269       *eventEndPP = end;
1270       if (characterDataHandler) {
1271         XML_Char c = 0xA;
1272         characterDataHandler(handlerArg, &c, 1);
1273       }
1274       else if (defaultHandler)
1275         reportDefault(parser, enc, s, end);
1276       if (startTagLevel == 0)
1277         return XML_ERROR_NO_ELEMENTS;
1278       if (tagLevel != startTagLevel)
1279         return XML_ERROR_ASYNC_ENTITY;
1280       return XML_ERROR_NONE;
1281     case XML_TOK_NONE:
1282       if (nextPtr) {
1283         *nextPtr = s;
1284         return XML_ERROR_NONE;
1285       }
1286       if (startTagLevel > 0) {
1287         if (tagLevel != startTagLevel)
1288           return XML_ERROR_ASYNC_ENTITY;
1289         return XML_ERROR_NONE;
1290       }
1291       return XML_ERROR_NO_ELEMENTS;
1292     case XML_TOK_INVALID:
1293       *eventPP = next;
1294       return XML_ERROR_INVALID_TOKEN;
1295     case XML_TOK_PARTIAL:
1296       if (nextPtr) {
1297         *nextPtr = s;
1298         return XML_ERROR_NONE;
1299       }
1300       return XML_ERROR_UNCLOSED_TOKEN;
1301     case XML_TOK_PARTIAL_CHAR:
1302       if (nextPtr) {
1303         *nextPtr = s;
1304         return XML_ERROR_NONE;
1305       }
1306       return XML_ERROR_PARTIAL_CHAR;
1307     case XML_TOK_ENTITY_REF:
1308       {
1309         const XML_Char *name;
1310         ENTITY *entity;
1311         XML_Char ch = XmlPredefinedEntityName(enc,
1312                                               s + enc->minBytesPerChar,
1313                                               next - enc->minBytesPerChar);
1314         if (ch) {
1315           if (characterDataHandler)
1316             characterDataHandler(handlerArg, &ch, 1);
1317           else if (defaultHandler)
1318             reportDefault(parser, enc, s, next);
1319           break;
1320         }
1321         name = poolStoreString(&dtd.pool, enc,
1322                                 s + enc->minBytesPerChar,
1323                                 next - enc->minBytesPerChar);
1324         if (!name)
1325           return XML_ERROR_NO_MEMORY;
1326         entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
1327         poolDiscard(&dtd.pool);
1328         if (!entity) {
1329           if (dtd.complete || dtd.standalone)
1330             return XML_ERROR_UNDEFINED_ENTITY;
1331           if (defaultHandler)
1332             reportDefault(parser, enc, s, next);
1333           break;
1334         }
1335         if (entity->open)
1336           return XML_ERROR_RECURSIVE_ENTITY_REF;
1337         if (entity->notation)
1338           return XML_ERROR_BINARY_ENTITY_REF;
1339         if (entity) {
1340           if (entity->textPtr) {
1341             enum XML_Error result;
1342             OPEN_INTERNAL_ENTITY openEntity;
1343             if (defaultHandler && !defaultExpandInternalEntities) {
1344               reportDefault(parser, enc, s, next);
1345               break;
1346             }
1347             entity->open = 1;
1348             openEntity.next = openInternalEntities;
1349             openInternalEntities = &openEntity;
1350             openEntity.entity = entity;
1351             openEntity.internalEventPtr = 0;
1352             openEntity.internalEventEndPtr = 0;
1353             result = doContent(parser,
1354                                tagLevel,
1355                                internalEncoding,
1356                                (char *)entity->textPtr,
1357                                (char *)(entity->textPtr + entity->textLen),
1358                                0);
1359             entity->open = 0;
1360             openInternalEntities = openEntity.next;
1361             if (result)
1362               return result;
1363           }
1364           else if (externalEntityRefHandler) {
1365             const XML_Char *context;
1366             entity->open = 1;
1367             context = getContext(parser);
1368             entity->open = 0;
1369             if (!context)
1370               return XML_ERROR_NO_MEMORY;
1371             if (!externalEntityRefHandler(externalEntityRefHandlerArg,
1372                                           context,
1373                                           entity->base,
1374                                           entity->systemId,
1375                                           entity->publicId))
1376               return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
1377             poolDiscard(&tempPool);
1378           }
1379           else if (defaultHandler)
1380             reportDefault(parser, enc, s, next);
1381         }
1382         break;
1383       }
1384     case XML_TOK_START_TAG_WITH_ATTS:
1385       if (!startElementHandler) {
1386         enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
1387         if (result)
1388           return result;
1389       }
1390       /* fall through */
1391     case XML_TOK_START_TAG_NO_ATTS:
1392       {
1393         TAG *tag;
1394         if (freeTagList) {
1395           tag = freeTagList;
1396           freeTagList = freeTagList->parent;
1397         }
1398         else {
1399           tag = malloc(sizeof(TAG));
1400           if (!tag)
1401             return XML_ERROR_NO_MEMORY;
1402           tag->buf = malloc(INIT_TAG_BUF_SIZE);
1403           if (!tag->buf)
1404             return XML_ERROR_NO_MEMORY;
1405           tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
1406         }
1407         tag->bindings = 0;
1408         tag->parent = tagStack;
1409         tagStack = tag;
1410         tag->name.localPart = 0;
1411         tag->rawName = s + enc->minBytesPerChar;
1412         tag->rawNameLength = XmlNameLength(enc, tag->rawName);
1413         if (nextPtr) {
1414           /* Need to guarantee that:
1415              tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */
1416           if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) {
1417             int bufSize = tag->rawNameLength * 4;
1418             bufSize = ROUND_UP(bufSize, sizeof(XML_Char));
1419             tag->buf = realloc(tag->buf, bufSize);
1420             if (!tag->buf)
1421               return XML_ERROR_NO_MEMORY;
1422             tag->bufEnd = tag->buf + bufSize;
1423           }
1424           memcpy(tag->buf, tag->rawName, tag->rawNameLength);
1425           tag->rawName = tag->buf;
1426         }
1427         ++tagLevel;
1428         if (startElementHandler) {
1429           enum XML_Error result;
1430           XML_Char *toPtr;
1431           for (;;) {
1432             const char *rawNameEnd = tag->rawName + tag->rawNameLength;
1433             const char *fromPtr = tag->rawName;
1434             int bufSize;
1435             if (nextPtr)
1436               toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)));
1437             else
1438               toPtr = (XML_Char *)tag->buf;
1439             tag->name.str = toPtr;
1440             XmlConvert(enc,
1441                        &fromPtr, rawNameEnd,
1442                        (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
1443             if (fromPtr == rawNameEnd)
1444               break;
1445             bufSize = (tag->bufEnd - tag->buf) << 1;
1446             tag->buf = realloc(tag->buf, bufSize);
1447             if (!tag->buf)
1448               return XML_ERROR_NO_MEMORY;
1449             tag->bufEnd = tag->buf + bufSize;
1450             if (nextPtr)
1451               tag->rawName = tag->buf;
1452           }
1453           *toPtr = XML_T('\0');
1454           result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
1455           if (result)
1456             return result;
1457           startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts);
1458           poolClear(&tempPool);
1459         }
1460         else {
1461           tag->name.str = 0;
1462           if (defaultHandler)
1463             reportDefault(parser, enc, s, next);
1464         }
1465         break;
1466       }
1467     case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
1468       if (!startElementHandler) {
1469         enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
1470         if (result)
1471           return result;
1472       }
1473       /* fall through */
1474     case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
1475       if (startElementHandler || endElementHandler) {
1476         const char *rawName = s + enc->minBytesPerChar;
1477         enum XML_Error result;
1478         BINDING *bindings = 0;
1479         TAG_NAME name;
1480         name.str = poolStoreString(&tempPool, enc, rawName,
1481                                    rawName + XmlNameLength(enc, rawName));
1482         if (!name.str)
1483           return XML_ERROR_NO_MEMORY;
1484         poolFinish(&tempPool);
1485         result = storeAtts(parser, enc, s, &name, &bindings);
1486         if (result)
1487           return result;
1488         poolFinish(&tempPool);
1489         if (startElementHandler)
1490           startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
1491         if (endElementHandler) {
1492           if (startElementHandler)
1493             *eventPP = *eventEndPP;
1494           endElementHandler(handlerArg, name.str);
1495         }
1496         poolClear(&tempPool);
1497         while (bindings) {
1498           BINDING *b = bindings;
1499           if (endNamespaceDeclHandler)
1500             endNamespaceDeclHandler(handlerArg, b->prefix->name);
1501           bindings = bindings->nextTagBinding;
1502           b->nextTagBinding = freeBindingList;
1503           freeBindingList = b;
1504           b->prefix->binding = b->prevPrefixBinding;
1505         }
1506       }
1507       else if (defaultHandler)
1508         reportDefault(parser, enc, s, next);
1509       if (tagLevel == 0)
1510         return epilogProcessor(parser, next, end, nextPtr);
1511       break;
1512     case XML_TOK_END_TAG:
1513       if (tagLevel == startTagLevel)
1514         return XML_ERROR_ASYNC_ENTITY;
1515       else {
1516         int len;
1517         const char *rawName;
1518         TAG *tag = tagStack;
1519         tagStack = tag->parent;
1520         tag->parent = freeTagList;
1521         freeTagList = tag;
1522         rawName = s + enc->minBytesPerChar*2;
1523         len = XmlNameLength(enc, rawName);
1524         if (len != tag->rawNameLength
1525             || memcmp(tag->rawName, rawName, len) != 0) {
1526           *eventPP = rawName;
1527           return XML_ERROR_TAG_MISMATCH;
1528         }
1529         --tagLevel;
1530         if (endElementHandler && tag->name.str) {
1531           if (tag->name.localPart) {
1532             XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen;
1533             const XML_Char *from = tag->name.localPart;
1534             while ((*to++ = *from++) != 0)
1535               ;
1536           }
1537           endElementHandler(handlerArg, tag->name.str);
1538         }
1539         else if (defaultHandler)
1540           reportDefault(parser, enc, s, next);
1541         while (tag->bindings) {
1542           BINDING *b = tag->bindings;
1543           if (endNamespaceDeclHandler)
1544             endNamespaceDeclHandler(handlerArg, b->prefix->name);
1545           tag->bindings = tag->bindings->nextTagBinding;
1546           b->nextTagBinding = freeBindingList;
1547           freeBindingList = b;
1548           b->prefix->binding = b->prevPrefixBinding;
1549         }
1550         if (tagLevel == 0)
1551           return epilogProcessor(parser, next, end, nextPtr);
1552       }
1553       break;
1554     case XML_TOK_CHAR_REF:
1555       {
1556         int n = XmlCharRefNumber(enc, s);
1557         if (n < 0)
1558           return XML_ERROR_BAD_CHAR_REF;
1559         if (characterDataHandler) {
1560           XML_Char buf[XML_ENCODE_MAX];
1561           characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
1562         }
1563         else if (defaultHandler)
1564           reportDefault(parser, enc, s, next);
1565       }
1566       break;
1567     case XML_TOK_XML_DECL:
1568       return XML_ERROR_MISPLACED_XML_PI;
1569     case XML_TOK_DATA_NEWLINE:
1570       if (characterDataHandler) {
1571         XML_Char c = 0xA;
1572         characterDataHandler(handlerArg, &c, 1);
1573       }
1574       else if (defaultHandler)
1575         reportDefault(parser, enc, s, next);
1576       break;
1577     case XML_TOK_CDATA_SECT_OPEN:
1578       {
1579         enum XML_Error result;
1580         if (startCdataSectionHandler)
1581           startCdataSectionHandler(handlerArg);
1582 #if 0
1583         /* Suppose you doing a transformation on a document that involves
1584            changing only the character data.  You set up a defaultHandler
1585            and a characterDataHandler.  The defaultHandler simply copies
1586            characters through.  The characterDataHandler does the transformation
1587            and writes the characters out escaping them as necessary.  This case
1588            will fail to work if we leave out the following two lines (because &
1589            and < inside CDATA sections will be incorrectly escaped).
1590
1591            However, now we have a start/endCdataSectionHandler, so it seems
1592            easier to let the user deal with this. */
1593
1594         else if (characterDataHandler)
1595           characterDataHandler(handlerArg, dataBuf, 0);
1596 #endif
1597         else if (defaultHandler)
1598           reportDefault(parser, enc, s, next);
1599         result = doCdataSection(parser, enc, &next, end, nextPtr);
1600         if (!next) {
1601           processor = cdataSectionProcessor;
1602           return result;
1603         }
1604       }
1605       break;
1606     case XML_TOK_TRAILING_RSQB:
1607       if (nextPtr) {
1608         *nextPtr = s;
1609         return XML_ERROR_NONE;
1610       }
1611       if (characterDataHandler) {
1612         if (MUST_CONVERT(enc, s)) {
1613           ICHAR *dataPtr = (ICHAR *)dataBuf;
1614           XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
1615           characterDataHandler(handlerArg, dataBuf,
1616                                dataPtr - (ICHAR *)dataBuf);
1617         }
1618         else
1619           characterDataHandler(handlerArg,
1620                                (XML_Char *)s,
1621                                (XML_Char *)end - (XML_Char *)s);
1622       }
1623       else if (defaultHandler)
1624         reportDefault(parser, enc, s, end);
1625       if (startTagLevel == 0) {
1626         *eventPP = end;
1627         return XML_ERROR_NO_ELEMENTS;
1628       }
1629       if (tagLevel != startTagLevel) {
1630         *eventPP = end;
1631         return XML_ERROR_ASYNC_ENTITY;
1632       }
1633       return XML_ERROR_NONE;
1634     case XML_TOK_DATA_CHARS:
1635       if (characterDataHandler) {
1636         if (MUST_CONVERT(enc, s)) {
1637           for (;;) {
1638             ICHAR *dataPtr = (ICHAR *)dataBuf;
1639             XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
1640             *eventEndPP = s;
1641             characterDataHandler(handlerArg, dataBuf,
1642                                  dataPtr - (ICHAR *)dataBuf);
1643             if (s == next)
1644               break;
1645             *eventPP = s;
1646           }
1647         }
1648         else
1649           characterDataHandler(handlerArg,
1650                                (XML_Char *)s,
1651                                (XML_Char *)next - (XML_Char *)s);
1652       }
1653       else if (defaultHandler)
1654         reportDefault(parser, enc, s, next);
1655       break;
1656     case XML_TOK_PI:
1657       if (!reportProcessingInstruction(parser, enc, s, next))
1658         return XML_ERROR_NO_MEMORY;
1659       break;
1660     case XML_TOK_COMMENT:
1661       if (!reportComment(parser, enc, s, next))
1662         return XML_ERROR_NO_MEMORY;
1663       break;
1664     default:
1665       if (defaultHandler)
1666         reportDefault(parser, enc, s, next);
1667       break;
1668     }
1669     *eventPP = s = next;
1670   }
1671   /* not reached */
1672 }
1673
1674 /* If tagNamePtr is non-null, build a real list of attributes,
1675 otherwise just check the attributes for well-formedness. */
1676
1677 static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
1678                                 const char *attStr, TAG_NAME *tagNamePtr,
1679                                 BINDING **bindingsPtr)
1680 {
1681   ELEMENT_TYPE *elementType = 0;
1682   int nDefaultAtts = 0;
1683   const XML_Char ** appAtts;
1684       /* the attribute list to pass to the application */
1685   int attIndex = 0;
1686   int i;
1687   int n;
1688   int nPrefixes = 0;
1689   BINDING *binding;
1690   const XML_Char *localPart;
1691
1692   /* lookup the element type name */
1693   if (tagNamePtr) {
1694     elementType = (ELEMENT_TYPE *)
1695         lookup(&dtd.elementTypes, tagNamePtr->str, 0);
1696     if (!elementType) {
1697       tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str);
1698       if (!tagNamePtr->str)
1699         return XML_ERROR_NO_MEMORY;
1700       elementType = (ELEMENT_TYPE *)
1701           lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE));
1702       if (!elementType)
1703         return XML_ERROR_NO_MEMORY;
1704       if (ns && !setElementTypePrefix(parser, elementType))
1705         return XML_ERROR_NO_MEMORY;
1706     }
1707     nDefaultAtts = elementType->nDefaultAtts;
1708   }
1709   /* get the attributes from the tokenizer */
1710   n = XmlGetAttributes(enc, attStr, attsSize, atts);
1711   if (n + nDefaultAtts > attsSize) {
1712     int oldAttsSize = attsSize;
1713     attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
1714     atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE));
1715     if (!atts)
1716       return XML_ERROR_NO_MEMORY;
1717     if (n > oldAttsSize)
1718       XmlGetAttributes(enc, attStr, n, atts);
1719   }
1720   appAtts = (const XML_Char **)atts;
1721   for (i = 0; i < n; i++) {
1722     /* add the name and value to the attribute list */
1723     ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
1724                                          atts[i].name
1725                                          + XmlNameLength(enc, atts[i].name));
1726     if (!attId)
1727       return XML_ERROR_NO_MEMORY;
1728     /* detect duplicate attributes */
1729     if ((attId->name)[-1]) {
1730       if (enc == encoding)
1731         eventPtr = atts[i].name;
1732       return XML_ERROR_DUPLICATE_ATTRIBUTE;
1733     }
1734     (attId->name)[-1] = 1;
1735     appAtts[attIndex++] = attId->name;
1736     if (!atts[i].normalized) {
1737       enum XML_Error result;
1738       int isCdata = 1;
1739
1740       /* figure out whether declared as other than CDATA */
1741       if (attId->maybeTokenized) {
1742         int j;
1743         for (j = 0; j < nDefaultAtts; j++) {
1744           if (attId == elementType->defaultAtts[j].id) {
1745             isCdata = elementType->defaultAtts[j].isCdata;
1746             break;
1747           }
1748         }
1749       }
1750
1751       /* normalize the attribute value */
1752       result = storeAttributeValue(parser, enc, isCdata,
1753                                    atts[i].valuePtr, atts[i].valueEnd,
1754                                    &tempPool);
1755       if (result)
1756         return result;
1757       if (tagNamePtr) {
1758         appAtts[attIndex] = poolStart(&tempPool);
1759         poolFinish(&tempPool);
1760       }
1761       else
1762         poolDiscard(&tempPool);
1763     }
1764     else if (tagNamePtr) {
1765       /* the value did not need normalizing */
1766       appAtts[attIndex] =
1767           poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
1768       if (appAtts[attIndex] == 0)
1769         return XML_ERROR_NO_MEMORY;
1770       poolFinish(&tempPool);
1771     }
1772     /* handle prefixed attribute names */
1773     if (attId->prefix && tagNamePtr) {
1774       if (attId->xmlns) {
1775         /* deal with namespace declarations here */
1776         if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex],
1777                         bindingsPtr))
1778           return XML_ERROR_NO_MEMORY;
1779         --attIndex;
1780       }
1781       else {
1782         /* deal with other prefixed names later */
1783         attIndex++;
1784         nPrefixes++;
1785         (attId->name)[-1] = 2;
1786       }
1787     }
1788     else
1789       attIndex++;
1790   }
1791   if (tagNamePtr) {
1792     int j;
1793     nSpecifiedAtts = attIndex;
1794     if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
1795       for (i = 0; i < attIndex; i += 2)
1796         if (appAtts[i] == elementType->idAtt->name) {
1797           idAttIndex = i;
1798           break;
1799         }
1800     }
1801     else
1802       idAttIndex = -1;
1803     /* do attribute defaulting */
1804     for (j = 0; j < nDefaultAtts; j++) {
1805       const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j;
1806       if (!(da->id->name)[-1] && da->value) {
1807         if (da->id->prefix) {
1808           if (da->id->xmlns) {
1809             if (!addBinding(parser, da->id->prefix, da->id, da->value,
1810                             bindingsPtr))
1811               return XML_ERROR_NO_MEMORY;
1812           }
1813           else {
1814             (da->id->name)[-1] = 2;
1815             nPrefixes++;
1816             appAtts[attIndex++] = da->id->name;
1817             appAtts[attIndex++] = da->value;
1818           }
1819         }
1820         else {
1821           (da->id->name)[-1] = 1;
1822           appAtts[attIndex++] = da->id->name;
1823           appAtts[attIndex++] = da->value;
1824         }
1825       }
1826     }
1827     appAtts[attIndex] = 0;
1828   }
1829   i = 0;
1830   if (nPrefixes) {
1831     /* expand prefixed attribute names */
1832     for (; i < attIndex; i += 2) {
1833       if (appAtts[i][-1] == 2) {
1834         ATTRIBUTE_ID *id;
1835         ((XML_Char *)(appAtts[i]))[-1] = 0;
1836         id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0);
1837         if (id->prefix->binding) {
1838           int j;
1839           const BINDING *b = id->prefix->binding;
1840           const XML_Char *s = appAtts[i];
1841           for (j = 0; j < b->uriLen; j++) {
1842             if (!poolAppendChar(&tempPool, b->uri[j]))
1843               return XML_ERROR_NO_MEMORY;
1844           }
1845           while (*s++ != ':')
1846             ;
1847           do {
1848             if (!poolAppendChar(&tempPool, *s))
1849               return XML_ERROR_NO_MEMORY;
1850           } while (*s++);
1851           appAtts[i] = poolStart(&tempPool);
1852           poolFinish(&tempPool);
1853         }
1854         if (!--nPrefixes)
1855           break;
1856       }
1857       else
1858         ((XML_Char *)(appAtts[i]))[-1] = 0;
1859     }
1860   }
1861   /* clear the flags that say whether attributes were specified */
1862   for (; i < attIndex; i += 2)
1863     ((XML_Char *)(appAtts[i]))[-1] = 0;
1864   if (!tagNamePtr)
1865     return XML_ERROR_NONE;
1866   for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
1867     binding->attId->name[-1] = 0;
1868   /* expand the element type name */
1869   if (elementType->prefix) {
1870     binding = elementType->prefix->binding;
1871     if (!binding)
1872       return XML_ERROR_NONE;
1873     localPart = tagNamePtr->str;
1874     while (*localPart++ != XML_T(':'))
1875       ;
1876   }
1877   else if (dtd.defaultPrefix.binding) {
1878     binding = dtd.defaultPrefix.binding;
1879     localPart = tagNamePtr->str;
1880   }
1881   else
1882     return XML_ERROR_NONE;
1883   tagNamePtr->localPart = localPart;
1884   tagNamePtr->uriLen = binding->uriLen;
1885   for (i = 0; localPart[i++];)
1886     ;
1887   n = i + binding->uriLen;
1888   if (n > binding->uriAlloc) {
1889     TAG *p;
1890     XML_Char *uri = malloc((n + EXPAND_SPARE) * sizeof(XML_Char));
1891     if (!uri)
1892       return XML_ERROR_NO_MEMORY;
1893     binding->uriAlloc = n + EXPAND_SPARE;
1894     memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
1895     for (p = tagStack; p; p = p->parent)
1896       if (p->name.str == binding->uri)
1897         p->name.str = uri;
1898     free(binding->uri);
1899     binding->uri = uri;
1900   }
1901   memcpy(binding->uri + binding->uriLen, localPart, i * sizeof(XML_Char));
1902   tagNamePtr->str = binding->uri;
1903   return XML_ERROR_NONE;
1904 }
1905
1906 static
1907 int addBinding(XML_Parser parser,
1908                PREFIX *prefix,
1909                const ATTRIBUTE_ID *attId,
1910                const XML_Char *uri,
1911                BINDING **bindingsPtr)
1912 {
1913   BINDING *b;
1914   int len;
1915   for (len = 0; uri[len]; len++)
1916     ;
1917   if (namespaceSeparator)
1918     len++;
1919   if (freeBindingList) {
1920     b = freeBindingList;
1921     if (len > b->uriAlloc) {
1922       b->uri = realloc(b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
1923       if (!b->uri)
1924         return 0;
1925       b->uriAlloc = len + EXPAND_SPARE;
1926     }
1927     freeBindingList = b->nextTagBinding;
1928   }
1929   else {
1930     b = malloc(sizeof(BINDING));
1931     if (!b)
1932       return 0;
1933     b->uri = malloc(sizeof(XML_Char) * (len + EXPAND_SPARE));
1934     if (!b->uri) {
1935       free(b);
1936       return 0;
1937     }
1938     b->uriAlloc = len + EXPAND_SPARE;
1939   }
1940   b->uriLen = len;
1941   memcpy(b->uri, uri, len * sizeof(XML_Char));
1942   if (namespaceSeparator)
1943     b->uri[len - 1] = namespaceSeparator;
1944   b->prefix = prefix;
1945   b->attId = attId;
1946   b->prevPrefixBinding = prefix->binding;
1947   if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix)
1948     prefix->binding = 0;
1949   else
1950     prefix->binding = b;
1951   b->nextTagBinding = *bindingsPtr;
1952   *bindingsPtr = b;
1953   if (startNamespaceDeclHandler)
1954     startNamespaceDeclHandler(handlerArg, prefix->name,
1955                               prefix->binding ? uri : 0);
1956   return 1;
1957 }
1958
1959 /* The idea here is to avoid using stack for each CDATA section when
1960 the whole file is parsed with one call. */
1961
1962 static
1963 enum XML_Error cdataSectionProcessor(XML_Parser parser,
1964                                      const char *start,
1965                                      const char *end,
1966                                      const char **endPtr)
1967 {
1968   enum XML_Error result =
1969       doCdataSection(parser, encoding, &start, end, endPtr);
1970   if (start) {
1971     processor = contentProcessor;
1972     return contentProcessor(parser, start, end, endPtr);
1973   }
1974   return result;
1975 }
1976
1977 /* startPtr gets set to non-null is the section is closed, and to null if
1978 the section is not yet closed. */
1979
1980 static
1981 enum XML_Error doCdataSection(XML_Parser parser,
1982                               const ENCODING *enc,
1983                               const char **startPtr,
1984                               const char *end,
1985                               const char **nextPtr)
1986 {
1987   const char *s = *startPtr;
1988   const char **eventPP;
1989   const char **eventEndPP;
1990   if (enc == encoding) {
1991     eventPP = &eventPtr;
1992     *eventPP = s;
1993     eventEndPP = &eventEndPtr;
1994   }
1995   else {
1996     eventPP = &(openInternalEntities->internalEventPtr);
1997     eventEndPP = &(openInternalEntities->internalEventEndPtr);
1998   }
1999   *eventPP = s;
2000   *startPtr = 0;
2001   for (;;) {
2002     const char *next;
2003     int tok = XmlCdataSectionTok(enc, s, end, &next);
2004     *eventEndPP = next;
2005     switch (tok) {
2006     case XML_TOK_CDATA_SECT_CLOSE:
2007       if (endCdataSectionHandler)
2008         endCdataSectionHandler(handlerArg);
2009       else if (defaultHandler)
2010         reportDefault(parser, enc, s, next);
2011       *startPtr = next;
2012       return XML_ERROR_NONE;
2013     case XML_TOK_DATA_NEWLINE:
2014       if (characterDataHandler) {
2015         XML_Char c = 0xA;
2016         characterDataHandler(handlerArg, &c, 1);
2017       }
2018       else if (defaultHandler)
2019         reportDefault(parser, enc, s, next);
2020       break;
2021     case XML_TOK_DATA_CHARS:
2022       if (characterDataHandler) {
2023         if (MUST_CONVERT(enc, s)) {
2024           for (;;) {
2025             ICHAR *dataPtr = (ICHAR *)dataBuf;
2026             XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
2027             *eventEndPP = next;
2028             characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
2029             if (s == next)
2030               break;
2031             *eventPP = s;
2032           }
2033         }
2034         else
2035           characterDataHandler(handlerArg,
2036                                (XML_Char *)s,
2037                                (XML_Char *)next - (XML_Char *)s);
2038       }
2039       else if (defaultHandler)
2040         reportDefault(parser, enc, s, next);
2041       break;
2042     case XML_TOK_INVALID:
2043       *eventPP = next;
2044       return XML_ERROR_INVALID_TOKEN;
2045     case XML_TOK_PARTIAL_CHAR:
2046       if (nextPtr) {
2047         *nextPtr = s;
2048         return XML_ERROR_NONE;
2049       }
2050       return XML_ERROR_PARTIAL_CHAR;
2051     case XML_TOK_PARTIAL:
2052     case XML_TOK_NONE:
2053       if (nextPtr) {
2054         *nextPtr = s;
2055         return XML_ERROR_NONE;
2056       }
2057       return XML_ERROR_UNCLOSED_CDATA_SECTION;
2058     default:
2059       abort();
2060     }
2061     *eventPP = s = next;
2062   }
2063   /* not reached */
2064 }
2065
2066 #ifdef XML_DTD
2067
2068 /* The idea here is to avoid using stack for each IGNORE section when
2069 the whole file is parsed with one call. */
2070
2071 static
2072 enum XML_Error ignoreSectionProcessor(XML_Parser parser,
2073                                       const char *start,
2074                                       const char *end,
2075                                       const char **endPtr)
2076 {
2077   enum XML_Error result =
2078       doIgnoreSection(parser, encoding, &start, end, endPtr);
2079   if (start) {
2080     processor = prologProcessor;
2081     return prologProcessor(parser, start, end, endPtr);
2082   }
2083   return result;
2084 }
2085
2086 /* startPtr gets set to non-null is the section is closed, and to null if
2087 the section is not yet closed. */
2088
2089 static
2090 enum XML_Error doIgnoreSection(XML_Parser parser,
2091                                const ENCODING *enc,
2092                                const char **startPtr,
2093                                const char *end,
2094                                const char **nextPtr)
2095 {
2096   const char *next;
2097   int tok;
2098   const char *s = *startPtr;
2099   const char **eventPP;
2100   const char **eventEndPP;
2101   if (enc == encoding) {
2102     eventPP = &eventPtr;
2103     *eventPP = s;
2104     eventEndPP = &eventEndPtr;
2105   }
2106   else {
2107     eventPP = &(openInternalEntities->internalEventPtr);
2108     eventEndPP = &(openInternalEntities->internalEventEndPtr);
2109   }
2110   *eventPP = s;
2111   *startPtr = 0;
2112   tok = XmlIgnoreSectionTok(enc, s, end, &next);
2113   *eventEndPP = next;
2114   switch (tok) {
2115   case XML_TOK_IGNORE_SECT:
2116     if (defaultHandler)
2117       reportDefault(parser, enc, s, next);
2118     *startPtr = next;
2119     return XML_ERROR_NONE;
2120   case XML_TOK_INVALID:
2121     *eventPP = next;
2122     return XML_ERROR_INVALID_TOKEN;
2123   case XML_TOK_PARTIAL_CHAR:
2124     if (nextPtr) {
2125       *nextPtr = s;
2126       return XML_ERROR_NONE;
2127     }
2128     return XML_ERROR_PARTIAL_CHAR;
2129   case XML_TOK_PARTIAL:
2130   case XML_TOK_NONE:
2131     if (nextPtr) {
2132       *nextPtr = s;
2133       return XML_ERROR_NONE;
2134     }
2135     return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
2136   default:
2137     abort();
2138   }
2139   /* not reached */
2140 }
2141
2142 #endif /* XML_DTD */
2143
2144 static enum XML_Error
2145 initializeEncoding(XML_Parser parser)
2146 {
2147   const char *s;
2148 #ifdef XML_UNICODE
2149   char encodingBuf[128];
2150   if (!protocolEncodingName)
2151     s = 0;
2152   else {
2153     int i;
2154     for (i = 0; protocolEncodingName[i]; i++) {
2155       if (i == sizeof(encodingBuf) - 1
2156           || (protocolEncodingName[i] & ~0x7f) != 0) {
2157         encodingBuf[0] = '\0';
2158         break;
2159       }
2160       encodingBuf[i] = (char)protocolEncodingName[i];
2161     }
2162     encodingBuf[i] = '\0';
2163     s = encodingBuf;
2164   }
2165 #else
2166   s = protocolEncodingName;
2167 #endif
2168   if ((ns ? XmlInitEncodingNS : xmlrpc_XmlInitEncoding)(&initEncoding, &encoding, s))
2169     return XML_ERROR_NONE;
2170   return handleUnknownEncoding(parser, protocolEncodingName);
2171 }
2172
2173 static enum XML_Error
2174 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
2175                const char *s, const char *next)
2176 {
2177   const char *encodingName = 0;
2178   const ENCODING *newEncoding = 0;
2179   const char *version;
2180   int standalone = -1;
2181   if (!(ns
2182         ? XmlParseXmlDeclNS
2183         : xmlrpc_XmlParseXmlDecl)(isGeneralTextEntity,
2184                            encoding,
2185                            s,
2186                            next,
2187                            &eventPtr,
2188                            &version,
2189                            &encodingName,
2190                            &newEncoding,
2191                            &standalone))
2192     return XML_ERROR_SYNTAX;
2193   if (!isGeneralTextEntity && standalone == 1) {
2194     dtd.standalone = 1;
2195 #ifdef XML_DTD
2196     if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
2197       paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
2198 #endif /* XML_DTD */
2199   }
2200   if (defaultHandler)
2201     reportDefault(parser, encoding, s, next);
2202   if (!protocolEncodingName) {
2203     if (newEncoding) {
2204       if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
2205         eventPtr = encodingName;
2206         return XML_ERROR_INCORRECT_ENCODING;
2207       }
2208       encoding = newEncoding;
2209     }
2210     else if (encodingName) {
2211       enum XML_Error result;
2212       const XML_Char * s =
2213           poolStoreString(&tempPool,
2214                           encoding,
2215                           encodingName,
2216                           encodingName
2217                               + XmlNameLength(encoding, encodingName));
2218       if (!s)
2219         return XML_ERROR_NO_MEMORY;
2220       result = handleUnknownEncoding(parser, s);
2221       poolDiscard(&tempPool);
2222       if (result == XML_ERROR_UNKNOWN_ENCODING)
2223         eventPtr = encodingName;
2224       return result;
2225     }
2226   }
2227   return XML_ERROR_NONE;
2228 }
2229
2230 static enum XML_Error
2231 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
2232 {
2233   if (unknownEncodingHandler) {
2234     XML_Encoding info;
2235     int i;
2236     for (i = 0; i < 256; i++)
2237       info.map[i] = -1;
2238     info.convert = 0;
2239     info.data = 0;
2240     info.release = 0;
2241     if (unknownEncodingHandler(unknownEncodingHandlerData,
2242                                encodingName, &info)) {
2243       ENCODING *enc;
2244       unknownEncodingMem = malloc(xmlrpc_XmlSizeOfUnknownEncoding());
2245       if (!unknownEncodingMem) {
2246         if (info.release)
2247           info.release(info.data);
2248         return XML_ERROR_NO_MEMORY;
2249       }
2250       enc = (ns
2251              ? XmlInitUnknownEncodingNS
2252              : xmlrpc_XmlInitUnknownEncoding)(unknownEncodingMem,
2253                                        info.map,
2254                                        info.convert,
2255                                        info.data);
2256       if (enc) {
2257         unknownEncodingData = info.data;
2258         unknownEncodingRelease = info.release;
2259         encoding = enc;
2260         return XML_ERROR_NONE;
2261       }
2262     }
2263     if (info.release)
2264       info.release(info.data);
2265   }
2266   return XML_ERROR_UNKNOWN_ENCODING;
2267 }
2268
2269 static enum XML_Error
2270 prologInitProcessor(XML_Parser parser,
2271                     const char *s,
2272                     const char *end,
2273                     const char **nextPtr)
2274 {
2275   enum XML_Error result = initializeEncoding(parser);
2276   if (result != XML_ERROR_NONE)
2277     return result;
2278   processor = prologProcessor;
2279   return prologProcessor(parser, s, end, nextPtr);
2280 }
2281
2282 static enum XML_Error
2283 prologProcessor(XML_Parser parser,
2284                 const char *s,
2285                 const char *end,
2286                 const char **nextPtr)
2287 {
2288   const char *next;
2289   int tok = XmlPrologTok(encoding, s, end, &next);
2290   return doProlog(parser, encoding, s, end, tok, next, nextPtr);
2291 }
2292
2293 static enum XML_Error
2294 doProlog(XML_Parser parser,
2295          const ENCODING *enc,
2296          const char *s,
2297          const char *end,
2298          int tok,
2299          const char *next,
2300          const char **nextPtr)
2301 {
2302 #ifdef XML_DTD
2303   static const XML_Char externalSubsetName[] = { '#' , '\0' };
2304 #endif /* XML_DTD */
2305
2306   const char **eventPP;
2307   const char **eventEndPP;
2308   if (enc == encoding) {
2309     eventPP = &eventPtr;
2310     eventEndPP = &eventEndPtr;
2311   }
2312   else {
2313     eventPP = &(openInternalEntities->internalEventPtr);
2314     eventEndPP = &(openInternalEntities->internalEventEndPtr);
2315   }
2316   for (;;) {
2317     int role;
2318     *eventPP = s;
2319     *eventEndPP = next;
2320     if (tok <= 0) {
2321       if (nextPtr != 0 && tok != XML_TOK_INVALID) {
2322         *nextPtr = s;
2323         return XML_ERROR_NONE;
2324       }
2325       switch (tok) {
2326       case XML_TOK_INVALID:
2327         *eventPP = next;
2328         return XML_ERROR_INVALID_TOKEN;
2329       case XML_TOK_PARTIAL:
2330         return XML_ERROR_UNCLOSED_TOKEN;
2331       case XML_TOK_PARTIAL_CHAR:
2332         return XML_ERROR_PARTIAL_CHAR;
2333       case XML_TOK_NONE:
2334 #ifdef XML_DTD
2335         if (enc != encoding)
2336           return XML_ERROR_NONE;
2337         if (parentParser) {
2338           if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
2339               == XML_ROLE_ERROR)
2340             return XML_ERROR_SYNTAX;
2341           hadExternalDoctype = 0;
2342           return XML_ERROR_NONE;
2343         }
2344 #endif /* XML_DTD */
2345         return XML_ERROR_NO_ELEMENTS;
2346       default:
2347         tok = -tok;
2348         next = end;
2349         break;
2350       }
2351     }
2352     role = XmlTokenRole(&prologState, tok, s, next, enc);
2353     switch (role) {
2354     case XML_ROLE_XML_DECL:
2355       {
2356         enum XML_Error result = processXmlDecl(parser, 0, s, next);
2357         if (result != XML_ERROR_NONE)
2358           return result;
2359         enc = encoding;
2360       }
2361       break;
2362     case XML_ROLE_DOCTYPE_NAME:
2363       if (startDoctypeDeclHandler) {
2364         const XML_Char *name = poolStoreString(&tempPool, enc, s, next);
2365         if (!name)
2366           return XML_ERROR_NO_MEMORY;
2367         startDoctypeDeclHandler(handlerArg, name);
2368         poolClear(&tempPool);
2369       }
2370       break;
2371 #ifdef XML_DTD
2372     case XML_ROLE_TEXT_DECL:
2373       {
2374         enum XML_Error result = processXmlDecl(parser, 1, s, next);
2375         if (result != XML_ERROR_NONE)
2376           return result;
2377         enc = encoding;
2378       }
2379       break;
2380 #endif /* XML_DTD */
2381     case XML_ROLE_DOCTYPE_PUBLIC_ID:
2382 #ifdef XML_DTD
2383       declEntity = (ENTITY *)lookup(&dtd.paramEntities,
2384                                     externalSubsetName,
2385                                     sizeof(ENTITY));
2386       if (!declEntity)
2387         return XML_ERROR_NO_MEMORY;
2388 #endif /* XML_DTD */
2389       /* fall through */
2390     case XML_ROLE_ENTITY_PUBLIC_ID:
2391       if (!XmlIsPublicId(enc, s, next, eventPP))
2392         return XML_ERROR_SYNTAX;
2393       if (declEntity) {
2394         XML_Char *tem = poolStoreString(&dtd.pool,
2395                                         enc,
2396                                         s + enc->minBytesPerChar,
2397                                         next - enc->minBytesPerChar);
2398         if (!tem)
2399           return XML_ERROR_NO_MEMORY;
2400         normalizePublicId(tem);
2401         declEntity->publicId = tem;
2402         poolFinish(&dtd.pool);
2403       }
2404       break;
2405     case XML_ROLE_DOCTYPE_CLOSE:
2406       if (dtd.complete && hadExternalDoctype) {
2407         dtd.complete = 0;
2408 #ifdef XML_DTD
2409         if (paramEntityParsing && externalEntityRefHandler) {
2410           ENTITY *entity = (ENTITY *)lookup(&dtd.paramEntities,
2411                                             externalSubsetName,
2412                                             0);
2413           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
2414                                         0,
2415                                         entity->base,
2416                                         entity->systemId,
2417                                         entity->publicId))
2418            return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2419         }
2420 #endif /* XML_DTD */
2421         if (!dtd.complete
2422             && !dtd.standalone
2423             && notStandaloneHandler
2424             && !notStandaloneHandler(handlerArg))
2425           return XML_ERROR_NOT_STANDALONE;
2426       }
2427       if (endDoctypeDeclHandler)
2428         endDoctypeDeclHandler(handlerArg);
2429       break;
2430     case XML_ROLE_INSTANCE_START:
2431       processor = contentProcessor;
2432       return contentProcessor(parser, s, end, nextPtr);
2433     case XML_ROLE_ATTLIST_ELEMENT_NAME:
2434       {
2435         const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next);
2436         if (!name)
2437           return XML_ERROR_NO_MEMORY;
2438         declElementType = (ELEMENT_TYPE *)
2439             lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
2440         if (!declElementType)
2441           return XML_ERROR_NO_MEMORY;
2442         if (declElementType->name != name)
2443           poolDiscard(&dtd.pool);
2444         else {
2445           poolFinish(&dtd.pool);
2446           if (!setElementTypePrefix(parser, declElementType))
2447             return XML_ERROR_NO_MEMORY;
2448         }
2449         break;
2450       }
2451     case XML_ROLE_ATTRIBUTE_NAME:
2452       declAttributeId = getAttributeId(parser, enc, s, next);
2453       if (!declAttributeId)
2454         return XML_ERROR_NO_MEMORY;
2455       declAttributeIsCdata = 0;
2456       declAttributeIsId = 0;
2457       break;
2458     case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
2459       declAttributeIsCdata = 1;
2460       break;
2461     case XML_ROLE_ATTRIBUTE_TYPE_ID:
2462       declAttributeIsId = 1;
2463       break;
2464     case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
2465     case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
2466       if (dtd.complete
2467           && !defineAttribute(declElementType, declAttributeId,
2468                               declAttributeIsCdata,
2469                               declAttributeIsId, 0))
2470         return XML_ERROR_NO_MEMORY;
2471       break;
2472     case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
2473     case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
2474       {
2475         const XML_Char *attVal;
2476         enum XML_Error result
2477           = storeAttributeValue(parser, enc, declAttributeIsCdata,
2478                                 s + enc->minBytesPerChar,
2479                                 next - enc->minBytesPerChar,
2480                                 &dtd.pool);
2481         if (result)
2482           return result;
2483         attVal = poolStart(&dtd.pool);
2484         poolFinish(&dtd.pool);
2485         if (dtd.complete
2486             /* ID attributes aren't allowed to have a default */
2487             && !defineAttribute(declElementType, declAttributeId,
2488                                 declAttributeIsCdata, 0, attVal))
2489           return XML_ERROR_NO_MEMORY;
2490         break;
2491       }
2492     case XML_ROLE_ENTITY_VALUE:
2493       {
2494         enum XML_Error result = storeEntityValue(parser, enc,
2495                                                  s + enc->minBytesPerChar,
2496                                                  next - enc->minBytesPerChar);
2497         if (declEntity) {
2498           declEntity->textPtr = poolStart(&dtd.pool);
2499           declEntity->textLen = poolLength(&dtd.pool);
2500           poolFinish(&dtd.pool);
2501           if (internalParsedEntityDeclHandler
2502               /* Check it's not a parameter entity */
2503               && ((ENTITY *)lookup(&dtd.generalEntities, declEntity->name, 0)
2504                   == declEntity)) {
2505             *eventEndPP = s;
2506             internalParsedEntityDeclHandler(handlerArg,
2507                                             declEntity->name,
2508                                             declEntity->textPtr,
2509                                             declEntity->textLen);
2510           }
2511         }
2512         else
2513           poolDiscard(&dtd.pool);
2514         if (result != XML_ERROR_NONE)
2515           return result;
2516       }
2517       break;
2518     case XML_ROLE_DOCTYPE_SYSTEM_ID:
2519       if (!dtd.standalone
2520 #ifdef XML_DTD
2521           && !paramEntityParsing
2522 #endif /* XML_DTD */
2523           && notStandaloneHandler
2524           && !notStandaloneHandler(handlerArg))
2525         return XML_ERROR_NOT_STANDALONE;
2526       hadExternalDoctype = 1;
2527 #ifndef XML_DTD
2528       break;
2529 #else /* XML_DTD */
2530       if (!declEntity) {
2531         declEntity = (ENTITY *)lookup(&dtd.paramEntities,
2532                                       externalSubsetName,
2533                                       sizeof(ENTITY));
2534         if (!declEntity)
2535           return XML_ERROR_NO_MEMORY;
2536       }
2537       /* fall through */
2538 #endif /* XML_DTD */
2539     case XML_ROLE_ENTITY_SYSTEM_ID:
2540       if (declEntity) {
2541         declEntity->systemId = poolStoreString(&dtd.pool, enc,
2542                                                s + enc->minBytesPerChar,
2543                                                next - enc->minBytesPerChar);
2544         if (!declEntity->systemId)
2545           return XML_ERROR_NO_MEMORY;
2546         declEntity->base = curBase;
2547         poolFinish(&dtd.pool);
2548       }
2549       break;
2550     case XML_ROLE_ENTITY_NOTATION_NAME:
2551       if (declEntity) {
2552         declEntity->notation = poolStoreString(&dtd.pool, enc, s, next);
2553         if (!declEntity->notation)
2554           return XML_ERROR_NO_MEMORY;
2555         poolFinish(&dtd.pool);
2556         if (unparsedEntityDeclHandler) {
2557           *eventEndPP = s;
2558           unparsedEntityDeclHandler(handlerArg,
2559                                     declEntity->name,
2560                                     declEntity->base,
2561                                     declEntity->systemId,
2562                                     declEntity->publicId,
2563                                     declEntity->notation);
2564         }
2565
2566       }
2567       break;
2568     case XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION:
2569       if (declEntity && externalParsedEntityDeclHandler) {
2570         *eventEndPP = s;
2571         externalParsedEntityDeclHandler(handlerArg,
2572                                         declEntity->name,
2573                                         declEntity->base,
2574                                         declEntity->systemId,
2575                                         declEntity->publicId);
2576       }
2577       break;
2578     case XML_ROLE_GENERAL_ENTITY_NAME:
2579       {
2580         const XML_Char *name;
2581         if (XmlPredefinedEntityName(enc, s, next)) {
2582           declEntity = 0;
2583           break;
2584         }
2585         name = poolStoreString(&dtd.pool, enc, s, next);
2586         if (!name)
2587           return XML_ERROR_NO_MEMORY;
2588         if (dtd.complete) {
2589             declEntity = (ENTITY *)
2590                 lookup(&dtd.generalEntities, name, sizeof(ENTITY));
2591           if (!declEntity)
2592             return XML_ERROR_NO_MEMORY;
2593           if (declEntity->name != name) {
2594             poolDiscard(&dtd.pool);
2595             declEntity = 0;
2596           }
2597           else
2598             poolFinish(&dtd.pool);
2599         }
2600         else {
2601           poolDiscard(&dtd.pool);
2602           declEntity = 0;
2603         }
2604       }
2605       break;
2606     case XML_ROLE_PARAM_ENTITY_NAME:
2607 #ifdef XML_DTD
2608       if (dtd.complete) {
2609         const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next);
2610         if (!name)
2611           return XML_ERROR_NO_MEMORY;
2612         declEntity = (ENTITY *)
2613             lookup(&dtd.paramEntities, name, sizeof(ENTITY));
2614         if (!declEntity)
2615           return XML_ERROR_NO_MEMORY;
2616         if (declEntity->name != name) {
2617           poolDiscard(&dtd.pool);
2618           declEntity = 0;
2619         }
2620         else
2621           poolFinish(&dtd.pool);
2622       }
2623 #else /* not XML_DTD */
2624       declEntity = 0;
2625 #endif /* not XML_DTD */
2626       break;
2627     case XML_ROLE_NOTATION_NAME:
2628       declNotationPublicId = 0;
2629       declNotationName = 0;
2630       if (notationDeclHandler) {
2631         declNotationName = poolStoreString(&tempPool, enc, s, next);
2632         if (!declNotationName)
2633           return XML_ERROR_NO_MEMORY;
2634         poolFinish(&tempPool);
2635       }
2636       break;
2637     case XML_ROLE_NOTATION_PUBLIC_ID:
2638       if (!XmlIsPublicId(enc, s, next, eventPP))
2639         return XML_ERROR_SYNTAX;
2640       if (declNotationName) {
2641         XML_Char *tem = poolStoreString(&tempPool,
2642                                         enc,
2643                                         s + enc->minBytesPerChar,
2644                                         next - enc->minBytesPerChar);
2645         if (!tem)
2646           return XML_ERROR_NO_MEMORY;
2647         normalizePublicId(tem);
2648         declNotationPublicId = tem;
2649         poolFinish(&tempPool);
2650       }
2651       break;
2652     case XML_ROLE_NOTATION_SYSTEM_ID:
2653       if (declNotationName && notationDeclHandler) {
2654         const XML_Char *systemId
2655           = poolStoreString(&tempPool, enc,
2656                             s + enc->minBytesPerChar,
2657                             next - enc->minBytesPerChar);
2658         if (!systemId)
2659           return XML_ERROR_NO_MEMORY;
2660         *eventEndPP = s;
2661         notationDeclHandler(handlerArg,
2662                             declNotationName,
2663                             curBase,
2664                             systemId,
2665                             declNotationPublicId);
2666       }
2667       poolClear(&tempPool);
2668       break;
2669     case XML_ROLE_NOTATION_NO_SYSTEM_ID:
2670       if (declNotationPublicId && notationDeclHandler) {
2671         *eventEndPP = s;
2672         notationDeclHandler(handlerArg,
2673                             declNotationName,
2674                             curBase,
2675                             0,
2676                             declNotationPublicId);
2677       }
2678       poolClear(&tempPool);
2679       break;
2680     case XML_ROLE_ERROR:
2681       switch (tok) {
2682       case XML_TOK_PARAM_ENTITY_REF:
2683         return XML_ERROR_PARAM_ENTITY_REF;
2684       case XML_TOK_XML_DECL:
2685         return XML_ERROR_MISPLACED_XML_PI;
2686       default:
2687         return XML_ERROR_SYNTAX;
2688       }
2689 #ifdef XML_DTD
2690     case XML_ROLE_IGNORE_SECT:
2691       {
2692         enum XML_Error result;
2693         if (defaultHandler)
2694           reportDefault(parser, enc, s, next);
2695         result = doIgnoreSection(parser, enc, &next, end, nextPtr);
2696         if (!next) {
2697           processor = ignoreSectionProcessor;
2698           return result;
2699         }
2700       }
2701       break;
2702 #endif /* XML_DTD */
2703     case XML_ROLE_GROUP_OPEN:
2704       if (prologState.level >= groupSize) {
2705         if (groupSize)
2706           groupConnector = realloc(groupConnector, groupSize *= 2);
2707         else
2708           groupConnector = malloc(groupSize = 32);
2709         if (!groupConnector)
2710           return XML_ERROR_NO_MEMORY;
2711       }
2712       groupConnector[prologState.level] = 0;
2713       break;
2714     case XML_ROLE_GROUP_SEQUENCE:
2715       if (groupConnector[prologState.level] == '|')
2716         return XML_ERROR_SYNTAX;
2717       groupConnector[prologState.level] = ',';
2718       break;
2719     case XML_ROLE_GROUP_CHOICE:
2720       if (groupConnector[prologState.level] == ',')
2721         return XML_ERROR_SYNTAX;
2722       groupConnector[prologState.level] = '|';
2723       break;
2724     case XML_ROLE_PARAM_ENTITY_REF:
2725 #ifdef XML_DTD
2726     case XML_ROLE_INNER_PARAM_ENTITY_REF:
2727       if (paramEntityParsing
2728           && (dtd.complete || role == XML_ROLE_INNER_PARAM_ENTITY_REF)) {
2729         const XML_Char *name;
2730         ENTITY *entity;
2731         name = poolStoreString(&dtd.pool, enc,
2732                                 s + enc->minBytesPerChar,
2733                                 next - enc->minBytesPerChar);
2734         if (!name)
2735           return XML_ERROR_NO_MEMORY;
2736         entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
2737         poolDiscard(&dtd.pool);
2738         if (!entity) {
2739           /* FIXME what to do if !dtd.complete? */
2740           return XML_ERROR_UNDEFINED_ENTITY;
2741         }
2742         if (entity->open)
2743           return XML_ERROR_RECURSIVE_ENTITY_REF;
2744         if (entity->textPtr) {
2745           enum XML_Error result;
2746           result = processInternalParamEntity(parser, entity);
2747           if (result != XML_ERROR_NONE)
2748             return result;
2749           break;
2750         }
2751         if (role == XML_ROLE_INNER_PARAM_ENTITY_REF)
2752           return XML_ERROR_PARAM_ENTITY_REF;
2753         if (externalEntityRefHandler) {
2754           dtd.complete = 0;
2755           entity->open = 1;
2756           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
2757                                         0,
2758                                         entity->base,
2759                                         entity->systemId,
2760                                         entity->publicId)) {
2761             entity->open = 0;
2762             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2763           }
2764           entity->open = 0;
2765           if (dtd.complete)
2766             break;
2767         }
2768       }
2769 #endif /* XML_DTD */
2770       if (!dtd.standalone
2771           && notStandaloneHandler
2772           && !notStandaloneHandler(handlerArg))
2773         return XML_ERROR_NOT_STANDALONE;
2774       dtd.complete = 0;
2775       if (defaultHandler)
2776         reportDefault(parser, enc, s, next);
2777       break;
2778     case XML_ROLE_NONE:
2779       switch (tok) {
2780       case XML_TOK_PI:
2781         if (!reportProcessingInstruction(parser, enc, s, next))
2782           return XML_ERROR_NO_MEMORY;
2783         break;
2784       case XML_TOK_COMMENT:
2785         if (!reportComment(parser, enc, s, next))
2786           return XML_ERROR_NO_MEMORY;
2787         break;
2788       }
2789       break;
2790     }
2791     if (defaultHandler) {
2792       switch (tok) {
2793       case XML_TOK_PI:
2794       case XML_TOK_COMMENT:
2795       case XML_TOK_BOM:
2796       case XML_TOK_XML_DECL:
2797 #ifdef XML_DTD
2798       case XML_TOK_IGNORE_SECT:
2799 #endif /* XML_DTD */
2800       case XML_TOK_PARAM_ENTITY_REF:
2801         break;
2802       default:
2803 #ifdef XML_DTD
2804         if (role != XML_ROLE_IGNORE_SECT)
2805 #endif /* XML_DTD */
2806           reportDefault(parser, enc, s, next);
2807       }
2808     }
2809     s = next;
2810     tok = XmlPrologTok(enc, s, end, &next);
2811   }
2812   /* not reached */
2813 }
2814
2815 static
2816 enum XML_Error epilogProcessor(XML_Parser parser,
2817                                const char *s,
2818                                const char *end,
2819                                const char **nextPtr)
2820 {
2821   processor = epilogProcessor;
2822   eventPtr = s;
2823   for (;;) {
2824     const char *next;
2825     int tok = XmlPrologTok(encoding, s, end, &next);
2826     eventEndPtr = next;
2827     switch (tok) {
2828     case -XML_TOK_PROLOG_S:
2829       if (defaultHandler) {
2830         eventEndPtr = end;
2831         reportDefault(parser, encoding, s, end);
2832       }
2833       /* fall through */
2834     case XML_TOK_NONE:
2835       if (nextPtr)
2836         *nextPtr = end;
2837       return XML_ERROR_NONE;
2838     case XML_TOK_PROLOG_S:
2839       if (defaultHandler)
2840         reportDefault(parser, encoding, s, next);
2841       break;
2842     case XML_TOK_PI:
2843       if (!reportProcessingInstruction(parser, encoding, s, next))
2844         return XML_ERROR_NO_MEMORY;
2845       break;
2846     case XML_TOK_COMMENT:
2847       if (!reportComment(parser, encoding, s, next))
2848         return XML_ERROR_NO_MEMORY;
2849       break;
2850     case XML_TOK_INVALID:
2851       eventPtr = next;
2852       return XML_ERROR_INVALID_TOKEN;
2853     case XML_TOK_PARTIAL:
2854       if (nextPtr) {
2855         *nextPtr = s;
2856         return XML_ERROR_NONE;
2857       }
2858       return XML_ERROR_UNCLOSED_TOKEN;
2859     case XML_TOK_PARTIAL_CHAR:
2860       if (nextPtr) {
2861         *nextPtr = s;
2862         return XML_ERROR_NONE;
2863       }
2864       return XML_ERROR_PARTIAL_CHAR;
2865     default:
2866       return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
2867     }
2868     eventPtr = s = next;
2869   }
2870 }
2871
2872 #ifdef XML_DTD
2873
2874 static enum XML_Error
2875 processInternalParamEntity(XML_Parser parser, ENTITY *entity)
2876 {
2877   const char *s, *end, *next;
2878   int tok;
2879   enum XML_Error result;
2880   OPEN_INTERNAL_ENTITY openEntity;
2881   entity->open = 1;
2882   openEntity.next = openInternalEntities;
2883   openInternalEntities = &openEntity;
2884   openEntity.entity = entity;
2885   openEntity.internalEventPtr = 0;
2886   openEntity.internalEventEndPtr = 0;
2887   s = (char *)entity->textPtr;
2888   end = (char *)(entity->textPtr + entity->textLen);
2889   tok = XmlPrologTok(internalEncoding, s, end, &next);
2890   result = doProlog(parser, internalEncoding, s, end, tok, next, 0);
2891   entity->open = 0;
2892   openInternalEntities = openEntity.next;
2893   return result;
2894 }
2895
2896 #endif /* XML_DTD */
2897
2898
2899
2900 static enum XML_Error
2901 errorProcessor(XML_Parser    const parser  ATTR_UNUSED,
2902                const char *  const s       ATTR_UNUSED,
2903                const char *  const end     ATTR_UNUSED,
2904                const char ** const nextPtr ATTR_UNUSED) {
2905
2906     return errorCode;
2907 }
2908
2909
2910
2911 static enum XML_Error
2912 storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
2913                     const char *ptr, const char *end,
2914                     STRING_POOL *pool)
2915 {
2916   enum XML_Error result =
2917       appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
2918   if (result)
2919     return result;
2920   if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
2921     poolChop(pool);
2922   if (!poolAppendChar(pool, XML_T('\0')))
2923     return XML_ERROR_NO_MEMORY;
2924   return XML_ERROR_NONE;
2925 }
2926
2927 static enum XML_Error
2928 appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
2929                      const char *ptr, const char *end,
2930                      STRING_POOL *pool)
2931 {
2932   for (;;) {
2933     const char *next;
2934     int tok = XmlAttributeValueTok(enc, ptr, end, &next);
2935     switch (tok) {
2936     case XML_TOK_NONE:
2937       return XML_ERROR_NONE;
2938     case XML_TOK_INVALID:
2939       if (enc == encoding)
2940         eventPtr = next;
2941       return XML_ERROR_INVALID_TOKEN;
2942     case XML_TOK_PARTIAL:
2943       if (enc == encoding)
2944         eventPtr = ptr;
2945       return XML_ERROR_INVALID_TOKEN;
2946     case XML_TOK_CHAR_REF:
2947       {
2948         XML_Char buf[XML_ENCODE_MAX];
2949         int i;
2950         int n = XmlCharRefNumber(enc, ptr);
2951         if (n < 0) {
2952           if (enc == encoding)
2953             eventPtr = ptr;
2954           return XML_ERROR_BAD_CHAR_REF;
2955         }
2956         if (!isCdata
2957             && n == 0x20 /* space */
2958             && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
2959           break;
2960         n = XmlEncode(n, (ICHAR *)buf);
2961         if (!n) {
2962           if (enc == encoding)
2963             eventPtr = ptr;
2964           return XML_ERROR_BAD_CHAR_REF;
2965         }
2966         for (i = 0; i < n; i++) {
2967           if (!poolAppendChar(pool, buf[i]))
2968             return XML_ERROR_NO_MEMORY;
2969         }
2970       }
2971       break;
2972     case XML_TOK_DATA_CHARS:
2973       if (!poolAppend(pool, enc, ptr, next))
2974         return XML_ERROR_NO_MEMORY;
2975       break;
2976       break;
2977     case XML_TOK_TRAILING_CR:
2978       next = ptr + enc->minBytesPerChar;
2979       /* fall through */
2980     case XML_TOK_ATTRIBUTE_VALUE_S:
2981     case XML_TOK_DATA_NEWLINE:
2982       if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
2983         break;
2984       if (!poolAppendChar(pool, 0x20))
2985         return XML_ERROR_NO_MEMORY;
2986       break;
2987     case XML_TOK_ENTITY_REF:
2988       {
2989         const XML_Char *name;
2990         ENTITY *entity;
2991         XML_Char ch = XmlPredefinedEntityName(enc,
2992                                               ptr + enc->minBytesPerChar,
2993                                               next - enc->minBytesPerChar);
2994         if (ch) {
2995           if (!poolAppendChar(pool, ch))
2996             return XML_ERROR_NO_MEMORY;
2997           break;
2998         }
2999         name = poolStoreString(&temp2Pool, enc,
3000                                ptr + enc->minBytesPerChar,
3001                                next - enc->minBytesPerChar);
3002         if (!name)
3003           return XML_ERROR_NO_MEMORY;
3004         entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
3005         poolDiscard(&temp2Pool);
3006         if (!entity) {
3007           if (dtd.complete) {
3008             if (enc == encoding)
3009               eventPtr = ptr;
3010             return XML_ERROR_UNDEFINED_ENTITY;
3011           }
3012         }
3013         else if (entity->open) {
3014           if (enc == encoding)
3015             eventPtr = ptr;
3016           return XML_ERROR_RECURSIVE_ENTITY_REF;
3017         }
3018         else if (entity->notation) {
3019           if (enc == encoding)
3020             eventPtr = ptr;
3021           return XML_ERROR_BINARY_ENTITY_REF;
3022         }
3023         else if (!entity->textPtr) {
3024           if (enc == encoding)
3025             eventPtr = ptr;
3026           return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
3027         }
3028         else {
3029           enum XML_Error result;
3030           const XML_Char *textEnd = entity->textPtr + entity->textLen;
3031           entity->open = 1;
3032           result = appendAttributeValue(parser, internalEncoding,
3033                                         isCdata, (char *)entity->textPtr,
3034                                         (char *)textEnd, pool);
3035           entity->open = 0;
3036           if (result)
3037             return result;
3038         }
3039       }
3040       break;
3041     default:
3042       abort();
3043     }
3044     ptr = next;
3045   }
3046   /* not reached */
3047 }
3048
3049 static
3050 enum XML_Error storeEntityValue(XML_Parser parser,
3051                                 const ENCODING *enc,
3052                                 const char *entityTextPtr,
3053                                 const char *entityTextEnd)
3054 {
3055   STRING_POOL *pool = &(dtd.pool);
3056   for (;;) {
3057     const char *next;
3058     int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
3059     switch (tok) {
3060     case XML_TOK_PARAM_ENTITY_REF:
3061 #ifdef XML_DTD
3062       if (parentParser || enc != encoding) {
3063         enum XML_Error result;
3064         const XML_Char *name;
3065         ENTITY *entity;
3066         name = poolStoreString(&tempPool, enc,
3067                                entityTextPtr + enc->minBytesPerChar,
3068                                next - enc->minBytesPerChar);
3069         if (!name)
3070           return XML_ERROR_NO_MEMORY;
3071         entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
3072         poolDiscard(&tempPool);
3073         if (!entity) {
3074           if (enc == encoding)
3075             eventPtr = entityTextPtr;
3076           return XML_ERROR_UNDEFINED_ENTITY;
3077         }
3078         if (entity->open) {
3079           if (enc == encoding)
3080             eventPtr = entityTextPtr;
3081           return XML_ERROR_RECURSIVE_ENTITY_REF;
3082         }
3083         if (entity->systemId) {
3084           if (enc == encoding)
3085             eventPtr = entityTextPtr;
3086           return XML_ERROR_PARAM_ENTITY_REF;
3087         }
3088         entity->open = 1;
3089         result = storeEntityValue(parser,
3090                                   internalEncoding,
3091                                   (char *)entity->textPtr,
3092                                   (char *)(entity->textPtr + entity->textLen));
3093         entity->open = 0;
3094         if (result)
3095           return result;
3096         break;
3097       }
3098 #endif /* XML_DTD */
3099       eventPtr = entityTextPtr;
3100       return XML_ERROR_SYNTAX;
3101     case XML_TOK_NONE:
3102       return XML_ERROR_NONE;
3103     case XML_TOK_ENTITY_REF:
3104     case XML_TOK_DATA_CHARS:
3105       if (!poolAppend(pool, enc, entityTextPtr, next))
3106         return XML_ERROR_NO_MEMORY;
3107       break;
3108     case XML_TOK_TRAILING_CR:
3109       next = entityTextPtr + enc->minBytesPerChar;
3110       /* fall through */
3111     case XML_TOK_DATA_NEWLINE:
3112       if (pool->end == pool->ptr && !poolGrow(pool))
3113         return XML_ERROR_NO_MEMORY;
3114       *(pool->ptr)++ = 0xA;
3115       break;
3116     case XML_TOK_CHAR_REF:
3117       {
3118         XML_Char buf[XML_ENCODE_MAX];
3119         int i;
3120         int n = XmlCharRefNumber(enc, entityTextPtr);
3121         if (n < 0) {
3122           if (enc == encoding)
3123             eventPtr = entityTextPtr;
3124           return XML_ERROR_BAD_CHAR_REF;
3125         }
3126         n = XmlEncode(n, (ICHAR *)buf);
3127         if (!n) {
3128           if (enc == encoding)
3129             eventPtr = entityTextPtr;
3130           return XML_ERROR_BAD_CHAR_REF;
3131         }
3132         for (i = 0; i < n; i++) {
3133           if (pool->end == pool->ptr && !poolGrow(pool))
3134             return XML_ERROR_NO_MEMORY;
3135           *(pool->ptr)++ = buf[i];
3136         }
3137       }
3138       break;
3139     case XML_TOK_PARTIAL:
3140       if (enc == encoding)
3141         eventPtr = entityTextPtr;
3142       return XML_ERROR_INVALID_TOKEN;
3143     case XML_TOK_INVALID:
3144       if (enc == encoding)
3145         eventPtr = next;
3146       return XML_ERROR_INVALID_TOKEN;
3147     default:
3148       abort();
3149     }
3150     entityTextPtr = next;
3151   }
3152   /* not reached */
3153 }
3154
3155 static void
3156 normalizeLines(XML_Char *s)
3157 {
3158   XML_Char *p;
3159   for (;; s++) {
3160     if (*s == XML_T('\0'))
3161       return;
3162     if (*s == 0xD)
3163       break;
3164   }
3165   p = s;
3166   do {
3167     if (*s == 0xD) {
3168       *p++ = 0xA;
3169       if (*++s == 0xA)
3170         s++;
3171     }
3172     else
3173       *p++ = *s++;
3174   } while (*s);
3175   *p = XML_T('\0');
3176 }
3177
3178 static int
3179 reportProcessingInstruction(XML_Parser parser,
3180                             const ENCODING *enc,
3181                             const char *start,
3182                             const char *end)
3183 {
3184   const XML_Char *target;
3185   XML_Char *data;
3186   const char *tem;
3187   if (!processingInstructionHandler) {
3188     if (defaultHandler)
3189       reportDefault(parser, enc, start, end);
3190     return 1;
3191   }
3192   start += enc->minBytesPerChar * 2;
3193   tem = start + XmlNameLength(enc, start);
3194   target = poolStoreString(&tempPool, enc, start, tem);
3195   if (!target)
3196     return 0;
3197   poolFinish(&tempPool);
3198   data = poolStoreString(&tempPool, enc,
3199                         XmlSkipS(enc, tem),
3200                         end - enc->minBytesPerChar*2);
3201   if (!data)
3202     return 0;
3203   normalizeLines(data);
3204   processingInstructionHandler(handlerArg, target, data);
3205   poolClear(&tempPool);
3206   return 1;
3207 }
3208
3209 static int
3210 reportComment(XML_Parser parser,
3211               const ENCODING *enc,
3212               const char *start,
3213               const char *end)
3214 {
3215   XML_Char *data;
3216   if (!commentHandler) {
3217     if (defaultHandler)
3218       reportDefault(parser, enc, start, end);
3219     return 1;
3220   }
3221   data = poolStoreString(&tempPool,
3222                          enc,
3223                          start + enc->minBytesPerChar * 4, 
3224                          end - enc->minBytesPerChar * 3);
3225   if (!data)
3226     return 0;
3227   normalizeLines(data);
3228   commentHandler(handlerArg, data);
3229   poolClear(&tempPool);
3230   return 1;
3231 }
3232
3233 static void
3234 reportDefault(XML_Parser parser,
3235               const ENCODING *enc,
3236               const char *s,
3237               const char *end)
3238 {
3239   if (MUST_CONVERT(enc, s)) {
3240     const char **eventPP;
3241     const char **eventEndPP;
3242     if (enc == encoding) {
3243       eventPP = &eventPtr;
3244       eventEndPP = &eventEndPtr;
3245     }
3246     else {
3247       eventPP = &(openInternalEntities->internalEventPtr);
3248       eventEndPP = &(openInternalEntities->internalEventEndPtr);
3249     }
3250     do {
3251       ICHAR *dataPtr = (ICHAR *)dataBuf;
3252       XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
3253       *eventEndPP = s;
3254       defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
3255       *eventPP = s;
3256     } while (s != end);
3257   }
3258   else
3259     defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
3260 }
3261
3262
3263 static int
3264 defineAttribute(ELEMENT_TYPE *type,
3265                 ATTRIBUTE_ID *attId,
3266                 int isCdata,
3267                 int isId,
3268                 const XML_Char *value)
3269 {
3270   DEFAULT_ATTRIBUTE *att;
3271   if (value || isId) {
3272     /* The handling of default attributes gets messed up if we have
3273        a default which duplicates a non-default. */
3274     int i;
3275     for (i = 0; i < type->nDefaultAtts; i++)
3276       if (attId == type->defaultAtts[i].id)
3277         return 1;
3278     if (isId && !type->idAtt && !attId->xmlns)
3279       type->idAtt = attId;
3280   }
3281   if (type->nDefaultAtts == type->allocDefaultAtts) {
3282     if (type->allocDefaultAtts == 0) {
3283       type->allocDefaultAtts = 8;
3284       type->defaultAtts =
3285           malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
3286     }
3287     else {
3288       type->allocDefaultAtts *= 2;
3289       type->defaultAtts =
3290           realloc(type->defaultAtts,
3291                   type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
3292     }
3293     if (!type->defaultAtts)
3294       return 0;
3295   }
3296   att = type->defaultAtts + type->nDefaultAtts;
3297   att->id = attId;
3298   att->value = value;
3299   att->isCdata = isCdata;
3300   if (!isCdata)
3301     attId->maybeTokenized = 1;
3302   type->nDefaultAtts += 1;
3303   return 1;
3304 }
3305
3306 static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
3307 {
3308   const XML_Char *name;
3309   for (name = elementType->name; *name; name++) {
3310     if (*name == XML_T(':')) {
3311       PREFIX *prefix;
3312       const XML_Char *s;
3313       for (s = elementType->name; s != name; s++) {
3314         if (!poolAppendChar(&dtd.pool, *s))
3315           return 0;
3316       }
3317       if (!poolAppendChar(&dtd.pool, XML_T('\0')))
3318         return 0;
3319       prefix = (PREFIX *)
3320           lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
3321       if (!prefix)
3322         return 0;
3323       if (prefix->name == poolStart(&dtd.pool))
3324         poolFinish(&dtd.pool);
3325       else
3326         poolDiscard(&dtd.pool);
3327       elementType->prefix = prefix;
3328
3329     }
3330   }
3331   return 1;
3332 }
3333
3334 static ATTRIBUTE_ID *
3335 getAttributeId(XML_Parser parser,
3336                const ENCODING *enc,
3337                const char *start,
3338                const char *end)
3339 {
3340   ATTRIBUTE_ID *id;
3341   const XML_Char *name;
3342   if (!poolAppendChar(&dtd.pool, XML_T('\0')))
3343     return 0;
3344   name = poolStoreString(&dtd.pool, enc, start, end);
3345   if (!name)
3346     return 0;
3347   ++name;
3348   id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID));
3349   if (!id)
3350     return 0;
3351   if (id->name != name)
3352     poolDiscard(&dtd.pool);
3353   else {
3354     poolFinish(&dtd.pool);
3355     if (!ns)
3356       ;
3357     else if (name[0] == 'x'
3358         && name[1] == 'm'
3359         && name[2] == 'l'
3360         && name[3] == 'n'
3361         && name[4] == 's'
3362         && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
3363       if (name[5] == '\0')
3364         id->prefix = &dtd.defaultPrefix;
3365       else
3366         id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX));
3367       id->xmlns = 1;
3368     }
3369     else {
3370       int i;
3371       for (i = 0; name[i]; i++) {
3372         if (name[i] == XML_T(':')) {
3373           int j;
3374           for (j = 0; j < i; j++) {
3375             if (!poolAppendChar(&dtd.pool, name[j]))
3376               return 0;
3377           }
3378           if (!poolAppendChar(&dtd.pool, XML_T('\0')))
3379             return 0;
3380           id->prefix = (PREFIX *)
3381               lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
3382           if (id->prefix->name == poolStart(&dtd.pool))
3383             poolFinish(&dtd.pool);
3384           else
3385             poolDiscard(&dtd.pool);
3386           break;
3387         }
3388       }
3389     }
3390   }
3391   return id;
3392 }
3393
3394 #define CONTEXT_SEP XML_T('\f')
3395
3396 static
3397 const XML_Char *getContext(XML_Parser parser)
3398 {
3399   HASH_TABLE_ITER iter;
3400   int needSep = 0;
3401
3402   if (dtd.defaultPrefix.binding) {
3403     int i;
3404     int len;
3405     if (!poolAppendChar(&tempPool, XML_T('=')))
3406       return 0;
3407     len = dtd.defaultPrefix.binding->uriLen;
3408     if (namespaceSeparator != XML_T('\0'))
3409       len--;
3410     for (i = 0; i < len; i++)
3411       if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i]))
3412         return 0;
3413     needSep = 1;
3414   }
3415
3416   hashTableIterInit(&iter, &(dtd.prefixes));
3417   for (;;) {
3418     int i;
3419     int len;
3420     const XML_Char *s;
3421     PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
3422     if (!prefix)
3423       break;
3424     if (!prefix->binding)
3425       continue;
3426     if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
3427       return 0;
3428     for (s = prefix->name; *s; s++)
3429       if (!poolAppendChar(&tempPool, *s))
3430         return 0;
3431     if (!poolAppendChar(&tempPool, XML_T('=')))
3432       return 0;
3433     len = prefix->binding->uriLen;
3434     if (namespaceSeparator != XML_T('\0'))
3435       len--;
3436     for (i = 0; i < len; i++)
3437       if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
3438         return 0;
3439     needSep = 1;
3440   }
3441
3442
3443   hashTableIterInit(&iter, &(dtd.generalEntities));
3444   for (;;) {
3445     const XML_Char *s;
3446     ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
3447     if (!e)
3448       break;
3449     if (!e->open)
3450       continue;
3451     if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
3452       return 0;
3453     for (s = e->name; *s; s++)
3454       if (!poolAppendChar(&tempPool, *s))
3455         return 0;
3456     needSep = 1;
3457   }
3458
3459   if (!poolAppendChar(&tempPool, XML_T('\0')))
3460     return 0;
3461   return tempPool.start;
3462 }
3463
3464 static
3465 int setContext(XML_Parser parser, const XML_Char *context)
3466 {
3467   const XML_Char *s = context;
3468
3469   while (*context != XML_T('\0')) {
3470     if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
3471       ENTITY *e;
3472       if (!poolAppendChar(&tempPool, XML_T('\0')))
3473         return 0;
3474       e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0);
3475       if (e)
3476         e->open = 1;
3477       if (*s != XML_T('\0'))
3478         s++;
3479       context = s;
3480       poolDiscard(&tempPool);
3481     }
3482     else if (*s == '=') {
3483       PREFIX *prefix;
3484       if (poolLength(&tempPool) == 0)
3485         prefix = &dtd.defaultPrefix;
3486       else {
3487         if (!poolAppendChar(&tempPool, XML_T('\0')))
3488           return 0;
3489         prefix = (PREFIX *)
3490             lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX));
3491         if (!prefix)
3492           return 0;
3493         if (prefix->name == poolStart(&tempPool)) {
3494           prefix->name = poolCopyString(&dtd.pool, prefix->name);
3495           if (!prefix->name)
3496             return 0;
3497         }
3498         poolDiscard(&tempPool);
3499       }
3500       for (context = s + 1;
3501            *context != CONTEXT_SEP && *context != XML_T('\0');
3502            ++context)
3503         if (!poolAppendChar(&tempPool, *context))
3504           return 0;
3505       if (!poolAppendChar(&tempPool, XML_T('\0')))
3506         return 0;
3507       if (!addBinding(parser, prefix, 0, poolStart(&tempPool),
3508                       &inheritedBindings))
3509         return 0;
3510       poolDiscard(&tempPool);
3511       if (*context != XML_T('\0'))
3512         ++context;
3513       s = context;
3514     }
3515     else {
3516       if (!poolAppendChar(&tempPool, *s))
3517         return 0;
3518       s++;
3519     }
3520   }
3521   return 1;
3522 }
3523
3524
3525 static
3526 void normalizePublicId(XML_Char *publicId)
3527 {
3528   XML_Char *p = publicId;
3529   XML_Char *s;
3530   for (s = publicId; *s; s++) {
3531     switch (*s) {
3532     case 0x20:
3533     case 0xD:
3534     case 0xA:
3535       if (p != publicId && p[-1] != 0x20)
3536         *p++ = 0x20;
3537       break;
3538     default:
3539       *p++ = *s;
3540     }
3541   }
3542   if (p != publicId && p[-1] == 0x20)
3543     --p;
3544   *p = XML_T('\0');
3545 }
3546
3547 static int dtdInit(DTD *p)
3548 {
3549   poolInit(&(p->pool));
3550   hashTableInit(&(p->generalEntities));
3551   hashTableInit(&(p->elementTypes));
3552   hashTableInit(&(p->attributeIds));
3553   hashTableInit(&(p->prefixes));
3554   p->complete = 1;
3555   p->standalone = 0;
3556 #ifdef XML_DTD
3557   hashTableInit(&(p->paramEntities));
3558 #endif /* XML_DTD */
3559   p->defaultPrefix.name = 0;
3560   p->defaultPrefix.binding = 0;
3561   return 1;
3562 }
3563
3564 #ifdef XML_DTD
3565
3566 static void dtdSwap(DTD *p1, DTD *p2)
3567 {
3568   DTD tem;
3569   memcpy(&tem, p1, sizeof(DTD));
3570   memcpy(p1, p2, sizeof(DTD));
3571   memcpy(p2, &tem, sizeof(DTD));
3572 }
3573
3574 #endif /* XML_DTD */
3575
3576 static void dtdDestroy(DTD *p)
3577 {
3578   HASH_TABLE_ITER iter;
3579   hashTableIterInit(&iter, &(p->elementTypes));
3580   for (;;) {
3581     ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
3582     if (!e)
3583       break;
3584     if (e->allocDefaultAtts != 0)
3585       free(e->defaultAtts);
3586   }
3587   hashTableDestroy(&(p->generalEntities));
3588 #ifdef XML_DTD
3589   hashTableDestroy(&(p->paramEntities));
3590 #endif /* XML_DTD */
3591   hashTableDestroy(&(p->elementTypes));
3592   hashTableDestroy(&(p->attributeIds));
3593   hashTableDestroy(&(p->prefixes));
3594   poolDestroy(&(p->pool));
3595 }
3596
3597 /* Do a deep copy of the DTD.  Return 0 for out of memory; non-zero otherwise.
3598 The new DTD has already been initialized. */
3599
3600 static int dtdCopy(DTD *newDtd, const DTD *oldDtd)
3601 {
3602   HASH_TABLE_ITER iter;
3603
3604   /* Copy the prefix table. */
3605
3606   hashTableIterInit(&iter, &(oldDtd->prefixes));
3607   for (;;) {
3608     const XML_Char *name;
3609     const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
3610     if (!oldP)
3611       break;
3612     name = poolCopyString(&(newDtd->pool), oldP->name);
3613     if (!name)
3614       return 0;
3615     if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
3616       return 0;
3617   }
3618
3619   hashTableIterInit(&iter, &(oldDtd->attributeIds));
3620
3621   /* Copy the attribute id table. */
3622
3623   for (;;) {
3624     ATTRIBUTE_ID *newA;
3625     const XML_Char *name;
3626     const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
3627
3628     if (!oldA)
3629       break;
3630     /* Remember to allocate the scratch byte before the name. */
3631     if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
3632       return 0;
3633     name = poolCopyString(&(newDtd->pool), oldA->name);
3634     if (!name)
3635       return 0;
3636     ++name;
3637     newA = (ATTRIBUTE_ID *)
3638         lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID));
3639     if (!newA)
3640       return 0;
3641     newA->maybeTokenized = oldA->maybeTokenized;
3642     if (oldA->prefix) {
3643       newA->xmlns = oldA->xmlns;
3644       if (oldA->prefix == &oldDtd->defaultPrefix)
3645         newA->prefix = &newDtd->defaultPrefix;
3646       else
3647         newA->prefix = (PREFIX *)
3648             lookup(&(newDtd->prefixes), oldA->prefix->name, 0);
3649     }
3650   }
3651
3652   /* Copy the element type table. */
3653
3654   hashTableIterInit(&iter, &(oldDtd->elementTypes));
3655
3656   for (;;) {
3657     int i;
3658     ELEMENT_TYPE *newE;
3659     const XML_Char *name;
3660     const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
3661     if (!oldE)
3662       break;
3663     name = poolCopyString(&(newDtd->pool), oldE->name);
3664     if (!name)
3665       return 0;
3666     newE = (ELEMENT_TYPE *)
3667         lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE));
3668     if (!newE)
3669       return 0;
3670     if (oldE->nDefaultAtts) {
3671       newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
3672           malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
3673       if (!newE->defaultAtts)
3674         return 0;
3675     }
3676     if (oldE->idAtt)
3677       newE->idAtt = (ATTRIBUTE_ID *)
3678           lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
3679     newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
3680     if (oldE->prefix)
3681       newE->prefix = (PREFIX *)
3682           lookup(&(newDtd->prefixes), oldE->prefix->name, 0);
3683     for (i = 0; i < newE->nDefaultAtts; i++) {
3684       newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
3685           lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
3686       newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
3687       if (oldE->defaultAtts[i].value) {
3688         newE->defaultAtts[i].value =
3689             poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
3690         if (!newE->defaultAtts[i].value)
3691           return 0;
3692       }
3693       else
3694         newE->defaultAtts[i].value = 0;
3695     }
3696   }
3697
3698   /* Copy the entity tables. */
3699   if (!copyEntityTable(&(newDtd->generalEntities),
3700                        &(newDtd->pool),
3701                        &(oldDtd->generalEntities)))
3702       return 0;
3703
3704 #ifdef XML_DTD
3705   if (!copyEntityTable(&(newDtd->paramEntities),
3706                        &(newDtd->pool),
3707                        &(oldDtd->paramEntities)))
3708       return 0;
3709 #endif /* XML_DTD */
3710
3711   newDtd->complete = oldDtd->complete;
3712   newDtd->standalone = oldDtd->standalone;
3713   return 1;
3714 }
3715
3716 static int copyEntityTable(HASH_TABLE *newTable,
3717                            STRING_POOL *newPool,
3718                            const HASH_TABLE *oldTable)
3719 {
3720   HASH_TABLE_ITER iter;
3721   const XML_Char *cachedOldBase = 0;
3722   const XML_Char *cachedNewBase = 0;
3723
3724   hashTableIterInit(&iter, oldTable);
3725
3726   for (;;) {
3727     ENTITY *newE;
3728     const XML_Char *name;
3729     const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
3730     if (!oldE)
3731       break;
3732     name = poolCopyString(newPool, oldE->name);
3733     if (!name)
3734       return 0;
3735     newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
3736     if (!newE)
3737       return 0;
3738     if (oldE->systemId) {
3739       const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
3740       if (!tem)
3741         return 0;
3742       newE->systemId = tem;
3743       if (oldE->base) {
3744         if (oldE->base == cachedOldBase)
3745           newE->base = cachedNewBase;
3746         else {
3747           cachedOldBase = oldE->base;
3748           tem = poolCopyString(newPool, cachedOldBase);
3749           if (!tem)
3750             return 0;
3751           cachedNewBase = newE->base = tem;
3752         }
3753       }
3754     }
3755     else {
3756       const XML_Char *tem =
3757           poolCopyStringN(newPool, oldE->textPtr, oldE->textLen);
3758       if (!tem)
3759         return 0;
3760       newE->textPtr = tem;
3761       newE->textLen = oldE->textLen;
3762     }
3763     if (oldE->notation) {
3764       const XML_Char *tem = poolCopyString(newPool, oldE->notation);
3765       if (!tem)
3766         return 0;
3767       newE->notation = tem;
3768     }
3769   }
3770   return 1;
3771 }
3772
3773 #define INIT_SIZE 64
3774
3775 static
3776 int keyeq(KEY s1, KEY s2)
3777 {
3778   for (; *s1 == *s2; s1++, s2++)
3779     if (*s1 == 0)
3780       return 1;
3781   return 0;
3782 }
3783
3784 static
3785 unsigned long hash(KEY s)
3786 {
3787   unsigned long h = 0;
3788   while (*s)
3789     h = (h << 5) + h + (unsigned char)*s++;
3790   return h;
3791 }
3792
3793 static
3794 NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize)
3795 {
3796   size_t i;
3797   if (table->size == 0) {
3798     if (!createSize)
3799       return 0;
3800     table->v = calloc(INIT_SIZE, sizeof(NAMED *));
3801     if (!table->v)
3802       return 0;
3803     table->size = INIT_SIZE;
3804     table->usedLim = INIT_SIZE / 2;
3805     i = hash(name) & (table->size - 1);
3806   }
3807   else {
3808     unsigned long h = hash(name);
3809     for (i = h & (table->size - 1);
3810          table->v[i];
3811          i == 0 ? i = table->size - 1 : --i) {
3812       if (keyeq(name, table->v[i]->name))
3813         return table->v[i];
3814     }
3815     if (!createSize)
3816       return 0;
3817     if (table->used == table->usedLim) {
3818       /* check for overflow */
3819       size_t newSize = table->size * 2;
3820       NAMED **newV = calloc(newSize, sizeof(NAMED *));
3821       if (!newV)
3822         return 0;
3823       for (i = 0; i < table->size; i++)
3824         if (table->v[i]) {
3825           size_t j;
3826           for (j = hash(table->v[i]->name) & (newSize - 1);
3827                newV[j];
3828                j == 0 ? j = newSize - 1 : --j)
3829             ;
3830           newV[j] = table->v[i];
3831         }
3832       free(table->v);
3833       table->v = newV;
3834       table->size = newSize;
3835       table->usedLim = newSize/2;
3836       for (i = h & (table->size - 1);
3837            table->v[i];
3838            i == 0 ? i = table->size - 1 : --i)
3839         ;
3840     }
3841   }
3842   table->v[i] = calloc(1, createSize);
3843   if (!table->v[i])
3844     return 0;
3845   table->v[i]->name = name;
3846   (table->used)++;
3847   return table->v[i];
3848 }
3849
3850 static
3851 void hashTableDestroy(HASH_TABLE *table)
3852 {
3853   size_t i;
3854   for (i = 0; i < table->size; i++) {
3855     NAMED *p = table->v[i];
3856     if (p)
3857       free(p);
3858   }
3859   if (table->v)
3860     free(table->v);
3861 }
3862
3863 static
3864 void hashTableInit(HASH_TABLE *p)
3865 {
3866   p->size = 0;
3867   p->usedLim = 0;
3868   p->used = 0;
3869   p->v = 0;
3870 }
3871
3872 static
3873 void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
3874 {
3875   iter->p = table->v;
3876   iter->end = iter->p + table->size;
3877 }
3878
3879 static
3880 NAMED *hashTableIterNext(HASH_TABLE_ITER *iter)
3881 {
3882   while (iter->p != iter->end) {
3883     NAMED *tem = *(iter->p)++;
3884     if (tem)
3885       return tem;
3886   }
3887   return 0;
3888 }
3889
3890
3891 static
3892 void poolInit(STRING_POOL *pool)
3893 {
3894   pool->blocks = 0;
3895   pool->freeBlocks = 0;
3896   pool->start = 0;
3897   pool->ptr = 0;
3898   pool->end = 0;
3899 }
3900
3901 static
3902 void poolClear(STRING_POOL *pool)
3903 {
3904   if (!pool->freeBlocks)
3905     pool->freeBlocks = pool->blocks;
3906   else {
3907     BLOCK *p = pool->blocks;
3908     while (p) {
3909       BLOCK *tem = p->next;
3910       p->next = pool->freeBlocks;
3911       pool->freeBlocks = p;
3912       p = tem;
3913     }
3914   }
3915   pool->blocks = 0;
3916   pool->start = 0;
3917   pool->ptr = 0;
3918   pool->end = 0;
3919 }
3920
3921 static
3922 void poolDestroy(STRING_POOL *pool)
3923 {
3924   BLOCK *p = pool->blocks;
3925   while (p) {
3926     BLOCK *tem = p->next;
3927     free(p);
3928     p = tem;
3929   }
3930   pool->blocks = 0;
3931   p = pool->freeBlocks;
3932   while (p) {
3933     BLOCK *tem = p->next;
3934     free(p);
3935     p = tem;
3936   }
3937   pool->freeBlocks = 0;
3938   pool->ptr = 0;
3939   pool->start = 0;
3940   pool->end = 0;
3941 }
3942
3943 static
3944 XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
3945                      const char *ptr, const char *end)
3946 {
3947   if (!pool->ptr && !poolGrow(pool))
3948     return 0;
3949   for (;;) {
3950     XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
3951     if (ptr == end)
3952       break;
3953     if (!poolGrow(pool))
3954       return 0;
3955   }
3956   return pool->start;
3957 }
3958
3959 static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s)
3960 {
3961   do {
3962     if (!poolAppendChar(pool, *s))
3963       return 0;
3964   } while (*s++);
3965   s = pool->start;
3966   poolFinish(pool);
3967   return s;
3968 }
3969
3970 static const XML_Char *
3971 poolCopyStringN(STRING_POOL *pool,
3972                 const XML_Char *s,
3973                 int n)
3974 {
3975   if (!pool->ptr && !poolGrow(pool))
3976     return 0;
3977   for (; n > 0; --n, s++) {
3978     if (!poolAppendChar(pool, *s))
3979       return 0;
3980
3981   }
3982   s = pool->start;
3983   poolFinish(pool);
3984   return s;
3985 }
3986
3987 static
3988 XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
3989                           const char *ptr, const char *end)
3990 {
3991   if (!poolAppend(pool, enc, ptr, end))
3992     return 0;
3993   if (pool->ptr == pool->end && !poolGrow(pool))
3994     return 0;
3995   *(pool->ptr)++ = 0;
3996   return pool->start;
3997 }
3998
3999 static
4000 int poolGrow(STRING_POOL *pool)
4001 {
4002   if (pool->freeBlocks) {
4003     if (pool->start == 0) {
4004       pool->blocks = pool->freeBlocks;
4005       pool->freeBlocks = pool->freeBlocks->next;
4006       pool->blocks->next = 0;
4007       pool->start = pool->blocks->s;
4008       pool->end = pool->start + pool->blocks->size;
4009       pool->ptr = pool->start;
4010       return 1;
4011     }
4012     if (pool->end - pool->start < pool->freeBlocks->size) {
4013       BLOCK *tem = pool->freeBlocks->next;
4014       pool->freeBlocks->next = pool->blocks;
4015       pool->blocks = pool->freeBlocks;
4016       pool->freeBlocks = tem;
4017       memcpy(pool->blocks->s, pool->start,
4018              (pool->end - pool->start) * sizeof(XML_Char));
4019       pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
4020       pool->start = pool->blocks->s;
4021       pool->end = pool->start + pool->blocks->size;
4022       return 1;
4023     }
4024   }
4025   if (pool->blocks && pool->start == pool->blocks->s) {
4026     int blockSize = (pool->end - pool->start)*2;
4027     pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) +
4028                            blockSize * sizeof(XML_Char));
4029     if (!pool->blocks)
4030       return 0;
4031     pool->blocks->size = blockSize;
4032     pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
4033     pool->start = pool->blocks->s;
4034     pool->end = pool->start + blockSize;
4035   }
4036   else {
4037     BLOCK *tem;
4038     int blockSize = pool->end - pool->start;
4039     if (blockSize < INIT_BLOCK_SIZE)
4040       blockSize = INIT_BLOCK_SIZE;
4041     else
4042       blockSize *= 2;
4043     tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
4044     if (!tem)
4045       return 0;
4046     tem->size = blockSize;
4047     tem->next = pool->blocks;
4048     pool->blocks = tem;
4049     if (pool->ptr != pool->start)
4050       memcpy(tem->s, pool->start,
4051              (pool->ptr - pool->start) * sizeof(XML_Char));
4052     pool->ptr = tem->s + (pool->ptr - pool->start);
4053     pool->start = tem->s;
4054     pool->end = tem->s + blockSize;
4055   }
4056   return 1;
4057 }