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