source: protocols/jabber/xmlparse.c @ 65e2ce1

Last change on this file since 65e2ce1 was b7d3cc34, checked in by Wilmer van der Gaast <wilmer@…>, at 2005-11-06T18:23:18Z

Initial repository (0.99 release tree)

  • Property mode set to 100644
File size: 90.0 KB
Line 
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
20*/
21
22#include "xmldef.h"
23#include "xmlparse.h"
24
25#ifdef XML_UNICODE
26#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
27#define XmlConvert XmlUtf16Convert
28#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
29#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
30#define XmlEncode XmlUtf16Encode
31#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
32typedef unsigned short ICHAR;
33#else
34#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
35#define XmlConvert XmlUtf8Convert
36#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
37#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
38#define XmlEncode XmlUtf8Encode
39#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
40typedef char ICHAR;
41#endif
42
43
44#ifndef XML_NS
45
46#define XmlInitEncodingNS XmlInitEncoding
47#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
48#undef XmlGetInternalEncodingNS
49#define XmlGetInternalEncodingNS XmlGetInternalEncoding
50#define XmlParseXmlDeclNS XmlParseXmlDecl
51
52#endif
53
54
55#ifdef XML_UNICODE_WCHAR_T
56#define XML_T(x) L ## x
57#else
58#define XML_T(x) x
59#endif
60
61/* Round up n to be a multiple of sz, where sz is a power of 2. */
62#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
63
64#include "xmltok.h"
65#include "xmlrole.h"
66#include "hashtable.h"
67
68#define INIT_TAG_BUF_SIZE 32  /* must be a multiple of sizeof(XML_Char) */
69#define INIT_DATA_BUF_SIZE 1024
70#define INIT_ATTS_SIZE 16
71#define INIT_BLOCK_SIZE 1024
72#define INIT_BUFFER_SIZE 1024
73
74#define EXPAND_SPARE 24
75
76typedef struct binding {
77    struct prefix *prefix;
78    struct binding *nextTagBinding;
79    struct binding *prevPrefixBinding;
80    const struct attribute_id *attId;
81    XML_Char *uri;
82    int uriLen;
83    int uriAlloc;
84} BINDING;
85
86typedef struct prefix {
87    const XML_Char *name;
88    BINDING *binding;
89} PREFIX;
90
91typedef struct {
92    const XML_Char *str;
93    const XML_Char *localPart;
94    int uriLen;
95} TAG_NAME;
96
97typedef struct tag {
98    struct tag *parent;
99    const char *rawName;
100    int rawNameLength;
101    TAG_NAME name;
102    char *buf;
103    char *bufEnd;
104    BINDING *bindings;
105} TAG;
106
107typedef struct {
108    const XML_Char *name;
109    const XML_Char *textPtr;
110    int textLen;
111    const XML_Char *systemId;
112    const XML_Char *base;
113    const XML_Char *publicId;
114    const XML_Char *notation;
115    char open;
116} ENTITY;
117
118typedef struct block {
119    struct block *next;
120    int size;
121    XML_Char s[1];
122} BLOCK;
123
124typedef struct {
125    BLOCK *blocks;
126    BLOCK *freeBlocks;
127    const XML_Char *end;
128    XML_Char *ptr;
129    XML_Char *start;
130} STRING_POOL;
131
132/* The XML_Char before the name is used to determine whether
133an attribute has been specified. */
134typedef struct attribute_id {
135    XML_Char *name;
136    PREFIX *prefix;
137    char maybeTokenized;
138    char xmlns;
139} ATTRIBUTE_ID;
140
141typedef struct {
142    const ATTRIBUTE_ID *id;
143    char isCdata;
144    const XML_Char *value;
145} DEFAULT_ATTRIBUTE;
146
147typedef struct {
148    const XML_Char *name;
149    PREFIX *prefix;
150    int nDefaultAtts;
151    int allocDefaultAtts;
152    DEFAULT_ATTRIBUTE *defaultAtts;
153} ELEMENT_TYPE;
154
155typedef struct {
156    HASH_TABLE generalEntities;
157    HASH_TABLE elementTypes;
158    HASH_TABLE attributeIds;
159    HASH_TABLE prefixes;
160    STRING_POOL pool;
161    int complete;
162    int standalone;
163    const XML_Char *base;
164    PREFIX defaultPrefix;
165} DTD;
166
167typedef struct open_internal_entity {
168    const char *internalEventPtr;
169    const char *internalEventEndPtr;
170    struct open_internal_entity *next;
171    ENTITY *entity;
172} OPEN_INTERNAL_ENTITY;
173
174typedef enum XML_Error Processor(XML_Parser parser,
175                                 const char *start,
176                                 const char *end,
177                                 const char **endPtr);
178
179static Processor prologProcessor;
180static Processor prologInitProcessor;
181static Processor contentProcessor;
182static Processor cdataSectionProcessor;
183static Processor epilogProcessor;
184
185static enum XML_Error
186handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
187static enum XML_Error
188processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *);
189static enum XML_Error
190initializeEncoding(XML_Parser parser);
191static enum XML_Error
192doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
193          const char *start, const char *end, const char **endPtr);
194static enum XML_Error
195doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
196static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s,
197                                TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
198static
199int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr);
200static int
201defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, const XML_Char *dfltValue);
202static enum XML_Error
203storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
204                    STRING_POOL *);
205static enum XML_Error
206appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
207                     STRING_POOL *);
208static ATTRIBUTE_ID *
209getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
210static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
211static enum XML_Error
212storeEntityValue(XML_Parser parser, const char *start, const char *end);
213static int
214reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
215static int
216reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
217static void
218reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
219
220static const XML_Char *getContext(XML_Parser parser);
221static void normalizePublicId(XML_Char *s);
222static int dtdInit(DTD *);
223static void dtdDestroy(DTD *);
224static void poolInit(STRING_POOL *);
225static void poolClear(STRING_POOL *);
226static void poolDestroy(STRING_POOL *);
227static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
228                            const char *ptr, const char *end);
229static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
230                                 const char *ptr, const char *end);
231static int poolGrow(STRING_POOL *pool);
232static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s);
233static void *XML_GetBuffer(XML_Parser parser, int len);
234static int XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
235
236#define poolStart(pool) ((pool)->start)
237#define poolEnd(pool) ((pool)->ptr)
238#define poolLength(pool) ((pool)->ptr - (pool)->start)
239#define poolChop(pool) ((void)--(pool->ptr))
240#define poolLastChar(pool) (((pool)->ptr)[-1])
241#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
242#define poolFinish(pool) ((pool)->start = (pool)->ptr)
243#define poolAppendChar(pool, c) \
244  (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
245   ? 0 \
246   : ((*((pool)->ptr)++ = c), 1))
247
248typedef struct {
249    /* The first member must be userData so that the XML_GetUserData macro works. */
250    void *m_userData;
251    void *m_handlerArg;
252    char *m_buffer;
253    /* first character to be parsed */
254    const char *m_bufferPtr;
255    /* past last character to be parsed */
256    char *m_bufferEnd;
257    /* allocated end of buffer */
258    const char *m_bufferLim;
259    long m_parseEndByteIndex;
260    const char *m_parseEndPtr;
261    XML_Char *m_dataBuf;
262    XML_Char *m_dataBufEnd;
263    XML_StartElementHandler m_startElementHandler;
264    XML_EndElementHandler m_endElementHandler;
265    XML_CharacterDataHandler m_characterDataHandler;
266    XML_ProcessingInstructionHandler m_processingInstructionHandler;
267    XML_CommentHandler m_commentHandler;
268    XML_StartCdataSectionHandler m_startCdataSectionHandler;
269    XML_EndCdataSectionHandler m_endCdataSectionHandler;
270    XML_DefaultHandler m_defaultHandler;
271    XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
272    XML_NotationDeclHandler m_notationDeclHandler;
273    XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
274    XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
275    XML_NotStandaloneHandler m_notStandaloneHandler;
276    XML_ExternalEntityRefHandler m_externalEntityRefHandler;
277    void *m_externalEntityRefHandlerArg;
278    XML_UnknownEncodingHandler m_unknownEncodingHandler;
279    const ENCODING *m_encoding;
280    INIT_ENCODING m_initEncoding;
281    const XML_Char *m_protocolEncodingName;
282    int m_ns;
283    void *m_unknownEncodingMem;
284    void *m_unknownEncodingData;
285    void *m_unknownEncodingHandlerData;
286    void (*m_unknownEncodingRelease)(void *);
287    PROLOG_STATE m_prologState;
288    Processor *m_processor;
289    enum XML_Error m_errorCode;
290    const char *m_eventPtr;
291    const char *m_eventEndPtr;
292    const char *m_positionPtr;
293    OPEN_INTERNAL_ENTITY *m_openInternalEntities;
294    int m_defaultExpandInternalEntities;
295    int m_tagLevel;
296    ENTITY *m_declEntity;
297    const XML_Char *m_declNotationName;
298    const XML_Char *m_declNotationPublicId;
299    ELEMENT_TYPE *m_declElementType;
300    ATTRIBUTE_ID *m_declAttributeId;
301    char m_declAttributeIsCdata;
302    DTD m_dtd;
303    TAG *m_tagStack;
304    TAG *m_freeTagList;
305    BINDING *m_inheritedBindings;
306    BINDING *m_freeBindingList;
307    int m_attsSize;
308    int m_nSpecifiedAtts;
309    ATTRIBUTE *m_atts;
310    POSITION m_position;
311    STRING_POOL m_tempPool;
312    STRING_POOL m_temp2Pool;
313    char *m_groupConnector;
314    unsigned m_groupSize;
315    int m_hadExternalDoctype;
316    XML_Char m_namespaceSeparator;
317} Parser;
318
319#define userData (((Parser *)parser)->m_userData)
320#define handlerArg (((Parser *)parser)->m_handlerArg)
321#define startElementHandler (((Parser *)parser)->m_startElementHandler)
322#define endElementHandler (((Parser *)parser)->m_endElementHandler)
323#define characterDataHandler (((Parser *)parser)->m_characterDataHandler)
324#define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler)
325#define commentHandler (((Parser *)parser)->m_commentHandler)
326#define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler)
327#define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler)
328#define defaultHandler (((Parser *)parser)->m_defaultHandler)
329#define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler)
330#define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler)
331#define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler)
332#define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler)
333#define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler)
334#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler)
335#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg)
336#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler)
337#define encoding (((Parser *)parser)->m_encoding)
338#define initEncoding (((Parser *)parser)->m_initEncoding)
339#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem)
340#define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData)
341#define unknownEncodingHandlerData \
342  (((Parser *)parser)->m_unknownEncodingHandlerData)
343#define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease)
344#define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName)
345#define ns (((Parser *)parser)->m_ns)
346#define prologState (((Parser *)parser)->m_prologState)
347#define processor (((Parser *)parser)->m_processor)
348#define errorCode (((Parser *)parser)->m_errorCode)
349#define eventPtr (((Parser *)parser)->m_eventPtr)
350#define eventEndPtr (((Parser *)parser)->m_eventEndPtr)
351#define positionPtr (((Parser *)parser)->m_positionPtr)
352#define position (((Parser *)parser)->m_position)
353#define openInternalEntities (((Parser *)parser)->m_openInternalEntities)
354#define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities)
355#define tagLevel (((Parser *)parser)->m_tagLevel)
356#define buffer (((Parser *)parser)->m_buffer)
357#define bufferPtr (((Parser *)parser)->m_bufferPtr)
358#define bufferEnd (((Parser *)parser)->m_bufferEnd)
359#define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex)
360#define parseEndPtr (((Parser *)parser)->m_parseEndPtr)
361#define bufferLim (((Parser *)parser)->m_bufferLim)
362#define dataBuf (((Parser *)parser)->m_dataBuf)
363#define dataBufEnd (((Parser *)parser)->m_dataBufEnd)
364#define dtd (((Parser *)parser)->m_dtd)
365#define declEntity (((Parser *)parser)->m_declEntity)
366#define declNotationName (((Parser *)parser)->m_declNotationName)
367#define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId)
368#define declElementType (((Parser *)parser)->m_declElementType)
369#define declAttributeId (((Parser *)parser)->m_declAttributeId)
370#define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata)
371#define freeTagList (((Parser *)parser)->m_freeTagList)
372#define freeBindingList (((Parser *)parser)->m_freeBindingList)
373#define inheritedBindings (((Parser *)parser)->m_inheritedBindings)
374#define tagStack (((Parser *)parser)->m_tagStack)
375#define atts (((Parser *)parser)->m_atts)
376#define attsSize (((Parser *)parser)->m_attsSize)
377#define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts)
378#define tempPool (((Parser *)parser)->m_tempPool)
379#define temp2Pool (((Parser *)parser)->m_temp2Pool)
380#define groupConnector (((Parser *)parser)->m_groupConnector)
381#define groupSize (((Parser *)parser)->m_groupSize)
382#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype)
383#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator)
384
385#ifdef _MSC_VER
386#ifdef _DEBUG
387Parser *asParser(XML_Parser parser)
388{
389    return parser;
390}
391#endif
392#endif
393
394XML_Parser XML_ParserCreate(const XML_Char *encodingName)
395{
396    XML_Parser parser = malloc(sizeof(Parser));
397    if (!parser)
398        return parser;
399    processor = prologInitProcessor;
400    XmlPrologStateInit(&prologState);
401    userData = 0;
402    handlerArg = 0;
403    startElementHandler = 0;
404    endElementHandler = 0;
405    characterDataHandler = 0;
406    processingInstructionHandler = 0;
407    commentHandler = 0;
408    startCdataSectionHandler = 0;
409    endCdataSectionHandler = 0;
410    defaultHandler = 0;
411    unparsedEntityDeclHandler = 0;
412    notationDeclHandler = 0;
413    startNamespaceDeclHandler = 0;
414    endNamespaceDeclHandler = 0;
415    notStandaloneHandler = 0;
416    externalEntityRefHandler = 0;
417    externalEntityRefHandlerArg = parser;
418    unknownEncodingHandler = 0;
419    buffer = 0;
420    bufferPtr = 0;
421    bufferEnd = 0;
422    parseEndByteIndex = 0;
423    parseEndPtr = 0;
424    bufferLim = 0;
425    declElementType = 0;
426    declAttributeId = 0;
427    declEntity = 0;
428    declNotationName = 0;
429    declNotationPublicId = 0;
430    memset(&position, 0, sizeof(POSITION));
431    errorCode = XML_ERROR_NONE;
432    eventPtr = 0;
433    eventEndPtr = 0;
434    positionPtr = 0;
435    openInternalEntities = 0;
436    tagLevel = 0;
437    tagStack = 0;
438    freeTagList = 0;
439    freeBindingList = 0;
440    inheritedBindings = 0;
441    attsSize = INIT_ATTS_SIZE;
442    atts = malloc(attsSize * sizeof(ATTRIBUTE));
443    nSpecifiedAtts = 0;
444    dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
445    groupSize = 0;
446    groupConnector = 0;
447    hadExternalDoctype = 0;
448    unknownEncodingMem = 0;
449    unknownEncodingRelease = 0;
450    unknownEncodingData = 0;
451    unknownEncodingHandlerData = 0;
452    namespaceSeparator = '!';
453    ns = 0;
454    poolInit(&tempPool);
455    poolInit(&temp2Pool);
456    protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0;
457    if (!dtdInit(&dtd) || !atts || !dataBuf
458            || (encodingName && !protocolEncodingName)) {
459        XML_ParserFree(parser);
460        return 0;
461    }
462    dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
463    XmlInitEncoding(&initEncoding, &encoding, 0);
464    return parser;
465}
466
467static
468void destroyBindings(BINDING *bindings)
469{
470    for (;;) {
471        BINDING *b = bindings;
472        if (!b)
473            break;
474        bindings = b->nextTagBinding;
475        g_free(b->uri);
476        g_free(b);
477    }
478}
479
480void XML_ParserFree(XML_Parser parser)
481{
482    for (;;) {
483        TAG *p;
484        if (tagStack == 0) {
485            if (freeTagList == 0)
486                break;
487            tagStack = freeTagList;
488            freeTagList = 0;
489        }
490        p = tagStack;
491        tagStack = tagStack->parent;
492        g_free(p->buf);
493        destroyBindings(p->bindings);
494        g_free(p);
495    }
496    destroyBindings(freeBindingList);
497    destroyBindings(inheritedBindings);
498    poolDestroy(&tempPool);
499    poolDestroy(&temp2Pool);
500    dtdDestroy(&dtd);
501    g_free((void *)atts);
502    g_free(groupConnector);
503    g_free(buffer);
504    g_free(dataBuf);
505    g_free(unknownEncodingMem);
506    if (unknownEncodingRelease)
507        unknownEncodingRelease(unknownEncodingData);
508    g_free(parser);
509}
510
511void XML_SetUserData(XML_Parser parser, void *p)
512{
513    if (handlerArg == userData)
514        handlerArg = userData = p;
515    else
516        userData = p;
517}
518
519void XML_SetElementHandler(XML_Parser parser,
520                           XML_StartElementHandler start,
521                           XML_EndElementHandler end)
522{
523    startElementHandler = start;
524    endElementHandler = end;
525}
526
527void XML_SetCharacterDataHandler(XML_Parser parser,
528                                 XML_CharacterDataHandler handler)
529{
530    characterDataHandler = handler;
531}
532
533int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
534{
535    if (len == 0) {
536        if (!isFinal)
537            return 1;
538        positionPtr = bufferPtr;
539        errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0);
540        if (errorCode == XML_ERROR_NONE)
541            return 1;
542        eventEndPtr = eventPtr;
543        return 0;
544    }
545    else if (bufferPtr == bufferEnd) {
546        const char *end;
547        int nLeftOver;
548        parseEndByteIndex += len;
549        positionPtr = s;
550        if (isFinal) {
551            errorCode = processor(parser, s, parseEndPtr = s + len, 0);
552            if (errorCode == XML_ERROR_NONE)
553                return 1;
554            eventEndPtr = eventPtr;
555            return 0;
556        }
557        errorCode = processor(parser, s, parseEndPtr = s + len, &end);
558        if (errorCode != XML_ERROR_NONE) {
559            eventEndPtr = eventPtr;
560            return 0;
561        }
562        XmlUpdatePosition(encoding, positionPtr, end, &position);
563        nLeftOver = s + len - end;
564        if (nLeftOver) {
565            if (buffer == 0 || nLeftOver > bufferLim - buffer) {
566                /* FIXME avoid integer overflow */
567                buffer = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2);
568                if (!buffer) {
569                    errorCode = XML_ERROR_NO_MEMORY;
570                    eventPtr = eventEndPtr = 0;
571                    return 0;
572                }
573                bufferLim = buffer + len * 2;
574            }
575            memcpy(buffer, end, nLeftOver);
576            bufferPtr = buffer;
577            bufferEnd = buffer + nLeftOver;
578        }
579        return 1;
580    }
581    else {
582        memcpy(XML_GetBuffer(parser, len), s, len);
583        return XML_ParseBuffer(parser, len, isFinal);
584    }
585}
586
587static int XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
588{
589    const char *start = bufferPtr;
590    positionPtr = start;
591    bufferEnd += len;
592    parseEndByteIndex += len;
593    errorCode = processor(parser, start, parseEndPtr = bufferEnd,
594                          isFinal ? (const char **)0 : &bufferPtr);
595    if (errorCode == XML_ERROR_NONE) {
596        if (!isFinal)
597            XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
598        return 1;
599    }
600    else {
601        eventEndPtr = eventPtr;
602        return 0;
603    }
604}
605
606static void *XML_GetBuffer(XML_Parser parser, int len)
607{
608    if (len > bufferLim - bufferEnd) {
609        /* FIXME avoid integer overflow */
610        int neededSize = len + (bufferEnd - bufferPtr);
611        if (neededSize  <= bufferLim - buffer) {
612            memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
613            bufferEnd = buffer + (bufferEnd - bufferPtr);
614            bufferPtr = buffer;
615        }
616        else {
617            char *newBuf;
618            int bufferSize = bufferLim - bufferPtr;
619            if (bufferSize == 0)
620                bufferSize = INIT_BUFFER_SIZE;
621            do {
622                bufferSize *= 2;
623            } while (bufferSize < neededSize);
624            newBuf = malloc(bufferSize);
625            if (newBuf == 0) {
626                errorCode = XML_ERROR_NO_MEMORY;
627                return 0;
628            }
629            bufferLim = newBuf + bufferSize;
630            if (bufferPtr) {
631                memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
632                g_free(buffer);
633            }
634            bufferEnd = newBuf + (bufferEnd - bufferPtr);
635            bufferPtr = buffer = newBuf;
636        }
637    }
638    return bufferEnd;
639}
640
641static
642enum XML_Error contentProcessor(XML_Parser parser,
643                                const char *start,
644                                const char *end,
645                                const char **endPtr)
646{
647    return doContent(parser, 0, encoding, start, end, endPtr);
648}
649
650static enum XML_Error
651doContent(XML_Parser parser,
652          int startTagLevel,
653          const ENCODING *enc,
654          const char *s,
655          const char *end,
656          const char **nextPtr)
657{
658    const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
659    const char **eventPP;
660    const char **eventEndPP;
661    if (enc == encoding) {
662        eventPP = &eventPtr;
663        eventEndPP = &eventEndPtr;
664    }
665    else {
666        eventPP = &(openInternalEntities->internalEventPtr);
667        eventEndPP = &(openInternalEntities->internalEventEndPtr);
668    }
669    *eventPP = s;
670    for (;;) {
671        const char *next = s; /* XmlContentTok doesn't always set the last arg */
672        int tok = XmlContentTok(enc, s, end, &next);
673        *eventEndPP = next;
674        switch (tok) {
675        case XML_TOK_TRAILING_CR:
676            if (nextPtr) {
677                *nextPtr = s;
678                return XML_ERROR_NONE;
679            }
680            *eventEndPP = end;
681            if (characterDataHandler) {
682                XML_Char c = 0xA;
683                characterDataHandler(handlerArg, &c, 1);
684            }
685            else if (defaultHandler)
686                reportDefault(parser, enc, s, end);
687            if (startTagLevel == 0)
688                return XML_ERROR_NO_ELEMENTS;
689            if (tagLevel != startTagLevel)
690                return XML_ERROR_ASYNC_ENTITY;
691            return XML_ERROR_NONE;
692        case XML_TOK_NONE:
693            if (nextPtr) {
694                *nextPtr = s;
695                return XML_ERROR_NONE;
696            }
697            if (startTagLevel > 0) {
698                if (tagLevel != startTagLevel)
699                    return XML_ERROR_ASYNC_ENTITY;
700                return XML_ERROR_NONE;
701            }
702            return XML_ERROR_NO_ELEMENTS;
703        case XML_TOK_INVALID:
704            *eventPP = next;
705            return XML_ERROR_INVALID_TOKEN;
706        case XML_TOK_PARTIAL:
707            if (nextPtr) {
708                *nextPtr = s;
709                return XML_ERROR_NONE;
710            }
711            return XML_ERROR_UNCLOSED_TOKEN;
712        case XML_TOK_PARTIAL_CHAR:
713            if (nextPtr) {
714                *nextPtr = s;
715                return XML_ERROR_NONE;
716            }
717            return XML_ERROR_PARTIAL_CHAR;
718        case XML_TOK_ENTITY_REF:
719            {
720                const XML_Char *name;
721                ENTITY *entity;
722                XML_Char ch = XmlPredefinedEntityName(enc,
723                                                      s + enc->minBytesPerChar,
724                                                      next - enc->minBytesPerChar);
725                if (ch) {
726                    if (characterDataHandler)
727                        characterDataHandler(handlerArg, &ch, 1);
728                    else if (defaultHandler)
729                        reportDefault(parser, enc, s, next);
730                    break;
731                }
732                name = poolStoreString(&dtd.pool, enc,
733                                       s + enc->minBytesPerChar,
734                                       next - enc->minBytesPerChar);
735                if (!name)
736                    return XML_ERROR_NO_MEMORY;
737                entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
738                poolDiscard(&dtd.pool);
739                if (!entity) {
740                    if (dtd.complete || dtd.standalone)
741                        return XML_ERROR_UNDEFINED_ENTITY;
742                    if (defaultHandler)
743                        reportDefault(parser, enc, s, next);
744                    break;
745                }
746                if (entity->open)
747                    return XML_ERROR_RECURSIVE_ENTITY_REF;
748                if (entity->notation)
749                    return XML_ERROR_BINARY_ENTITY_REF;
750                if (entity) {
751                    if (entity->textPtr) {
752                        enum XML_Error result;
753                        OPEN_INTERNAL_ENTITY openEntity;
754                        if (defaultHandler && !defaultExpandInternalEntities) {
755                            reportDefault(parser, enc, s, next);
756                            break;
757                        }
758                        entity->open = 1;
759                        openEntity.next = openInternalEntities;
760                        openInternalEntities = &openEntity;
761                        openEntity.entity = entity;
762                        openEntity.internalEventPtr = 0;
763                        openEntity.internalEventEndPtr = 0;
764                        result = doContent(parser,
765                                           tagLevel,
766                                           internalEnc,
767                                           (char *)entity->textPtr,
768                                           (char *)(entity->textPtr + entity->textLen),
769                                           0);
770                        entity->open = 0;
771                        openInternalEntities = openEntity.next;
772                        if (result)
773                            return result;
774                    }
775                    else if (externalEntityRefHandler) {
776                        const XML_Char *context;
777                        entity->open = 1;
778                        context = getContext(parser);
779                        entity->open = 0;
780                        if (!context)
781                            return XML_ERROR_NO_MEMORY;
782                        if (!externalEntityRefHandler(externalEntityRefHandlerArg,
783                                                      context,
784                                                      dtd.base,
785                                                      entity->systemId,
786                                                      entity->publicId))
787                            return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
788                        poolDiscard(&tempPool);
789                    }
790                    else if (defaultHandler)
791                        reportDefault(parser, enc, s, next);
792                }
793                break;
794            }
795        case XML_TOK_START_TAG_WITH_ATTS:
796            if (!startElementHandler) {
797                enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
798                if (result)
799                    return result;
800            }
801            /* fall through */
802        case XML_TOK_START_TAG_NO_ATTS:
803            {
804                TAG *tag;
805                if (freeTagList) {
806                    tag = freeTagList;
807                    freeTagList = freeTagList->parent;
808                }
809                else {
810                    tag = malloc(sizeof(TAG));
811                    if (!tag)
812                        return XML_ERROR_NO_MEMORY;
813                    tag->buf = malloc(INIT_TAG_BUF_SIZE);
814                    if (!tag->buf)
815                        return XML_ERROR_NO_MEMORY;
816                    tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
817                }
818                tag->bindings = 0;
819                tag->parent = tagStack;
820                tagStack = tag;
821                tag->name.localPart = 0;
822                tag->rawName = s + enc->minBytesPerChar;
823                tag->rawNameLength = XmlNameLength(enc, tag->rawName);
824                if (nextPtr) {
825                    /* Need to guarantee that:
826                       tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */
827                    if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) {
828                        int bufSize = tag->rawNameLength * 4;
829                        bufSize = ROUND_UP(bufSize, sizeof(XML_Char));
830                        tag->buf = realloc(tag->buf, bufSize);
831                        if (!tag->buf)
832                            return XML_ERROR_NO_MEMORY;
833                        tag->bufEnd = tag->buf + bufSize;
834                    }
835                    memcpy(tag->buf, tag->rawName, tag->rawNameLength);
836                    tag->rawName = tag->buf;
837                }
838                ++tagLevel;
839                if (startElementHandler) {
840                    enum XML_Error result;
841                    XML_Char *toPtr;
842                    for (;;) {
843                        const char *rawNameEnd = tag->rawName + tag->rawNameLength;
844                        const char *fromPtr = tag->rawName;
845                        int bufSize;
846                        if (nextPtr)
847                            toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)));
848                        else
849                            toPtr = (XML_Char *)tag->buf;
850                        tag->name.str = toPtr;
851                        XmlConvert(enc,
852                                   &fromPtr, rawNameEnd,
853                                   (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
854                        if (fromPtr == rawNameEnd)
855                            break;
856                        bufSize = (tag->bufEnd - tag->buf) << 1;
857                        tag->buf = realloc(tag->buf, bufSize);
858                        if (!tag->buf)
859                            return XML_ERROR_NO_MEMORY;
860                        tag->bufEnd = tag->buf + bufSize;
861                        if (nextPtr)
862                            tag->rawName = tag->buf;
863                    }
864                    *toPtr = XML_T('\0');
865                    result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
866                    if (result)
867                        return result;
868                    startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts);
869                    poolClear(&tempPool);
870                }
871                else {
872                    tag->name.str = 0;
873                    if (defaultHandler)
874                        reportDefault(parser, enc, s, next);
875                }
876                break;
877            }
878        case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
879            if (!startElementHandler) {
880                enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
881                if (result)
882                    return result;
883            }
884            /* fall through */
885        case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
886            if (startElementHandler || endElementHandler) {
887                const char *rawName = s + enc->minBytesPerChar;
888                enum XML_Error result;
889                BINDING *bindings = 0;
890                TAG_NAME name;
891                name.str = poolStoreString(&tempPool, enc, rawName,
892                                           rawName + XmlNameLength(enc, rawName));
893                if (!name.str)
894                    return XML_ERROR_NO_MEMORY;
895                poolFinish(&tempPool);
896                result = storeAtts(parser, enc, s, &name, &bindings);
897                if (result)
898                    return result;
899                poolFinish(&tempPool);
900                if (startElementHandler)
901                    startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
902                if (endElementHandler) {
903                    if (startElementHandler)
904                        *eventPP = *eventEndPP;
905                    endElementHandler(handlerArg, name.str);
906                }
907                poolClear(&tempPool);
908                while (bindings) {
909                    BINDING *b = bindings;
910                    if (endNamespaceDeclHandler)
911                        endNamespaceDeclHandler(handlerArg, b->prefix->name);
912                    bindings = bindings->nextTagBinding;
913                    b->nextTagBinding = freeBindingList;
914                    freeBindingList = b;
915                    b->prefix->binding = b->prevPrefixBinding;
916                }
917            }
918            else if (defaultHandler)
919                reportDefault(parser, enc, s, next);
920            if (tagLevel == 0)
921                return epilogProcessor(parser, next, end, nextPtr);
922            break;
923        case XML_TOK_END_TAG:
924            if (tagLevel == startTagLevel)
925                return XML_ERROR_ASYNC_ENTITY;
926            else {
927                int len;
928                const char *rawName;
929                TAG *tag = tagStack;
930                tagStack = tag->parent;
931                tag->parent = freeTagList;
932                freeTagList = tag;
933                rawName = s + enc->minBytesPerChar*2;
934                len = XmlNameLength(enc, rawName);
935                if (len != tag->rawNameLength
936                        || memcmp(tag->rawName, rawName, len) != 0) {
937                    *eventPP = rawName;
938                    return XML_ERROR_TAG_MISMATCH;
939                }
940                --tagLevel;
941                if (endElementHandler && tag->name.str) {
942                    if (tag->name.localPart) {
943                        XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen;
944                        const XML_Char *from = tag->name.localPart;
945                        while ((*to++ = *from++) != 0)
946                            ;
947                    }
948                    endElementHandler(handlerArg, tag->name.str);
949                }
950                else if (defaultHandler)
951                    reportDefault(parser, enc, s, next);
952                while (tag->bindings) {
953                    BINDING *b = tag->bindings;
954                    if (endNamespaceDeclHandler)
955                        endNamespaceDeclHandler(handlerArg, b->prefix->name);
956                    tag->bindings = tag->bindings->nextTagBinding;
957                    b->nextTagBinding = freeBindingList;
958                    freeBindingList = b;
959                    b->prefix->binding = b->prevPrefixBinding;
960                }
961                if (tagLevel == 0)
962                    return epilogProcessor(parser, next, end, nextPtr);
963            }
964            break;
965        case XML_TOK_CHAR_REF:
966            {
967                int n = XmlCharRefNumber(enc, s);
968                if (n < 0)
969                    return XML_ERROR_BAD_CHAR_REF;
970                if (characterDataHandler) {
971                    XML_Char buf[XML_ENCODE_MAX];
972                    characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
973                }
974                else if (defaultHandler)
975                    reportDefault(parser, enc, s, next);
976            }
977            break;
978        case XML_TOK_XML_DECL:
979            return XML_ERROR_MISPLACED_XML_PI;
980        case XML_TOK_DATA_NEWLINE:
981            if (characterDataHandler) {
982                XML_Char c = 0xA;
983                characterDataHandler(handlerArg, &c, 1);
984            }
985            else if (defaultHandler)
986                reportDefault(parser, enc, s, next);
987            break;
988        case XML_TOK_CDATA_SECT_OPEN:
989            {
990                enum XML_Error result;
991                if (startCdataSectionHandler)
992                    startCdataSectionHandler(handlerArg);
993#if 0
994                /* Suppose you doing a transformation on a document that involves
995                   changing only the character data.  You set up a defaultHandler
996                   and a characterDataHandler.  The defaultHandler simply copies
997                   characters through.  The characterDataHandler does the transformation
998                   and writes the characters out escaping them as necessary.  This case
999                   will fail to work if we leave out the following two lines (because &
1000                   and < inside CDATA sections will be incorrectly escaped).
1001
1002                   However, now we have a start/endCdataSectionHandler, so it seems
1003                   easier to let the user deal with this. */
1004
1005                else if (characterDataHandler)
1006                    characterDataHandler(handlerArg, dataBuf, 0);
1007#endif
1008                else if (defaultHandler)
1009                    reportDefault(parser, enc, s, next);
1010                result = doCdataSection(parser, enc, &next, end, nextPtr);
1011                if (!next) {
1012                    processor = cdataSectionProcessor;
1013                    return result;
1014                }
1015            }
1016            break;
1017        case XML_TOK_TRAILING_RSQB:
1018            if (nextPtr) {
1019                *nextPtr = s;
1020                return XML_ERROR_NONE;
1021            }
1022            if (characterDataHandler) {
1023                if (MUST_CONVERT(enc, s)) {
1024                    ICHAR *dataPtr = (ICHAR *)dataBuf;
1025                    XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
1026                    characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
1027                }
1028                else
1029                    characterDataHandler(handlerArg,
1030                                         (XML_Char *)s,
1031                                         (XML_Char *)end - (XML_Char *)s);
1032            }
1033            else if (defaultHandler)
1034                reportDefault(parser, enc, s, end);
1035            if (startTagLevel == 0) {
1036                *eventPP = end;
1037                return XML_ERROR_NO_ELEMENTS;
1038            }
1039            if (tagLevel != startTagLevel) {
1040                *eventPP = end;
1041                return XML_ERROR_ASYNC_ENTITY;
1042            }
1043            return XML_ERROR_NONE;
1044        case XML_TOK_DATA_CHARS:
1045            if (characterDataHandler) {
1046                if (MUST_CONVERT(enc, s)) {
1047                    for (;;) {
1048                        ICHAR *dataPtr = (ICHAR *)dataBuf;
1049                        XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
1050                        *eventEndPP = s;
1051                        characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
1052                        if (s == next)
1053                            break;
1054                        *eventPP = s;
1055                    }
1056                }
1057                else
1058                    characterDataHandler(handlerArg,
1059                                         (XML_Char *)s,
1060                                         (XML_Char *)next - (XML_Char *)s);
1061            }
1062            else if (defaultHandler)
1063                reportDefault(parser, enc, s, next);
1064            break;
1065        case XML_TOK_PI:
1066            if (!reportProcessingInstruction(parser, enc, s, next))
1067                return XML_ERROR_NO_MEMORY;
1068            break;
1069        case XML_TOK_COMMENT:
1070            if (!reportComment(parser, enc, s, next))
1071                return XML_ERROR_NO_MEMORY;
1072            break;
1073        default:
1074            if (defaultHandler)
1075                reportDefault(parser, enc, s, next);
1076            break;
1077        }
1078        *eventPP = s = next;
1079    }
1080    /* not reached */
1081}
1082
1083/* If tagNamePtr is non-null, build a real list of attributes,
1084otherwise just check the attributes for well-formedness. */
1085
1086static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
1087                                const char *s, TAG_NAME *tagNamePtr,
1088                                BINDING **bindingsPtr)
1089{
1090    ELEMENT_TYPE *elementType = 0;
1091    int nDefaultAtts = 0;
1092    const XML_Char **appAtts;
1093    int attIndex = 0;
1094    int i;
1095    int n;
1096    int nPrefixes = 0;
1097    BINDING *binding;
1098    const XML_Char *localPart;
1099
1100    if (tagNamePtr) {
1101        elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, 0);
1102        if (!elementType) {
1103            tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str);
1104            if (!tagNamePtr->str)
1105                return XML_ERROR_NO_MEMORY;
1106            elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE));
1107            if (!elementType)
1108                return XML_ERROR_NO_MEMORY;
1109            if (ns && !setElementTypePrefix(parser, elementType))
1110                return XML_ERROR_NO_MEMORY;
1111        }
1112        nDefaultAtts = elementType->nDefaultAtts;
1113    }
1114    n = XmlGetAttributes(enc, s, attsSize, atts);
1115    if (n + nDefaultAtts > attsSize) {
1116        int oldAttsSize = attsSize;
1117        attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
1118        atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE));
1119        if (!atts)
1120            return XML_ERROR_NO_MEMORY;
1121        if (n > oldAttsSize)
1122            XmlGetAttributes(enc, s, n, atts);
1123    }
1124    appAtts = (const XML_Char **)atts;
1125    for (i = 0; i < n; i++) {
1126        ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
1127                                             atts[i].name
1128                                             + XmlNameLength(enc, atts[i].name));
1129        if (!attId)
1130            return XML_ERROR_NO_MEMORY;
1131        if ((attId->name)[-1]) {
1132            if (enc == encoding)
1133                eventPtr = atts[i].name;
1134            return XML_ERROR_DUPLICATE_ATTRIBUTE;
1135        }
1136        (attId->name)[-1] = 1;
1137        appAtts[attIndex++] = attId->name;
1138        if (!atts[i].normalized) {
1139            enum XML_Error result;
1140            int isCdata = 1;
1141
1142            if (attId->maybeTokenized) {
1143                int j;
1144                for (j = 0; j < nDefaultAtts; j++) {
1145                    if (attId == elementType->defaultAtts[j].id) {
1146                        isCdata = elementType->defaultAtts[j].isCdata;
1147                        break;
1148                    }
1149                }
1150            }
1151
1152            result = storeAttributeValue(parser, enc, isCdata,
1153                                         atts[i].valuePtr, atts[i].valueEnd,
1154                                         &tempPool);
1155            if (result)
1156                return result;
1157            if (tagNamePtr) {
1158                appAtts[attIndex] = poolStart(&tempPool);
1159                poolFinish(&tempPool);
1160            }
1161            else
1162                poolDiscard(&tempPool);
1163        }
1164        else if (tagNamePtr) {
1165            appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
1166            if (appAtts[attIndex] == 0)
1167                return XML_ERROR_NO_MEMORY;
1168            poolFinish(&tempPool);
1169        }
1170        if (attId->prefix && tagNamePtr) {
1171            if (attId->xmlns) {
1172                if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr))
1173                    return XML_ERROR_NO_MEMORY;
1174                --attIndex;
1175            }
1176            else {
1177                attIndex++;
1178                nPrefixes++;
1179                (attId->name)[-1] = 2;
1180            }
1181        }
1182        else
1183            attIndex++;
1184    }
1185    nSpecifiedAtts = attIndex;
1186    if (tagNamePtr) {
1187        int j;
1188        for (j = 0; j < nDefaultAtts; j++) {
1189            const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j;
1190            if (!(da->id->name)[-1] && da->value) {
1191                if (da->id->prefix) {
1192                    if (da->id->xmlns) {
1193                        if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr))
1194                            return XML_ERROR_NO_MEMORY;
1195                    }
1196                    else {
1197                        (da->id->name)[-1] = 2;
1198                        nPrefixes++;
1199                        appAtts[attIndex++] = da->id->name;
1200                        appAtts[attIndex++] = da->value;
1201                    }
1202                }
1203                else {
1204                    (da->id->name)[-1] = 1;
1205                    appAtts[attIndex++] = da->id->name;
1206                    appAtts[attIndex++] = da->value;
1207                }
1208            }
1209        }
1210        appAtts[attIndex] = 0;
1211    }
1212    i = 0;
1213    if (nPrefixes) {
1214        for (; i < attIndex; i += 2) {
1215            if (appAtts[i][-1] == 2) {
1216                ATTRIBUTE_ID *id;
1217                ((XML_Char *)(appAtts[i]))[-1] = 0;
1218                id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0);
1219                if (id->prefix->binding) {
1220                    int j;
1221                    const BINDING *b = id->prefix->binding;
1222                    const XML_Char *s = appAtts[i];
1223                    for (j = 0; j < b->uriLen; j++) {
1224                        if (!poolAppendChar(&tempPool, b->uri[j]))
1225                            return XML_ERROR_NO_MEMORY;
1226                    }
1227                    while (*s++ != ':')
1228                        ;
1229                    do {
1230                        if (!poolAppendChar(&tempPool, *s))
1231                            return XML_ERROR_NO_MEMORY;
1232                    } while (*s++);
1233                    appAtts[i] = poolStart(&tempPool);
1234                    poolFinish(&tempPool);
1235                }
1236                if (!--nPrefixes)
1237                    break;
1238            }
1239            else
1240                ((XML_Char *)(appAtts[i]))[-1] = 0;
1241        }
1242    }
1243    for (; i < attIndex; i += 2)
1244        ((XML_Char *)(appAtts[i]))[-1] = 0;
1245    if (!tagNamePtr)
1246        return XML_ERROR_NONE;
1247    for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
1248        binding->attId->name[-1] = 0;
1249    if (elementType->prefix) {
1250        binding = elementType->prefix->binding;
1251        if (!binding)
1252            return XML_ERROR_NONE;
1253        localPart = tagNamePtr->str;
1254        while (*localPart++ != XML_T(':'))
1255            ;
1256    }
1257    else if (dtd.defaultPrefix.binding) {
1258        binding = dtd.defaultPrefix.binding;
1259        localPart = tagNamePtr->str;
1260    }
1261    else
1262        return XML_ERROR_NONE;
1263    tagNamePtr->localPart = localPart;
1264    tagNamePtr->uriLen = binding->uriLen;
1265    i = binding->uriLen;
1266    do {
1267        if (i == binding->uriAlloc) {
1268            binding->uri = realloc(binding->uri, binding->uriAlloc *= 2);
1269            if (!binding->uri)
1270                return XML_ERROR_NO_MEMORY;
1271        }
1272        binding->uri[i++] = *localPart;
1273    } while (*localPart++);
1274    tagNamePtr->str = binding->uri;
1275    return XML_ERROR_NONE;
1276}
1277
1278static
1279int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr)
1280{
1281    BINDING *b;
1282    int len;
1283    for (len = 0; uri[len]; len++)
1284        ;
1285    if (namespaceSeparator)
1286        len++;
1287    if (freeBindingList) {
1288        b = freeBindingList;
1289        if (len > b->uriAlloc) {
1290            b->uri = realloc(b->uri, len + EXPAND_SPARE);
1291            if (!b->uri)
1292                return 0;
1293            b->uriAlloc = len + EXPAND_SPARE;
1294        }
1295        freeBindingList = b->nextTagBinding;
1296    }
1297    else {
1298        b = malloc(sizeof(BINDING));
1299        if (!b)
1300            return 0;
1301        b->uri = malloc(sizeof(XML_Char) * len + EXPAND_SPARE);
1302        if (!b->uri) {
1303            g_free(b);
1304            return 0;
1305        }
1306        b->uriAlloc = len;
1307    }
1308    b->uriLen = len;
1309    memcpy(b->uri, uri, len * sizeof(XML_Char));
1310    if (namespaceSeparator)
1311        b->uri[len - 1] = namespaceSeparator;
1312    b->prefix = prefix;
1313    b->attId = attId;
1314    b->prevPrefixBinding = prefix->binding;
1315    if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix)
1316        prefix->binding = 0;
1317    else
1318        prefix->binding = b;
1319    b->nextTagBinding = *bindingsPtr;
1320    *bindingsPtr = b;
1321    if (startNamespaceDeclHandler)
1322        startNamespaceDeclHandler(handlerArg, prefix->name,
1323                                  prefix->binding ? uri : 0);
1324    return 1;
1325}
1326
1327/* The idea here is to avoid using stack for each CDATA section when
1328the whole file is parsed with one call. */
1329
1330static
1331enum XML_Error cdataSectionProcessor(XML_Parser parser,
1332                                     const char *start,
1333                                     const char *end,
1334                                     const char **endPtr)
1335{
1336    enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr);
1337    if (start) {
1338        processor = contentProcessor;
1339        return contentProcessor(parser, start, end, endPtr);
1340    }
1341    return result;
1342}
1343
1344/* startPtr gets set to non-null is the section is closed, and to null if
1345the section is not yet closed. */
1346
1347static
1348enum XML_Error doCdataSection(XML_Parser parser,
1349                              const ENCODING *enc,
1350                              const char **startPtr,
1351                              const char *end,
1352                              const char **nextPtr)
1353{
1354    const char *s = *startPtr;
1355    const char **eventPP;
1356    const char **eventEndPP;
1357    if (enc == encoding) {
1358        eventPP = &eventPtr;
1359        *eventPP = s;
1360        eventEndPP = &eventEndPtr;
1361    }
1362    else {
1363        eventPP = &(openInternalEntities->internalEventPtr);
1364        eventEndPP = &(openInternalEntities->internalEventEndPtr);
1365    }
1366    *eventPP = s;
1367    *startPtr = 0;
1368    for (;;) {
1369        const char *next;
1370        int tok = XmlCdataSectionTok(enc, s, end, &next);
1371        *eventEndPP = next;
1372        switch (tok) {
1373        case XML_TOK_CDATA_SECT_CLOSE:
1374            if (endCdataSectionHandler)
1375                endCdataSectionHandler(handlerArg);
1376#if 0
1377            /* see comment under XML_TOK_CDATA_SECT_OPEN */
1378            else if (characterDataHandler)
1379                characterDataHandler(handlerArg, dataBuf, 0);
1380#endif
1381            else if (defaultHandler)
1382                reportDefault(parser, enc, s, next);
1383            *startPtr = next;
1384            return XML_ERROR_NONE;
1385        case XML_TOK_DATA_NEWLINE:
1386            if (characterDataHandler) {
1387                XML_Char c = 0xA;
1388                characterDataHandler(handlerArg, &c, 1);
1389            }
1390            else if (defaultHandler)
1391                reportDefault(parser, enc, s, next);
1392            break;
1393        case XML_TOK_DATA_CHARS:
1394            if (characterDataHandler) {
1395                if (MUST_CONVERT(enc, s)) {
1396                    for (;;) {
1397                        ICHAR *dataPtr = (ICHAR *)dataBuf;
1398                        XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
1399                        *eventEndPP = next;
1400                        characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
1401                        if (s == next)
1402                            break;
1403                        *eventPP = s;
1404                    }
1405                }
1406                else
1407                    characterDataHandler(handlerArg,
1408                                         (XML_Char *)s,
1409                                         (XML_Char *)next - (XML_Char *)s);
1410            }
1411            else if (defaultHandler)
1412                reportDefault(parser, enc, s, next);
1413            break;
1414        case XML_TOK_INVALID:
1415            *eventPP = next;
1416            return XML_ERROR_INVALID_TOKEN;
1417        case XML_TOK_PARTIAL_CHAR:
1418            if (nextPtr) {
1419                *nextPtr = s;
1420                return XML_ERROR_NONE;
1421            }
1422            return XML_ERROR_PARTIAL_CHAR;
1423        case XML_TOK_PARTIAL:
1424        case XML_TOK_NONE:
1425            if (nextPtr) {
1426                *nextPtr = s;
1427                return XML_ERROR_NONE;
1428            }
1429            return XML_ERROR_UNCLOSED_CDATA_SECTION;
1430        default:
1431            abort();
1432        }
1433        *eventPP = s = next;
1434    }
1435    /* not reached */
1436}
1437
1438static enum XML_Error
1439initializeEncoding(XML_Parser parser)
1440{
1441    const char *s;
1442#ifdef XML_UNICODE
1443    char encodingBuf[128];
1444    if (!protocolEncodingName)
1445        s = 0;
1446    else {
1447        int i;
1448        for (i = 0; protocolEncodingName[i]; i++) {
1449            if (i == sizeof(encodingBuf) - 1
1450                    || protocolEncodingName[i] >= 0x80
1451                    || protocolEncodingName[i] < 0) {
1452                encodingBuf[0] = '\0';
1453                break;
1454            }
1455            encodingBuf[i] = (char)protocolEncodingName[i];
1456        }
1457        encodingBuf[i] = '\0';
1458        s = encodingBuf;
1459    }
1460#else
1461s = protocolEncodingName;
1462#endif
1463    if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
1464        return XML_ERROR_NONE;
1465    return handleUnknownEncoding(parser, protocolEncodingName);
1466}
1467
1468static enum XML_Error
1469processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
1470               const char *s, const char *next)
1471{
1472    const char *encodingName = 0;
1473    const ENCODING *newEncoding = 0;
1474    const char *version;
1475    int standalone = -1;
1476    if (!(ns
1477            ? XmlParseXmlDeclNS
1478            : XmlParseXmlDecl)(isGeneralTextEntity,
1479                               encoding,
1480                               s,
1481                               next,
1482                               &eventPtr,
1483                               &version,
1484                               &encodingName,
1485                               &newEncoding,
1486                               &standalone))
1487        return XML_ERROR_SYNTAX;
1488    if (!isGeneralTextEntity && standalone == 1)
1489        dtd.standalone = 1;
1490    if (defaultHandler)
1491        reportDefault(parser, encoding, s, next);
1492    if (!protocolEncodingName) {
1493        if (newEncoding) {
1494            if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
1495                eventPtr = encodingName;
1496                return XML_ERROR_INCORRECT_ENCODING;
1497            }
1498            encoding = newEncoding;
1499        }
1500        else if (encodingName) {
1501            enum XML_Error result;
1502            const XML_Char *s = poolStoreString(&tempPool,
1503                                                encoding,
1504                                                encodingName,
1505                                                encodingName
1506                                                + XmlNameLength(encoding, encodingName));
1507            if (!s)
1508                return XML_ERROR_NO_MEMORY;
1509            result = handleUnknownEncoding(parser, s);
1510            poolDiscard(&tempPool);
1511            if (result == XML_ERROR_UNKNOWN_ENCODING)
1512                eventPtr = encodingName;
1513            return result;
1514        }
1515    }
1516    return XML_ERROR_NONE;
1517}
1518
1519static enum XML_Error
1520handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
1521{
1522    if (unknownEncodingHandler) {
1523        XML_Encoding info;
1524        int i;
1525        for (i = 0; i < 256; i++)
1526            info.map[i] = -1;
1527        info.convert = 0;
1528        info.data = 0;
1529        info.release = 0;
1530        if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) {
1531            ENCODING *enc;
1532            unknownEncodingMem = malloc(XmlSizeOfUnknownEncoding());
1533            if (!unknownEncodingMem) {
1534                if (info.release)
1535                    info.release(info.data);
1536                return XML_ERROR_NO_MEMORY;
1537            }
1538            enc = (ns
1539                   ? XmlInitUnknownEncodingNS
1540                   : XmlInitUnknownEncoding)(unknownEncodingMem,
1541                                             info.map,
1542                                             info.convert,
1543                                             info.data);
1544            if (enc) {
1545                unknownEncodingData = info.data;
1546                unknownEncodingRelease = info.release;
1547                encoding = enc;
1548                return XML_ERROR_NONE;
1549            }
1550        }
1551        if (info.release)
1552            info.release(info.data);
1553    }
1554    return XML_ERROR_UNKNOWN_ENCODING;
1555}
1556
1557static enum XML_Error
1558prologInitProcessor(XML_Parser parser,
1559                    const char *s,
1560                    const char *end,
1561                    const char **nextPtr)
1562{
1563    enum XML_Error result = initializeEncoding(parser);
1564    if (result != XML_ERROR_NONE)
1565        return result;
1566    processor = prologProcessor;
1567    return prologProcessor(parser, s, end, nextPtr);
1568}
1569
1570static enum XML_Error
1571prologProcessor(XML_Parser parser,
1572                const char *s,
1573                const char *end,
1574                const char **nextPtr)
1575{
1576    for (;;) {
1577        const char *next;
1578        int tok = XmlPrologTok(encoding, s, end, &next);
1579        if (tok <= 0) {
1580            if (nextPtr != 0 && tok != XML_TOK_INVALID) {
1581                *nextPtr = s;
1582                return XML_ERROR_NONE;
1583            }
1584            switch (tok) {
1585            case XML_TOK_INVALID:
1586                eventPtr = next;
1587                return XML_ERROR_INVALID_TOKEN;
1588            case XML_TOK_NONE:
1589                return XML_ERROR_NO_ELEMENTS;
1590            case XML_TOK_PARTIAL:
1591                return XML_ERROR_UNCLOSED_TOKEN;
1592            case XML_TOK_PARTIAL_CHAR:
1593                return XML_ERROR_PARTIAL_CHAR;
1594            case XML_TOK_TRAILING_CR:
1595                eventPtr = s + encoding->minBytesPerChar;
1596                return XML_ERROR_NO_ELEMENTS;
1597            default:
1598                abort();
1599            }
1600        }
1601        switch (XmlTokenRole(&prologState, tok, s, next, encoding)) {
1602        case XML_ROLE_XML_DECL:
1603            {
1604                enum XML_Error result = processXmlDecl(parser, 0, s, next);
1605                if (result != XML_ERROR_NONE)
1606                    return result;
1607            }
1608            break;
1609        case XML_ROLE_DOCTYPE_SYSTEM_ID:
1610            if (!dtd.standalone
1611                    && notStandaloneHandler
1612                    && !notStandaloneHandler(handlerArg))
1613                return XML_ERROR_NOT_STANDALONE;
1614            hadExternalDoctype = 1;
1615            break;
1616        case XML_ROLE_DOCTYPE_PUBLIC_ID:
1617        case XML_ROLE_ENTITY_PUBLIC_ID:
1618            if (!XmlIsPublicId(encoding, s, next, &eventPtr))
1619                return XML_ERROR_SYNTAX;
1620            if (declEntity) {
1621                XML_Char *tem = poolStoreString(&dtd.pool,
1622                                                encoding,
1623                                                s + encoding->minBytesPerChar,
1624                                                next - encoding->minBytesPerChar);
1625                if (!tem)
1626                    return XML_ERROR_NO_MEMORY;
1627                normalizePublicId(tem);
1628                declEntity->publicId = tem;
1629                poolFinish(&dtd.pool);
1630            }
1631            break;
1632        case XML_ROLE_INSTANCE_START:
1633            processor = contentProcessor;
1634            if (hadExternalDoctype)
1635                dtd.complete = 0;
1636            return contentProcessor(parser, s, end, nextPtr);
1637        case XML_ROLE_ATTLIST_ELEMENT_NAME:
1638            {
1639                const XML_Char *name = poolStoreString(&dtd.pool, encoding, s, next);
1640                if (!name)
1641                    return XML_ERROR_NO_MEMORY;
1642                declElementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
1643                if (!declElementType)
1644                    return XML_ERROR_NO_MEMORY;
1645                if (declElementType->name != name)
1646                    poolDiscard(&dtd.pool);
1647                else {
1648                    poolFinish(&dtd.pool);
1649                    if (!setElementTypePrefix(parser, declElementType))
1650                        return XML_ERROR_NO_MEMORY;
1651                }
1652                break;
1653            }
1654        case XML_ROLE_ATTRIBUTE_NAME:
1655            declAttributeId = getAttributeId(parser, encoding, s, next);
1656            if (!declAttributeId)
1657                return XML_ERROR_NO_MEMORY;
1658            declAttributeIsCdata = 0;
1659            break;
1660        case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
1661            declAttributeIsCdata = 1;
1662            break;
1663        case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
1664        case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
1665            if (dtd.complete
1666                    && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0))
1667                return XML_ERROR_NO_MEMORY;
1668            break;
1669        case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
1670        case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
1671            {
1672                const XML_Char *attVal;
1673                enum XML_Error result
1674                = storeAttributeValue(parser, encoding, declAttributeIsCdata,
1675                                      s + encoding->minBytesPerChar,
1676                                      next - encoding->minBytesPerChar,
1677                                      &dtd.pool);
1678                if (result)
1679                    return result;
1680                attVal = poolStart(&dtd.pool);
1681                poolFinish(&dtd.pool);
1682                if (dtd.complete
1683                        && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, attVal))
1684                    return XML_ERROR_NO_MEMORY;
1685                break;
1686            }
1687        case XML_ROLE_ENTITY_VALUE:
1688            {
1689                enum XML_Error result = storeEntityValue(parser, s, next);
1690                if (result != XML_ERROR_NONE)
1691                    return result;
1692            }
1693            break;
1694        case XML_ROLE_ENTITY_SYSTEM_ID:
1695            if (declEntity) {
1696                declEntity->systemId = poolStoreString(&dtd.pool, encoding,
1697                                                       s + encoding->minBytesPerChar,
1698                                                       next - encoding->minBytesPerChar);
1699                if (!declEntity->systemId)
1700                    return XML_ERROR_NO_MEMORY;
1701                declEntity->base = dtd.base;
1702                poolFinish(&dtd.pool);
1703            }
1704            break;
1705        case XML_ROLE_ENTITY_NOTATION_NAME:
1706            if (declEntity) {
1707                declEntity->notation = poolStoreString(&dtd.pool, encoding, s, next);
1708                if (!declEntity->notation)
1709                    return XML_ERROR_NO_MEMORY;
1710                poolFinish(&dtd.pool);
1711                if (unparsedEntityDeclHandler) {
1712                    eventPtr = eventEndPtr = s;
1713                    unparsedEntityDeclHandler(handlerArg,
1714                                              declEntity->name,
1715                                              declEntity->base,
1716                                              declEntity->systemId,
1717                                              declEntity->publicId,
1718                                              declEntity->notation);
1719                }
1720
1721            }
1722            break;
1723        case XML_ROLE_GENERAL_ENTITY_NAME:
1724            {
1725                const XML_Char *name;
1726                if (XmlPredefinedEntityName(encoding, s, next)) {
1727                    declEntity = 0;
1728                    break;
1729                }
1730                name = poolStoreString(&dtd.pool, encoding, s, next);
1731                if (!name)
1732                    return XML_ERROR_NO_MEMORY;
1733                if (dtd.complete) {
1734                    declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY));
1735                    if (!declEntity)
1736                        return XML_ERROR_NO_MEMORY;
1737                    if (declEntity->name != name) {
1738                        poolDiscard(&dtd.pool);
1739                        declEntity = 0;
1740                    }
1741                    else
1742                        poolFinish(&dtd.pool);
1743                }
1744                else {
1745                    poolDiscard(&dtd.pool);
1746                    declEntity = 0;
1747                }
1748            }
1749            break;
1750        case XML_ROLE_PARAM_ENTITY_NAME:
1751            declEntity = 0;
1752            break;
1753        case XML_ROLE_NOTATION_NAME:
1754            declNotationPublicId = 0;
1755            declNotationName = 0;
1756            if (notationDeclHandler) {
1757                declNotationName = poolStoreString(&tempPool, encoding, s, next);
1758                if (!declNotationName)
1759                    return XML_ERROR_NO_MEMORY;
1760                poolFinish(&tempPool);
1761            }
1762            break;
1763        case XML_ROLE_NOTATION_PUBLIC_ID:
1764            if (!XmlIsPublicId(encoding, s, next, &eventPtr))
1765                return XML_ERROR_SYNTAX;
1766            if (declNotationName) {
1767                XML_Char *tem = poolStoreString(&tempPool,
1768                                                encoding,
1769                                                s + encoding->minBytesPerChar,
1770                                                next - encoding->minBytesPerChar);
1771                if (!tem)
1772                    return XML_ERROR_NO_MEMORY;
1773                normalizePublicId(tem);
1774                declNotationPublicId = tem;
1775                poolFinish(&tempPool);
1776            }
1777            break;
1778        case XML_ROLE_NOTATION_SYSTEM_ID:
1779            if (declNotationName && notationDeclHandler) {
1780                const XML_Char *systemId
1781                = poolStoreString(&tempPool, encoding,
1782                                  s + encoding->minBytesPerChar,
1783                                  next - encoding->minBytesPerChar);
1784                if (!systemId)
1785                    return XML_ERROR_NO_MEMORY;
1786                eventPtr = eventEndPtr = s;
1787                notationDeclHandler(handlerArg,
1788                                    declNotationName,
1789                                    dtd.base,
1790                                    systemId,
1791                                    declNotationPublicId);
1792            }
1793            poolClear(&tempPool);
1794            break;
1795        case XML_ROLE_NOTATION_NO_SYSTEM_ID:
1796            if (declNotationPublicId && notationDeclHandler) {
1797                eventPtr = eventEndPtr = s;
1798                notationDeclHandler(handlerArg,
1799                                    declNotationName,
1800                                    dtd.base,
1801                                    0,
1802                                    declNotationPublicId);
1803            }
1804            poolClear(&tempPool);
1805            break;
1806        case XML_ROLE_ERROR:
1807            eventPtr = s;
1808            switch (tok) {
1809            case XML_TOK_PARAM_ENTITY_REF:
1810                return XML_ERROR_PARAM_ENTITY_REF;
1811            case XML_TOK_XML_DECL:
1812                return XML_ERROR_MISPLACED_XML_PI;
1813            default:
1814                return XML_ERROR_SYNTAX;
1815            }
1816        case XML_ROLE_GROUP_OPEN:
1817            if (prologState.level >= groupSize) {
1818                if (groupSize)
1819                    groupConnector = realloc(groupConnector, groupSize *= 2);
1820                else
1821                    groupConnector = malloc(groupSize = 32);
1822                if (!groupConnector)
1823                    return XML_ERROR_NO_MEMORY;
1824            }
1825            groupConnector[prologState.level] = 0;
1826            break;
1827        case XML_ROLE_GROUP_SEQUENCE:
1828            if (groupConnector[prologState.level] == '|') {
1829                eventPtr = s;
1830                return XML_ERROR_SYNTAX;
1831            }
1832            groupConnector[prologState.level] = ',';
1833            break;
1834        case XML_ROLE_GROUP_CHOICE:
1835            if (groupConnector[prologState.level] == ',') {
1836                eventPtr = s;
1837                return XML_ERROR_SYNTAX;
1838            }
1839            groupConnector[prologState.level] = '|';
1840            break;
1841        case XML_ROLE_PARAM_ENTITY_REF:
1842            if (!dtd.standalone
1843                    && notStandaloneHandler
1844                    && !notStandaloneHandler(handlerArg))
1845                return XML_ERROR_NOT_STANDALONE;
1846            dtd.complete = 0;
1847            break;
1848        case XML_ROLE_NONE:
1849            switch (tok) {
1850            case XML_TOK_PI:
1851                eventPtr = s;
1852                eventEndPtr = next;
1853                if (!reportProcessingInstruction(parser, encoding, s, next))
1854                    return XML_ERROR_NO_MEMORY;
1855                break;
1856            case XML_TOK_COMMENT:
1857                eventPtr = s;
1858                eventEndPtr = next;
1859                if (!reportComment(parser, encoding, s, next))
1860                    return XML_ERROR_NO_MEMORY;
1861                break;
1862            }
1863            break;
1864        }
1865        if (defaultHandler) {
1866            switch (tok) {
1867            case XML_TOK_PI:
1868            case XML_TOK_COMMENT:
1869            case XML_TOK_BOM:
1870            case XML_TOK_XML_DECL:
1871                break;
1872            default:
1873                eventPtr = s;
1874                eventEndPtr = next;
1875                reportDefault(parser, encoding, s, next);
1876            }
1877        }
1878        s = next;
1879    }
1880    /* not reached */
1881}
1882
1883static
1884enum XML_Error epilogProcessor(XML_Parser parser,
1885                               const char *s,
1886                               const char *end,
1887                               const char **nextPtr)
1888{
1889    processor = epilogProcessor;
1890    eventPtr = s;
1891    for (;;) {
1892        const char *next;
1893        int tok = XmlPrologTok(encoding, s, end, &next);
1894        eventEndPtr = next;
1895        switch (tok) {
1896        case XML_TOK_TRAILING_CR:
1897            if (defaultHandler) {
1898                eventEndPtr = end;
1899                reportDefault(parser, encoding, s, end);
1900            }
1901            /* fall through */
1902        case XML_TOK_NONE:
1903            if (nextPtr)
1904                *nextPtr = end;
1905            return XML_ERROR_NONE;
1906        case XML_TOK_PROLOG_S:
1907            if (defaultHandler)
1908                reportDefault(parser, encoding, s, next);
1909            break;
1910        case XML_TOK_PI:
1911            if (!reportProcessingInstruction(parser, encoding, s, next))
1912                return XML_ERROR_NO_MEMORY;
1913            break;
1914        case XML_TOK_COMMENT:
1915            if (!reportComment(parser, encoding, s, next))
1916                return XML_ERROR_NO_MEMORY;
1917            break;
1918        case XML_TOK_INVALID:
1919            eventPtr = next;
1920            return XML_ERROR_INVALID_TOKEN;
1921        case XML_TOK_PARTIAL:
1922            if (nextPtr) {
1923                *nextPtr = s;
1924                return XML_ERROR_NONE;
1925            }
1926            return XML_ERROR_UNCLOSED_TOKEN;
1927        case XML_TOK_PARTIAL_CHAR:
1928            if (nextPtr) {
1929                *nextPtr = s;
1930                return XML_ERROR_NONE;
1931            }
1932            return XML_ERROR_PARTIAL_CHAR;
1933        default:
1934            return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
1935        }
1936        eventPtr = s = next;
1937    }
1938}
1939
1940static enum XML_Error
1941storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
1942                    const char *ptr, const char *end,
1943                    STRING_POOL *pool)
1944{
1945    enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
1946    if (result)
1947        return result;
1948    if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
1949        poolChop(pool);
1950    if (!poolAppendChar(pool, XML_T('\0')))
1951        return XML_ERROR_NO_MEMORY;
1952    return XML_ERROR_NONE;
1953}
1954
1955static enum XML_Error
1956appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
1957                     const char *ptr, const char *end,
1958                     STRING_POOL *pool)
1959{
1960    const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
1961    for (;;) {
1962        const char *next;
1963        int tok = XmlAttributeValueTok(enc, ptr, end, &next);
1964        switch (tok) {
1965        case XML_TOK_NONE:
1966            return XML_ERROR_NONE;
1967        case XML_TOK_INVALID:
1968            if (enc == encoding)
1969                eventPtr = next;
1970            return XML_ERROR_INVALID_TOKEN;
1971        case XML_TOK_PARTIAL:
1972            if (enc == encoding)
1973                eventPtr = ptr;
1974            return XML_ERROR_INVALID_TOKEN;
1975        case XML_TOK_CHAR_REF:
1976            {
1977                XML_Char buf[XML_ENCODE_MAX];
1978                int i;
1979                int n = XmlCharRefNumber(enc, ptr);
1980                if (n < 0) {
1981                    if (enc == encoding)
1982                        eventPtr = ptr;
1983                    return XML_ERROR_BAD_CHAR_REF;
1984                }
1985                if (!isCdata
1986                        && n == 0x20 /* space */
1987                        && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
1988                    break;
1989                n = XmlEncode(n, (ICHAR *)buf);
1990                if (!n) {
1991                    if (enc == encoding)
1992                        eventPtr = ptr;
1993                    return XML_ERROR_BAD_CHAR_REF;
1994                }
1995                for (i = 0; i < n; i++) {
1996                    if (!poolAppendChar(pool, buf[i]))
1997                        return XML_ERROR_NO_MEMORY;
1998                }
1999            }
2000            break;
2001        case XML_TOK_DATA_CHARS:
2002            if (!poolAppend(pool, enc, ptr, next))
2003                return XML_ERROR_NO_MEMORY;
2004            break;
2005            break;
2006        case XML_TOK_TRAILING_CR:
2007            next = ptr + enc->minBytesPerChar;
2008            /* fall through */
2009        case XML_TOK_ATTRIBUTE_VALUE_S:
2010        case XML_TOK_DATA_NEWLINE:
2011            if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
2012                break;
2013            if (!poolAppendChar(pool, 0x20))
2014                return XML_ERROR_NO_MEMORY;
2015            break;
2016        case XML_TOK_ENTITY_REF:
2017            {
2018                const XML_Char *name;
2019                ENTITY *entity;
2020                XML_Char ch = XmlPredefinedEntityName(enc,
2021                                                      ptr + enc->minBytesPerChar,
2022                                                      next - enc->minBytesPerChar);
2023                if (ch) {
2024                    if (!poolAppendChar(pool, ch))
2025                        return XML_ERROR_NO_MEMORY;
2026                    break;
2027                }
2028                name = poolStoreString(&temp2Pool, enc,
2029                                       ptr + enc->minBytesPerChar,
2030                                       next - enc->minBytesPerChar);
2031                if (!name)
2032                    return XML_ERROR_NO_MEMORY;
2033                entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
2034                poolDiscard(&temp2Pool);
2035                if (!entity) {
2036                    if (dtd.complete) {
2037                        if (enc == encoding)
2038                            eventPtr = ptr;
2039                        return XML_ERROR_UNDEFINED_ENTITY;
2040                    }
2041                }
2042                else if (entity->open) {
2043                    if (enc == encoding)
2044                        eventPtr = ptr;
2045                    return XML_ERROR_RECURSIVE_ENTITY_REF;
2046                }
2047                else if (entity->notation) {
2048                    if (enc == encoding)
2049                        eventPtr = ptr;
2050                    return XML_ERROR_BINARY_ENTITY_REF;
2051                }
2052                else if (!entity->textPtr) {
2053                    if (enc == encoding)
2054                        eventPtr = ptr;
2055                    return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
2056                }
2057                else {
2058                    enum XML_Error result;
2059                    const XML_Char *textEnd = entity->textPtr + entity->textLen;
2060                    entity->open = 1;
2061                    result = appendAttributeValue(parser, internalEnc, isCdata, (char *)entity->textPtr, (char *)textEnd, pool);
2062                    entity->open = 0;
2063                    if (result)
2064                        return result;
2065                }
2066            }
2067            break;
2068        default:
2069            abort();
2070        }
2071        ptr = next;
2072    }
2073    /* not reached */
2074}
2075
2076static
2077enum XML_Error storeEntityValue(XML_Parser parser,
2078                                const char *entityTextPtr,
2079                                const char *entityTextEnd)
2080{
2081    const ENCODING *internalEnc;
2082    STRING_POOL *pool = &(dtd.pool);
2083    entityTextPtr += encoding->minBytesPerChar;
2084    entityTextEnd -= encoding->minBytesPerChar;
2085    internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
2086    for (;;) {
2087        const char *next;
2088        int tok = XmlEntityValueTok(encoding, entityTextPtr, entityTextEnd, &next);
2089        switch (tok) {
2090        case XML_TOK_PARAM_ENTITY_REF:
2091            eventPtr = entityTextPtr;
2092            return XML_ERROR_SYNTAX;
2093        case XML_TOK_NONE:
2094            if (declEntity) {
2095                declEntity->textPtr = pool->start;
2096                declEntity->textLen = pool->ptr - pool->start;
2097                poolFinish(pool);
2098            }
2099            else
2100                poolDiscard(pool);
2101            return XML_ERROR_NONE;
2102        case XML_TOK_ENTITY_REF:
2103        case XML_TOK_DATA_CHARS:
2104            if (!poolAppend(pool, encoding, entityTextPtr, next))
2105                return XML_ERROR_NO_MEMORY;
2106            break;
2107        case XML_TOK_TRAILING_CR:
2108            next = entityTextPtr + encoding->minBytesPerChar;
2109            /* fall through */
2110        case XML_TOK_DATA_NEWLINE:
2111            if (pool->end == pool->ptr && !poolGrow(pool))
2112                return XML_ERROR_NO_MEMORY;
2113            *(pool->ptr)++ = 0xA;
2114            break;
2115        case XML_TOK_CHAR_REF:
2116            {
2117                XML_Char buf[XML_ENCODE_MAX];
2118                int i;
2119                int n = XmlCharRefNumber(encoding, entityTextPtr);
2120                if (n < 0) {
2121                    eventPtr = entityTextPtr;
2122                    return XML_ERROR_BAD_CHAR_REF;
2123                }
2124                n = XmlEncode(n, (ICHAR *)buf);
2125                if (!n) {
2126                    eventPtr = entityTextPtr;
2127                    return XML_ERROR_BAD_CHAR_REF;
2128                }
2129                for (i = 0; i < n; i++) {
2130                    if (pool->end == pool->ptr && !poolGrow(pool))
2131                        return XML_ERROR_NO_MEMORY;
2132                    *(pool->ptr)++ = buf[i];
2133                }
2134            }
2135            break;
2136        case XML_TOK_PARTIAL:
2137            eventPtr = entityTextPtr;
2138            return XML_ERROR_INVALID_TOKEN;
2139        case XML_TOK_INVALID:
2140            eventPtr = next;
2141            return XML_ERROR_INVALID_TOKEN;
2142        default:
2143            abort();
2144        }
2145        entityTextPtr = next;
2146    }
2147    /* not reached */
2148}
2149
2150static void
2151normalizeLines(XML_Char *s)
2152{
2153    XML_Char *p;
2154    for (;; s++) {
2155        if (*s == XML_T('\0'))
2156            return;
2157        if (*s == 0xD)
2158            break;
2159    }
2160    p = s;
2161    do {
2162        if (*s == 0xD) {
2163            *p++ = 0xA;
2164            if (*++s == 0xA)
2165                s++;
2166        }
2167        else
2168            *p++ = *s++;
2169    } while (*s);
2170    *p = XML_T('\0');
2171}
2172
2173static int
2174reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
2175{
2176    const XML_Char *target;
2177    XML_Char *data;
2178    const char *tem;
2179    if (!processingInstructionHandler) {
2180        if (defaultHandler)
2181            reportDefault(parser, enc, start, end);
2182        return 1;
2183    }
2184    start += enc->minBytesPerChar * 2;
2185    tem = start + XmlNameLength(enc, start);
2186    target = poolStoreString(&tempPool, enc, start, tem);
2187    if (!target)
2188        return 0;
2189    poolFinish(&tempPool);
2190    data = poolStoreString(&tempPool, enc,
2191                           XmlSkipS(enc, tem),
2192                           end - enc->minBytesPerChar*2);
2193    if (!data)
2194        return 0;
2195    normalizeLines(data);
2196    processingInstructionHandler(handlerArg, target, data);
2197    poolClear(&tempPool);
2198    return 1;
2199}
2200
2201static int
2202reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
2203{
2204    XML_Char *data;
2205    if (!commentHandler) {
2206        if (defaultHandler)
2207            reportDefault(parser, enc, start, end);
2208        return 1;
2209    }
2210    data = poolStoreString(&tempPool,
2211                           enc,
2212                           start + enc->minBytesPerChar * 4,
2213                           end - enc->minBytesPerChar * 3);
2214    if (!data)
2215        return 0;
2216    normalizeLines(data);
2217    commentHandler(handlerArg, data);
2218    poolClear(&tempPool);
2219    return 1;
2220}
2221
2222static void
2223reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end)
2224{
2225    if (MUST_CONVERT(enc, s)) {
2226        const char **eventPP;
2227        const char **eventEndPP;
2228        if (enc == encoding) {
2229            eventPP = &eventPtr;
2230            eventEndPP = &eventEndPtr;
2231        }
2232        else {
2233            eventPP = &(openInternalEntities->internalEventPtr);
2234            eventEndPP = &(openInternalEntities->internalEventEndPtr);
2235        }
2236        do {
2237            ICHAR *dataPtr = (ICHAR *)dataBuf;
2238            XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
2239            *eventEndPP = s;
2240            defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
2241            *eventPP = s;
2242        } while (s != end);
2243    }
2244    else
2245        defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
2246}
2247
2248
2249static int
2250defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata, const XML_Char *value)
2251{
2252    DEFAULT_ATTRIBUTE *att;
2253    if (type->nDefaultAtts == type->allocDefaultAtts) {
2254        if (type->allocDefaultAtts == 0) {
2255            type->allocDefaultAtts = 8;
2256            type->defaultAtts = malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
2257        }
2258        else {
2259            type->allocDefaultAtts *= 2;
2260            type->defaultAtts = realloc(type->defaultAtts,
2261                                        type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
2262        }
2263        if (!type->defaultAtts)
2264            return 0;
2265    }
2266    att = type->defaultAtts + type->nDefaultAtts;
2267    att->id = attId;
2268    att->value = value;
2269    att->isCdata = isCdata;
2270    if (!isCdata)
2271        attId->maybeTokenized = 1;
2272    type->nDefaultAtts += 1;
2273    return 1;
2274}
2275
2276static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
2277{
2278    const XML_Char *name;
2279    for (name = elementType->name; *name; name++) {
2280        if (*name == XML_T(':')) {
2281            PREFIX *prefix;
2282            const XML_Char *s;
2283            for (s = elementType->name; s != name; s++) {
2284                if (!poolAppendChar(&dtd.pool, *s))
2285                    return 0;
2286            }
2287            if (!poolAppendChar(&dtd.pool, XML_T('\0')))
2288                return 0;
2289            prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
2290            if (!prefix)
2291                return 0;
2292            if (prefix->name == poolStart(&dtd.pool))
2293                poolFinish(&dtd.pool);
2294            else
2295                poolDiscard(&dtd.pool);
2296            elementType->prefix = prefix;
2297
2298        }
2299    }
2300    return 1;
2301}
2302
2303static ATTRIBUTE_ID *
2304getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
2305{
2306    ATTRIBUTE_ID *id;
2307    const XML_Char *name;
2308    if (!poolAppendChar(&dtd.pool, XML_T('\0')))
2309        return 0;
2310    name = poolStoreString(&dtd.pool, enc, start, end);
2311    if (!name)
2312        return 0;
2313    ++name;
2314    id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID));
2315    if (!id)
2316        return 0;
2317    if (id->name != name)
2318        poolDiscard(&dtd.pool);
2319    else {
2320        poolFinish(&dtd.pool);
2321        if (!ns)
2322            ;
2323        else if (name[0] == 'x'
2324                 && name[1] == 'm'
2325                 && name[2] == 'l'
2326                 && name[3] == 'n'
2327                 && name[4] == 's'
2328                 && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
2329            if (name[5] == '\0')
2330                id->prefix = &dtd.defaultPrefix;
2331            else
2332                id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX));
2333            id->xmlns = 1;
2334        }
2335        else {
2336            int i;
2337            for (i = 0; name[i]; i++) {
2338                if (name[i] == XML_T(':')) {
2339                    int j;
2340                    for (j = 0; j < i; j++) {
2341                        if (!poolAppendChar(&dtd.pool, name[j]))
2342                            return 0;
2343                    }
2344                    if (!poolAppendChar(&dtd.pool, XML_T('\0')))
2345                        return 0;
2346                    id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
2347                    if (id->prefix->name == poolStart(&dtd.pool))
2348                        poolFinish(&dtd.pool);
2349                    else
2350                        poolDiscard(&dtd.pool);
2351                    break;
2352                }
2353            }
2354        }
2355    }
2356    return id;
2357}
2358
2359#define CONTEXT_SEP XML_T('\f')
2360
2361static
2362const XML_Char *getContext(XML_Parser parser)
2363{
2364    HASH_TABLE_ITER iter;
2365    int needSep = 0;
2366
2367    if (dtd.defaultPrefix.binding) {
2368        int i;
2369        int len;
2370        if (!poolAppendChar(&tempPool, XML_T('=')))
2371            return 0;
2372        len = dtd.defaultPrefix.binding->uriLen;
2373        if (namespaceSeparator != XML_T('\0'))
2374            len--;
2375        for (i = 0; i < len; i++)
2376            if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i]))
2377                return 0;
2378        needSep = 1;
2379    }
2380
2381    hashTableIterInit(&iter, &(dtd.prefixes));
2382    for (;;) {
2383        int i;
2384        int len;
2385        const XML_Char *s;
2386        PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
2387        if (!prefix)
2388            break;
2389        if (!prefix->binding)
2390            continue;
2391        if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
2392            return 0;
2393        for (s = prefix->name; *s; s++)
2394            if (!poolAppendChar(&tempPool, *s))
2395                return 0;
2396        if (!poolAppendChar(&tempPool, XML_T('=')))
2397            return 0;
2398        len = prefix->binding->uriLen;
2399        if (namespaceSeparator != XML_T('\0'))
2400            len--;
2401        for (i = 0; i < len; i++)
2402            if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
2403                return 0;
2404        needSep = 1;
2405    }
2406
2407
2408    hashTableIterInit(&iter, &(dtd.generalEntities));
2409    for (;;) {
2410        const XML_Char *s;
2411        ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
2412        if (!e)
2413            break;
2414        if (!e->open)
2415            continue;
2416        if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
2417            return 0;
2418        for (s = e->name; *s; s++)
2419            if (!poolAppendChar(&tempPool, *s))
2420                return 0;
2421        needSep = 1;
2422    }
2423
2424    if (!poolAppendChar(&tempPool, XML_T('\0')))
2425        return 0;
2426    return tempPool.start;
2427}
2428
2429static
2430void normalizePublicId(XML_Char *publicId)
2431{
2432    XML_Char *p = publicId;
2433    XML_Char *s;
2434    for (s = publicId; *s; s++) {
2435        switch (*s) {
2436        case 0x20:
2437        case 0xD:
2438        case 0xA:
2439            if (p != publicId && p[-1] != 0x20)
2440                *p++ = 0x20;
2441            break;
2442        default:
2443            *p++ = *s;
2444        }
2445    }
2446    if (p != publicId && p[-1] == 0x20)
2447        --p;
2448    *p = XML_T('\0');
2449}
2450
2451static int dtdInit(DTD *p)
2452{
2453    poolInit(&(p->pool));
2454    hashTableInit(&(p->generalEntities));
2455    hashTableInit(&(p->elementTypes));
2456    hashTableInit(&(p->attributeIds));
2457    hashTableInit(&(p->prefixes));
2458    p->complete = 1;
2459    p->standalone = 0;
2460    p->base = 0;
2461    p->defaultPrefix.name = 0;
2462    p->defaultPrefix.binding = 0;
2463    return 1;
2464}
2465
2466static void dtdDestroy(DTD *p)
2467{
2468    HASH_TABLE_ITER iter;
2469    hashTableIterInit(&iter, &(p->elementTypes));
2470    for (;;) {
2471        ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
2472        if (!e)
2473            break;
2474        if (e->allocDefaultAtts != 0)
2475            g_free(e->defaultAtts);
2476    }
2477    hashTableDestroy(&(p->generalEntities));
2478    hashTableDestroy(&(p->elementTypes));
2479    hashTableDestroy(&(p->attributeIds));
2480    hashTableDestroy(&(p->prefixes));
2481    poolDestroy(&(p->pool));
2482}
2483
2484static
2485void poolInit(STRING_POOL *pool)
2486{
2487    pool->blocks = 0;
2488    pool->freeBlocks = 0;
2489    pool->start = 0;
2490    pool->ptr = 0;
2491    pool->end = 0;
2492}
2493
2494static
2495void poolClear(STRING_POOL *pool)
2496{
2497    if (!pool->freeBlocks)
2498        pool->freeBlocks = pool->blocks;
2499    else {
2500        BLOCK *p = pool->blocks;
2501        while (p) {
2502            BLOCK *tem = p->next;
2503            p->next = pool->freeBlocks;
2504            pool->freeBlocks = p;
2505            p = tem;
2506        }
2507    }
2508    pool->blocks = 0;
2509    pool->start = 0;
2510    pool->ptr = 0;
2511    pool->end = 0;
2512}
2513
2514static
2515void poolDestroy(STRING_POOL *pool)
2516{
2517    BLOCK *p = pool->blocks;
2518    while (p) {
2519        BLOCK *tem = p->next;
2520        g_free(p);
2521        p = tem;
2522    }
2523    pool->blocks = 0;
2524    p = pool->freeBlocks;
2525    while (p) {
2526        BLOCK *tem = p->next;
2527        g_free(p);
2528        p = tem;
2529    }
2530    pool->freeBlocks = 0;
2531    pool->ptr = 0;
2532    pool->start = 0;
2533    pool->end = 0;
2534}
2535
2536static
2537XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
2538                     const char *ptr, const char *end)
2539{
2540    if (!pool->ptr && !poolGrow(pool))
2541        return 0;
2542    for (;;) {
2543        XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
2544        if (ptr == end)
2545            break;
2546        if (!poolGrow(pool))
2547            return 0;
2548    }
2549    return pool->start;
2550}
2551
2552static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s)
2553{
2554    do {
2555        if (!poolAppendChar(pool, *s))
2556            return 0;
2557    } while (*s++);
2558    s = pool->start;
2559    poolFinish(pool);
2560    return s;
2561}
2562
2563static
2564XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
2565                          const char *ptr, const char *end)
2566{
2567    if (!poolAppend(pool, enc, ptr, end))
2568        return 0;
2569    if (pool->ptr == pool->end && !poolGrow(pool))
2570        return 0;
2571    *(pool->ptr)++ = 0;
2572    return pool->start;
2573}
2574
2575static
2576int poolGrow(STRING_POOL *pool)
2577{
2578    if (pool->freeBlocks) {
2579        if (pool->start == 0) {
2580            pool->blocks = pool->freeBlocks;
2581            pool->freeBlocks = pool->freeBlocks->next;
2582            pool->blocks->next = 0;
2583            pool->start = pool->blocks->s;
2584            pool->end = pool->start + pool->blocks->size;
2585            pool->ptr = pool->start;
2586            return 1;
2587        }
2588        if (pool->end - pool->start < pool->freeBlocks->size) {
2589            BLOCK *tem = pool->freeBlocks->next;
2590            pool->freeBlocks->next = pool->blocks;
2591            pool->blocks = pool->freeBlocks;
2592            pool->freeBlocks = tem;
2593            memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char));
2594            pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
2595            pool->start = pool->blocks->s;
2596            pool->end = pool->start + pool->blocks->size;
2597            return 1;
2598        }
2599    }
2600    if (pool->blocks && pool->start == pool->blocks->s) {
2601        int blockSize = (pool->end - pool->start)*2;
2602        pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
2603        if (!pool->blocks)
2604            return 0;
2605        pool->blocks->size = blockSize;
2606        pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
2607        pool->start = pool->blocks->s;
2608        pool->end = pool->start + blockSize;
2609    }
2610    else {
2611        BLOCK *tem;
2612        int blockSize = pool->end - pool->start;
2613        if (blockSize < INIT_BLOCK_SIZE)
2614            blockSize = INIT_BLOCK_SIZE;
2615        else
2616            blockSize *= 2;
2617        tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
2618        if (!tem)
2619            return 0;
2620        tem->size = blockSize;
2621        tem->next = pool->blocks;
2622        pool->blocks = tem;
2623        memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
2624        pool->ptr = tem->s + (pool->ptr - pool->start);
2625        pool->start = tem->s;
2626        pool->end = tem->s + blockSize;
2627    }
2628    return 1;
2629}
Note: See TracBrowser for help on using the repository browser.